Files
yunkong2.vis/www/js/visEditInspect.js
2018-09-16 09:04:26 +08:00

2601 lines
120 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* yunkong2.vis
* https://github.com/yunkong2/yunkong2.vis
*
* Copyright (c) 2013-2018 bluefox https://github.com/GermanBluefox, hobbyquaker https://github.com/hobbyquaker
* Creative Common Attribution-NonCommercial (CC BY-NC)
*
* http://creativecommons.org/licenses/by-nc/4.0/
*
* Short content:
* Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
* Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
* (Free for non-commercial use).
*/
// visEdit - the yunkong2.vis Editor
/* jshint browser:true */
/* global document */
/* global console */
/* global session */
/* global window */
/* global location */
/* global setTimeout */
/* global clearTimeout */
/* global io */
/* global $ */
/* global vis:true */
/* global local */
/* global can */
/* global colorSelect */
/* global storage */
/* global html2canvas */
/* global translateAll */
/* global ace */
/* global _ */
/* jshint -W097 */// jshint strict:false
// Format: attr_name(start-end)[default_value]/type/onChangeFunc
// attr_name can be extended with numbers (1-2) means it will be attr_name1 and attr_name2 created
// end number can be other attribute, e.g (1-count)
// defaultValue: If defaultValue has ';' it must be replaced by §
// defaultValue: If defaultValue has '/' it must be replaced by ~
// defaultValue: If defaultValue has '"' it must be replaced by ^
// defaultValue: If defaultValue has '^' it must be replaced by ^^
// onChangeFunc has following attributes (widgetID, view, newId, attr, isCss) and must return back the array with changed attributes or null
// Type format: id - Object ID Dialog
// hid
// checkbox
// image - image
// number,min,max,step - non-float number. min,max,step are optional
// color - color picker
// views - Name of the view
// effect - jquery UI show/hide effects
// eff_opt - additional option to effect slide (up, down, left, right)
// fontname - Font name
// slider,min,max,step - Default step is ((max - min) / 100)
// select,value1,value2,... - dropdown select
// nselect,value1,value2,... - same as select, but without translation of items
// auto,value1,value2,... - autocomplete
// style,fileFilter,nameFilter,attrFilter
// custom,functionName,options,... - custom editor - functionName is starting from vis.binds.[widgetset.funct]. E.g. custom/timeAndWeather.editWeather,short
// group.name - define new or old group. All following attributes belongs to new group till new group.xyz
// group.name/byindex/icon - like group, but all following attributes will be grouped by ID. Icon is optional. Like group.windows/byindex;slide(1-4)/id;slide_type(1-4)/select,open,closed Following groups will be created Windows1(slide1,slide_type1), Windows2(slide2,slide_type2), Windows3(slide3,slide_type3), Windows4(slide4,slide_type4)
// text - dialog box with html editor
// html - dialog box with html editor
// widget - existing widget selector
// history - select history instances
'use strict';
vis = $.extend(true, vis, {
fontNames: [
'Verdana, Geneva, sans-serif',
'Georgia, "Times New Roman", Times, serif',
'"Courier New", Courier, monospace',
'Arial, Helvetica, sans-serif',
'Tahoma, Geneva, sans-serif',
'"Trebuchet MS", Arial, Helvetica, sans-serif',
'"Arial Black", Gadget, sans-serif',
'"Times New Roman", Times, serif',
'"Palatino Linotype", "Book Antiqua", Palatino, serif',
'"Lucida Sans Unicode", "Lucida Grande", sans-serif',
'"MS Serif", "New York", serif',
'"Comic Sans MS", cursive'
],
editObjectID: function (widAttr, widgetFilter, isHistory, onChange) {
var that = this;
if (typeof isHistory === 'function') {
onChange = isHistory;
isHistory = false;
}
// Edit for Object ID
var line = [
{
input: '<input type="text" id="inspect_' + widAttr + '" data-onchange="' + (onChange || '')+ '">'
}
];
if (this.objectSelector) {
line[0].button = {
icon: 'ui-icon-note',
text: false,
title: _('Select object ID'),
click: function () {
var wdata = $(this).data('wdata');
$('#dialog-select-member-' + wdata.attr).selectId('show', that.views[wdata.view].widgets[wdata.widgets[0]].data[wdata.attr], function (newId, oldId) {
if (oldId !== newId) {
$('#inspect_' + wdata.attr).val(newId).trigger('change');
if ($('#inspect_min').length) {
if (that.objects[newId] && that.objects[newId].common && that.objects[newId].common.min !== undefined) {
$('#inspect_min').val(that.objects[newId].common.min).trigger('change');
}
}
if ($('#inspect_max').length) {
if (that.objects[newId] && that.objects[newId].common && that.objects[newId].common.max !== undefined) {
$('#inspect_max').val(that.objects[newId].common.max).trigger('change');
}
}
if ($('#inspect_oid-working').length) {
if (that.objects[newId] && that.objects[newId].common && that.objects[newId].common.workingID) {
if (that.objects[newId].common.workingID.indexOf('.') !== -1) {
$('#inspect_oid-working').val(that.objects[newId].common.workingID).trigger('change');
} else {
var parts = newId.split('.');
parts.pop();
parts.push(that.objects[newId].common.workingID);
$('#inspect_oid-working').val(parts.join('.')).trigger('change');
}
}
}
/*
if (document.getElementById('inspect_hm_wid')) {
if (that.objects[newId]['Type'] !== undefined && that.objects[value]['Parent'] !== undefined &&
(that.objects[newId]['Type'] === 'STATE' ||
that.objects[newId]['Type'] === 'LEVEL')) {
var parent = that.objects[newId]['Parent'];
if (that.objects[parent]['DPs'] !== undefined &&
that.objects[parent]['DPs']['WORKING'] !== undefined) {
$('#inspect_hm_wid').val(that.objects[parent]['DPs']['WORKING']);
$('#inspect_hm_wid').trigger('change');
}
}
}
// Try to find Function of the device and fill the Filter field
var $filterkey = $('#inspect_filterkey');
if ($filterkey.length) {
if ($filterkey.val() === '') {
var oid = newId;
var func = null;
if (that.metaIndex && that.metaIndex['ENUM_FUNCTIONS']) {
while (oid && that.objects[oid]) {
for (var t = 0; t < that.metaIndex['ENUM_FUNCTIONS'].length; t++) {
var list = that.objects[that.metaIndex['ENUM_FUNCTIONS'][t]];
for (var z = 0; z < list['Channels'].length; z++) {
if (list['Channels'][z] === oid) {
func = list.Name;
break;
}
}
if (func) break;
}
if (func) break;
oid = that.objects[oid]['Parent'];
}
}
if (func) $filterkey.val(func).trigger('change');
}
}*/
}
});
}
};
line[0].onchange = function (val, oldValue) {
var wdata = $(this).data('wdata');
$('#inspect_' + wdata.attr + '_desc').html(that.getObjDesc(val));
var userOnchange = $(this).data('onchange');
if (userOnchange) {
for (var w = 0; w < wdata.widgets.length; w++) {
var widgetSet = $('#' + that.views[wdata.view].widgets[wdata.widgets[w]].tpl).attr('data-vis-set');
if (that.binds[widgetSet] && that.binds[widgetSet][userOnchange]) {
return that.binds[widgetSet][userOnchange](wdata.widgets[w], wdata.view, that.widgets[wdata.widgets[w]].data[wdata.attr], wdata.attr, false, oldValue);
}
}
}
};
line.push({input: '<div id="inspect_' + widAttr + '_desc"></div>'});
var $dialog = $('#dialog-select-member-' + widAttr);
// Init select dialog
if (!$dialog.length) {
$('body').append('<div id="dialog-select-member-' + widAttr + '" style="display: none"></div>');
$('#dialog-select-member-' + widAttr).selectId('init', {
filter: {
common: {
history: isHistory ? {
enabled: true
} : undefined
}
},
texts: {
select: _('Select'),
cancel: _('Cancel'),
all: _('All'),
id: _('ID'),
name: _('Name'),
role: _('Role'),
room: _('Room'),
value: _('Value'),
selectid: _('Select ID'),
enum: _('Members'),
from: _('from'),
lc: _('lc'),
ts: _('ts'),
ack: _('ack'),
expand: _('expand'),
collapse: _('collapse'),
refresh: _('refresh'),
edit: _('edit'),
ok: _('ok'),
wait: _('wait'),
list: _('list'),
tree: _('tree'),
copyToClipboard: _('Copy to clipboard')
},
filterPresets: {role: widgetFilter},
noMultiselect: true,
columns: ['image', 'name', 'type', 'role', 'enum', 'room', 'value'],
imgPath: '/lib/css/fancytree/',
objects: this.objects,
states: this.states,
zindex: 1001
});
} else {
$dialog.selectId('option', 'filterPresets', {role: widgetFilter});
$dialog.selectId('option', 'filter', {
common: {
history: isHistory ? {
enabled: true
} : undefined
}
});
}
}
return line;
},
editWidgetNames: function (widAttr, options) {
// options[0] all views
var widgets = [''];
if (options && options[0] === 'all') {
for (var w in this.widgets) {
widgets.push(w);
}
} else {
for (var w in this.views[this.activeView].widgets) {
widgets.push(w);
}
}
return this.editSelect(widAttr, widgets, true);
},
editSelect: function (widAttr, values, notTranslate, init, onchange) {
if (typeof notTranslate === 'function') {
onchange = init;
init = notTranslate;
notTranslate = false;
}
// Select
var line = {
input: '<select type="text" id="inspect_' + widAttr + '">'
};
if (onchange) line.onchange = onchange;
if (init) line.init = init;
if (values.length && values[0] !== undefined) {
for (var t = 0; t < values.length; t++) {
line.input += '<option value="' + values[t] + '">' + (notTranslate ? values[t] : _(values[t])) + '</option>';
}
} else {
for (var name in values) {
line.input += '<option value="' + values[name] + '">' + name + '</option>';
}
}
line.input += '</select>';
return line;
},
editStyle: function (widAttr, options) {
var that = this;
// options[0] fileFilter
// options[1] nameFilter
// options[2] attrFilter
// Effect selector
return {
input: '<input type="text" id="inspect_' + widAttr + '" class="vis-edit-textbox"/>',
init: function (_wid_attr, data) {
if (that.styleSelect) {
that.styleSelect.show({
width: '100%',
name: 'inspect_' + _wid_attr,
filterFile: options[0],
filterName: options[1],
filterAttrs: options[2],
removeName: options[3],
style: data,
parent: $(this).parent(),
onchange: function (newStyle) {
$('#inspect_' + widAttr).val(newStyle).trigger('change');
}
});
$('#inspect_' + widAttr).hide();
}
}
};
},
editFontName: function (widAttr) {
var that = this;
// Auto-complete
return {
input: '<input type="text" id="inspect_' + widAttr + '" class="vis-edit-textbox"/>',
init: function (_wid_attr, data) {
$(this).autocomplete({
minLength: 0,
source: function (request, response) {
var _data = $.grep(that.fontNames, function (value) {
return value.substring(0, request.term.length).toLowerCase() === request.term.toLowerCase();
});
response(_data);
},
select: function (event, ui) {
$(this).val(ui.item.value);
$(this).trigger('change', ui.item.value);
}
}).focus(function () {
// Show dropdown menu
$(this).autocomplete('search', '');
}).autocomplete('instance')._renderItem = function (ul, item) {
return $('<li>')
.append('<a><span style="font-family: ' + item.label + '">' + item.label + '(En, Рус, Äü)</span></a>')
.appendTo(ul);
};
}
};
},
editHistoryInstance: function (widAttr) {
if (!this.historyInstances) {
for (var id in this.objects) {
if (this.objects[id].type === 'instance' && this.objects[id].common && this.objects[id].common.type === 'storage') {
this.historyInstances = this.historyInstances || [];
id = id.substring('system.adapter.'.length);
if (this.historyInstances.indexOf(id) === -1) this.historyInstances.push(id);
}
}
}
return this.editAutoComplete(widAttr, this.historyInstances);
},
editClass: function (widAttr) {
var that = this;
if (!this.styleClasses) {
this.styleClasses = [];
var classes = vis.styleSelect.collectClasses();
var reg = /^vis-style-/;
for (var c in classes) {
if (reg.test(c) && this.styleClasses.indexOf(c) === -1) this.styleClasses.push(c);
}
classes = null;
}
return this.editAutoComplete(widAttr, this.styleClasses);
},
editAutoComplete: function (widAttr, values) {
// Auto-complete
return {
input: '<input type="text" id="inspect_' + widAttr + '" class="vis-edit-textbox"/>',
init: function (_wid_attr, data) {
$(this).autocomplete({
minLength: 0,
source: function (request, response) {
var _data = $.grep(values, function (value) {
return value.substring(0, request.term.length).toLowerCase() === request.term.toLowerCase();
});
response(_data);
},
select: function (event, ui) {
$(this).val(ui.item.value);
$(this).trigger('change', ui.item.value);
}
}).focus(function () {
// Show dropdown menu
$(this).autocomplete('search', '');
});
}
};
},
_editSetFontColor: function (element) {
try {
var r;
var b;
var g;
var hsp;
var $element = $('#' + element);
var a = $element.css('background-color');
if (a.match(/^rgb/)) {
a = a.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/);
r = a[1];
g = a[2];
b = a[3];
} else {
a = '0x' + a.slice(1).replace(a.length < 5 && /./g, '$&$&');
r = a >> 16;
g = a >> 8 & 255;
b = a & 255;
}
hsp = Math.sqrt(
0.299 * (r * r) +
0.587 * (g * g) +
0.114 * (b * b)
);
if (hsp > 127.5) {
$element.css('color', '#000000');
} else {
$element.css('color', '#FFFFFF');
}
} catch (err) {
}
},
editColor: function (widAttr) {
var that = this;
var line = {
input: '<input type="text" id="inspect_' + widAttr + '"/>',
onchange: function (value) {
$(this).css('background-color', value || '');
that._editSetFontColor('inspect_' + widAttr);
}
};
if ((typeof colorSelect !== 'undefined' && $().farbtastic)) {
line.button = {
icon: 'ui-icon-note',
text: false,
title: _('Select color'),
click: function (/*event*/) {
var wdata = $(this).data('wdata');
var _settings = {
current: $('#inspect_' + wdata.attr).val(),
onselectArg: wdata,
onselect: function (img, _data) {
$('#inspect_' + wdata.attr).val(colorSelect.GetColor()).trigger('change');
}
};
colorSelect.show(_settings);
}
};
}
return line;
},
editViewName: function (widAttr) {
var views = [''];
for (var v in this.views) {
if (!this.views.hasOwnProperty(v) || v === '___settings') continue;
views.push(v);
}
return this.editAutoComplete(widAttr, views);
},
editFilterName: function (widAttr) {
var filters = this.updateFilter();
filters.unshift('');
//return this.editSelect(widAttr, filters, true);
return this.editAutoComplete(widAttr, filters);
},
editEffect: function (widAttr) {
var that = this;
return this.editSelect(widAttr, [
'',
'show',
'blind',
'bounce',
'clip',
'drop',
'explode',
'fade',
'fold',
'highlight',
'puff',
'pulsate',
'scale',
'shake',
'size',
'slide'
], null, function (_widAttr, data) {
if (_widAttr.indexOf('_effect') !== -1) {
var eff = _widAttr.replace('_effect', '_options');
var $elem = $('#inspect_' + eff);
if ($elem.length) {
if (data === 'slide') {
that.hideShowAttr(eff, true);
} else {
that.hideShowAttr(eff, false);
$elem.val('').trigger('change');
}
}
}
});
},
editNumber: function (widAttr, options, onchange) {
// options = {min: ?,max: ?,step: ?}
// Select
var line = {
input: '<input id="inspect_' + widAttr + '" style="width: calc(100% - 2px);"/>',
init: function (w, data) {
var platform = window.navigator.oscpu || window.navigator.platform;
// Do not show spin on MAc OS
if (platform.indexOf('Mac') === -1) {
options = options || {};
options.spin = function () {
var $this = $(this);
var timer = $this.data('timer');
if (timer) clearTimeout(timer);
$this.data('timer', setTimeout(function () {
$this.trigger('change');
},200));
};
$(this).spinner(options);
$(this).parent().css({width: 'calc(100% - 2px)'});
} else {
$(this).parent().css({width: 'calc(100% - 8px)'});
}
// Allow only numbers
$(this).on('keypress', function(e) {
var code = e.keyCode || e.charCode;
return (code >= 48 && code <= 57) || (code === 110);
});
}
};
if (onchange) line.onchange = onchange;
return line;
},
editButton: function (widAttr, options, onchange) {
// options = {min: ?,max: ?,step: ?}
// Select
var line = {
input: '<button id="inspect_' + widAttr + '">' + widAttr + '</button>',
init: function (w, data) {
$(this).button().click(function () {
$(this).val(true).trigger('change');
});
}
};
if (onchange) line.onchange = onchange;
return line;
},
editUrl: function (widAttr, filter) {
var line = {
input: '<input type="text" id="inspect_' + widAttr + '"/>'
};
var that = this;
if ($.fm) {
line.button = {
icon: 'ui-icon-note',
text: false,
title: _('Select image'),
click: function (/*event*/) {
var wdata = $(this).data('wdata');
var defPath = ('/' + (that.conn.namespace ? that.conn.namespace + '/' : '') + that.projectPrefix + 'img/');
var current = that.widgets[wdata.widgets[0]].data[wdata.attr];
//workaround, that some widgets calling direct the img/picure.png without /vis/
if (current && current.substring(0, 4) === 'img/') {
current = '/vis/' + current;
}
$.fm({
lang: that.language,
defaultPath: defPath,
path: current || defPath,
uploadDir: '/' + (that.conn.namespace ? that.conn.namespace + '/' : ''),
fileFilter: filter || ['gif', 'png', 'bmp', 'jpg', 'jpeg', 'tif', 'svg'],
folderFilter: false,
mode: 'open',
view: 'prev',
userArg: wdata,
conn: that.conn,
zindex: 1001
}, function (_data, userData) {
var src = _data.path + _data.file;
$('#inspect_' + wdata.attr).val(src).trigger('change');
});
}
};
}
return line;
},
editCustom: function (widAttr, options) {
if (!options) {
console.log('No path to custom function');
} else {
var funcs = options[0].split('.');
options.unshift();
if (funcs[0] === 'vis') funcs.unshift();
if (funcs[0] === 'binds') funcs.unshift();
if (funcs.length === 1) {
if (typeof this.binds[funcs[0]] === 'function') {
return this.binds[funcs[0]](widAttr, options);
} else {
console.log('No function: vis.binds.' + funcs.join('.'));
}
} else if (funcs.length === 2) {
if (this.binds[funcs[0]] && typeof this.binds[funcs[0]][funcs[1]] === 'function') {
return this.binds[funcs[0]][funcs[1]](widAttr, options);
} else {
console.log('No function: vis.binds.' + funcs.join('.'));
}
} else if (funcs.length === 3) {
if (this.binds[funcs[0]] && this.binds[funcs[0]][funcs[1]] && typeof this.binds[funcs[0]][funcs[1]][funcs[2]] === 'function') {
return this.binds[funcs[0]][funcs[1]][funcs[2]](widAttr, options);
} else {
console.log('No function: vis.binds.' + funcs.join('.'));
}
} else {
if (!funcs.length) {
console.log('Function name is too short: vis.binds');
} else {
console.log('Function name is too long: vis.binds.' + funcs.join('.'));
}
}
return {};
}
},
editSlider: function (widAttr, options) {
options.min = (!options.min) ? 0 : options.min;
options.max = (!options.max) ? 0 : options.max;
options.step = (!options.step) ? (options.max - options.min) / 100 : options.step;
return {
input: '<table width="100%"><tr><td style="width:50px"><input style="width:50px" id="inspect_' + widAttr + '"/></td><td width="100%"><div id="inspect_' + widAttr + '_slider"></div></td></tr>',
init: function (w, data) {
options.value = (data === undefined) ? options.min : data;
var input = this;
options.slide = function (event, ui) {
$(input).val(ui.value).trigger('change');
};
$('#inspect_' + widAttr + '_slider').slider(options);
},
onchange: function (value) {
$('#inspect_' + widAttr + '_slider').slider('value', (value === undefined) ? options.min : value);
}
};
},
editEnableAbsolute: function () {
var val = $('#inspect_css_position').val();
if (val === 'relative' || val === 'static' || val === 'sticky') {
// disable
$('#inspect_css_left').val('').prop('disabled', true);
$('#inspect_css_top').val('').prop('disabled', true);
$('#inspect_css_display').prop('disabled', false);
} else {
// enable
$('#inspect_css_left').prop('disabled', false);
$('#inspect_css_top').prop('disabled', false);
$('#inspect_css_display').val('').prop('disabled', true);
}
},
editCssCommon: function (viewDiv, view) {
var that = this;
var group = 'css_common';
this.groups[group] = this.groups[group] || {};
this.groups[group].css_position = this.editSelect('css_position', ['', /*'absolute', 'fixed',*/ 'relative', /*'static', */'sticky'], true, function () {
$(this).data('old-value', $(this).val());
}, function () {
var val = $('#inspect_css_position').val();
var oldVal = $(this).data('old-value');
if (val === 'relative' || val === 'static' || val === 'sticky') {
if (oldVal !== 'relative' && oldVal !== 'static' && oldVal !== 'sticky') {
$(this).data('old-value', val);
// disable
$('#inspect_css_display').prop('disabled', false);
$('#inspect_css_left').val('').prop('disabled', true).trigger('change');
$('#inspect_css_top').val('').prop('disabled', true).trigger('change');
setTimeout(function () {
for (var r = 0; r < that.activeWidgets.length; r++) {
that.reRenderWidgetEdit(viewDiv, view, that.activeWidgets[r]);
}
} , 100);
}
} else {
if (oldVal === 'relative' || oldVal === 'static' || oldVal === 'sticky') {
$(this).data('old-value', val);
// enable
$('#inspect_css_left').prop('disabled', false).val('0px').trigger('change');
$('#inspect_css_top').prop('disabled', false).val('0px').trigger('change');
$('#inspect_css_display').prop('disabled', true);
setTimeout(function () {
for (var r = 0; r < that.activeWidgets.length; r++) {
that.reRenderWidgetEdit(viewDiv, view, that.activeWidgets[r]);
}
} , 100);
}
}
});
this.groups[group].css_display = this.editSelect('css_display', ['', /*'inline', 'block', */'inline-block'/*, 'flex', 'list-item', 'run-in'*/], true, this.editEnableAbsolute);
this.groups[group].css_left = {input: '<input class="vis-edit-textbox-with-button" type="text" id="inspect_css_left"/><button class="vis-edit-percent-calc" data-attr="left"></button>', init: this.editEnableAbsolute};
this.groups[group].css_top = {input: '<input class="vis-edit-textbox-with-button" type="text" id="inspect_css_top"/><button class="vis-edit-percent-calc" data-attr="top"></button>', init: this.editEnableAbsolute};
this.groups[group].css_width = {input: '<input class="vis-edit-textbox-with-button" type="text" id="inspect_css_width"/><button class="vis-edit-percent-calc" data-attr="width"></button>'};
this.groups[group].css_height = {input: '<input class="vis-edit-textbox-with-button" type="text" id="inspect_css_height"/><button class="vis-edit-percent-calc" data-attr="height"></button>'};
this.groups[group]['css_z-index'] = this.editNumber('css_z-index');
this.groups[group]['css_overflow-x'] = this.editSelect('css_overflow-x', ['', 'visible', 'hidden', 'scroll', 'auto', 'initial', 'inherit'], true);
this.groups[group]['css_overflow-y'] = this.editSelect('css_overflow-y', ['', 'visible', 'hidden', 'scroll', 'auto', 'initial', 'inherit'], true);
this.groups[group].css_opacity = {input: '<input type="text" id="inspect_css_opacity"/>'};
this.groups[group].css_cursor = this.editAutoComplete('css_cursor', ['', 'pointer', 'auto', 'alias', 'all-scroll', 'cell', 'context-menu', 'col-resize', 'copy', 'crosshair', 'default', 'e-resize', 'ew-resize', 'grab', 'grabbing', 'help', 'move', 'n-resize', 'ne-resize', 'nesw-resize', 'ns-resize', 'nw-resize', 'nwse-resize', 'no-drop', 'none', 'not-allowed', 'progress', 'row-resize', 's-resize', 'se-resize', 'sw-resize', 'text', 'vertical-text', 'w-resize', 'wait', 'zoom-in', 'zoom-out', 'initial', 'inherit']);
this.groups[group].css_transform = {input: '<input type="text" id="inspect_css_transform"/>'};
for (var attr in this.groups[group]) {
if (!this.groups[group].hasOwnProperty(attr)) continue;
this.groups[group][attr].css = true;
this.groups[group][attr].attrName = attr;
this.groups[group][attr].attrIndex = '';
}
},
editCssFontText: function () {
var group = 'css_font_text';
this.groups[group] = this.groups[group] || {};
this.groups[group].css_color = this.editColor('css_color');
this.groups[group]['css_text-align'] = this.editSelect('css_text-align', ['', 'left', 'right', 'center' ,'justify', 'initial', 'inherit'], true);
this.groups[group]['css_text-shadow'] = {input: '<input type="text" id="inspect_css_text-shadow"/>'};
this.groups[group]['css_font-family'] = this.editFontName('css_font-family');
this.groups[group]['css_font-style'] = this.editSelect('css_font-style', ['', 'normal', 'italic', 'oblique', 'initial', 'inherit'], true);
this.groups[group]['css_font-variant'] = this.editSelect('css_font-variant', ['', 'normal', 'small-caps', 'initial', 'inherit'], true);
this.groups[group]['css_font-weight'] = this.editAutoComplete('css_font-weight', ['', 'normal', 'bold', 'bolder', 'lighter', 'initial', 'inherit']);
this.groups[group]['css_font-size'] = this.editAutoComplete('css_font-size', ['', 'medium', 'xx-small', 'x-small', 'small', 'large', 'x-large', 'xx-large', 'smaller', 'larger', 'initial', 'inherit']);
this.groups[group]['css_line-height'] = {input: '<input type="text" id="inspect_css_line-height"/>'};
this.groups[group]['css_letter-spacing'] = {input: '<input type="text" id="inspect_css_letter-spacing"/>'};
this.groups[group]['css_word-spacing'] = {input: '<input type="text" id="inspect_css_word-spacing"/>'};
for(var attr in this.groups[group]) {
this.groups[group][attr].css = true;
this.groups[group][attr].attrName = attr;
this.groups[group][attr].attrIndex = '';
}
},
editCssBackground: function () {
var group = 'css_background';
this.groups[group] = this.groups[group] || {};
this.groups[group].css_background = {input: '<input type="text" id="inspect_css_background" class="vis-edit-textbox vis-inspect-widget"/>'};
this.groups[group]['css_background-color'] = this.editColor('css_background-color');
this.groups[group]['css_background-image'] = {input: '<input type="text" id="inspect_background-image" class="vis-edit-textbox vis-inspect-widget"/>'};
this.groups[group]['css_background-repeat'] = this.editSelect('css_background-repeat', ['', 'repeat', 'repeat-x', 'repeat-y', 'no-repeat', 'initial', 'inherit'], true);
this.groups[group]['css_background-attachment'] = this.editSelect('css_background-attachment', ['', 'scroll', 'fixed', 'local', 'initial', 'inherit'], true);
this.groups[group]['css_background-position'] = {input: '<input type="text" id="inspect_background-position" class="vis-edit-textbox vis-inspect-widget"/>'};
this.groups[group]['css_background-size'] = {input: '<input type="text" id="inspect_background-size" class="vis-edit-textbox vis-inspect-widget"/>'};
this.groups[group]['css_background-clip'] = this.editSelect('css_background-clip', ['', 'border-box', 'padding-box', 'content-box', 'initial', 'inherit'], true);
this.groups[group]['css_background-origin'] = this.editSelect('css_background-origin', ['', 'padding-box', 'border-box', 'content-box', 'initial', 'inherit'], true);
for(var attr in this.groups[group]) {
this.groups[group][attr].css = true;
this.groups[group][attr].attrName = attr;
this.groups[group][attr].attrIndex = '';
}
},
editDimensionOnChangeHelper: function (elem, value) {
if (value && typeof value !== 'object') {
var e = value.substring(value.length - 2);
if (e !== 'px' && e !== 'em' && value[value.length - 1] !== '%') {
var wdata = $(elem).data('wdata');
for (var t = 0; t < wdata.widgets.length; t++) {
this.views[wdata.view].widgets[wdata.widgets[t]].style[wdata.attr.substring(4)] = value + 'px';
$('#' + wdata.widgets[t]).css(wdata.attr.substring(4), value + 'px');
}
}
}
},
editCssBorder: function () {
var group = 'css_border';
var that = this;
this.groups[group] = this.groups[group] || {};
this.groups[group]['css_border-width'] = {
input: '<input type="text" id="inspect_css_border-width"/>',
onchange: function (value) {
that.editDimensionOnChangeHelper(this, value);
}
};
this.groups[group]['css_border-style'] = this.editAutoComplete('css_border-style', ['', 'none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset', 'initial', 'inherit']);
this.groups[group]['css_border-color'] = this.editColor('css_border-color');
this.groups[group]['css_border-radius'] = {
input: '<input type="text" id="inspect_css_border-radius"/>',
onchange: function (value) {
that.editDimensionOnChangeHelper(this, value);
}
};
for(var attr in this.groups[group]) {
if (!this.groups[group].hasOwnProperty(attr)) continue;
this.groups[group][attr].css = true;
this.groups[group][attr].attrName = attr;
this.groups[group][attr].attrIndex = '';
}
},
editCssShadowPadding: function () {
var group = 'css_shadow_padding';
this.groups[group] = this.groups[group] || {};
this.groups[group].css_padding = {input: '<input type="text" id="inspect_css_padding"/>'};
this.groups[group]['css_padding-left'] = {input: '<input type="text" id="inspect_css_padding-left"/>'};
this.groups[group]['css_padding-top'] = {input: '<input type="text" id="inspect_css_padding-top"/>'};
this.groups[group]['css_padding-right'] = {input: '<input type="text" id="inspect_css_padding-right"/>'};
this.groups[group]['css_padding-bottom'] = {input: '<input type="text" id="inspect_css_padding-bottom"/>'};
this.groups[group]['css_box-shadow'] = {input: '<input type="text" id="inspect_css_box-shadow"/>'};
this.groups[group]['css_margin-left'] = {input: '<input type="text" id="inspect_css_margin-left"/>'};
this.groups[group]['css_margin-top'] = {input: '<input type="text" id="inspect_css_margin-top"/>'};
this.groups[group]['css_margin-right'] = {input: '<input type="text" id="inspect_css_margin-right"/>'};
this.groups[group]['css_margin-bottom'] = {input: '<input type="text" id="inspect_css_margin-bottom"/>'};
for(var attr in this.groups[group]) {
this.groups[group][attr].css = true;
this.groups[group][attr].attrName = attr;
this.groups[group][attr].attrIndex = '';
}
},
editCssAnimation: function () {
var group = 'css_animation';
this.groups[group] = this.groups[group] || {};
this.groups[group]['css_animation-name'] = {input: '<input type="text" id="inspect_css_animation-name"/>'};
this.groups[group]['css_animation-duration'] = {input: '<input type="text" id="inspect_css_animation-duration"/>'};
for(var attr in this.groups[group]) {
this.groups[group][attr].css = true;
this.groups[group][attr].attrName = attr;
this.groups[group][attr].attrIndex = '';
}
},
editSignalIcons: function () {
var group = 'signals';
this.groups[group] = this.groups[group] || {};
var i = 0;
for (var i = 0; i < 3; i++) {
// oid
this.addToInspect(this.activeWidgets, {name: 'signals-oid-' + i, type: 'id'}, group);
// condition
this.addToInspect(this.activeWidgets, {name: 'signals-cond-' + i, type: 'select', options: ['==', '!=', '<=', '>=', '<', '>', 'consist', 'not consist', 'exist', 'not exist'], default: '=='}, group);
// value
this.addToInspect(this.activeWidgets, {name: 'signals-val-' + i, default: true}, group);
// icon path
this.addToInspect(this.activeWidgets, {name: 'signals-icon-' + i, type: 'image', default: '/vis/signals/lowbattery.png'}, group);
// icon size in px
this.addToInspect(this.activeWidgets, {name: 'signals-icon-size-' + i, type: 'slider', options: {min: 1, max: 120, step: 1}, default: 0}, group);
// icon style
this.addToInspect(this.activeWidgets, {name: 'signals-icon-style-' + i}, group);
// icon text
this.addToInspect(this.activeWidgets, {name: 'signals-text-' + i}, group);
// text style
this.addToInspect(this.activeWidgets, {name: 'signals-text-style-' + i}, group);
// text class
this.addToInspect(this.activeWidgets, {name: 'signals-text-class-' + i}, group);
// blink
this.addToInspect(this.activeWidgets, {name: 'signals-blink-' + i, type: 'checkbox', default: false}, group);
// icon position vertical
this.addToInspect(this.activeWidgets, {name: 'signals-horz-' + i, type: 'slider', options: {min: -20, max: 120, step: 1}, default: 0}, group);
// icon position horizontal
this.addToInspect(this.activeWidgets, {name: 'signals-vert-' + i, type: 'slider', options: {min: -20, max: 120, step: 1}, default: 0}, group);
// icon hide by edit
this.addToInspect(this.activeWidgets, {name: 'signals-hide-edit-' + i, type: 'checkbox', default: false}, group);
if (i < 2) this.addToInspect('delimiterInGroup', group);
}
},
editLastChange: function () {
var group = 'last_change';
this.groups[group] = this.groups[group] || {};
// oid
this.addToInspect(this.activeWidgets, {name: 'lc-oid', type: 'id'}, group);
// type (or timestamp)
this.addToInspect(this.activeWidgets, {name: 'lc-type', type: 'select', options: ['last-change', 'timestamp'], default: 'last-change'}, group);
// is interval
this.addToInspect(this.activeWidgets, {name: 'lc-is-interval', type: 'checkbox', default: true}, group);
// is moment.js
this.addToInspect(this.activeWidgets, {name: 'lc-is-moment', type: 'checkbox', default: false}, group);
// format
this.addToInspect(this.activeWidgets, {name: 'lc-format', type: 'auto', options: ['YYYY.MM.DD hh:mm:ss','DD.MM.YYYY hh:mm:ss','YYYY.MM.DD','DD.MM.YYYY','YYYY/MM/DD hh:mm:ss','YYYY/MM/DD','hh:mm:ss'], default: ''}, group);
// position vertical
this.addToInspect(this.activeWidgets, {name: 'lc-position-vert', type: 'select', options: ['top', 'middle', 'bottom'], default: 'top'}, group);
// position horizontal
this.addToInspect(this.activeWidgets, {name: 'lc-position-horz', type: 'select', options: ['left', /*'middle', */'right'], default: 'right'}, group);
// offset vertical
this.addToInspect(this.activeWidgets, {name: 'lc-offset-vert', type: 'slider', options: {min: -120, max: 120, step: 1}, default: 0}, group);
// offset horizontal
this.addToInspect(this.activeWidgets, {name: 'lc-offset-horz', type: 'slider', options: {min: -120, max: 120, step: 1}, default: 0}, group);
this.addToInspect('delimiterInGroup', group);
// font-size
this.addToInspect(this.activeWidgets, {name: 'lc-font-size', type: 'auto', options: ['', 'medium', 'xx-small', 'x-small', 'small', 'large', 'x-large', 'xx-large', 'smaller', 'larger', 'initial', 'inherit'], default: '12px'}, group);
// font-family
this.addToInspect(this.activeWidgets, {name: 'lc-font-family', type: 'fontname', default: ''}, group);
// font-style
this.addToInspect(this.activeWidgets, {name: 'lc-font-style', type: 'auto', options: ['', 'normal', 'italic', 'oblique', 'initial', 'inherit'], default: ''}, group);
// background-color
this.addToInspect(this.activeWidgets, {name: 'lc-bkg-color', type: 'color', default: ''}, group);
// color
this.addToInspect(this.activeWidgets, {name: 'lc-color', type: 'color', default: ''}, group);
// border-width
this.addToInspect(this.activeWidgets, {name: 'lc-border-width', default: '0'}, group);
// border-style
this.addToInspect(this.activeWidgets, {name: 'lc-border-style', type: 'auto', options: ['', 'none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset', 'initial', 'inherit'], default: ''}, group);
// border-color
this.addToInspect(this.activeWidgets, {name: 'lc-border-color', type: 'color', default: ''}, group);
// border-radius
this.addToInspect(this.activeWidgets, {name: 'lc-border-radius', type: 'slider', options: {min: 0, max: 20, step: 1}, default: 10}, group);
// padding
this.addToInspect(this.activeWidgets, {name: 'lc-padding'}, group);
// z-index
this.addToInspect(this.activeWidgets, {name: 'lc-zindex', type: 'slider', options: {min: -10, max: 20, step: 1}, default: 0}, group);
},
editGestures: function (view) {
var group = 'gestures';
this.groups[group] = this.groups[group] || {};
var gesturesAnalog = ['swiping', 'rotating', 'pinching'];
var gestures = ['swipeRight', 'swipeLeft', 'swipeUp', 'swipeDown', 'rotateLeft', 'rotateRight', 'pinchIn', 'pinchOut'];
this.addToInspect(this.activeWidgets, {name: 'gestures-indicator', type: 'auto', options: this.getWidgetIds(view, 'tplValueGesture')}, group);
this.addToInspect(this.activeWidgets, {name: 'gestures-offsetX', default: 0, type: 'number'}, group);
this.addToInspect(this.activeWidgets, {name: 'gestures-offsetY', default: 0, type: 'number'}, group);
this.addToInspect('delimiterInGroup', group);
var j;
var gesture;
for (j = 0; j < gesturesAnalog.length; j++) {
gesture = gesturesAnalog[j];
this.addToInspect(this.activeWidgets, {name: 'gestures-' + gesture + '-oid', type: 'id'}, group);
this.addToInspect(this.activeWidgets, {name: 'gestures-' + gesture + '-value', default: ''}, group);
this.addToInspect(this.activeWidgets, {name: 'gestures-' + gesture + '-minimum', type: 'number'}, group);
this.addToInspect(this.activeWidgets, {name: 'gestures-' + gesture + '-maximum', type: 'number'}, group);
this.addToInspect(this.activeWidgets, {name: 'gestures-' + gesture + '-delta', type: 'number'}, group);
this.addToInspect('delimiterInGroup', group);
}
for (j = 0; j < gestures.length; j++) {
gesture = gestures[j];
this.addToInspect(this.activeWidgets, {name: 'gestures-' + gesture + '-oid', type: 'id'}, group);
this.addToInspect(this.activeWidgets, {name: 'gestures-' + gesture + '-value', default: ''}, group);
this.addToInspect(this.activeWidgets, {name: 'gestures-' + gesture + '-limit', type: 'number'}, group);
if (j < gestures.length - 1) this.addToInspect('delimiterInGroup', group);
}
var that = this;
// install handlers
setTimeout(function () {
for (var j = 0; j < gesturesAnalog.length; j++) {
gesture = gesturesAnalog[j];
$('#inspect_gestures-' + gesture + '-oid').change(function () {
var id = $(this).attr('id');
var val = $(this).val();
var g = id.split('-');
if (that.objects[val] && that.objects[val].common) {
if (that.objects[val].common.min !== undefined) {
var $min = $('#inspect_gestures-' + g[1] + '-minimum');
if ($min.val() === '') {
$min.val(that.objects[val].common.min);
}
}
if (that.objects[val].common.max !== undefined) {
var $max = $('#inspect_gestures-' + g[1] + '-maximum');
if ($max.val() === '') {
$max.val(that.objects[val].common.max);
}
}
}
}).keyup(function () {
$(this).trigger('change');
});
}
}, 300);
},
editText: function (widAttr) {
var that = this;
var line = {
input: '<textarea id="inspect_' + widAttr + '"></textarea>'
};
line.button = {
icon: 'ui-icon-note',
text: false,
title: _('Select color'),
click: function (/*event*/) {
var wdata = $(this).data('wdata');
var data = {};
if (that.config['dialog-edit-text']) {
data = JSON.parse(that.config['dialog-edit-text']);
}
var editor = ace.edit('dialog-edit-text-textarea');
var changed = false;
$('#dialog-edit-text').dialog({
autoOpen: true,
width: data.width || 800,
height: data.height || 600,
modal: true,
resize: function () {
editor.resize();
},
open: function (event) {
$(event.target).parent().find('.ui-dialog-titlebar-close .ui-button-text').html('');
$(this).parent().css({'z-index': 1000});
if (data.top !== undefined) {
if (data.top >= 0) {
$(this).parent().css({top: data.top});
} else {
$(this).parent().css({top: 0});
}
}
if (data.left !== undefined) {
if (data.left >= 0) {
$(this).parent().css({left: data.left});
} else {
$(this).parent().css({left: 0});
}
}
editor.getSession().setMode('ace/mode/html');
editor.setOptions({
enableBasicAutocompletion: true,
enableLiveAutocompletion: true
});
editor.$blockScrolling = Infinity;
editor.getSession().setUseWrapMode(true);
editor.setValue($('#inspect_' + wdata.attr).val());
editor.navigateFileEnd();
editor.focus();
editor.getSession().on('change', function() {
changed = true;
});
},
beforeClose: function () {
var $parent = $('#dialog-edit-text').parent();
var pos = $parent.position();
that.editSaveConfig('dialog-edit-text', JSON.stringify({
top: pos.top > 0 ? pos.top : 0,
left: pos.left > 0 ? pos.left : 0,
width: $parent.width(),
height: $parent.height() + 9
}));
if (changed) {
if (!window.confirm(_('Changes are not saved!. Continue?'))) {
return false;
}
}
},
buttons: [
{
text: _('Ok'),
click: function () {
$('#inspect_' + wdata.attr).val(editor.getValue()).trigger('change');
changed = false;
$(this).dialog('close');
}
},
{
text: _('Cancel'),
click: function () {
$(this).dialog('close');
}
}
]
}).show();
}
};
return line;
},
// add font name to font selector (used in adapters, eg. vis-google-fonts
addFont: function (fontName) {
if (this.fontNames.indexOf(fontName) === -1) this.fontNames.push(fontName);
},
// find states with requested roles of device
findByRoles: function (stateId, roles) {
if (typeof roles !== 'object') {
roles = [roles];
} else {
roles = JSON.parse(JSON.stringify(roles));
}
var result = {};
// try to detect other values
// Go trough all channels of this device
var parts = stateId.split('.');
parts.pop(); // remove state
var channel = parts.join('.');
var reg = new RegExp('^' + channel.replace(/\./g, '\\.') + '\\.');
// channels
for (var id in this.objects) {
if (reg.test(id) &&
this.objects[id].common &&
this.objects[id].type === 'state') {
for (var r = 0; r < roles.length; r++) {
if (this.objects[id].common.role === roles[r]) {
result[roles[r]] = id;
roles.splice(r, 1);
break;
}
if (!roles.length) break;
}
}
}
// try to search in channels
if (roles.length) {
parts.pop(); // remove channel
var device = parts.join('.');
var reg = new RegExp("^" + device.replace(/\./g, '\\.') + '\\.');
for (var id in this.objects) {
if (reg.test(id) &&
this.objects[id].common &&
this.objects[id].type === 'state') {
for (var r = 0; r < roles.length; r++) {
if (this.objects[id].common.role === roles[r]) {
result[roles[r]] = id;
roles.splice(r, 1);
break;
}
}
if (!roles.length) break;
}
}
}
return result;
},
findByName: function (stateId, objName) {
// try to detect other values
// Go trough all channels of this device
var parts = stateId.split('.');
parts.pop(); // remove state
var channel = parts.join('.');
// check same channel
var id = channel + '.' + objName;
if ((id in this.objects) &&
this.objects[id].common &&
this.objects[id].type === 'state') {
return id;
}
// try to search in channels
parts.pop(); // remove channel
var device = parts.join('.');
var reg = new RegExp('^' + device.replace(/\./g, '\\.') + '\\.' + '.*\\.' + objName);
for (var id in this.objects) {
if (reg.test(id) &&
this.objects[id].common &&
this.objects[id].type === 'state') {
return id;
}
}
return false;
},
hideShowAttr: function (widAttr, isShow) {
if (isShow) {
$('#td_' + widAttr).show();
} else {
$('#td_' + widAttr).hide();
}
},
addToInspect: function (widgets, widAttr, group, options, onchange) {
if (widgets === 'delimiter') {
this.groups[widAttr || group] = this.groups[widAttr || group] || {};
var d = 0;
while (this.groups[widAttr || group]['delimiter' + d]) d++;
this.groups[widAttr || group]['delimiter' + d] = 'delimiter';
return;
}
if (widgets === 'delimiterInGroup') {
this.groups[widAttr || group] = this.groups[widAttr || group] || {};
var d = 0;
while (this.groups[widAttr || group]['delimiterInGroup' + d]) d++;
this.groups[widAttr || group]['delimiterInGroup' + d] = 'delimiterInGroup';
return;
}
if (typeof widAttr !== 'object') {
widAttr = {name: widAttr};
}
if (widAttr.clearName === undefined) widAttr.clearName = widAttr.name;
if (widAttr.index === undefined) widAttr.index = '';
if (typeof group === 'function') {
onchange = group;
group = null;
}
if (typeof options === 'function') {
onchange = options;
options = null;
}
options = options || {};
var input;
var line;
// set default value if attr is empty
if (widAttr.default !== undefined) {
for (var i = 0; i < widgets.length; i++) {
var view = this.getViewOfWidget(widgets[i]);
var widgetData = this.views[view].widgets[widgets[i]].data;
if (widgetData && (widgetData[widAttr.name] === null || widgetData[widAttr.name] === undefined) && !widAttr.name.match(/^gestures-/)) {
widgetData[widAttr.name] = widAttr.default;
this.reRenderList = this.reRenderList || [];
if (this.reRenderList.indexOf(widgets[i]) === -1) {
this.reRenderList.push(widgets[i]);
}
}
}
} else if (widAttr.name === 'lc-oid' && widgets.length === 1) {
var _view = this.getViewOfWidget(widgets[0]);
var _widgetData = this.views[_view].widgets[widgets[0]].data;
if (!_widgetData['lc-oid'] && _widgetData['g_last_change']) {
// find any oid value
for (var a in _widgetData) {
if (_widgetData.hasOwnProperty(a) && a.match(/^oid|oid$/)) {
if (_widgetData[a] && _widgetData[a] !== 'nothing_selected') {
_widgetData['lc-oid'] = _widgetData[a];
}
break;
}
}
}
}
// Depends on attribute type
switch (widAttr.type) {
case 'id':
line = this.editObjectID(widAttr.name, widAttr.options, false, widAttr.onChangeWidget);
break;
case 'hid':
case 'history-id':
line = this.editObjectID(widAttr.name, widAttr.options, true, widAttr.onChangeWidget);
break;
case 'checkbox':
// All other attributes
line = '<input id="inspect_' + widAttr.name + '" type="checkbox"/>';
break;
case 'select-views':
line = '<select multiple="multiple" id="inspect_' + widAttr.name + '" class="select-views"></select>';
break;
case 'groups':
line = '<select multiple="multiple" id="inspect_' + widAttr.name + '" class="select-groups"></select>';
break;
case 'color':
line = this.editColor(widAttr.name);
break;
case 'class':
line = this.editClass(widAttr.name);
break;
case 'text':
line = this.editText(widAttr.name);
break;
case 'html':
line = this.editText(widAttr.name);
break;
case 'number':
line = this.editNumber(widAttr.name, widAttr.options);
break;
case 'button':
line = this.editButton(widAttr.name, widAttr.options);
break;
case 'auto':
line = this.editAutoComplete(widAttr.name, widAttr.options);
break;
case 'slider':
line = this.editSlider(widAttr.name, widAttr.options);
break;
case 'views':
line = this.editViewName(widAttr.name);
break;
case 'filters':
line = this.editFilterName(widAttr.name);
break;
case 'custom':
line = this.editCustom(widAttr.name, widAttr.options);
break;
case 'image':
line = this.editUrl(widAttr.name);
break;
case 'sound':
line = this.editUrl(widAttr.name, ['mp3', 'wav', 'ogg']);
break;
case 'select':
line = this.editSelect(widAttr.name, widAttr.options, widAttr.notTranslate);
break;
case 'style':
line = this.editStyle(widAttr.name, widAttr.options);
break;
case 'effect':
line = this.editEffect(widAttr.name);
break;
case 'widget':
line = this.editWidgetNames(widAttr.name, widAttr.options);
break;
case 'effect-options':
var _opts = {};
_opts[_('left')] = 'left';
_opts[_('right')] = 'right';
_opts[_('top')] = 'top';
_opts[_('bottom')] = 'bottom';
line = this.editSelect(widAttr.name, _opts);
break;
case 'hidden':
return;
case 'fontname':
line = this.editFontName(widAttr.name);
break;
case 'history':
line = this.editHistoryInstance(widAttr.name);
break;
default:
line = '<input type="text" id="inspect_' + widAttr.name + '"/>';
}
if (typeof line === 'string') line = {input: line};
if (line[0]) {
line[0].attrName = widAttr.clearName;
line[0].attrIndex = widAttr.index;
line[0].type = widAttr.type;
line[0].onChangeWidget = widAttr.onChangeWidget;
if (widAttr.title) line[0].attrTitle = widAttr.title;
if (widAttr.depends && widAttr.depends.length) line[0].depends = widAttr.depends;
} else {
line.attrName = widAttr.clearName;
line.attrIndex = widAttr.index;
line.type = widAttr.type;
line.onChangeWidget = widAttr.onChangeWidget;
if (widAttr.title) line.attrTitle = widAttr.title;
if (widAttr.depends && widAttr.depends.length) line.depends = widAttr.depends;
}
// <tr><td>title:</td><td><input /></td><td>button</td></tr>
this.groups[group] = this.groups[group] || {};
this.groups[group][widAttr.name] = line;
},
// Render edit panel
showInspect: function (viewDiv, view, widgets) {
var $widgetAttrs = $('#widget_attrs');
var that = this;
var depends = [];
var values = {};
var widAttr;
for (var group in this.groups) {
if (!this.groups.hasOwnProperty(group)) continue;
if (this.groupsState[group] === undefined) this.groupsState[group] = false;
var groupName = group;
if (groupName.indexOf('_§') !== -1) {
var m = groupName.match(/^([\w_]+)_§([0-9]+)/);
groupName = _('group_' + m[1]) + '[' + m[2] + ']';
} else {
groupName = _('group_' + group);
}
// $widgetAttrs.append('<tr data-group="' + group + '" class="ui-state-default vis-inspect-group"><td colspan="3" style="background: url(this.groupsIcons[group]) no-repeat center center;">' + (this.groupsIcons[group] ? '<img class="vis-group-icon" src="' + this.groupsIcons[group] + '"/><div>' + groupName + '</div>' : groupName) + '</td><td><button class="group-control" data-group="' + group + '">' + group + '</button></td>');
var gText = '<tr data-group="' + group + '" class="ui-state-default vis-inspect-group"><td colspan="2"';
if (this.groupsIcons[group]) {
gText += ' style="background: url(' + (this.groupsIcons[group] || '') + ') no-repeat left center; padding-left: 30px"'
}
gText += '>' + groupName + '</td>';
var isGroupEnabledObj = group === 'common' || group === 'css_common' ? true : this.findCommonValue(view, widgets, 'g_' + group);
var isGroupEnabled = false;
var isGroupEnabledIndeterminate = false;
if (typeof isGroupEnabledObj === 'object' && isGroupEnabledObj.values) {
for (var g = 0; g < isGroupEnabledObj.values.length; g++) {
if (isGroupEnabledObj.values[g] !== false) {
isGroupEnabled = true;
isGroupEnabledIndeterminate = true;
break;
}
}
} else {
isGroupEnabled = isGroupEnabledObj;
}
isGroupEnabled = isGroupEnabled !== false;
this.groups[group].___enabled = isGroupEnabled;
if (group === 'common' || group === 'css_common') {
gText += '<td></td>';
} else {
gText += '<td><input type="checkbox" ' + (!isGroupEnabledIndeterminate && isGroupEnabled ? 'checked ' : '') + ' data-indeterminate="' + isGroupEnabledIndeterminate + '" class="group-enable" data-group="' + group + '"/></td>';
}
if (isGroupEnabled) {
gText += '<td><button class="group-control" data-group="' + group + '">' + group + '</button></td>';
} else {
gText += '<td></td>';
}
$widgetAttrs.append(gText);
if (isGroupEnabled) {
for (widAttr in this.groups[group]) {
if (!this.groups[group].hasOwnProperty(widAttr) || widAttr === '___enabled') continue;
var line = this.groups[group][widAttr];
if (line === 'delimiter') {
$widgetAttrs.append('<tr><td colspan="5" style="height: 2px" class="ui-widget-header"></td></tr>');
continue;
}
if (line === 'delimiterInGroup') {
$widgetAttrs.append('<tr><td colspan="5" style="height: 2px" class="ui-widget-header group-' + group + '"></td></tr>');
continue;
}
if (line[0]) line = line[0];
if (typeof line === 'string') line = {input: line};
var title = line.attrTitle;
title = title || _(widAttr + '_tooltip');
var icon;
if (title === widAttr + '_tooltip') {
title = '';
icon = '';
} else {
icon = '<div class="ui-icon ui-icon-notice" style="float: right"/>';
}
var text = '<tr class="vis-edit-td-caption group-' + group + '" id="td_' + widAttr + '"><td ' + (title ? 'title="' + title + '"' : '') + '>' + (icon ? '<i>' : '') + _(line.attrName) + (line.attrIndex !== '' ? ('[' + line.attrIndex + ']') : '') + ':' + (icon ? '</i>' : '') + '</td><td class="vis-edit-td-field"';
if (!line.button && !line.css) {
text += ' colspan="3"';
} else if (!line.css) {
if (!line.button && !line.css) text += ' colspan="2"';
} else if (!line.button) {
text += ' colspan="2"';
}
text += '>' + (line.input || '') + '</td>';
if (line.button) {
if (!line.button.html) {
text += '<td><button id="inspect_' + widAttr + '_btn">' + (line.button.text || line.button.title || '') + '</button></td>';
} else {
text += '<td>' + line.button.html + '</td>';
}
}
if (line.css) {
text += '<td><input id="steal_' + widAttr + '" type="checkbox" data-vis-steal="' + widAttr.substring(4) + '" class="vis-steal-css"/><label class="vis-steal-label" for="steal_' + widAttr + '">steal</label></td>';
}
text += '</tr>';
$widgetAttrs.append(text);
// Init button
if (line.button) {
// If init function specified => call it
if (typeof line.button.code === 'function') {
line.button.code(line.button);
} else {
// init button
var $btn = $widgetAttrs.find('#inspect_' + widAttr + '_btn').button({
text: line.button.text || false,
icons: {
primary: line.button.icon || ''
}
}).css({width: line.button.width || 22, height: line.button.height || 22});
if (line.button.click) $btn.click(line.button.click);
if (line.button.data) $btn.data('data-custom', line.button.data);
$btn.data('wdata', {
attr: widAttr,
widgets: widgets,
view: view
});
}
}
// Init value
var $input = $widgetAttrs.find('#inspect_' + widAttr);
if ($input.attr('type') === 'text' || $input.prop('tagName') === 'TEXTAREA') {
if (!$input.hasClass('vis-edit-textbox-with-button')){
$input.addClass('vis-edit-textbox');
}
}
// Set the value
this.setAttrValue(view, this.activeWidgets, widAttr, line.css, values);
var wdata = {
attr: widAttr,
widgets: widgets,
view: view,
type: line.type,
css: line.css,
onChangeWidget: line.onChangeWidget
};
if (line.onchange) wdata.onchange = line.onchange;
$input.addClass('vis-inspect-widget');
$input.data('wdata', wdata);
if (this.groups[group][widAttr][0]) {
for (var i = 1; i < this.groups[group][widAttr].length; i++) {
text = '<tr class="vis-edit-td-caption group-' + group + '"><td></td><td class="vis-edit-td-field" colspan="2">' + this.groups[group][widAttr][i].input + '</td>';
$widgetAttrs.append(text);
}
}
// Collect list of attribute names on which depends other attributes
if (line.depends) {
for (var u = 0; u < line.depends.length; u++) {
if (depends.indexOf(line.depends[u]) === -1) depends.push(line.depends[u]);
}
}
}
// Hide elements
if (!this.groupsState[group]) $widgetAttrs.find('.group-' + group).hide();
}
}
$('.vis-edit-percent-calc').each(function () {
var attr = $(this).data('attr');
var val = $('#inspect_css_' + attr).val();
if (val.toString().indexOf('%') === -1) {
$(this).html('px');
} else {
$(this).html('%');
}
$(this).button().css({width: 18, height: 18}).click(function () {
var attr = $(this).data('attr');
var $input = $('#inspect_css_' + attr);
var val = $input.val();
if (val.toString().indexOf('%') === -1) {
// convert to %
for (var i = 0; i < that.activeWidgets.length; i++) {
var rect = that.editConvertToPercent(viewDiv, view, that.activeWidgets[i], viewDiv !== view ? viewDiv : null);
that.views[view].widgets[that.activeWidgets[i]].style[attr] = rect[attr];
$('#' + that.activeWidgets[i]).css(attr, rect[attr]);
}
that.setAttrValue(view, that.activeWidgets, 'css_' + attr, true, {});
$(this).html('%');
} else {
// convert to px
for (var j = 0; j < that.activeWidgets.length; j++) {
var pRect = that.editConvertToPx(viewDiv, view, that.activeWidgets[j], viewDiv !== view ? viewDiv : null);
that.views[view].widgets[that.activeWidgets[j]].style[attr] = pRect[attr];
$('#' + that.activeWidgets[j]).css(attr, pRect[attr]);
}
that.setAttrValue(view, that.activeWidgets, 'css_' + attr, true, {});
$(this).html('px');
}
});
});
// Init all elements together
for (group in this.groups) {
if (!this.groups.hasOwnProperty(group) || !this.groups[group].___enabled) continue;
for (widAttr in this.groups[group]) {
var line_ = this.groups[group][widAttr];
var $input_ = $widgetAttrs.find('#inspect_' + widAttr);
var wdata_ = $input_.data('wdata');
if (depends.length) $input_.data('depends', depends);
if (line_[0]) line_ = line_[0];
if (typeof line_ === 'string') line_ = {input: line_};
if (typeof line_.init === 'function') {
if (wdata_.css) {
var cwidAttr_ = widAttr.substring(4);
if (values[cwidAttr_] === undefined) values[cwidAttr_] = this.findCommonValue(view, widgets, cwidAttr_);
line_.init.call($input_[0], cwidAttr_, values[cwidAttr_]);
} else {
if (values[widAttr] === undefined) values[widAttr] = this.findCommonValue(view, widgets, widAttr);
line_.init.call($input_[0], widAttr, values[widAttr]);
}
}
// Call on change
if (typeof line_.onchange === 'function') {
if (wdata_.css) {
var cwidAttr = widAttr.substring(4);
if (values[cwidAttr] === undefined) values[cwidAttr] = this.findCommonValue(view, widgets, cwidAttr);
line_.onchange.call($input_[0], values[cwidAttr]);
} else {
if (values[widAttr] === undefined) values[widAttr] = this.findCommonValue(view, widgets, widAttr);
line_.onchange.call($input_[0], values[widAttr]);
}
}
}
}
this.initStealHandlers();
$widgetAttrs.find('.vis-inspect-widget').change(function () {
var $this = $(this);
var wdata = $this.data('wdata');
var depends = $this.data('depends');
var diff = $this.data('different');
var oldValue = null;
// Set flag, that value was modified
if (diff) $this.data('different', false).removeClass('vis-edit-different');
var css = wdata.attr.substring(4);
var val = ($this.attr('type') === 'checkbox') ? $this.prop('checked') : $this.val();
for (var i = 0; i < wdata.widgets.length; i++) {
if (wdata.css) {
if (!that.views[wdata.view].widgets[wdata.widgets[i]].style) {
that.views[wdata.view].widgets[wdata.widgets[i]].style = {};
}
oldValue = that.views[wdata.view].widgets[wdata.widgets[i]].style[css];
that.views[wdata.view].widgets[wdata.widgets[i]].style[css] = val;
if (css !== 'transform') {
var $widget = $('#' + wdata.widgets[i]);
if (val !== '' && (css === 'left' || css === 'top') &&
(val.indexOf('%') === -1 && val.indexOf('px') === -1 && val.indexOf('em') === -1)) {
$widget.css(css, val + 'px');
} else {
$widget.css(css, val);
}
}
if (that.activeWidgets.indexOf(wdata.widgets[i]) !== -1) {
that.showWidgetHelper(viewDiv, view, wdata.widgets[i], true);
}
if ($('#' + that.views[wdata.view].widgets[wdata.widgets[i]].tpl).attr('data-vis-update-style')) {
that.reRenderWidgetEdit(viewDiv, view, wdata.widgets[i]);
}
} else {
oldValue = that.widgets[wdata.widgets[i]].data[wdata.attr];
that.views[wdata.view].widgets[wdata.widgets[i]].data[wdata.attr] = that.widgets[wdata.widgets[i]].data[wdata.attr] = val;
}
// Some user adds ui-draggable and ui-resizable as class to widget.
// The result is DashUI tries to remove draggable and resizable properties and fails
if (wdata.attr === 'class') {
var _val_ = that.views[wdata.view].widgets[wdata.widgets[i]].data[wdata.attr];
if (_val_.indexOf('ui-draggable') !== -1 || _val_.indexOf('ui-resizable') !== -1) {
var vals = _val_.split(' ');
_val_ = '';
for (var j = 0; j < vals.length; j++) {
if (vals[j] && vals[j] !== 'ui-draggable' && vals[j] !== 'ui-resizable') {
_val_ += ((_val_) ? ' ' : '') + vals[j];
}
}
that.views[wdata.view].widgets[wdata.widgets[i]].data[wdata.attr] = _val_;
$this.val(_val_);
}
}
// Update select widget dropdown
if (wdata.attr === 'name') {
that.$selectActiveWidgets.find('option[value="' + wdata.widgets[i] + '"]').text(that.getWidgetName(wdata.view, wdata.widgets[i]));
that.sortSelectWidget();
that.$selectActiveWidgets.multiselect('refresh');
}
var changed = false;
if (typeof wdata.onchange === 'function') {
if (wdata.css) {
var _css = wdata.attr.substring(4);
changed = wdata.onchange.call(this, that.views[wdata.view].widgets[wdata.widgets[i]].style[_css], oldValue) || false;
} else {
changed = wdata.onchange.call(this, that.widgets[wdata.widgets[i]].data[wdata.attr], oldValue) || false;
}
}
if (wdata.onChangeWidget) {
var widgetSet = $('#' + that.views[wdata.view].widgets[wdata.widgets[i]].tpl).attr('data-vis-set');
if (that.binds[widgetSet] && that.binds[widgetSet][wdata.onChangeWidget]) {
var _changed;
if (wdata.css) {
var __css = wdata.attr.substring(4);
_changed = that.binds[widgetSet][wdata.onChangeWidget](wdata.widgets[i], wdata.view, that.views[wdata.view].widgets[wdata.widgets[i]].style[__css], __css, true, oldValue);
} else {
_changed = that.binds[widgetSet][wdata.onChangeWidget](wdata.widgets[i], wdata.view, that.widgets[wdata.widgets[i]].data[wdata.attr], wdata.attr, false, oldValue);
}
if (!changed) changed = _changed;
}
}
that.save(viewDiv, view);
if (!wdata.css) that.reRenderWidgetEdit(viewDiv, view, wdata.widgets[i]);
// Rebuild attr list
if (changed || (depends && depends.indexOf(wdata.attr) !== -1)) that.inspectWidgets(viewDiv, view);
}
//Update containers
if (wdata.type === 'views') {
// Set ths views for containers
that.updateContainers(wdata.view, wdata.view);
}
});
$widgetAttrs.find('.group-control').each(function () {
var group = $(this).attr('data-group');
$(this).button({
text: false,
icons: {
primary: that.groupsState[group] ? "ui-icon-triangle-1-n" : "ui-icon-triangle-1-s"
}
}).css({width: 22, height: 22}).click(function () {
var group = $(this).attr('data-group');
that.groupsState[group] = !that.groupsState[group];
$(this).button('option', {
icons: {primary: that.groupsState[group] ? "ui-icon-triangle-1-n" : "ui-icon-triangle-1-s"}
});
if (that.groupsState[group]) {
$('.group-' + group).show();
if (that.widgetAccordeon) {
//close others
$('.group-control').each(function () {
var _group = $(this).attr('data-group');
if (_group !== group && that.groupsState[_group]) {
that.groupsState[_group] = false;
$('.group-control[data-group="' + _group + '"]').button('option', {icons: {primary: "ui-icon-triangle-1-s"}});
$('.group-' + _group).hide();
}
});
}
} else {
$('.group-' + group).hide();
}
that.editSaveConfig('groupsState', that.groupsState);
});
});
function deleteAttrs(group, widgets, viewDiv, view, value) {
var isCss = group.substring(0, 4) === 'css_';
for (var i = 0; i < widgets.length; i++) {
if (!value) {
var cssChanged = false;
var $style;
if (isCss) $style = $('#' + wdata.widgets[i]).prop('style');
for (var attr in that.groups[group]) {
if (!that.groups[group].hasOwnProperty(attr)) continue;
if (isCss) {
if (that.views[view].widgets[widgets[i]].style) {
attr = attr.substring(4);
delete that.views[view].widgets[widgets[i]].style[attr];
cssChanged = true;
$style.removeProperty(attr);
}
} else {
delete that.views[view].widgets[widgets[i]].data[attr];
}
}
if (cssChanged && $('#' + that.views[view].widgets[widgets[i]].tpl).attr('data-vis-update-style')) {
that.reRenderWidgetEdit(viewDiv, view, widgets[i]);
}
}
that.widgets[widgets[i]].data['g_' + group] = value;
that.views[view].widgets[widgets[i]].data['g_' + group] = value;
}
that.save(viewDiv, view);
// Rebuild attr list
that.inspectWidgets(viewDiv, view);
}
$widgetAttrs.find('.group-enable').change(function () {
var $this = $(this);
var group = $this.attr('data-group');
var wdata = $this.data('wdata');
var checked = $this.prop('checked');
// Set flag, that value was modified
var isCss = group.substring(0, 4) === 'css_';
var isEmpty = true;
if (!checked) {
// check all attributes in this group and if some are not empty, ask
for (var i = 0; i < wdata.widgets.length; i++) {
for (var attr in that.groups[group]) {
var val;
if (isCss) {
val = that.views[wdata.view].widgets[wdata.widgets[i]].style[attr.substring(4)];
} else {
val = that.views[wdata.view].widgets[wdata.widgets[i]].data[attr];
}
if (val !== undefined && val !== null && val !== '') {
isEmpty = false;
break;
}
}
if (!isEmpty) break;
}
if (!isEmpty) {
vis.showMessage(_('Some field are not empty. Sure?'), _('Are you sure?'), 450, function (result) {
if (result) {
deleteAttrs(group, wdata.widgets, wdata.viewDiv, wdata.view, false);
} else {
$this.prop('checked', true);
}
});
} else {
deleteAttrs(group, wdata.widgets, wdata.viewDiv, wdata.view, false);
}
} else {
deleteAttrs(group, wdata.widgets, wdata.viewDiv, wdata.view, true);
}
}).each(function() {
$(this).data('wdata', {
widgets: widgets,
view: view,
viewDiv: viewDiv
});
if ($(this).data('indeterminate')) {
$(this).prop('indeterminate', true)
}
});
},
extractAttributes: function (_wid_attr, widget) {
//returns array of all attributes with groups
/*var oneAttr = {
name: '',
type: '',
default: '',
options: '',
notTranslate: false,
depends: []
}
Result: array of oneAttr
*/
if (!this.regexAttr) this.regexAttr = /([a-zA-Z0-9._-]+)(\([a-zA-Z.0-9-_]*\))?(\[.*])?(\/[-_,^§~\s:\/\.a-zA-Z0-9]+)?/;
var match = this.regexAttr.exec(_wid_attr);
var widAttr = match[1];
var wid_repeats = match[2];
var wid_default = match[3];
var wid_type = match[4];
var wid_on_change = null;
var wid_type_opt = null;
var notTranslate = false;
var index = '';
var attrDepends = [];
// remove /
if (wid_type) {
wid_type = wid_type.substring(1);
// extract on change function
var _parts = wid_type.split('/');
wid_type = _parts[0];
wid_on_change = _parts[1];
wid_type = wid_type.replace(/§/g, ';');
wid_type = wid_type.replace(/~/g, '/');
wid_type = wid_type.replace(/\^/g, '"');
wid_type = wid_type.replace(/\^\^/g, '^');
parts = wid_type.split(',');
// extract min,max,step or select values
if (parts.length > 1) {
wid_type = parts.shift();
wid_type_opt = parts;
}
}
// remove ()
if (wid_repeats) {
wid_repeats = wid_repeats.substring(1, wid_repeats.length - 1);
var parts = wid_repeats.split('-', 2);
if (parts.length === 2) {
wid_repeats = {
start: parseInt(parts[0], 10),
end: parseInt(parts[1], 10)
};
// If end is not number, it can be attribute
if (parts[1][0] < '0' || parts[1][0] > '9') {
var view = this.getViewOfWidget(widget);
var widgetData = this.views[view].widgets[widget].data;
wid_repeats.end = (widgetData[parts[1]] !== undefined) ? parseInt(widgetData[parts[1]], 10) : 1;
attrDepends.push(parts[1]);
}
index = wid_repeats.start;
} else {
throw 'Invalid repeat argument: ' + wid_repeats;
}
}
// remove []
if (wid_default) {
wid_default = wid_default.substring(1, wid_default.length - 1);
wid_default = wid_default.replace(/§/g, ';');
wid_default = wid_default.replace(/~/g, '/');
wid_default = wid_default.replace(/\^/g, '"');
wid_default = wid_default.replace(/\^\^/g, '^');
} else {
wid_default = undefined;
}
if (widAttr === 'color') {
wid_type = 'color';
} else if (widAttr === 'oid' || widAttr.match(/^oid-/)) {
wid_type = wid_type || 'id';
} else if (widAttr.match(/nav_view$/)) {
wid_type = 'views';
} else
/*if (widAttr.match(/src$/)) {
wid_type = 'image';
} else*/
if (widAttr === 'sound') {
wid_type = 'sound';
} else if (widAttr.indexOf('_effect') !== -1) {
wid_type = 'effect';
} else if (widAttr.indexOf('_eff_opt') !== -1) {
wid_type = 'effect-options';
}
if (wid_type === 'nselect') {
wid_type = 'select';
notTranslate = true;
}
// Extract min, max, step for number and slider
if ((wid_type === 'number' || wid_type === 'slider') && wid_type_opt) {
var old = wid_type_opt;
wid_type_opt = {};
if (old[0] !== undefined) {
wid_type_opt.min = parseFloat(old[0]);
if (old[1] !== undefined) {
wid_type_opt.max = parseFloat(old[1]);
if (old[2] !== undefined) {
wid_type_opt.step = parseFloat(old[2]);
}
}
}
}
var result = [];
do {
result.push({
name: (widAttr + index),
type: wid_type,
default: wid_default,
options: wid_type_opt,
onChangeWidget: wid_on_change,
notTranslate: notTranslate,
depends: attrDepends,
clearName: widAttr,
index: index
});
} while (wid_repeats && ((++index) <= wid_repeats.end));
return result;
},
findCommonAttributes: function (view, widgets) {
view = view || this.activeView;
var allWidgetsAttr = null;
for (var i = 0; i < widgets.length; i++) {
var widget = this.views[view].widgets[widgets[i]];
if (!widget) {
console.log('inspectWidget ' + widgets[i] + ' undefined');
return [];
}
if (!widget.tpl) return false;
var $widgetTpl = $('#' + widget.tpl);
if (!$widgetTpl) {
console.log(widget.tpl + ' is not included');
return [];
}
var widgetAttrs = $widgetTpl.attr('data-vis-attrs');
// Combine attributes from data-vis-attrs, data-vis-attrs0, data-vis-attrs1, ...
var t = 0;
var attr;
while ((attr = $widgetTpl.attr('data-vis-attrs' + t))) {
widgetAttrs += attr;
t++;
}
if (widgetAttrs) {
widgetAttrs = widgetAttrs.split(';');
} else {
widgetAttrs = [];
}
var group = 'common';
var groupMode = 'normal';
var attrs = {};
for (var j = 0; j < widgetAttrs.length; j++) {
if (widgetAttrs[j].match(/^group\./)) {
group = widgetAttrs[j].substring('group.'.length);
// extract group mode
if (group.indexOf('/') !== -1) {
var parts = group.split('/');
group = parts[0];
groupMode = parts[1] || 'normal';
// if icon
if (parts[2]) this.groupsIcons[group] = groupMode;
} else {
groupMode = 'normal';
}
continue;
}
if (!widgetAttrs[j]) continue;
var a = this.extractAttributes(widgetAttrs[j], widgets[i]);
if (groupMode === 'byindex') {
for (var k = 0; k < a.length; k++) {
attrs[group + '_§' + k] = attrs[group + '_§' + k] || {};
attrs[group + '_§' + k][a[k].name] = a[k];
}
} else {
attrs[group] = attrs[group] || {};
for (var k = 0; k < a.length; k++) {
attrs[group][a[k].name] = a[k];
}
}
}
if (!allWidgetsAttr) {
allWidgetsAttr = attrs;
} else {
// Combine these too groups
for (group in allWidgetsAttr) {
if (!attrs[group]) delete allWidgetsAttr[group];
}
for (group in attrs) {
if (!allWidgetsAttr[group]) delete attrs[group];
}
for (group in allWidgetsAttr) {
for (var name in allWidgetsAttr[group]) {
if (!attrs[group][name]) delete allWidgetsAttr[group][name];
}
for (name in attrs[group]) {
if (!allWidgetsAttr[group][name]) delete attrs[group][name];
}
for (name in allWidgetsAttr[group]) {
var d1 = allWidgetsAttr[group][name].default;
delete allWidgetsAttr[group][name].default;
delete attrs[group][name].default;
if (JSON.stringify(allWidgetsAttr[group][name]) !== JSON.stringify(attrs[group][name])){
delete allWidgetsAttr[group][name];
} else {
allWidgetsAttr[group][name].default = d1;
}
}
}
}
}
return allWidgetsAttr;
},
// If only one widget, it returns the value
// If array of widgets, ot returns object {values, widgetValues}, where values are all found different values and widgetValues is array with values for every widget
findCommonValue: function (view, widgets, attr, isStyle) {
view = view || this.activeView;
var widgetValues = [];
var values = [];
for (var i = 0; i < widgets.length; i++) {
var widget = this.views[view].widgets[widgets[i]];
var obj = isStyle ? widget.style : widget.data;
var val = (isStyle && (!obj || obj[attr] === undefined)) ? '' : (obj ? obj[attr] : '');
widgetValues[i] = val;
if (values.indexOf(val) === -1) values.push(val);
}
if (values.length === 1) {
return values[0];
} else {
return {
values: values,
widgetValues: widgetValues
};
}
},
setAttrValue: function (view, widgets, attr, isStyle, values) {
var $input = $('#inspect_' + attr);
if (isStyle && attr.substring(0, 4) === 'css_') attr = attr.substring(4);
if (values[attr] === undefined) values[attr] = this.findCommonValue(view, widgets, attr, isStyle);
if ($input.attr('type') === 'checkbox') {
if (typeof values[attr] === 'object') {
$input.prop('indeterminate', true);
} else {
$input.prop('checked', values[attr]);
}
} else {
if (typeof values[attr] === 'object') {
$input.addClass('vis-edit-different').val(_('--different--')).data('value', values[attr]).data('different', true);
$input.autocomplete({
minLength: 0,
source: function (request, response) {
var data = $.grep(this.element.data('value').values, function (value) {
if (value === undefined || value === null) return false;
value = value.toString();
return value.substring(0, request.term.length).toLowerCase() === request.term.toLowerCase();
});
response(data);
},
select: function (event, ui) {
$(this).val(ui.item.value).trigger('change');
},
change: function (event, ui) {
//$(this).trigger('change');
}
}).focus(function (event, ui) {
if ($(this).data('different')) {
$(this).val('');
}
$(this).autocomplete('search', '');
}).blur(function (event, ui) {
if ($(this).data('different')) {
$(this).val(_('--different--')).addClass('vis-edit-different');
}
});
} else {
$input.val(values[attr]);
}
}
$input.unbind('keyup').keyup(function () {
var $this = $(this);
var timer = $this.data('timer');
if (timer) clearTimeout(timer);
$this.data('timer', setTimeout(function () {
$this.data('timer', null);
$this.trigger('change');
}, 500));
});
},
inspectWidgets: function (viewDiv, view, addWidget, delWidget, onlyUpdate) {
if (this.isStealCss) return false;
var that = this;
if (typeof viewDiv === 'object') {
addWidget = viewDiv;
viewDiv = this.activeViewDiv;
view = this.activeView;
}
var oldView;
$('.vis-widget[data-zmodified="true"]').each(function () {
var wid = $(this).attr('id');
$(this).removeAttr('data-zmodified');
oldView = oldView || that.getViewOfWidget(wid);
var zIndex = that.views[oldView].widgets[wid] && that.views[oldView].widgets[wid].style && that.views[oldView].widgets[wid].style['z-index'];
if (!zIndex && zIndex !== '0' && zIndex !== 0) {
$(this).prop('style').removeProperty('z-index');
} else {
$(this).css('z-index', zIndex);
}
});
$('.vis-widget[data-tmodified="true"]').each(function () {
var wid = $(this).attr('id');
$(this).removeAttr('data-tmodified');
oldView = oldView || that.getViewOfWidget(wid);
var transform = that.views[oldView].widgets[wid] && that.views[oldView].widgets[wid].style && that.views[oldView].widgets[wid].style.transform;
if (!transform) {
$(this).prop('style').removeProperty('transform');
} else {
$(this).css('transform', transform);
}
});
// Deselect all elements
$(':focus').blur();
// Hide context menu
$('#context_menu').hide();
if (typeof addWidget === 'boolean') {
onlyUpdate = addWidget;
addWidget = undefined;
delWidget = undefined;
}
if (addWidget) {
if (typeof addWidget === 'object') {
this.activeWidgets = addWidget;
} else {
if (this.activeWidgets.indexOf(addWidget) === -1) this.activeWidgets.push(addWidget);
}
}
if (typeof delWidget === 'string') {
var pos = this.activeWidgets.indexOf(delWidget);
if (pos !== -1) this.activeWidgets.splice(pos, 1);
}
var wid = this.activeWidgets[0] || 'none';
this.groups = {};
this.groupsIcons = {
fixed: 'icon/groupFixed.png'
};
if (view !== viewDiv) {
// disable group resize
var $group = $('#' + viewDiv);
if ($group.hasClass('vis-resize-group')) {
$group.resizable('destroy').removeClass('vis-resize-group');
}
}
if (!onlyUpdate) {
this.alignIndex = 0;
var s = JSON.stringify(this.activeWidgets);
if (this.views[view] && JSON.stringify(this.views[view].activeWidgets) !== s) {
this.views[view].activeWidgets = JSON.parse(s);
// Store selected widgets
this.save(viewDiv, view);
}
//this.$selectActiveWidgets.find('option[value="' + wid + '"]').prop('selected', true);
//this.$selectActiveWidgets.multiselect('refresh');
var $widget;
var select = [];
var deselect = [];
for (var i = 0; i < this.activeWidgets.length; i++) {
if (this.oldActiveWidgets.indexOf(this.activeWidgets[i]) === -1) select.push(this.activeWidgets[i]);
}
for (i = 0; i < this.oldActiveWidgets.length; i++) {
if (this.activeWidgets.indexOf(this.oldActiveWidgets[i]) === -1) deselect.push(this.oldActiveWidgets[i]);
}
// Deselect unselected widgets
for (i = 0; i < deselect.length; i++) {
this.showWidgetHelper(viewDiv, view, deselect[i], false);
$widget = $('#' + deselect[i]);
$widget.removeClass('ui-selected');
if ($widget.hasClass('ui-draggable')) {
try {
$widget.draggable('destroy');
} catch (e) {
this.conn.logError('inspectWidgets - Cannot destroy draggable ' + deselect[i] + ' ' + e);
}
}
if ($widget.hasClass('ui-resizable')) {
try {
$widget.resizable('destroy');
} catch (e) {
this.conn.logError('inspectWidgets - Cannot destroy resizable ' + deselect[i] + ' ' + e);
}
}
}
// disable resize if widget not more selected alone
if (this.oldActiveWidgets.length === 1 && this.activeWidgets.length !== 1) {
$widget = $('#' + this.oldActiveWidgets[0]);
if ($widget.hasClass('ui-resizable')) {
try {
$widget.resizable('destroy');
} catch (e) {
this.conn.logError('inspectWidgets - Cannot destroy resizable ' + deselect[i] + ' ' + e);
}
}
}
// Select selected widgets
for (var p = 0; p < select.length; p++) {
try {
$widget = this.showWidgetHelper(viewDiv, view, select[p], true);
if ($widget && !$('#wid_all_lock_d').hasClass('ui-state-active')) {
this.draggable(viewDiv, view, $widget);
}
} catch (e) {
console.log(e);
}
}
this.$selectActiveWidgets.val(this.activeWidgets);
// Enable disable buttons
if (this.activeWidgets.length) {
$('#rib_wid_del').button('enable');
$('#rib_wid_copy').button('enable');
$('#rib_wid_doc').button('enable');
$('#export_widgets').button('enable');
} else {
$('#rib_wid_del').button('disable');
$('#rib_wid_copy').button('disable');
$('#rib_wid_doc').button('disable');
$('#export_widgets').button('disable');
}
if (this.activeWidgets.length === 1) {
try {
$widget = $('#' + this.activeWidgets[0]);
if (!$widget.hasClass('ui-resizable') && this.widgets[wid] && this.widgets[wid].data && !this.widgets[wid].data._no_resize) {
this.resizable(viewDiv, view, $widget);
}
} catch (e) {
console.log(e);
}
}
this.oldActiveWidgets = [];
for (var k = 0; k < this.activeWidgets.length; k++) {
this.oldActiveWidgets.push(this.activeWidgets[k]);
}
// update selected widgets dropdown
this.$selectActiveWidgets.multiselect('refresh');
// Disable copy widget if was active
$('#rib_wid_copy_cancel').trigger('click');
this.actualAttrs = this.findCommonAttributes(view, this.activeWidgets);
}
var $widgetAttrs = $('#widget_attrs').hide();
// Clear Inspector
$widgetAttrs[0].innerHTML = '';
//$widgetAttrs.empty();
if (!wid || wid === 'none') {
// Switch tabs to View settings
$('#pan_attr').tabs('option', 'disabled', [1]).tabs({active: 0});
$('#widget_tab').text(_('Widget'));
if (view !== viewDiv) {
// enable group resize of nothing selected
this.editResizeGroup(viewDiv, view);
}
return false;
}
$('#pan_attr').tabs('option', 'disabled', []).tabs({active: 1});
$('#widget_tab').text((this.activeWidgets.length === 1) ? wid : _('Widget') + ': ' + this.activeWidgets.length);
if (!this.views[view]) {
console.warn('No view "' + view + ' for ' + wid + ' found');
return;
}
var widget = this.views[view].widgets[wid];
if (!widget) {
console.log('inspectWidget ' + wid + ' undefined');
return false;
}
if (!widget.tpl) return false;
var $widgetTpl = $('#' + widget.tpl);
if (!$widgetTpl) {
console.log(widget.tpl + ' is not included');
return false;
}
/*var widgetAttrs = $widgetTpl.attr('data-vis-attrs');
// Combine attributes from data-vis-attrs, data-vis-attrs0, data-vis-attrs1, ...
var t = 0;
var attr;
while ((attr = $widgetTpl.attr('data-vis-attrs' + t))) {
widgetAttrs += attr;
t++;
}
if (widgetAttrs) {
widgetAttrs = widgetAttrs.split(';');
} else {
widgetAttrs = [];
}
var widgetFilter = $widgetTpl.attr('data-vis-filter');*/
$('#inspect_comment_tr').show();
$('#inspect_class_tr').show();
$widgetAttrs.css({width: '100%'});
// Add fixed attributes
var group = 'fixed';
this.addToInspect(this.activeWidgets, 'name', group);
this.addToInspect(this.activeWidgets, 'comment', group);
this.addToInspect(this.activeWidgets, {name: 'class', type: 'class'}, group);
this.addToInspect(this.activeWidgets, {name: 'filterkey', type: 'auto', options: this.updateFilter(view)}, group);
this.addToInspect(this.activeWidgets, {name: 'views', type: 'select-views'}, group);
this.addToInspect(this.activeWidgets, {name: 'locked', type: 'checkbox'}, group);
group = 'visibility';
this.addToInspect(this.activeWidgets, {name: 'visibility-oid', type: 'id'}, group);
this.addToInspect(this.activeWidgets, {name: 'visibility-cond', type: 'select', options: ['==', '!=', '<=', '>=', '<', '>', 'consist', 'not consist', 'exist', 'not exist'], default: '=='}, group);
this.addToInspect(this.activeWidgets, {name: 'visibility-val', default: 1}, group);
this.addToInspect(this.activeWidgets, {name: 'visibility-groups', type: 'groups'}, group);
this.addToInspect(this.activeWidgets, {name: 'visibility-groups-action', type: 'select', options: ['hide', 'disabled'], default: 'hide'}, group);
this.addToInspect('delimiter', group);
// special case for group widget
group = 'common';
if ($widgetTpl.attr('id') === '_tplGroup' && this.activeWidgets.length === 1) {
var _wid = this.activeWidgets[0];
var id = 1;
var _data = this.views[view].widgets[_wid].data;
var maxCount = parseInt(_data.attrCount, 10);
if (maxCount) {
for (var a = 1; a <= maxCount; a++) {
this.addToInspect(this.activeWidgets, {
name: 'groupAttr' + a,
type: _data['attrType' + a],
clearName: _data['attrName' + a] || ('attrName' + a),
title: _('Use inside of group groupAttr%s', a)
}, group);
}
}
}
// Edit all attributes
for (group in this.actualAttrs) {
if (!this.actualAttrs.hasOwnProperty(group)) continue;
for (var attr in this.actualAttrs[group]) {
if (!this.actualAttrs[group].hasOwnProperty(attr)) continue;
this.addToInspect(this.activeWidgets, this.actualAttrs[group][attr], group);
}
}
this.addToInspect('delimiter', group);
// Add common css
this.editCssCommon();
this.editCssFontText();
this.editCssBackground();
this.editCssBorder();
this.editCssShadowPadding();
//this.editCssAnimation();
this.addToInspect('delimiter', 'css_shadow_padding');
if ($widgetTpl.attr('data-vis-no-gestures') !== 'true') {
this.editGestures(view);
}
if ($widgetTpl.attr('data-vis-no-signals') !== 'true') {
this.editSignalIcons(view);
}
if ($widgetTpl.attr('data-vis-no-ls') !== 'true') {
this.editLastChange(view);
}
// Re-render all widgets, where default values applied
if (this.reRenderList && this.reRenderList.length) {
for (var r = 0; r < this.reRenderList.length; r++) {
this.reRenderWidgetEdit(viewDiv, view, this.reRenderList[r]);
}
this.reRenderList = [];
}
this.showInspect(viewDiv, view, this.activeWidgets);
// snap objects to the grid, elsewise cannot move
/*if (this.views[view].settings.snapType == 2) {
this.gridWidth = parseInt(this.views[view].settings.gridSize, 10);
if (this.gridWidth < 1 || isNaN(this.gridWidth)) this.gridWidth = 10;
for (var i = 0; i < this.activeWidgets.length; i++) {
var $this = $('#' + this.activeWidgets[i]);
var x = parseInt($this.css('left'));
var y = parseInt($this.css('top'));
x = Math.round(x / this.gridWidth) * this.gridWidth;
y = Math.round(y / this.gridWidth) * this.gridWidth;
$this.css({'left': x, 'top': y});
this.showWidgetHelper(this.activeWidgets[i], true);
}
// show grid
}*/
// Put all view names in the select element
var $inspectViews = $('#inspect_views');
if ($inspectViews.length) {
$inspectViews.html('');
var views = this.getViewsOfWidget(this.activeWidgets[0]);
for (var v in this.views) {
if (v === '___settings') continue;
if (v !== this.activeView) {
var selected = '';
for (var m = 0; m < views.length; m++) {
if (views[m] === v) {
selected = 'selected';
break;
}
}
$inspectViews.append('<option value="' + v + '" ' + selected + '>' + v + '</option>');
}
}
$inspectViews.multiselect({
maxWidth: 180,
height: 260,
noneSelectedText: _('Single view'),
selectedText: function (numChecked, numTotal, checkedItems) {
var text = '';
for (var i = 0; i < checkedItems.length; i++) {
text += (!text ? '' : ',') + checkedItems[i].title;
}
return text;
},
multiple: true,
checkAllText: _('Check all'),
uncheckAllText: _('Uncheck all'),
close: function () {
if ($inspectViews.data('changed')) {
$inspectViews.data('changed', false);
that.syncWidgets(that.activeWidgets, $(this).val());
that.save(viewDiv, view);
}
}
//noneSelectedText: _("Select options")
}).change(function () {
$inspectViews.data('changed', true);
}).data('changed', false);
$inspectViews.next().css('width', '100%');
}
// Put all view names in the select element
var $inspectGroups = $('#inspect_visibility-groups');
if ($inspectGroups.length) {
$inspectGroups.html('');
var groups = this.getUserGroups();
var widGroups = this.findCommonValue(view, this.activeWidgets, 'visibility-groups');
if (widGroups && !(widGroups instanceof Array)) widGroups = widGroups.values;
widGroups = widGroups || [];
for (var g in groups) {
var val = g.substring('system.group.'.length);
$inspectGroups.append('<option value="' + val + '" ' + ((widGroups.indexOf(val) !== -1) ? 'selected' : '') + '>' + (groups[g] && groups[g].common ? groups[g].common.name || val : val) + '</option>');
}
$inspectGroups.multiselect({
maxWidth: 180,
height: 260,
noneSelectedText: _('All groups'),
selectedText: function (numChecked, numTotal, checkedItems) {
var text = '';
for (var i = 0; i < checkedItems.length; i++) {
text += (!text ? '' : ',') + checkedItems[i].title;
}
return text;
},
multiple: true,
checkAllText: _('Check all'),
uncheckAllText: _('Uncheck all'),
close: function () {
if ($inspectGroups.data('changed')) {
$inspectGroups.data('changed', false);
that.save(viewDiv, view);
}
}
//noneSelectedText: _("Select options")
}).change(function () {
$inspectGroups.data('changed', true);
}).data('changed', false);
$inspectGroups.next().css('width', '100%');
}
// If tab Widget is not selected => select it
var $menu = $('#menu_body');
if ($menu.tabs('option', 'active') === 1) $menu.tabs({'active': 2});
$widgetAttrs.show();
// modify by all selected widgets the z-index
if (this.views[view]) {
for (var w in this.views[view].widgets) {
if (!this.views[view].widgets.hasOwnProperty(w)) continue;
if (this.activeWidgets.indexOf(w) !== -1) {
$('#' + w)
.attr('data-zmodified', 'true')
.css('z-index', 700);
} else {
var wwidget = this.views[view].widgets[w];
$('#' + w)
.attr('data-zmodified', 'true')
.css('z-index', (wwidget && wwidget.style) ? (wwidget.style['z-index'] || 0) : 0);
}
}
}
}
});