' + getTimeString(new Date(message.ts)) + ' | [' + message.severity + '] | ' + message.message + ' |
';
var h = this.$parentOutput.height();
var oldHeight = $('#script-output').height();
var scrollTop = this.$parentOutput.scrollTop();
var shiftToEnd = (scrollTop + h >= oldHeight - 5);
if (oldHeight > 2000) {
$('#script-output tr:first').remove();
var oldHeight1 = $('#script-output').height();
this.$parentOutput.scrollTop(scrollTop - (oldHeight - oldHeight1));
oldHeight = oldHeight1;
}
var scrollTop = this.$parentOutput.scrollTop();
var shiftToEnd = (scrollTop + h >= oldHeight - 5);
$('#script-output').append(text);
if (shiftToEnd) {
this.$parentOutput.scrollTop(oldHeight + 50);
}
}
};
this.showCronDialog = function (value, cb) {
if (value) {
value = value.replace(/\"/g, '').replace(/\'/g, '');
if (value) {
try {
$('#div-cron').cron('value', value);
} catch (e) {
alert(_('Cannot parse value as cron'));
}
}
}
$('#dialog_cron_callback').show();
$('#dialog_cron_insert').hide();
$('#dialog_cron_callback').unbind('click').click(function () {
var val = $('#div-cron').cron('value');
that.$dialogCron.dialog('close');
if (cb) cb(val);
});
this.$dialogCron.dialog('open');
};
this.showScriptDialog = function (value, args, isReturn, cb) {
this.editorDialog.setValue(value || '');
var width = 700;
var height = 550;
if (this.main.config['script-edit-width']) width = this.main.config['script-edit-width'];
if (this.main.config['script-edit-height']) height = this.main.config['script-edit-height'];
this.$dialogScript.data('callback', cb);
if (args && args.length) {
this.$dialogScript.dialog('option', 'title', _('Edit script') + '. ' + _('Arguments: ') + args.join(', '));
} else {
this.$dialogScript.dialog('option', 'title', _('Edit script'));
}
setEditorOptions(this.editorDialog, {
lineWrap: $('#dialog-edit-wrap-lines').prop('checked'),
});
this.$dialogScript
.dialog('option', 'width', width)
.dialog('option', 'height', height)
.dialog('open');
this.editorDialog.focus();
that.editorDialog._isReturn = isReturn;
setTimeout(function () {
that.editorDialog._changed = false;
$('#dialog_script_save').button('disable');
}, 100);
};
}
/**
* Tests if the given ID belongs to a global script
* @param {string} id
* @returns {boolean}
*/
function isIdOfGlobalScript(id) {
return /^script\.js\.global\./.test(id);
}
var main = {
socket: io.connect(location.protocol + '//' + location.host, {
query: 'ws=true'
}),
saveConfig: function (attr, value) {
if (!main.config) return;
if (attr) main.config[attr] = value;
if (typeof storage !== 'undefined') {
storage.set('adminConfig', JSON.stringify(main.config));
}
},
showError: function (error, cb) {
main.showMessage(_(error), _('Error'), 'alert', cb);
},
showMessage: function (message, title, icon, cb) {
if (typeof title === 'function') {
cb = title;
title = null;
icon = null;
}
if (typeof icon === 'function') {
cb = icon;
icon = null;
}
$dialogMessage.dialog('option', 'title', title || _('Message'));
$('#dialog-message-text').html(message);
if (icon) {
if (!icon.match(/^ui\-icon\-/)) icon = 'ui-icon-' + icon;
$('#dialog-message-icon')
.show()
.attr('class', '')
.addClass('ui-icon ' + icon);
} else {
$('#dialog-message-icon').hide();
}
$dialogMessage.data('callback', cb);
$dialogMessage.dialog('open');
},
confirmMessage: function (message, title, icon, buttons, callback) {
if (typeof buttons === 'function') {
callback = buttons;
$dialogConfirm.dialog('option', 'buttons', [
{
text: _('Ok'),
click: function () {
var cb = $(this).data('callback');
$(this).dialog('close');
if (cb) cb(true);
}
},
{
text: _('Cancel'),
click: function () {
var cb = $(this).data('callback');
$(this).dialog('close');
if (cb) cb(false);
}
}
]);
} else if (typeof buttons === 'object') {
for (var b = 0; b < buttons.length; b++) {
buttons[b] = {
text: buttons[b],
id: 'dialog-confirm-button-' + b,
click: function (e) {
var id = parseInt(e.currentTarget.id.substring('dialog-confirm-button-'.length), 10);
var cb = $(this).data('callback');
$(this).dialog('close');
if (cb) cb(id);
}
}
}
$dialogConfirm.dialog('option', 'buttons', buttons);
}
$dialogConfirm.dialog('option', 'title', title || _('Message'));
$('#dialog-confirm-text').html(message);
if (icon) {
$('#dialog-confirm-icon')
.show()
.attr('class', '')
.addClass('ui-icon ui-icon-' + icon);
} else {
$('#dialog-confirm-icon').hide();
}
$dialogConfirm.data('callback', callback);
$dialogConfirm.dialog('open');
},
initSelectId: function () {
if (main.selectId) return main.selectId;
main.selectId = $('#dialog-select-member').selectId('init', {
objects: main.objects,
states: main.states,
noMultiselect: true,
imgPath: '../../lib/css/fancytree/',
filter: {type: 'state'},
getObjects: getObjects,
texts: {
select: _('Select'),
cancel: _('Cancel'),
all: _('All'),
id: _('ID'),
name: _('Name'),
role: _('Role'),
room: _('Room'),
value: _('Value'),
selectid: _('Select ID'),
from: _('From'),
lc: _('Last changed'),
ts: _('Time stamp'),
wait: _('Processing...'),
ack: _('Acknowledged')
},
columns: ['image', 'name', 'role', 'room', 'value']
});
return main.selectId;
},
subscribe: function (isSubscribe) {
if (!main.socket) return;
if (isSubscribe) {
main.socket.emit('subscribeObjects', 'script.*');
main.socket.emit('subscribeObjects', 'system.adapter.*');
main.socket.emit('requireLog', true);
} else {
main.socket.emit('unsubscribeObjects', 'script.*');
main.socket.emit('unsubscribeObjects', 'system.adapter.*');
main.socket.emit('requireLog', false);
}
},
objects: {},
states: {},
currentHost: '',
instances: [],
objectsLoaded: false,
waitForRestart: false,
selectId: null
};
var $dialogMessage = $('#dialog-message');
var $dialogConfirm = $('#dialog-confirm');
// Read all positions, selected widgets for every view,
// Selected view, selected menu page,
// Selected widget or view page
// Selected filter
if (typeof storage !== 'undefined') {
try {
main.config = storage.get('adminConfig');
if (main.config) {
main.config = JSON.parse(main.config);
} else {
main.config = {};
}
} catch (e) {
console.log('Cannot load edit config');
main.config = {};
}
}
var firstConnect = true;
var scripts = new Scripts(main);
function getStates(callback) {
main.socket.emit('getStates', function (err, res) {
main.states = res;
if (typeof callback === 'function') {
setTimeout(function () {
callback();
}, 0);
}
});
}
function getObjects(callback) {
main.socket.emit('getAllObjects', function (err, res) {
setTimeout(function () {
var obj;
main.objects = res;
for (var id in main.objects) {
if (!main.objects.hasOwnProperty(id) || id.slice(0, 7) === '_design') continue;
obj = res[id];
if (obj.type === 'instance') main.instances.push(id);
if (obj.type === 'script') scripts.list.push(id);
if (obj.type === 'channel' && id.match(/^script\.js\./)) scripts.groups.push(id);
if (obj.type === 'host') scripts.hosts.push(id);
}
main.objectsLoaded = true;
scripts.prepare();
scripts.init();
if (typeof callback === 'function') callback(null, res);
}, 0);
});
}
function objectChange(id, obj) {
// update main.objects cache
if (obj) {
if (obj._rev && main.objects[id]) main.objects[id]._rev = obj._rev;
if (!main.objects[id] || JSON.stringify(main.objects[id]) !== JSON.stringify(obj)) {
main.objects[id] = obj;
if (obj.type === 'instance') {
pos = main.instances.indexOf(id);
if (pos === -1) main.instances.push(id);
} else
if (obj.type === 'script') {
pos = scripts.list.indexOf(id);
if (pos === -1) scripts.list.push(id);
} else
if (id.match(/^script\.js\./) && obj.type === 'channel') {
pos = scripts.groups.indexOf(id);
if (pos === -1) scripts.groups.push(id);
}
}
} else if (main.objects[id]) {
var oldObj = {_id: id, type: main.objects[id].type};
delete main.objects[id];
var pos;
if (oldObj.type === 'instance') {
pos = main.instances.indexOf(id);
if (pos !== -1) main.instances.splice(pos, 1);
} else
if (oldObj.type === 'script') {
pos = scripts.list.indexOf(id);
if (pos !== -1) scripts.list.splice(pos, 1);
} else
if (id.match(/^script\.js\./) && oldObj.type === 'channel') {
pos = scripts.groups.indexOf(id);
if (pos !== -1) scripts.groups.splice(pos, 1);
}
}
if (main.selectId) main.selectId.selectId('object', id, obj);
if (id.match(/^system\.adapter\.[-\w]+\.[0-9]+$/)) {
// Disable scripts tab if no one script engine instance found
var engines = scripts.fillEngines();
$('#tabs').tabs('option', 'disabled', (engines && engines.length) ? [] : [4]);
}
scripts.objectChange(id, obj);
}
function stateChange(id, state) {
var rowData;
id = id ? id.replace(/[\s'"]/g, '_') : '';
if (!id || !id.match(/\.messagebox$/)) {
if (main.selectId) main.selectId.selectId('state', id, state);
}
}
function onLog(message) {
scripts.onLog(message);
}
main.socket.on('permissionError', function (err) {
main.showMessage(_('Has no permission to %s %s %s', err.operation, err.type, (err.id || '')));
});
main.socket.on('objectChange', function (id, obj) {
setTimeout(objectChange, 0, id, obj);
});
main.socket.on('stateChange', function (id, obj) {
setTimeout(stateChange, 0, id, obj);
});
main.socket.on('connect', function () {
$('#connecting').hide();
if (firstConnect) {
firstConnect = false;
main.socket.emit('getUserPermissions', function (err, acl) {
main.acl = acl;
// Read system configuration
main.socket.emit('getObject', 'system.config', function (err, data) {
main.systemConfig = data;
if (!err && main.systemConfig && main.systemConfig.common) {
systemLang = main.systemConfig.common.language;
} else {
systemLang = window.navigator.userLanguage || window.navigator.language;
if (systemLang !== 'en' && systemLang !== 'de' && systemLang !== 'ru') {
main.systemConfig.common.language = 'en';
systemLang = 'en';
}
}
translateAll();
$dialogMessage.dialog({
autoOpen: false,
modal: true,
buttons: [
{
text: _('Ok'),
click: function () {
$(this).dialog('close');
var cb = $(this).data('callback');
if (typeof cb === 'function') {
$(this).data('callback', null);
cb();
}
}
}
]
});
$dialogConfirm.dialog({
autoOpen: false,
modal: true,
width: 400,
height: 200,
buttons: [
{
text: _('Ok'),
click: function () {
var cb = $(this).data('callback');
$(this).dialog('close');
if (cb) cb(true);
}
},
{
text: _('Cancel'),
click: function () {
var cb = $(this).data('callback');
$(this).dialog('close');
if (cb) cb(false);
}
}
]
});
getStates(getObjects);
});
});
}
main.subscribe(true);
if (main.waitForRestart) {
location.reload();
}
});
main.socket.on('disconnect', function () {
$('#connecting').show();
});
main.socket.on('reconnect', function () {
$('#connecting').hide();
if (main.waitForRestart) {
location.reload();
}
});
main.socket.on('reauthenticate', function () {
location.reload();
});
main.socket.on('log', function (message) {
setTimeout(onLog, 0, message);
});
function applyResizableH(install, timeout) {
if (timeout) {
setTimeout(function () {
applyResizableH(install);
}, timeout);
} else {
var $gridScripts = $('#grid-scripts');
if ($gridScripts.hasClass('ui-resizable')) {
$gridScripts.resizable('destroy');
}
if (!install) return;
var width = parseInt(main.config['script-editor-width'] || '30%', 10);
$gridScripts.width(width + '%').next().width(100 - width + '%');
$gridScripts.resizable({
autoHide: false,
handles: 'e',
start: function (e, ui) {
var $editor = $('#blockly-editor');
$editor.data('wasVisible', $editor.is(':visible'));
$editor.hide();
$editor = $('#script-editor');
$editor.data('wasVisible', $editor.is(':visible'));
$editor.hide();
$('.blocklyWidgetDiv').hide();
$('.blocklyTooltipDiv').hide();
$('.blocklyToolboxDiv').hide();
},
resize: function(e, ui) {
var parent = ui.element.parent();
var remainingSpace = parent.width() - ui.element.outerWidth();
var divTwo = ui.element.next();
var divTwoWidth = (remainingSpace - (divTwo.outerWidth() - divTwo.width())) / parent.width() * 100 + '%';
divTwo.width(divTwoWidth);
},
stop: function(e, ui) {
var parent = ui.element.parent();
var width = ui.element.width() / parent.width() * 100 + '%';
ui.element.css({
width: width
});
main.saveConfig('script-editor-width', width);
scripts.resize();
}
});
}
}
function applyResizableV() {
var height = parseInt(main.config['script-editor-height'] || '80%', 10);
var $textarea = $('#editor-scripts-textarea');
$textarea
.height(height + '%')
.next()
.height(100 - height + '%');
$textarea.resizable({
autoHide: false,
handles: 's',
start: function (e, ui) {
var $editor = $('#blockly-editor');
$editor.data('wasVisible', $editor.is(':visible'));
$editor.hide();
$('.blocklyWidgetDiv').hide();
$('.blocklyTooltipDiv').hide();
$('.blocklyToolboxDiv').hide();
},
resize: function (e, ui) {
var parent = ui.element.parent();
var remainingSpace = parent.height() - ui.element.outerHeight();
var divTwo = ui.element.next();
var divTwoWidth = (remainingSpace - (divTwo.outerHeight() - divTwo.height())) / parent.height() * 100 + '%';
divTwo.height(divTwoWidth);
},
stop: function (e, ui) {
var parent = ui.element.parent();
var height = ui.element.height() / parent.height() * 100 + '%';
ui.element.css({
height: height
});
main.saveConfig('script-editor-height', height);
scripts.resize();
}
});
}
window.onbeforeunload = function (evt) {
if (scripts.changed) {
if (window.confirm(_('Script changes are not saved. Discard?'))) {
main.subscribe(false);
return null;
} else {
return _('Configuration not saved.');
}
}
main.subscribe(false);
return null;
};