iobroker.eusec 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2423 @@
1
+ var path = location.pathname;
2
+ var parts = path.split('/');
3
+ parts.splice(-3);
4
+
5
+ if (location.pathname.match(/^\/admin\//)) {
6
+ parts = [];
7
+ }
8
+
9
+ var systemConfig;
10
+ var socket = io.connect('/', {path: parts.join('/') + '/socket.io'});
11
+ var instance = window.location.search.slice(1);
12
+ var common = null; // common information of adapter
13
+ var host = null; // host object on which the adapter runs
14
+ var changed = false;
15
+ var certs = [];
16
+ var adapter = '';
17
+ var onChangeSupported = false;
18
+ var isMaterialize = false;
19
+ var ___onChange = null;
20
+ var systemSecret = 'Zgfr56gFe87jJOM';
21
+ var supportedFeatures = [
22
+ 'ADAPTER_AUTO_DECRYPT_NATIVE', // all native attributes, that are listed in an array `encryptedNative` in io-pack will be automatically decrypted and encrypted. Since js-controller 3.0
23
+ ];
24
+
25
+ function preInit () {
26
+ 'use strict';
27
+ var tmp = window.location.pathname.split('/');
28
+ adapter = tmp[tmp.length - 2];
29
+ var id = 'system.adapter.' + adapter + '.' + instance;
30
+
31
+ // Extend dictionary with standard words for adapter
32
+ if (typeof systemDictionary === 'undefined') {
33
+ systemDictionary = {};
34
+ }
35
+
36
+ systemDictionary.save = {"en": "Save", "fr": "Sauvegarder", "nl": "Opslaan", "es": "Salvar", "pt": "Salve", "it": "Salvare", "de": "Speichern", "pl": "Zapisać", "ru": "Сохранить", "zh-cn": "保存"};
37
+ systemDictionary.saveclose = {"en": "Save and close", "fr": "Sauver et fermer", "nl": "Opslaan en afsluiten","es": "Guardar y cerrar", "pt": "Salvar e fechar", "it": "Salva e chiudi", "de": "Speichern und schließen", "pl": "Zapisz i zamknij", "ru": "Сохранить и выйти", "zh-cn": "保存并关闭"};
38
+ systemDictionary.none = {"en": "none", "fr": "aucun", "nl": "geen", "es": "ninguna", "pt": "Nenhum", "it": "nessuna", "de": "keins", "pl": "Żaden", "ru": "ничего", "zh-cn": "无"};
39
+ systemDictionary.nonerooms = {"en": "", "fr": "", "nl": "", "es": "", "pt": "", "it": "", "de": "", "pl": "", "ru": "", "zh-cn": ""};
40
+ systemDictionary.nonefunctions = {"en": "", "fr": "", "nl": "", "es": "", "pt": "", "it": "", "de": "", "pl": "", "ru": "", "zh-cn": ""};
41
+ systemDictionary.all = {"en": "all", "fr": "tout", "nl": "alle", "es": "todas", "pt": "todos", "it": "tutti", "de": "alle", "pl": "wszystko", "ru": "все", "zh-cn": "所有"};
42
+ systemDictionary['Device list'] = {"en": "Device list", "fr": "Liste des périphériques", "nl": "Lijst met apparaten", "es": "Lista de dispositivos", "pt": "Lista de dispositivos", "it": "Elenco dispositivi", "de": "Geräteliste", "pl": "Lista urządzeń", "ru": "Список устройств", "zh-cn": "设备清单"};
43
+ systemDictionary['new device'] = {"en": "new device", "fr": "nouvel appareil", "nl": "nieuw apparaat", "es": "Nuevo dispositivo", "pt": "Novo dispositivo", "it": "nuovo dispositivo", "de": "Neues Gerät", "pl": "nowe urządzenie", "ru": "Новое устройство", "zh-cn": "新设备"};
44
+ systemDictionary.edit = {"en": "edit", "fr": "modifier", "nl": "Bewerk", "es": "editar", "pt": "editar", "it": "modificare", "de": "Ändern", "pl": "edytować", "ru": "Изменить", "zh-cn": "编辑"};
45
+ systemDictionary.delete = {"en": "delete", "fr": "effacer", "nl": "Delete", "es": "borrar", "pt": "excluir", "it": "Elimina", "de": "Löschen", "pl": "kasować", "ru": "Удалить", "zh-cn": "删除"};
46
+ systemDictionary.pair = {"en": "pair", "fr": "paire", "nl": "paar", "es": "par", "pt": "par", "it": "paio", "de": "Verbinden", "pl": "para", "ru": "Связать", "zh-cn": "配对"};
47
+ systemDictionary.unpair = {"en": "unpair", "fr": "unpair", "nl": "Unpair", "es": "desvincular", "pt": "unpair", "it": "Disaccoppia", "de": "Trennen", "pl": "unpair", "ru": "Разорвать связь", "zh-cn": "取消配对"};
48
+ systemDictionary.ok = {"en": "Ok", "fr": "D'accord", "nl": "OK", "es": "De acuerdo", "pt": "Está bem", "it": "Ok", "de": "Ok", "pl": "Ok", "ru": "Ok", "zh-cn": "确认"};
49
+ systemDictionary.cancel = {"en": "Cancel", "fr": "Annuler", "nl": "Annuleer", "es": "Cancelar", "pt": "Cancelar", "it": "Annulla", "de": "Abbrechen", "pl": "Anuluj", "ru": "Отмена", "zh-cn": "取消"};
50
+ systemDictionary.Message = {"en": "Message", "fr": "Message", "nl": "Bericht", "es": "Mensaje", "pt": "Mensagem", "it": "Messaggio", "de": "Mitteilung", "pl": "Wiadomość", "ru": "Сообщение", "zh-cn": "信息"};
51
+ systemDictionary.close = {"en": "Close", "fr": "Fermer", "nl": "Dichtbij", "es": "Cerca", "pt": "Fechar", "it": "Vicino", "de": "Schließen", "pl": "Blisko", "ru": "Закрыть", "zh-cn": "关闭"};
52
+ systemDictionary.htooltip = {"en": "Click for help", "fr": "Cliquez pour obtenir de l'aide", "nl": "Klik voor hulp", "es": "Haz clic para obtener ayuda", "pt": "Clique para ajuda", "it": "Fai clic per chiedere aiuto", "de": "Anklicken", "pl": "Kliknij, aby uzyskać pomoc", "ru": "Перейти по ссылке", "zh-cn": "单击获取帮助"};
53
+ systemDictionary.saveConfig = {
54
+ "en": "Save configuration to file",
55
+ "de": "Speichern Sie die Konfiguration in der Datei",
56
+ "ru": "Сохранить конфигурацию в файл",
57
+ "pt": "Salvar configuração no arquivo",
58
+ "nl": "Sla configuratie op naar bestand",
59
+ "fr": "Enregistrer la configuration dans un fichier",
60
+ "it": "Salva la configurazione nel file",
61
+ "es": "Guardar configuración en archivo",
62
+ "pl": "Zapisz konfigurację do pliku",
63
+ "zh-cn": "将配置保存到文件"
64
+ };
65
+ systemDictionary.loadConfig = {
66
+ "en": "Load configuration from file",
67
+ "de": "Laden Sie die Konfiguration aus der Datei",
68
+ "ru": "Загрузить конфигурацию из файла",
69
+ "pt": "Carregar configuração do arquivo",
70
+ "nl": "Laad de configuratie uit het bestand",
71
+ "fr": "Charger la configuration à partir du fichier",
72
+ "it": "Carica la configurazione dal file",
73
+ "es": "Cargar configuración desde archivo",
74
+ "pl": "Załaduj konfigurację z pliku",
75
+ "zh-cn": "从文件加载配置"
76
+ };
77
+ systemDictionary.otherConfig = {
78
+ "en": "Configuration from other adapter %s",
79
+ "de": "Konfiguration von anderem Adapter %s",
80
+ "ru": "Конфигурация из другого адаптера %s",
81
+ "pt": "Configuração de outro adaptador %s",
82
+ "nl": "Configuratie vanaf andere adapter %s",
83
+ "fr": "Configuration à partir d'un autre adaptateur %s",
84
+ "it": "Configurazione da altro adattatore %s",
85
+ "es": "Configuración desde otro adaptador %s",
86
+ "pl": "Konfiguracja z innego adaptera %s",
87
+ "zh-cn": "从其他适配器%s配置"
88
+ };
89
+ systemDictionary.invalidConfig = {
90
+ "en": "Invalid JSON file",
91
+ "de": "Ungültige JSON-Datei",
92
+ "ru": "Недопустимый файл JSON",
93
+ "pt": "Arquivo JSON inválido",
94
+ "nl": "Ongeldig JSON-bestand",
95
+ "fr": "Fichier JSON non valide",
96
+ "it": "File JSON non valido",
97
+ "es": "Archivo JSON no válido",
98
+ "pl": "Nieprawidłowy plik JSON",
99
+ "zh-cn": "无效的JSON文件"
100
+ };
101
+ systemDictionary.configLoaded = {
102
+ "en": "Configuration was successfully loaded",
103
+ "de": "Die Konfiguration wurde erfolgreich geladen",
104
+ "ru": "Конфигурация успешно загружена",
105
+ "pt": "Configuração foi carregada com sucesso",
106
+ "nl": "Configuratie is succesvol geladen",
107
+ "fr": "La configuration a été chargée avec succès",
108
+ "it": "La configurazione è stata caricata correttamente",
109
+ "es": "La configuración se cargó correctamente",
110
+ "pl": "Konfiguracja została pomyślnie załadowana",
111
+ "zh-cn": "配置已成功加载"
112
+ };
113
+ systemDictionary.maxTableRaw = {
114
+ "en": "Maximum number of allowed raws",
115
+ "de": "Maximale Anzahl von erlaubten Tabellenzeilen",
116
+ "ru": "Достигнуто максимальное число строк",
117
+ "it": "Numero massimo di raw consentiti",
118
+ "fr": "Nombre maximum de raw autorisés",
119
+ "nl": "Maximumaantal toegestane raws",
120
+ "pt": "Número máximo de raias permitidas",
121
+ "es": "Número máximo de raws permitidos",
122
+ "pl": "Maksymalna liczba dozwolonych surowców",
123
+ "zh-cn": "允许的最大原始数量"
124
+ };
125
+ systemDictionary.maxTableRawInfo = {"en": "Warning", "de": "Warnung", "ru": "Внимание", "pt": "Atenção", "nl": "Waarschuwing", "fr": "Attention", "it": "avvertimento", "es": "Advertencia", "pl": "Ostrzeżenie", "zh-cn": "警告"};
126
+ systemDictionary["Main settings"] = {
127
+ "en": "Main settings",
128
+ "de": "Haupteinstellungen",
129
+ "ru": "Основные настройки",
130
+ "pt": "Configurações principais",
131
+ "nl": "Belangrijkste instellingen",
132
+ "fr": "Réglages principaux",
133
+ "it": "Impostazioni principali",
134
+ "es": "Ajustes principales",
135
+ "pl": "Ustawienia główne",
136
+ "zh-cn": "主要设置"
137
+ };
138
+
139
+ systemDictionary["Let's Encrypt SSL"] = {
140
+ "en": "Let's Encrypt Certificates",
141
+ "de": "Let's Encrypt Zertifikate",
142
+ "ru": "Let's Encrypt Сертификаты",
143
+ "pt": "Let's Encrypt Certificados",
144
+ "nl": "Let's Encrypt certificaten",
145
+ "fr": "Let's Encrypt Certificats",
146
+ "it": "Let's Encrypt certificati",
147
+ "es": "Let's Encrypt Certificados",
148
+ "pl": "Let's Encrypt certyfikaty",
149
+ "zh-cn": "Let's Encrypt证书"
150
+ };
151
+ systemDictionary["Please activate secure communication"] = {
152
+ "en": "Please activate secure communication",
153
+ "de": "Bitte sichere Kommunikation aktivieren",
154
+ "ru": "Включите безопасную связь",
155
+ "pt": "Active a comunicação segura",
156
+ "nl": "Activeer alstublieft beveiligde communicatie",
157
+ "fr": "Veuillez activer la communication sécurisée",
158
+ "it": "Si prega di attivare la comunicazione sicura",
159
+ "es": "Por favor active la comunicación segura",
160
+ "pl": "Aktywuj bezpieczną komunikację",
161
+ "zh-cn": "请激活安全通信"
162
+ };
163
+
164
+ if (socket.connected) {
165
+ loadSystemConfig(function () {
166
+ typeof translateAll === 'function' && translateAll();
167
+ loadSettings(prepareTooltips);
168
+ });
169
+ } else {
170
+ socket.on('connect', function () {
171
+ loadSystemConfig(function () {
172
+ typeof translateAll === 'function' && translateAll();
173
+ loadSettings(prepareTooltips);
174
+ });
175
+ });
176
+ }
177
+
178
+ var $body = $('body');
179
+
180
+ $body.wrapInner('<div class="adapter-body"></div>');
181
+ /*$body.prepend('<div class="header ui-tabs-nav ui-widget ui-widget-header ui-corner-all" style="padding: 2px" >' +
182
+ '<button id="save" class="translateB">save</button>&nbsp;' +
183
+ '<button id="saveclose" class="translateB">saveclose</button>&nbsp;' +
184
+ '<button id="close" class="translateB" style="float: right;">cancel</button>&nbsp;' +
185
+ '</div>');
186
+ */
187
+ $body.append(
188
+ '<div class="m"><nav class="dialog-config-buttons nav-wrapper footer">' +
189
+ ' <a class="btn btn-active btn-save"><i class="material-icons left">save</i><span class="translate">save</span></a> ' +
190
+ ' <a class="btn btn-save-close"><i class="material-icons left">save</i><i class="material-icons left">close</i><span class="translate">saveclose</span></a> ' +
191
+ ' <a class="btn btn-cancel"><i class="material-icons left">close</i><span class="translate">close</span></a>' +
192
+ '</nav></div>');
193
+
194
+ var $navButtons = $('.dialog-config-buttons');
195
+ $navButtons.find('.btn-save').on('click', function () {
196
+ if (typeof save === 'undefined') {
197
+ alert('Please implement save function in your admin/index.html');
198
+ return;
199
+ }
200
+ save(function (obj, common, redirect) {
201
+ if (redirect && parent && parent.adapterRedirect) {
202
+ parent.adapterRedirect(redirect);
203
+ }
204
+ saveSettings(obj, common);
205
+ });
206
+ });
207
+
208
+ function close() {
209
+ if (typeof parent !== 'undefined' && parent) {
210
+ try {
211
+ if (parent.$iframeDialog && typeof parent.$iframeDialog.close === 'function') {
212
+ parent.$iframeDialog.close();
213
+ } else {
214
+ parent.postMessage('close', '*');
215
+ }
216
+ } catch (e) {
217
+ parent.postMessage('close', '*');
218
+ }
219
+ }
220
+ }
221
+
222
+ $navButtons.find('.btn-save-close').on('click', function () {
223
+ if (typeof save === 'undefined') {
224
+ alert('Please implement save function in your admin/index.html');
225
+ return;
226
+ }
227
+ save(function (obj, common, redirect) {
228
+ if (redirect && parent && parent.adapterRedirect) {
229
+ parent.adapterRedirect(redirect);
230
+ }
231
+ saveSettings(obj, common, function () {
232
+ // window.close();
233
+ close();
234
+ });
235
+ });
236
+ });
237
+
238
+ $navButtons.find('.btn-cancel').on('click', function () {
239
+ close();
240
+ });
241
+
242
+ // detect, that we are now in react container
243
+ if (window.location.search.indexOf('react=true') !== -1) {
244
+ $('.adapter-container').addClass('react');
245
+ }
246
+
247
+ function saveSettings(native, common, callback) {
248
+ if (typeof common === 'function') {
249
+ callback = common;
250
+ common = null;
251
+ }
252
+
253
+ socket.emit('getObject', id, function (err, oldObj) {
254
+ oldObj = oldObj || {};
255
+
256
+ for (var a in native) {
257
+ if (native.hasOwnProperty(a)) {
258
+ oldObj.native[a] = native[a];
259
+ // encode all native attributes listed in oldObj.encryptedNative
260
+ if (oldObj.encryptedNative &&
261
+ typeof oldObj.encryptedNative === 'object' &&
262
+ oldObj.encryptedNative instanceof Array &&
263
+ oldObj.encryptedNative.indexOf(a) !== -1) {
264
+ oldObj.native[a] = encrypt(oldObj.native[a]);
265
+ }
266
+ }
267
+ }
268
+
269
+ if (common) {
270
+ for (var b in common) {
271
+ if (common.hasOwnProperty(b)) {
272
+ oldObj.common[b] = common[b];
273
+ }
274
+ }
275
+ }
276
+
277
+ if (onChangeSupported) {
278
+ $navButtons.find('.btn-save').addClass('disabled');
279
+ $navButtons.find('.btn-save-close').addClass('disabled');
280
+ $navButtons.find('.btn-cancel').find('span').html(_('close'));
281
+ }
282
+
283
+ socket.emit('setObject', id, oldObj, function (err) {
284
+ if (err) {
285
+ showMessage(err, _('Error'), 'alert');
286
+ return;
287
+ }
288
+ parent.postMessage('nochange', '*');
289
+ changed = false;
290
+ callback && callback();
291
+ });
292
+ });
293
+ }
294
+
295
+ var loadCount = 0;
296
+ var loaded = false;
297
+ // Read language settings
298
+ function loadSystemConfig(callback) {
299
+ if (loaded) {
300
+ return;
301
+ }
302
+ // retry strategy
303
+ var _timeout = setTimeout(function () {
304
+ _timeout = null;
305
+ loadCount++;
306
+ if (loadCount < 10) {
307
+ loadSystemConfig(callback);
308
+ }
309
+ }, 1000);
310
+
311
+ socket.emit('getObject', 'system.config', function (err, res) {
312
+ if (loaded) {
313
+ return;
314
+ }
315
+ loaded = true;
316
+ clearTimeout(_timeout);
317
+ _timeout = null;
318
+
319
+ if (!err && res && res.common) {
320
+ systemLang = res.common.language || systemLang;
321
+ systemConfig = res;
322
+ systemSecret = (systemConfig && systemConfig.native && systemConfig.native.secret) || 'Zgfr56gFe87jJOM';
323
+ }
324
+ socket.emit('getObject', 'system.certificates', function (err, res) {
325
+ if (!err && res) {
326
+ if (res.native && res.native.certificates) {
327
+ certs = [];
328
+ for (var c in res.native.certificates) {
329
+ if (!res.native.certificates.hasOwnProperty(c) || !res.native.certificates[c]) {
330
+ continue;
331
+ }
332
+
333
+ // If it is filename, it could be everything
334
+ if (res.native.certificates[c].length < 700 && (res.native.certificates[c].indexOf('/') !== -1 || res.native.certificates[c].indexOf('\\') !== -1)) {
335
+ var __cert = {
336
+ name: c,
337
+ type: ''
338
+ };
339
+ if (c.toLowerCase().indexOf('private') !== -1) {
340
+ __cert.type = 'private';
341
+ } else if (res.native.certificates[c].toLowerCase().indexOf('private') !== -1) {
342
+ __cert.type = 'private';
343
+ } else if (c.toLowerCase().indexOf('public') !== -1) {
344
+ __cert.type = 'public';
345
+ } else if (res.native.certificates[c].toLowerCase().indexOf('public') !== -1) {
346
+ __cert.type = 'public';
347
+ }
348
+ certs.push(__cert);
349
+ continue;
350
+ }
351
+
352
+ var _cert = {
353
+ name: c,
354
+ type: (res.native.certificates[c].substring(0, '-----BEGIN RSA PRIVATE KEY'.length) === '-----BEGIN RSA PRIVATE KEY' || res.native.certificates[c].substring(0, '-----BEGIN PRIVATE KEY'.length) === '-----BEGIN PRIVATE KEY') ? 'private' : 'public'
355
+ };
356
+ if (_cert.type === 'public') {
357
+ var m = res.native.certificates[c].split('-----END CERTIFICATE-----');
358
+ var count = 0;
359
+ for (var _m = 0; _m < m.length; _m++) {
360
+ if (m[_m].replace(/\r\n|\r|\n/, '').trim()) count++;
361
+ }
362
+ if (count > 1) _cert.type = 'chained';
363
+ }
364
+
365
+ certs.push(_cert);
366
+ }
367
+ }
368
+ }
369
+ callback && callback();
370
+ });
371
+ });
372
+ }
373
+
374
+ // callback if something changed
375
+ function onChange(isChanged) {
376
+ onChangeSupported = true;
377
+ if (typeof isChanged === 'boolean' && isChanged === false) {
378
+ parent.postMessage('nochange', '*');
379
+ changed = false;
380
+ $navButtons.find('.btn-save').addClass('disabled');
381
+ $navButtons.find('.btn-save-close').addClass('disabled');
382
+ $navButtons.find('.btn-cancel').find('span').html(_('close'));
383
+ } else {
384
+ parent.postMessage('change', '*');
385
+ changed = true;
386
+ $navButtons.find('.btn-save').removeClass('disabled');
387
+ $navButtons.find('.btn-save-close').removeClass('disabled');
388
+ $navButtons.find('.btn-cancel').find('span').html(_('cancel'));
389
+ }
390
+ }
391
+
392
+ function loadSettings(callback) {
393
+ socket.emit('getObject', id, function (err, res) {
394
+ if (!err && res && res.native) {
395
+ $('.adapter-instance').html(adapter + '.' + instance);
396
+ $('.adapter-config').html('system.adapter.' + adapter + '.' + instance);
397
+ common = res.common;
398
+ res.common && res.common.name && $('.adapter-name').html(res.common.name);
399
+ if (typeof load === 'undefined') {
400
+ alert('Please implement save function in your admin/index.html');
401
+ } else {
402
+ // decode all native attributes listed in res.encryptedNative
403
+ if (res.encryptedNative && typeof res.encryptedNative === 'object' && res.encryptedNative instanceof Array) {
404
+ for (var i = 0; i < res.encryptedNative.length; i++) {
405
+ if (res.native[res.encryptedNative[i]]) {
406
+ res.native[res.encryptedNative[i]] = decrypt(res.native[res.encryptedNative[i]]);
407
+ }
408
+ }
409
+ } else {
410
+ var idx = supportedFeatures.indexOf('ADAPTER_AUTO_DECRYPT_NATIVE');
411
+ if (idx !== -1) {
412
+ // if no encryptedNative exists the feature is irrelevant, remove for compatibility reasons
413
+ supportedFeatures.splice(idx, 1);
414
+ }
415
+ }
416
+
417
+ load(res.native, onChange);
418
+ // init selects
419
+ if (isMaterialize) {
420
+ $('select').select();
421
+ M.updateTextFields();
422
+
423
+ // workaround for materialize checkbox problem
424
+ $('input[type="checkbox"]+span').off('click').on('click', function (event) {
425
+ var $input = $(this).prev();
426
+ if (!$input.prop('disabled')) {
427
+ $input.prop('checked', !$input.prop('checked')).trigger('change');
428
+ // prevent propagation to prevent original handling from reverting our value change
429
+ event.preventDefault();
430
+ event.stopImmediatePropagation();
431
+ }
432
+ });
433
+ }
434
+ }
435
+ if (typeof callback === 'function') {
436
+ callback();
437
+ }
438
+ } else {
439
+ if (typeof callback === 'function') {
440
+ callback();
441
+ }
442
+ alert('error loading settings for ' + id + '\n\n' + err);
443
+ }
444
+ });
445
+ }
446
+ ___onChange = onChange;
447
+ }
448
+
449
+ $(document).ready(function () {
450
+ 'use strict';
451
+
452
+ if (window.location.pathname.indexOf('/index_m.html') === -1) {
453
+ // load materialize
454
+ var cssLink = document.createElement('link');
455
+ cssLink.href = '../../lib/css/materialize.css';
456
+ cssLink.type = 'text/css';
457
+ cssLink.rel = 'stylesheet';
458
+ cssLink.media = 'screen,print';
459
+ document.getElementsByTagName('head')[0].appendChild(cssLink);
460
+
461
+ // load materialize.js
462
+ var jsLink = document.createElement('script');
463
+ jsLink.onload = preInit;
464
+ jsLink.src = '../../lib/js/materialize.js';
465
+ document.head.appendChild(jsLink);
466
+ } else {
467
+ isMaterialize = true;
468
+ preInit();
469
+ }
470
+ });
471
+
472
+ function handleFileSelect(evt) {
473
+ var f = evt.target.files[0];
474
+ if (f) {
475
+ var r = new FileReader();
476
+ r.onload = function(e) {
477
+ var contents = e.target.result;
478
+ try {
479
+ var json = JSON.parse(contents);
480
+ if (json.native && json.common) {
481
+ if (json.common.name !== common.name) {
482
+ showError(_('otherConfig', json.common.name));
483
+ } else {
484
+ load(json.native, ___onChange);
485
+ // init selects
486
+ if (isMaterialize) {
487
+ $('select').select();
488
+ M.updateTextFields();
489
+
490
+ // workaround for materialize checkbox problem
491
+ $('input[type="checkbox"]+span').off('click').on('click', function (event) {
492
+ var $input = $(this).prev();
493
+ if (!$input.prop('disabled')) {
494
+ $input.prop('checked', !$input.prop('checked')).trigger('change');
495
+ // prevent propagation to prevent original handling from reverting our value change
496
+ event.preventDefault();
497
+ event.stopImmediatePropagation();
498
+ }
499
+ });
500
+ }
501
+ ___onChange();
502
+ showToast(null, _('configLoaded'));
503
+ }
504
+ } else {
505
+ showError(_('invalidConfig'));
506
+ }
507
+ } catch (e) {
508
+ showError(e.toString());
509
+ }
510
+ };
511
+ r.readAsText(f);
512
+ } else {
513
+ alert('Failed to open JSON File');
514
+ }
515
+ }
516
+
517
+ function generateFile(filename, obj) {
518
+ var el = document.createElement('a');
519
+ el.setAttribute('href', 'data:application/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(obj, null, 2)));
520
+ el.setAttribute('download', filename);
521
+
522
+ el.style.display = 'none';
523
+ document.body.appendChild(el);
524
+
525
+ el.click();
526
+
527
+ document.body.removeChild(el);
528
+ }
529
+
530
+ function prepareTooltips() {
531
+ if (isMaterialize) {
532
+ // init tabs
533
+ $('.tabs').mtabs();
534
+
535
+ var buttonsText = '';
536
+ if (common && common.readme) {
537
+ buttonsText += ' <a class="btn-floating btn-small waves-effect waves-light" href="' + common.readme +'" target="_blank">' +
538
+ ' <i class="material-icons">live_help</i>' +
539
+ ' </a>';
540
+ }
541
+
542
+ buttonsText += ' <a class="btn-floating btn-small waves-effect waves-light adapter-config-load" title="' + _('loadConfig') + '">' +
543
+ ' <i class="material-icons">file_upload</i>' +
544
+ ' </a>';
545
+
546
+ buttonsText += ' <a class="btn-floating btn-small waves-effect waves-light adapter-config-save" title="' + _('saveConfig') + '">' +
547
+ ' <i class="material-icons">file_download</i>' +
548
+ ' </a>';
549
+
550
+
551
+ if (buttonsText) {
552
+ // add help link after logo
553
+ var $logo = $('.logo').first().parent();
554
+ if ($logo.length) {
555
+ $('<div class="col s6 help-link">' + buttonsText + '</div>').insertAfter($logo);
556
+ }
557
+ $('.adapter-config-load').click(function () {
558
+ var input = document.createElement('input');
559
+ input.setAttribute('type', 'file');
560
+ input.setAttribute('id', 'files');
561
+ input.setAttribute('opacity', 0);
562
+ input.addEventListener('change', function (e) {
563
+ handleFileSelect(e, function () {});
564
+ }, false);
565
+ (input.click)();
566
+ });
567
+ $('.adapter-config-save').click(function () {
568
+ save(function (native, cmn) {
569
+ var result = {
570
+ _id: 'system.adapter.' + common.name + '.' + instance,
571
+ common: JSON.parse(JSON.stringify(common)),
572
+ native: native
573
+ };
574
+ // remove unimportant information
575
+ if (result.common.news) {
576
+ delete result.common.news;
577
+ }
578
+ if (result.common.titleLang) {
579
+ delete result.common.titleLang;
580
+ }
581
+ if (result.common.desc) {
582
+ delete result.common.desc;
583
+ }
584
+ if (cmn) {
585
+ for (var b in cmn) {
586
+ if (cmn.hasOwnProperty(b)) {
587
+ result.common[b] = cmn[b];
588
+ }
589
+ }
590
+ }
591
+
592
+ //window.open('data:application/iobroker; content-disposition=attachment; filename=' + result._id + '.json,' + JSON.stringify(result, null, 2));
593
+ generateFile(result._id + '.json', result);
594
+ });
595
+ })
596
+ }
597
+
598
+ $('.value').each(function () {
599
+ var $this = $(this);
600
+
601
+ // replace all labels after checkboxes to span (bug in materialize)
602
+ if ($this.attr('type') === 'checkbox') {
603
+ $this.addClass('filled-in');
604
+
605
+ var $label = $this.next();
606
+ if ($label.prop('tagName') === 'LABEL') {
607
+ $label.replaceWith('<span style="' + ($label.attr('style') || '') + '" class="' + ($label.attr('class') || '') + '">' + $label.html() +'</span>');
608
+ $label = $this.next();
609
+ }
610
+
611
+ $label.off('click').on('click', function () {
612
+ var $input = $(this).prev();
613
+ if (!$input.prop('disabled')) {
614
+ $input.prop('checked', !$input.prop('checked')).trigger('change');
615
+ }
616
+ });
617
+ }
618
+
619
+ var id = $this.data('id');
620
+ var tooltip = '';
621
+ if (systemDictionary['tooltip_' + id]) {
622
+ tooltip = systemDictionary['tooltip_' + id][systemLang] || systemDictionary['tooltip_' + id].en;
623
+ }
624
+
625
+ var link = $this.data('link');
626
+ if (link && common) {
627
+ if (link === true) {
628
+ if (common.readme) {
629
+ link = common.readme + '#' + id;
630
+ } else {
631
+ link = 'https://github.com/ioBroker/ioBroker.' + common.name + '#' + id;
632
+ }
633
+ }
634
+ if (!link.match('^https?:\/\/')) {
635
+ if (common.readme) {
636
+ link = common.readme + '#' + link;
637
+ } else {
638
+ link = 'https://github.com/ioBroker/ioBroker.' + common.name + '#' + link;
639
+ }
640
+ }
641
+ }
642
+
643
+ if (link) {
644
+ $('<a class="tooltip" href="' + link + '" title="' + (tooltip || systemDictionary.htooltip[systemLang]) + '" target="_blank"><i class="material-icons tooltip">live_help</i></a>').insertBefore($this);
645
+ } else if (tooltip) {
646
+ $('<i class="material-icons tooltip" title="' + tooltip + '">help_outline</i>').insertBefore($this);
647
+ }
648
+ });
649
+ } else {
650
+ $('.admin-icon').each(function () {
651
+ var id = $(this).data('id');
652
+ if (!id) {
653
+ var $prev = $(this).prev();
654
+ var $input = $prev.find('input');
655
+ if (!$input.length) $input = $prev.find('select');
656
+ if (!$input.length) $input = $prev.find('textarea');
657
+
658
+ if (!$input.length) {
659
+ $prev = $prev.parent();
660
+ $input = $prev.find('input');
661
+ if (!$input.length) $input = $prev.find('select');
662
+ if (!$input.length) $input = $prev.find('textarea');
663
+ }
664
+ if ($input.length) id = $input.attr('id');
665
+ }
666
+
667
+ if (!id) {
668
+ return;
669
+ }
670
+
671
+ var tooltip = '';
672
+ if (systemDictionary['tooltip_' + id]) {
673
+ tooltip = systemDictionary['tooltip_' + id][systemLang] || systemDictionary['tooltip_' + id].en;
674
+ }
675
+
676
+ var icon = '';
677
+ var link = $(this).data('link');
678
+ if (link && common) {
679
+ if (link === true) {
680
+ if (common.readme) {
681
+ link = common.readme + '#' + id;
682
+ } else {
683
+ link = 'https://github.com/ioBroker/ioBroker.' + common.name + '#' + id;
684
+ }
685
+ }
686
+ if (!link.match('^https?:\/\/')) {
687
+ if (common.readme) {
688
+ link = common.readme + '#' + link;
689
+ } else {
690
+ link = 'https://github.com/ioBroker/ioBroker.' + common.name + '#' + link;
691
+ }
692
+ }
693
+ icon += '<a class="admin-tooltip-link" target="config_help" href="' + link + '" title="' + (tooltip || systemDictionary.htooltip[systemLang]) + '"><img class="admin-tooltip-icon" src="../../img/info.png" /></a>';
694
+ } else if (tooltip) {
695
+ icon += '<img class="admin-tooltip-icon" title="' + tooltip + '" src="../../img/info.png"/>';
696
+ }
697
+
698
+ if (icon) {
699
+ $(this).html(icon);
700
+ }
701
+ });
702
+ $('.admin-text').each(function () {
703
+ var id = $(this).data('id');
704
+ if (!id) {
705
+ var $prev = $(this).prev();
706
+ var $input = $prev.find('input');
707
+ if (!$input.length) {
708
+ $input = $prev.find('select');
709
+ }
710
+ if (!$input.length) {
711
+ $input = $prev.find('textarea');
712
+ }
713
+ if (!$input.length) {
714
+ $prev = $prev.parent();
715
+ $input = $prev.find('input');
716
+ if (!$input.length) {
717
+ $input = $prev.find('select');
718
+ }
719
+ if (!$input.length) {
720
+ $input = $prev.find('textarea');
721
+ }
722
+ }
723
+ if ($input.length) {
724
+ id = $input.attr('id');
725
+ }
726
+ }
727
+
728
+ if (!id) {
729
+ return;
730
+ }
731
+
732
+ // check if translation for this exist
733
+ if (systemDictionary['info_' + id]) {
734
+ $(this).html('<span class="admin-tooltip-text">' + (systemDictionary['info_' + id][systemLang] || systemDictionary['info_' + id].en) + '</span>');
735
+ }
736
+ });
737
+ }
738
+ }
739
+
740
+ function supportsFeature(feature) {
741
+ return supportedFeatures.indexOf(feature) !== -1;
742
+ }
743
+
744
+ function showMessageJQ(message, title, icon, width) {
745
+ var $dialogMessage = $('#dialog-message-settings');
746
+ if (!$dialogMessage.length) {
747
+ $('body').append('<div id="dialog-message-settings" title="Message" style="display: none">\n' +
748
+ '<p>' +
749
+ '<span id="dialog-message-icon-settings" class="ui-icon ui-icon-circle-check" style="float :left; margin: 0 7px 50px 0;"></span>\n' +
750
+ '<span id="dialog-message-text-settings"></span>\n' +
751
+ '</p>\n' +
752
+ '</div>');
753
+ $dialogMessage = $('#dialog-message-settings');
754
+ $dialogMessage.dialog({
755
+ autoOpen: false,
756
+ modal: true,
757
+ buttons: [
758
+ {
759
+ text: _('Ok'),
760
+ click: function () {
761
+ $(this).dialog('close');
762
+ }
763
+ }
764
+ ]
765
+ });
766
+ }
767
+ $dialogMessage.dialog('option', 'width', width + 500);
768
+
769
+ if (typeof _ !== 'undefined') {
770
+ $dialogMessage.dialog('option', 'title', title || _('Message'));
771
+ } else {
772
+ $dialogMessage.dialog('option', 'title', title || 'Message');
773
+ }
774
+ $('#dialog-message-text-settings').html(message);
775
+ if (icon) {
776
+ $('#dialog-message-icon-settings')
777
+ .show()
778
+ .attr('class', '')
779
+ .addClass('ui-icon ui-icon-' + icon);
780
+ } else {
781
+ $('#dialog-message-icon-settings').hide();
782
+ }
783
+ $dialogMessage.dialog('open');
784
+ }
785
+
786
+ function showMessage(message, title, icon) {
787
+ if (!isMaterialize) {
788
+ return showMessageJQ(message, title, icon);
789
+ }
790
+ var $dialogMessage;
791
+ // noinspection JSJQueryEfficiency
792
+ $dialogMessage = $('#dialog-message');
793
+ if (!$dialogMessage.length) {
794
+ $('body').append(
795
+ '<div class="m"><div id="dialog-message" class="modal modal-fixed-footer">' +
796
+ ' <div class="modal-content">' +
797
+ ' <h6 class="dialog-title title"></h6>' +
798
+ ' <p><i class="large material-icons dialog-icon"></i><span class="dialog-text"></span></p>' +
799
+ ' </div>' +
800
+ ' <div class="modal-footer">' +
801
+ ' <a class="modal-action modal-close waves-effect waves-green btn-flat translate">Ok</a>' +
802
+ ' </div>' +
803
+ '</div></div>');
804
+ $dialogMessage = $('#dialog-message');
805
+ }
806
+ if (icon) {
807
+ $dialogMessage.find('.dialog-icon')
808
+ .show()
809
+ .html(icon);
810
+ } else {
811
+ $dialogMessage.find('.dialog-icon').hide();
812
+ }
813
+ if (title) {
814
+ $dialogMessage.find('.dialog-title').html(title).show();
815
+ } else {
816
+ $dialogMessage.find('.dialog-title').hide();
817
+ }
818
+ $dialogMessage.find('.dialog-text').html(message);
819
+ $dialogMessage.modal().modal('open');
820
+ }
821
+
822
+ function confirmMessageJQ(message, title, icon, buttons, callback) {
823
+ var $dialogConfirm = $('#dialog-confirm-settings');
824
+ if (!$dialogConfirm.length) {
825
+ $('body').append('<div id="dialog-confirm-settings" title="Message" style="display: none">\n' +
826
+ '<p>' +
827
+ '<span id="dialog-confirm-icon-settings" class="ui-icon ui-icon-circle-check" style="float :left; margin: 0 7px 50px 0;"></span>\n' +
828
+ '<span id="dialog-confirm-text-settings"></span>\n' +
829
+ '</p>\n' +
830
+ '</div>');
831
+ $dialogConfirm = $('#dialog-confirm-settings');
832
+ $dialogConfirm.dialog({
833
+ autoOpen: false,
834
+ modal: true
835
+ });
836
+ }
837
+ if (typeof buttons === 'function') {
838
+ callback = buttons;
839
+ $dialogConfirm.dialog('option', 'buttons', [
840
+ {
841
+ text: _('Ok'),
842
+ click: function () {
843
+ var cb = $(this).data('callback');
844
+ $(this).data('callback', null);
845
+ $(this).dialog('close');
846
+ cb && cb(true);
847
+ }
848
+ },
849
+ {
850
+ text: _('Cancel'),
851
+ click: function () {
852
+ var cb = $(this).data('callback');
853
+ $(this).data('callback', null);
854
+ $(this).dialog('close');
855
+ cb && cb(false);
856
+ }
857
+ }
858
+
859
+ ]);
860
+ } else if (typeof buttons === 'object') {
861
+ for (var b = 0; b < buttons.length; b++) {
862
+ buttons[b] = {
863
+ text: buttons[b],
864
+ id: 'dialog-confirm-button-' + b,
865
+ click: function (e) {
866
+ var id = parseInt(e.currentTarget.id.substring('dialog-confirm-button-'.length), 10);
867
+ var cb = $(this).data('callback');
868
+ $(this).data('callback', null);
869
+ $(this).dialog('close');
870
+ cb && cb(id);
871
+ }
872
+ }
873
+ }
874
+ $dialogConfirm.dialog('option', 'buttons', buttons);
875
+ }
876
+
877
+ $dialogConfirm.dialog('option', 'title', title || _('Message'));
878
+ $('#dialog-confirm-text-settings').html(message);
879
+ if (icon) {
880
+ $('#dialog-confirm-icon-settings')
881
+ .show()
882
+ .attr('class', '')
883
+ .addClass('ui-icon ui-icon-' + icon);
884
+ } else {
885
+ $('#dialog-confirm-icon-settings').hide();
886
+ }
887
+ $dialogConfirm.data('callback', callback);
888
+ $dialogConfirm.dialog('open');
889
+ }
890
+
891
+ function confirmMessage(message, title, icon, buttons, callback) {
892
+ if (!isMaterialize) {
893
+ return confirmMessageJQ(message, title, icon, buttons, callback);
894
+ }
895
+
896
+ var $dialogConfirm;
897
+ // noinspection JSJQueryEfficiency
898
+ $dialogConfirm = $('#dialog-confirm');
899
+ if (!$dialogConfirm.length) {
900
+ $('body').append(
901
+ '<div class="m"><div id="dialog-confirm" class="modal modal-fixed-footer">' +
902
+ ' <div class="modal-content">' +
903
+ ' <h6 class="dialog-title title"></h6>' +
904
+ ' <p><i class="large material-icons dialog-icon"></i><span class="dialog-text"></span></p>' +
905
+ ' </div>' +
906
+ ' <div class="modal-footer">' +
907
+ ' </div>' +
908
+ '</div></div>'
909
+ );
910
+ $dialogConfirm = $('#dialog-confirm');
911
+ }
912
+ if (typeof buttons === 'function') {
913
+ callback = buttons;
914
+ $dialogConfirm.find('.modal-footer').html(
915
+ '<a class="modal-action modal-close waves-effect waves-green btn-flat translate" data-result="true">' + _('Ok') + '</a>' +
916
+ '<a class="modal-action modal-close waves-effect waves-green btn-flat translate">' + _('Cancel') + '</a>');
917
+ $dialogConfirm.find('.modal-footer .modal-action').on('click', function () {
918
+ var cb = $dialogConfirm.data('callback');
919
+ cb && cb($(this).data('result'));
920
+ });
921
+ } else if (typeof buttons === 'object') {
922
+ var tButtons = '';
923
+ for (var b = buttons.length - 1; b >= 0; b--) {
924
+ tButtons += '<a class="modal-action modal-close waves-effect waves-green btn-flat translate" data-id="' + b + '">' + buttons[b] + '</a>';
925
+ }
926
+ $dialogConfirm.find('.modal-footer').html(tButtons);
927
+ $dialogConfirm.find('.modal-footer .modal-action').on('click', function () {
928
+ var cb = $dialogConfirm.data('callback');
929
+ cb && cb($(this).data('id'));
930
+ });
931
+ }
932
+
933
+ $dialogConfirm.find('.dialog-title').text(title || _('Please confirm'));
934
+ if (icon) {
935
+ $dialogConfirm.find('.dialog-icon')
936
+ .show()
937
+ .html(icon);
938
+ } else {
939
+ $dialogConfirm.find('.dialog-icon').hide();
940
+ }
941
+ if (title) {
942
+ $dialogConfirm.find('.dialog-title').html(title).show();
943
+ } else {
944
+ $dialogConfirm.find('.dialog-title').hide();
945
+ }
946
+ $dialogConfirm.find('.dialog-text').html(message);
947
+ $dialogConfirm.data('callback', callback);
948
+ $dialogConfirm.modal({
949
+ dismissible: false
950
+ }).modal('open');
951
+ }
952
+
953
+ function showError(error) {
954
+ showMessage(_(error), _('Error'), 'error_outline');
955
+ }
956
+
957
+ function showToast(parent, message, icon, duration, isError, classes) {
958
+ if (typeof parent === 'string') {
959
+ classes = isError;
960
+ isError = duration;
961
+ icon = message;
962
+ message = parent;
963
+ parent = null;
964
+ }
965
+ if (parent && parent instanceof jQuery) {
966
+ parent = parent[0];
967
+ }
968
+ classes = classes || [];
969
+
970
+ if (typeof classes === 'string') {
971
+ classes = [classes];
972
+ }
973
+ isError && classes.push('dropZone-error');
974
+
975
+ M.toast({
976
+ parentSelector: parent || $('body')[0],
977
+ html: message + (icon ? '<i class="material-icons">' + icon + '</i>' : ''),
978
+ displayLength: duration || 3000,
979
+ classes: classes
980
+ });
981
+ }
982
+
983
+ function getObject(id, callback) {
984
+ socket.emit('getObject', id, function (err, res) {
985
+ if (!err && res) {
986
+ callback && callback(err, res);
987
+ } else {
988
+ callback && callback(null);
989
+ }
990
+ });
991
+ }
992
+
993
+ function getState(id, callback) {
994
+ socket.emit('getState', id, function (err, res) {
995
+ if (!err && res) {
996
+ callback && callback(err, res);
997
+ } else {
998
+ callback && callback(null);
999
+ }
1000
+ });
1001
+ }
1002
+
1003
+ function getEnums(_enum, callback) {
1004
+ socket.emit('getObjectView', 'system', 'enum', {startkey: 'enum.' + _enum, endkey: 'enum.' + _enum + '.\u9999'}, function (err, res) {
1005
+ if (!err && res) {
1006
+ var _res = {};
1007
+ for (var i = 0; i < res.rows.length; i++) {
1008
+ if (res.rows[i].id !== 'enum.' + _enum) {
1009
+ _res[res.rows[i].id] = res.rows[i].value;
1010
+ }
1011
+ }
1012
+ callback && callback(null, _res);
1013
+ } else {
1014
+ callback && callback(err, []);
1015
+ }
1016
+ });
1017
+ }
1018
+
1019
+ function getGroups(callback) {
1020
+ socket.emit('getObjectView', 'system', 'group', {startkey: 'system.group.', endkey: 'system.group.\u9999'}, function (err, res) {
1021
+ if (!err && res) {
1022
+ var _res = {};
1023
+ for (var i = 0; i < res.rows.length; i++) {
1024
+ _res[res.rows[i].id] = res.rows[i].value;
1025
+ }
1026
+ callback && callback(null, _res);
1027
+ } else {
1028
+ callback && callback(err, []);
1029
+ }
1030
+ });
1031
+ }
1032
+
1033
+ function getUsers(callback) {
1034
+ socket.emit('getObjectView', 'system', 'user', {startkey: 'system.user.', endkey: 'system.user.\u9999'}, function (err, res) {
1035
+ if (!err && res) {
1036
+ var _res = {};
1037
+ for (var i = 0; i < res.rows.length; i++) {
1038
+ _res[res.rows[i].id] = res.rows[i].value;
1039
+ }
1040
+ callback && callback(null, _res);
1041
+ } else {
1042
+ callback && callback(err, []);
1043
+ }
1044
+ });
1045
+ }
1046
+
1047
+ function fillUsers(elemId, current, callback) {
1048
+ getUsers(function (err, users) {
1049
+ // Answer is like
1050
+ // {
1051
+ // "admin": { <<=== This is a common.name!
1052
+ // "type": "user",
1053
+ // "common": {
1054
+ // "name": "admin",
1055
+ // "password": "aaa",
1056
+ // "dontDelete": true,
1057
+ // "enabled": true,
1058
+ // "icon": "data:image/png;base64,xxx",
1059
+ // "color": "#ca0808",
1060
+ // "desc": ""
1061
+ // },
1062
+ // "_id": "system.user.admin"
1063
+ // },
1064
+ // ...
1065
+ // }
1066
+
1067
+ var text = '';
1068
+ // Warning u is name of user and not ID.
1069
+ var len = 'system.user.'.length;
1070
+ for (var u in users) {
1071
+ if (users.hasOwnProperty(u)) {
1072
+ var id = users[u]._id.substring(len);
1073
+ text += '<option value="' + id + '" ' + (current === id ? 'selected' : '') + ' >' + (u ? u[0].toUpperCase() + u.substring(1) : '__noname__') + '</option>\n';
1074
+ }
1075
+ }
1076
+ $(elemId).html(text);
1077
+ if (isMaterialize) {
1078
+ $(elemId).select();
1079
+ }
1080
+ });
1081
+ }
1082
+
1083
+ function getIPs(host, callback) {
1084
+ if (typeof host === 'function') {
1085
+ callback = host;
1086
+ host = null;
1087
+ }
1088
+
1089
+ socket.emit('getHostByIp', host || common.host, function (ip, _host) {
1090
+ if (_host) {
1091
+ host = _host;
1092
+ var IPs4 = [{name: '[IPv4] 0.0.0.0 - ' + _('Listen on all IPs'), address: '0.0.0.0', family: 'ipv4'}];
1093
+ var IPs6 = [{name: '[IPv6] ::', address: '::', family: 'ipv6'}];
1094
+ if (host.native.hardware && host.native.hardware.networkInterfaces) {
1095
+ for (var eth in host.native.hardware.networkInterfaces) {
1096
+ if (!host.native.hardware.networkInterfaces.hasOwnProperty(eth)) {
1097
+ continue;
1098
+ }
1099
+ for (var num = 0; num < host.native.hardware.networkInterfaces[eth].length; num++) {
1100
+ if (host.native.hardware.networkInterfaces[eth][num].family !== 'IPv6') {
1101
+ IPs4.push({name: '[' + host.native.hardware.networkInterfaces[eth][num].family + '] ' + host.native.hardware.networkInterfaces[eth][num].address + ' - ' + eth, address: host.native.hardware.networkInterfaces[eth][num].address, family: 'ipv4'});
1102
+ } else {
1103
+ IPs6.push({name: '[' + host.native.hardware.networkInterfaces[eth][num].family + '] ' + host.native.hardware.networkInterfaces[eth][num].address + ' - ' + eth, address: host.native.hardware.networkInterfaces[eth][num].address, family: 'ipv6'});
1104
+ }
1105
+ }
1106
+ }
1107
+ }
1108
+ for (var i = 0; i < IPs6.length; i++) {
1109
+ IPs4.push(IPs6[i]);
1110
+ }
1111
+ callback(IPs4);
1112
+ }
1113
+ });
1114
+ }
1115
+
1116
+ function fillSelectIPs(id, actualAddr, noIPv4, noIPv6, callback) {
1117
+ getIPs(function (ips) {
1118
+ var str = '';
1119
+ for (var i = 0; i < ips.length; i++) {
1120
+ if (noIPv4 && ips[i].family === 'ipv4') {
1121
+ continue;
1122
+ }
1123
+ if (noIPv6 && ips[i].family === 'ipv6') {
1124
+ continue;
1125
+ }
1126
+ str += '<option value="' + ips[i].address + '" ' + ((ips[i].address === actualAddr) ? 'selected' : '') + '>' + ips[i].name + '</option>';
1127
+ }
1128
+
1129
+ $(id).html(str);
1130
+ if (isMaterialize) {
1131
+ $(id).select();
1132
+ }
1133
+ if (typeof callback === 'function') {
1134
+ callback();
1135
+ }
1136
+ });
1137
+ }
1138
+
1139
+ function sendTo(_adapter_instance, command, message, callback) {
1140
+ socket.emit('sendTo', _adapter_instance || (adapter + '.' + instance), command, message, callback);
1141
+ }
1142
+
1143
+ function sendToHost(host, command, message, callback) {
1144
+ socket.emit('sendToHost', host || common.host, command, message, callback);
1145
+ }
1146
+
1147
+ function getInterfaces(onlyNames, callback) {
1148
+ if (typeof onlyNames === 'function') {
1149
+ callback = onlyNames;
1150
+ onlyNames = false;
1151
+ }
1152
+
1153
+ socket.emit('sendToHost', common.host, 'getInterfaces', null, function (result) {
1154
+ if (result && result.result) {
1155
+ if (onlyNames) {
1156
+ callback(null, Object.keys(result.result));
1157
+ } else {
1158
+ callback(null, result);
1159
+ }
1160
+ } else {
1161
+ callback((result && result.error) || 'cannot read');
1162
+ }
1163
+ });
1164
+ }
1165
+
1166
+ // fills select with names of the certificates and preselect it
1167
+ function fillSelectCertificates(id, type, actualValued) {
1168
+ var str = '<option value="">' + _('none') + '</option>';
1169
+ for (var i = 0; i < certs.length; i++) {
1170
+ if (certs[i].type && certs[i].type !== type) {
1171
+ continue;
1172
+ }
1173
+ str += '<option value="' + certs[i].name + '" ' + ((certs[i].name === actualValued) ? 'selected' : '') + '>' + certs[i].name + '</option>';
1174
+ }
1175
+
1176
+ $(id).html(str);
1177
+ if (isMaterialize) {
1178
+ $(id).select();
1179
+ }
1180
+
1181
+ }
1182
+
1183
+ function getAdapterInstances(_adapter, callback) {
1184
+ if (typeof _adapter === 'function') {
1185
+ callback = _adapter;
1186
+ _adapter = null;
1187
+ }
1188
+
1189
+ socket.emit('getObjectView', 'system', 'instance', {startkey: 'system.adapter.' + (_adapter || adapter), endkey: 'system.adapter.' + (_adapter || adapter) + '.\u9999'}, function (err, doc) {
1190
+ if (err) {
1191
+ callback && callback([]);
1192
+ } else {
1193
+ if (doc.rows.length === 0) {
1194
+ callback && callback([]);
1195
+ } else {
1196
+ var res = [];
1197
+ for (var i = 0; i < doc.rows.length; i++) {
1198
+ res.push(doc.rows[i].value);
1199
+ }
1200
+ callback && callback(res);
1201
+ }
1202
+ }
1203
+
1204
+ });
1205
+ }
1206
+
1207
+ function getExtendableInstances(_adapter, callback) {
1208
+ if (typeof _adapter === 'function') {
1209
+ callback = _adapter;
1210
+ _adapter = null;
1211
+ }
1212
+
1213
+ socket.emit('getObjectView', 'system', 'instance', null, function (err, doc) {
1214
+ if (err) {
1215
+ callback && callback ([]);
1216
+ } else {
1217
+ if (doc.rows.length === 0) {
1218
+ callback && callback ([]);
1219
+ } else {
1220
+ var res = [];
1221
+ for (var i = 0; i < doc.rows.length; i++) {
1222
+ if (doc.rows[i].value.common.webExtendable) {
1223
+ res.push(doc.rows[i].value);
1224
+ }
1225
+ }
1226
+ callback && callback (res);
1227
+ }
1228
+ }
1229
+ });
1230
+ }
1231
+
1232
+ function getIsAdapterAlive(_adapter, callback) {
1233
+ if (typeof _adapter === 'function') {
1234
+ callback = _adapter;
1235
+ _adapter = null;
1236
+ }
1237
+ getState('system.adapter.' + (_adapter || adapter) + '.' + instance + '.alive', function (err, obj) {
1238
+ if (!obj || !obj.val) {
1239
+ callback(false);
1240
+ } else {
1241
+ callback(true);
1242
+ }
1243
+ });
1244
+ }
1245
+
1246
+ // Adds one entry to the created with editTable table
1247
+ // tabId - the id of the table used by editTable
1248
+ // value - is one object to add in form {ip: '3.3.3.3', room: 'enum.room.bla3', desc: 'Bla3'}
1249
+ // $grid - [optional] - object returned by editTable to speed up the addition
1250
+ // _isInitial - [optional] - if it is initial fill of the table. To not trigger the onChange
1251
+ function addToTable(tabId, value, $grid, _isInitial) {
1252
+ $grid = $grid || $('#' + tabId);
1253
+ var obj = {_id: $grid[0]._maxIdx++};
1254
+ var cols = $grid[0]._cols;
1255
+
1256
+ for (var i = 0; i < cols.length; i++) {
1257
+ if (cols[i] === 'room') {
1258
+ obj[cols[i]] = ($grid[0]._rooms[value[cols[i]]]) ? $grid[0]._rooms[value[cols[i]]].common.name : value[cols[i]];
1259
+ } else {
1260
+ obj[cols[i]] = value[cols[i]];
1261
+ }
1262
+ }
1263
+ obj._commands =
1264
+ '<button data-' + tabId + '-id="' + obj._id + '" class="' + tabId + '-edit-submit">' + _('edit') + '</button>' +
1265
+ '<button data-' + tabId + '-id="' + obj._id + '" class="' + tabId + '-delete-submit">' + _('delete') + '</button>' +
1266
+ '<button data-' + tabId + '-id="' + obj._id + '" class="' + tabId + '-ok-submit" style="display:none">' + _('ok') + '</button>' +
1267
+ '<button data-' + tabId + '-id="' + obj._id + '" class="' + tabId + '-cancel-submit" style="display:none">' + _('cancel') + '</button>';
1268
+
1269
+ $grid.jqGrid('addRowData', tabId + '_' + obj._id, obj);
1270
+
1271
+ _editInitButtons($grid, tabId, obj._id);
1272
+
1273
+ if (!_isInitial && $grid[0]._onChange) $grid[0]._onChange('add', value);
1274
+ }
1275
+
1276
+ function _editInitButtons($grid, tabId, objId) {
1277
+ var search = objId ? '[data-' + tabId + '-id="' + objId + '"]' : '';
1278
+
1279
+ $('.' + tabId + '-edit-submit' + search).off('click').button({
1280
+ icons: {primary: 'ui-icon-pencil'},
1281
+ text: false
1282
+ }).on('click', function () {
1283
+ var id = $(this).attr('data-' + tabId + '-id');
1284
+
1285
+ $('.' + tabId + '-edit-submit').hide();
1286
+ $('.' + tabId + '-delete-submit').hide();
1287
+ $('.' + tabId + '-ok-submit[data-' + tabId + '-id="' + id + '"]').show();
1288
+ $('.' + tabId + '-cancel-submit[data-' + tabId + '-id="' + id + '"]').show();
1289
+
1290
+ $grid.jqGrid('editRow', tabId + '_' + id, {url: 'clientArray'});
1291
+ if ($grid[0]._edited.indexOf(id) === -1) {
1292
+ $grid[0]._edited.push(id);
1293
+ }
1294
+ parent.postMessage('change', '*');
1295
+ changed = true;
1296
+ var $navButtons = $('.dialog-config-buttons');
1297
+ $navButtons.find('.btn-save').removeClass('disabled');
1298
+ $navButtons.find('.btn-save-close').removeClass('disabled');
1299
+ if (onChangeSupported) {
1300
+ $navButtons.find('.btn-cancel').find('span').html(_('cancel'));
1301
+ }
1302
+ }).css({'height': '18px', width: '22px'});
1303
+
1304
+ $('.' + tabId + '-delete-submit' + search).off('click').button({
1305
+ icons: {primary: 'ui-icon-trash'},
1306
+ text: false
1307
+ }).on('click', function () {
1308
+ var id = $(this).attr('data-' + tabId + '-id');
1309
+ $grid.jqGrid('delRowData', tabId + '_' + id);
1310
+ parent.postMessage('change', '*');
1311
+ changed = true;
1312
+ var $navButtons = $('.dialog-config-buttons');
1313
+ $navButtons.find('.btn-save').removeClass('disabled');
1314
+ $navButtons.find('.btn-save-close').removeClass('disabled');
1315
+ if (onChangeSupported) {
1316
+ $navButtons.find('.btn-cancel').find('span').html(_('cancel'));
1317
+ }
1318
+
1319
+ var pos = $grid[0]._edited.indexOf(id);
1320
+ if (pos !== -1) {
1321
+ $grid[0]._edited.splice(pos, 1);
1322
+ }
1323
+ if ($grid[0]._onChange) $grid[0]._onChange('del', id);
1324
+ }).css({'height': '18px', width: '22px'});
1325
+
1326
+ $('.' + tabId + '-ok-submit' + search).off('click').button({
1327
+ icons: {primary: 'ui-icon-check'},
1328
+ text: false
1329
+ }).on('click', function () {
1330
+ var id = $(this).attr('data-' + tabId + '-id');
1331
+
1332
+ $('.' + tabId + '-edit-submit').show();
1333
+ $('.' + tabId + '-delete-submit').show();
1334
+ $('.' + tabId + '-ok-submit').hide();
1335
+ $('.' + tabId + '-cancel-submit').hide();
1336
+
1337
+ $grid.jqGrid('saveRow', tabId + '_' + id, {url: 'clientArray'});
1338
+ parent.postMessage('change', '*');
1339
+ changed = true;
1340
+ var $navButtons = $('.dialog-config-buttons');
1341
+ $navButtons.find('.btn-save').removeClass('disabled');
1342
+ $navButtons.find('.btn-save-close').removeClass('disabled');
1343
+ if (onChangeSupported) {
1344
+ $navButtons.find('.btn-cancel').find('span').html(_('cancel'));
1345
+ }
1346
+
1347
+ var pos = $grid[0]._edited.indexOf(id);
1348
+ if (pos !== -1) {
1349
+ $grid[0]._edited.splice(pos, 1);
1350
+ }
1351
+ if ($grid[0]._onChange) $grid[0]._onChange('changed', $grid.jqGrid('getRowData', tabId + '_' + id));
1352
+ }).css({'height': '18px', width: '22px'});
1353
+
1354
+ $('.' + tabId + '-cancel-submit' + search).off('click').button({
1355
+ icons: {primary: 'ui-icon-close'},
1356
+ text: false
1357
+ }).on('click', function () {
1358
+ var id = $(this).attr('data-' + tabId + '-id');
1359
+
1360
+ $('.' + tabId + '-edit-submit').show();
1361
+ $('.' + tabId + '-delete-submit').show();
1362
+ $('.' + tabId + '-ok-submit').hide();
1363
+ $('.' + tabId + '-cancel-submit').hide();
1364
+
1365
+ $grid.jqGrid('restoreRow', tabId + '_' + id, false);
1366
+ var pos = $grid[0]._edited.indexOf(id);
1367
+ if (pos !== -1) {
1368
+ $grid[0]._edited.splice(pos, 1);
1369
+ }
1370
+ }).css({'height': '18px', width: '22px'});
1371
+ }
1372
+
1373
+ function _editTable(tabId, cols, values, rooms, top, onChange) {
1374
+ var title = 'Device list';
1375
+ if (typeof tabId === 'object') {
1376
+ cols = tabId.cols;
1377
+ values = tabId.values;
1378
+ rooms = tabId.rooms;
1379
+ top = tabId.top;
1380
+ onChange = tabId.onChange;
1381
+ if (tabId.title) title = tabId.title;
1382
+ tabId = tabId.tabId;
1383
+ }
1384
+
1385
+ initGridLanguage(systemLang);
1386
+ var colNames = [];
1387
+ var colModel = [];
1388
+ var $grid = $('#' + tabId);
1389
+ var room;
1390
+
1391
+ colNames.push('id');
1392
+ colModel.push({
1393
+ name: '_id',
1394
+ index: '_id',
1395
+ hidden: true
1396
+ });
1397
+ for (var i = 0; i < cols.length; i++) {
1398
+ var width = null;
1399
+ var checkbox = null;
1400
+
1401
+ if (typeof cols[i] === 'object') {
1402
+ width = cols[i].width;
1403
+ if (cols[i].checkbox) {
1404
+ checkbox = true;
1405
+ }
1406
+ cols[i] = cols[i].name;
1407
+ }
1408
+ colNames.push(_(cols[i]));
1409
+ var _obj = {
1410
+ name: cols[i],
1411
+ index: cols[i],
1412
+ // width: 160,
1413
+ editable: true
1414
+ };
1415
+ if (width) {
1416
+ _obj.width = width;
1417
+ }
1418
+ if (checkbox) {
1419
+ _obj.edittype = 'checkbox';
1420
+ _obj.editoptions = {value: 'true:false'};
1421
+ }
1422
+
1423
+ if (cols[i] === 'room') {
1424
+ var list = {'': _('none')};
1425
+ for (room in rooms) {
1426
+ list[room] = _(translateName(rooms[room].common.name));
1427
+ }
1428
+ _obj.stype = 'select';
1429
+ _obj.edittype = 'select';
1430
+ _obj.editoptions = {value: list};
1431
+ _obj.searchoptions = {
1432
+ sopt: ['eq'],
1433
+ value: ':' + _('all')
1434
+ };
1435
+ for (room in rooms) {
1436
+ _obj.searchoptions.value += ';' + _(translateName(rooms[room].common.name)) + ':' + _(translateName(rooms[room].common.name));
1437
+ }
1438
+ }
1439
+ colModel.push(_obj);
1440
+ }
1441
+ colNames.push('');
1442
+ colModel.push({name: '_commands', index: '_commands', width: 50, editable: false, align: 'center', search: false});
1443
+
1444
+ $grid[0]._cols = cols;
1445
+ $grid[0]._rooms = rooms;
1446
+ $grid[0]._maxIdx = 0;
1447
+ $grid[0]._top = top;
1448
+ $grid[0]._edited = [];
1449
+ $grid[0]._onChange = onChange;
1450
+
1451
+ $grid.jqGrid({
1452
+ datatype: 'local',
1453
+ colNames: colNames,
1454
+ colModel: colModel,
1455
+ width: 800,
1456
+ height: 330,
1457
+ pager: $('#pager-' + tabId),
1458
+ rowNum: 1000,
1459
+ rowList: [1000],
1460
+ ondblClickRow: function (rowid) {
1461
+ var id = rowid.substring((tabId + '_').length);
1462
+ $('.' + tabId + '-edit-submit').hide();
1463
+ $('.' + tabId + '-delete-submit').hide();
1464
+ $('.' + tabId + '-ok-submit[data-' + tabId + '-id="' + id + '"]').show();
1465
+ $('.' + tabId + '-cancel-submit[data-' + tabId + '-id="' + id + '"]').show();
1466
+ $grid.jqGrid('editRow', rowid, {url: 'clientArray'});
1467
+ if ($grid[0]._edited.indexOf(id) === -1) $grid[0]._edited.push(id);
1468
+ parent.postMessage('change', '*');
1469
+ changed = true;
1470
+ var $navButtons = $('.dialog-config-buttons');
1471
+ $navButtons.find('.btn-save').removeClass('disabled');
1472
+ $navButtons.find('.btn-save-close').removeClass('disabled');
1473
+ if (onChangeSupported) {
1474
+ $navButtons.find('.btn-cancel').find('span').html(_('cancel'));
1475
+ }
1476
+ },
1477
+ sortname: 'id',
1478
+ sortorder: 'desc',
1479
+ viewrecords: false,
1480
+ pgbuttons: false,
1481
+ pginput: false,
1482
+ pgtext: false,
1483
+ caption: _(title),
1484
+ ignoreCase: true,
1485
+ loadComplete: function () {
1486
+ _editInitButtons($grid, tabId);
1487
+ },
1488
+ onSortCol: function () {
1489
+ parent.postMessage('change', '*');
1490
+ changed = true;
1491
+ var $navButtons = $('.dialog-config-buttons');
1492
+ $navButtons.find('.btn-save').removeClass('disabled');
1493
+ $navButtons.find('.btn-save-close').removeClass('disabled');
1494
+ if (onChangeSupported) {
1495
+ $navButtons.find('.btn-cancel').find('span').html(_('cancel'));
1496
+ }
1497
+ }
1498
+ }).jqGrid('filterToolbar', {
1499
+ defaultSearch: 'cn',
1500
+ autosearch: true,
1501
+ searchOnEnter: false,
1502
+ enableClear: false,
1503
+ afterSearch: function () {
1504
+ _editInitButtons($grid, tabId);
1505
+ }
1506
+ });
1507
+
1508
+ $('#pager-' + tabId + '_center').hide();
1509
+
1510
+ if ($('#pager-' + tabId).length) {
1511
+ $grid.navGrid('#pager-' + tabId, {
1512
+ search: false,
1513
+ edit: false,
1514
+ add: false,
1515
+ del: false,
1516
+ refresh: false
1517
+ }).jqGrid('navButtonAdd', '#pager-' + tabId, {
1518
+ caption: '',
1519
+ buttonicon: 'ui-icon-plus',
1520
+ onClickButton: function () {
1521
+ // Find new unique name
1522
+ var found;
1523
+ var newText = _('New');
1524
+ var ids = $grid.jqGrid('getDataIDs');
1525
+ var idx = 1;
1526
+ var obj;
1527
+ do {
1528
+ found = true;
1529
+ for (var _id = 0; _id < ids.length; _id++) {
1530
+ obj = $grid.jqGrid('getRowData', ids[_id]);
1531
+ if (obj && obj[$grid[0]._cols[0]] === newText + idx) {
1532
+ idx++;
1533
+ found = false;
1534
+ break;
1535
+ }
1536
+ }
1537
+ } while (!found);
1538
+
1539
+ obj = {};
1540
+ for (var t = 0; t < $grid[0]._cols.length; t++) {
1541
+ obj[$grid[0]._cols[t]] = '';
1542
+ }
1543
+ obj[$grid[0]._cols[0]] = newText + idx;
1544
+ parent.postMessage('change', '*');
1545
+ changed = true;
1546
+ var $navButtons = $('.dialog-config-buttons');
1547
+ $navButtons.find('.btn-save').removeClass('disabled');
1548
+ $navButtons.find('.btn-save-close').removeClass('disabled');
1549
+ if (onChangeSupported) {
1550
+ $navButtons.find('.btn-cancel').find('span').html(_('cancel'));
1551
+ }
1552
+
1553
+ addToTable(tabId, obj, $grid);
1554
+ },
1555
+ position: 'first',
1556
+ id: 'add-cert',
1557
+ title: _('new device'),
1558
+ cursor: 'pointer'
1559
+ });
1560
+ }
1561
+
1562
+ if (values) {
1563
+ for (var u = 0; u < values.length; u++) {
1564
+ addToTable(tabId, values[u], $grid, true);
1565
+ }
1566
+ }
1567
+ $(window).on('resize', function () {
1568
+ $grid.setGridHeight($(this).height() - top).setGridWidth($(this).width() - 10);
1569
+ });
1570
+ $(window).trigger('resize');
1571
+
1572
+ // hide scrollbar
1573
+ $('.ui-jqgrid-bdiv').css({'overflow-x': 'hidden'});
1574
+
1575
+ return $grid;
1576
+ }
1577
+
1578
+ // converts "enum.room.Sleeping_room" to "Sleeping room"
1579
+ // As input gets the list from getEnum
1580
+ function enumName2Id(enums, name) {
1581
+ name = name.toLowerCase();
1582
+ for (var enumId in enums) {
1583
+ if (!enums.hasOwnProperty(enumId)) {
1584
+ continue;
1585
+ }
1586
+
1587
+ if (enums[enumId] && enums[enumId].common && enums[enumId].common.name) {
1588
+ if (typeof enums[enumId].common.name === 'object') {
1589
+ for (var lang in enums[enumId].common.name) {
1590
+ if (enums[enumId].common.name.hasOwnProperty(lang) && enums[enumId].common.name[lang].toLowerCase() === name) {
1591
+ return enumId;
1592
+ }
1593
+ }
1594
+ } else {
1595
+ if (enums[enumId].common.name && enums[enumId].common.name.toLowerCase() === name) {
1596
+ return enumId;
1597
+ }
1598
+ }
1599
+ }
1600
+ if (enums[enumId] && enums[enumId].name) {
1601
+ if (typeof enums[enumId].name === 'object') {
1602
+ for (var lang in enums[enumId].name) {
1603
+ if (enums[enumId].name.hasOwnProperty(lang) && enums[enumId].name[lang].toLowerCase() === name) {
1604
+ return enumId;
1605
+ }
1606
+ }
1607
+ } else {
1608
+ if (enums[enumId].name.toLowerCase() === name) {
1609
+ return enumId;
1610
+ }
1611
+ }
1612
+ }
1613
+ }
1614
+ return '';
1615
+ }
1616
+
1617
+ // Creates edit table for any configuration array
1618
+ // tabId - is id of table where the jqGrid must be created. E.g: <table id="devices"></table><div id="pager-devices"></div>
1619
+ // cols - array with names of the properties of entry. E.g: ['ip', 'room', 'desc']
1620
+ // if column has name room, for that will be automatically the room enums loaded and shown
1621
+ // values - array with values in form [{ip: '1.1.1.1', room: 'enum.room.bla1', desc: 'Bla1'}, {ip: '2.2.2.2', room: 'enum.room.bla2', desc: 'Bla2'}
1622
+ // top - top position of the table to set the height of the table automatically. Table must be always as last on the page.
1623
+ // onChange - callback called if something is changed in the table
1624
+ //
1625
+ // returns the jquery object of $('#tabId')
1626
+ // To extract data from table
1627
+ function editTable(tabId, cols, values, top, onChange) {
1628
+ if (typeof tabId === 'object') {
1629
+ cols = tabId.cols;
1630
+ }
1631
+
1632
+ if (cols.indexOf('room') !== -1) {
1633
+ getEnums('rooms', function (err, list) {
1634
+ return _editTable(tabId, cols, values, list, top, onChange);
1635
+ });
1636
+ } else {
1637
+ return _editTable(tabId, cols, values, null, top, onChange);
1638
+ }
1639
+ }
1640
+
1641
+ // Extract edited array from table
1642
+ // tabId - is id of table where the jqGrid must be created. E.g: <table id="devices"></table><div id="pager-devices"></div>
1643
+ // cols - array with names of the properties of entry. E.g: ['ip', 'room', 'desc']
1644
+ //
1645
+ // Returns array with values
1646
+ function getTableResult(tabId, cols) {
1647
+ var $grid = $('#' + tabId);
1648
+ for (var j = 0; j < $grid[0]._edited.length; j++) {
1649
+ $grid.jqGrid('saveRow', tabId + '_' + $grid[0]._edited[j], {url: 'clientArray'});
1650
+ }
1651
+
1652
+ $('.' + tabId + '-edit-submit').show();
1653
+ $('.' + tabId + '-delete-submit').show();
1654
+ $('.' + tabId + '-ok-submit').hide();
1655
+ $('.' + tabId + '-cancel-submit').hide();
1656
+
1657
+ var data = $grid.jqGrid('getRowData');
1658
+ var res = [];
1659
+ for (var i = 0; i < data.length; i++) {
1660
+ var obj = {};
1661
+ for (var z = 0; z < cols.length; z++) {
1662
+ if (cols[z] === 'room') {
1663
+ obj[cols[z]] = enumName2Id($grid[0]._rooms, data[i][cols[z]]);
1664
+ } else {
1665
+ obj[cols[z]] = data[i][cols[z]];
1666
+ }
1667
+ }
1668
+ res.push(obj);
1669
+ }
1670
+ return res;
1671
+ }
1672
+
1673
+ // Show select ID dialog
1674
+ // Required in index.html
1675
+ // <link type="text/css" rel="stylesheet" href="../../lib/css/themes/jquery-ui/default/jquery-ui.min.css">
1676
+ // <link type="text/css" rel="stylesheet" href="../../lib/css/fancytree/ui.fancytree.min.css"/>
1677
+ // <link rel="stylesheet" type="text/css" href="../../lib/css/iob/selectID.css"/>
1678
+ //
1679
+ // <script type="text/javascript" src="../../lib/js/jquery-ui-1.10.3.full.min.js"></script>
1680
+ // <script type="text/javascript" src="../../lib/js/jquery.fancytree-all.min.js"></script>
1681
+ // <script type="text/javascript" src="../../lib/js/selectID.js"></script>
1682
+ function showSelectIdDialog(val, callback) {
1683
+ // see cloud, tileboard adapters for details
1684
+ var $dialog = $('#dialog-select-member');
1685
+ if (!$dialog.length) {
1686
+ $('body').append('<div id="dialog-select-member" style="display: none; position: absolute; background: white"></div>');
1687
+ $dialog = $('#dialog-select-member');
1688
+ }
1689
+ if (!window.tableSelectId) {
1690
+ socket.emit('getObjects', function (err, res) {
1691
+ if (!err && res) {
1692
+ window.tableSelectId = $dialog.selectId('init', {
1693
+ noMultiselect: true,
1694
+ objects: res,
1695
+ dialogHeight: '420px!important',//'calc(100% - 100px) !important',
1696
+ imgPath: '../../lib/css/fancytree/',
1697
+ filter: {type: 'state'},
1698
+ name: 'table-select-state',
1699
+ texts: {
1700
+ select: _('Select'),
1701
+ cancel: _('Cancel'),
1702
+ all: _('All'),
1703
+ id: _('ID'),
1704
+ name: _('Name'),
1705
+ role: _('Role'),
1706
+ room: _('Room'),
1707
+ value: _('Value'),
1708
+ selectid: _('Select ID'),
1709
+ from: _('From'),
1710
+ lc: _('Last changed'),
1711
+ ts: _('Time stamp'),
1712
+ wait: _('Processing...'),
1713
+ ack: _('Acknowledged'),
1714
+ selectAll: _('Select all'),
1715
+ unselectAll: _('Deselect all'),
1716
+ invertSelection: _('Invert selection')
1717
+ },
1718
+ columns: ['image', 'name', 'role', 'room']
1719
+ });
1720
+ window.tableSelectId.selectId('show', val, function (newId, oldId) {
1721
+ newId && callback && callback(newId, oldId || '');
1722
+ });
1723
+ }
1724
+ });
1725
+ } else {
1726
+ window.tableSelectId.selectId('show', val, function (newId, oldId) {
1727
+ newId && callback && callback(newId, oldId || '');
1728
+ });
1729
+ }
1730
+ }
1731
+
1732
+ /*
1733
+ <div id="values">
1734
+ <button class="table-button-add" style="margin-left: 10px"></button>
1735
+ <table class="table-values" style="width: 100%; calc(100% - 200px)">
1736
+ <thead>
1737
+ <tr>
1738
+ <th data-name="regex" style="width: 30%" class="translate">Context</th>
1739
+ <th data-name="room" class="translate" data-type="select">Room</th>
1740
+ <th data-name="aaa" class="translate" data-options="1/A;2/B;3/C;4" data-type="select">Room</th>
1741
+ <th data-name="enabled" class="translate" data-type="checkbox">Enabled</th>
1742
+ <th data-buttons="delete up down copy" style="width: 32px"></th>
1743
+ </tr>
1744
+ </thead>
1745
+ </table>
1746
+ </div>
1747
+ */
1748
+
1749
+ /**
1750
+ * Create edit table from javascript array.
1751
+ *
1752
+ * This function creates a html edit table.
1753
+ *
1754
+ * <pre><code>
1755
+ * <div id="values" style="width: 100%; height: calc(100% - 205px)">
1756
+ * <button class="table-button-add" style="margin-left: 10px"></button>
1757
+ * <div style="width: 100%; height: calc(100% - 30px); overflow: auto;">
1758
+ * <table class="table-values" style="width: 100%;">
1759
+ * <thead>
1760
+ * <tr>
1761
+ * <th data-name="_index" style="width: 30px" data-style="width: 100%; text-align: right">Context</th>
1762
+ * <th data-name="regex" class="translate" style="width: 30%" data-style="text-align: right">Context</th>
1763
+ * <th data-name="room" class="translate" data-type="select">Room</th>
1764
+ * <th data-name="aaa" class="translate" data-options="1/A;2/B;3/C;4" data-type="select">Room</th>
1765
+ * <th data-name="id" class="translate" data-type="OID">Object ID</th>
1766
+ * <th data-name="enabled" class="translate" data-type="checkbox" data-default="true">Enabled</th>
1767
+ * <th data-buttons="delete up down copy" style="width: 32px"></th>
1768
+ * </tr>
1769
+ * </thead>
1770
+ * </table>
1771
+ * </div>
1772
+ * </div>
1773
+ * <pre><code>
1774
+ *
1775
+ * @param {string} divId name of the html element (or empty).
1776
+ * @param {string} values data array
1777
+ * @param {function} onChange this function will be called if something changed
1778
+ * @param {function} onReady called, when the table is ready (may be to modify some elements of it)
1779
+ * @param {number} maxRaw maximal number of rows
1780
+ * @return {object} array with values
1781
+ */
1782
+ function values2table(divId, values, onChange, onReady, maxRaw) {
1783
+ if (typeof values === 'function') {
1784
+ typeof onChange === 'number' ? maxRaw = onChange : maxRaw = null;
1785
+ onChange = values;
1786
+ values = divId;
1787
+ divId = '';
1788
+ }
1789
+
1790
+ if (typeof onReady === 'number') {
1791
+ maxRaw = onReady;
1792
+ onReady = null;
1793
+ } else if (typeof maxRaw === 'undefined') {
1794
+ maxRaw = null;
1795
+ }
1796
+
1797
+ values = values || [];
1798
+ var names = [];
1799
+ var $div;
1800
+ if (!divId) {
1801
+ $div = $('body');
1802
+ } else {
1803
+ $div = $('#' + divId);
1804
+ }
1805
+ var $add = $div.find('.table-button-add');
1806
+ $add.data('raw', values.length);
1807
+
1808
+ if (maxRaw) {
1809
+ $add.data('maxraw', maxRaw);
1810
+ }
1811
+
1812
+ if (!$add.data('inited')) {
1813
+ $add.data('inited', true);
1814
+
1815
+ var addText = $add.text();
1816
+
1817
+ if (!isMaterialize) {
1818
+ $add.button({
1819
+ icons: {primary: 'ui-icon-plus'},
1820
+ text: !!addText,
1821
+ label: addText ? _(addText) : undefined
1822
+ });
1823
+ }
1824
+
1825
+ $add.on('click', function () {
1826
+ if (!$add.data('maxraw') || ($add.data('raw') < $add.data('maxraw'))) {
1827
+ var $table = $div.find('.table-values');
1828
+ var values = $table.data('values');
1829
+ var names = $table.data('names');
1830
+ var obj = {};
1831
+ for (var i = 0; i < names.length; i++) {
1832
+ if (names[i]) {
1833
+ obj[names[i].name] = names[i].def;
1834
+ }
1835
+ }
1836
+ values.push(obj);
1837
+ onChange && onChange();
1838
+ setTimeout(function () {
1839
+ values2table(divId, values, onChange, onReady);
1840
+ }, 100);
1841
+ $add.data('raw', $add.data('raw') + 1);
1842
+ } else {
1843
+ confirmMessage(_('maxTableRaw') + ': ' + $add.data('maxraw'), _('maxTableRawInfo'), 'alert', ['Ok']);
1844
+ }
1845
+ });
1846
+ }
1847
+
1848
+ if (values) {
1849
+ var buttons = [];
1850
+ var $table = $div.find('.table-values');
1851
+ $table.data('values', values);
1852
+
1853
+ // load rooms
1854
+ if (!$table.data('rooms') && $table.find('th[data-name="room"]').length) {
1855
+ getEnums('rooms', function (err, list) {
1856
+ var result = {};
1857
+ var trRooms = _('nonerooms');
1858
+ if (trRooms !== 'nonerooms') {
1859
+ result[_('none')] = trRooms;
1860
+ } else {
1861
+ result[_('none')] = '';
1862
+ }
1863
+ var nnames = [];
1864
+ for (var n in list) {
1865
+ if (list.hasOwnProperty(n)) {
1866
+ nnames.push(n);
1867
+ }
1868
+ }
1869
+ nnames.sort(function (a, b) {
1870
+ a = a.toLowerCase();
1871
+ b = b.toLowerCase();
1872
+ if (a > b) {
1873
+ return 1;
1874
+ } else if (a < b) {
1875
+ return -1;
1876
+ } else {
1877
+ return 0;
1878
+ }
1879
+ });
1880
+
1881
+ for (var l = 0; l < nnames.length; l++) {
1882
+ result[nnames[l]] = list[nnames[l]].common.name || l;
1883
+ if (typeof result[nnames[l]] === 'object') {
1884
+ result[nnames[l]] = result[nnames[l]][systemLang] || result[nnames[l]].en;
1885
+ }
1886
+ }
1887
+ $table.data('rooms', result);
1888
+ values2table(divId, values, onChange, onReady);
1889
+ });
1890
+ return;
1891
+ }
1892
+
1893
+ // load functions
1894
+ if (!$table.data('functions') && $table.find('th[data-name="func"]').length) {
1895
+ getEnums('functions', function (err, list) {
1896
+ var result = {};
1897
+ var trFuncs = _('nonefunctions');
1898
+ if (trFuncs !== 'nonefunctions') {
1899
+ result[_('none')] = trFuncs;
1900
+ } else {
1901
+ result[_('none')] = '';
1902
+ }
1903
+
1904
+ var nnames = [];
1905
+ for (var n in list) {
1906
+ if (list.hasOwnProperty(n)) {
1907
+ nnames.push(n);
1908
+ }
1909
+ }
1910
+ nnames.sort(function (a, b) {
1911
+ a = a.toLowerCase();
1912
+ b = b.toLowerCase();
1913
+ if (a > b) {
1914
+ return 1;
1915
+ } else if (a < b) {
1916
+ return -1;
1917
+ } else {
1918
+ return 0;
1919
+ }
1920
+ });
1921
+
1922
+ for (var l = 0; l < nnames.length; l++) {
1923
+ result[nnames[l]] = list[nnames[l]].common.name || l;
1924
+ if (typeof result[nnames[l]] === 'object') {
1925
+ result[nnames[l]] = result[nnames[l]][systemLang] || result[nnames[l]].en;
1926
+ }
1927
+ }
1928
+ $table.data('functions', result);
1929
+ values2table(divId, values, onChange, onReady);
1930
+ });
1931
+ return;
1932
+ }
1933
+
1934
+ $table.find('th').each(function () {
1935
+ var name = $(this).data('name');
1936
+ if (name) {
1937
+ var obj = {
1938
+ name: name,
1939
+ type: $(this).data('type') || 'text',
1940
+ def: $(this).data('default'),
1941
+ style: $(this).data('style'),
1942
+ tdstyle: $(this).data('tdstyle')
1943
+ };
1944
+ if (obj.type === 'checkbox') {
1945
+ if (obj.def === 'false') {
1946
+ obj.def = false;
1947
+ }
1948
+ if (obj.def === 'true') {
1949
+ obj.def = true;
1950
+ }
1951
+ obj.def = !!obj.def;
1952
+ } else if (obj.type === 'select' || obj.type === 'select multiple') {
1953
+ var vals = ($(this).data('options') || '').split(';');
1954
+ obj.options = {};
1955
+ for (var v = 0; v < vals.length; v++) {
1956
+ var parts = vals[v].split('/');
1957
+ obj.options[parts[0]] = _(parts[1] || parts[0]);
1958
+ if (v === 0) {
1959
+ obj.def = (obj.def === undefined) ? parts[0] : obj.def;
1960
+ }
1961
+ }
1962
+ } else {
1963
+ obj.def = obj.def || '';
1964
+ }
1965
+ names.push(obj);
1966
+ } else {
1967
+ names.push(null);
1968
+ }
1969
+
1970
+ name = $(this).data('buttons');
1971
+
1972
+ if (name) {
1973
+ var bs = name.split(' ');
1974
+ buttons.push(bs);
1975
+ } else {
1976
+ buttons.push(null);
1977
+ }
1978
+ });
1979
+
1980
+ $table.data('names', names);
1981
+
1982
+ var text = '';
1983
+ for (var v = 0; v < values.length; v++) {
1984
+ var idName = values[v] && values[v].id;
1985
+ if (!idName && values[v]) {
1986
+ if (names[0] === '_index') {
1987
+ idName = values[v][names[1]];
1988
+ } else {
1989
+ idName = values[v][names[0]];
1990
+ }
1991
+ }
1992
+ text += '<tr ' + (idName ? 'data-id="' + idName + '"' : '') + ' data-index="' + v + '">';
1993
+
1994
+ for (var i = 0; i < names.length; i++) {
1995
+ text += '<td';
1996
+ var line = '';
1997
+ var style = '';
1998
+ var tdstyle = '';
1999
+ if (names[i]) {
2000
+ if (names[i].name !== '_index') {
2001
+ tdstyle = names[i].tdstyle || '';
2002
+ if (tdstyle && tdstyle[0] !== ';') {
2003
+ tdstyle = ';' + tdstyle;
2004
+ }
2005
+ }
2006
+ if (names[i].name === '_index') {
2007
+ style = (names[i].style ? names[i].style : 'text-align: right;');
2008
+ line += (v + 1);
2009
+ } else if (names[i].type === 'checkbox') {
2010
+ line += '<input style="' + (names[i].style || '') + '" class="values-input filled-in" type="checkbox" data-index="' + v + '" data-name="' + names[i].name + '" ' + (values[v][names[i].name] ? 'checked' : '') + '" data-old-value="' + (values[v][names[i].name] === undefined ? '' : values[v][names[i].name]) + '"/>';
2011
+ if (isMaterialize) {
2012
+ line += '<span></span>';
2013
+ }
2014
+ } else if (names[i].type === 'OID') {
2015
+ line += '<div style="' + (names[i].style ? names[i].style : 'width: calc(100% - 30px') + '"><input class="values-input" style="width: calc(100% - 30px)" type="text" data-index="' + v + '" data-name="' + names[i].name + '"/>';
2016
+ if (isMaterialize) {
2017
+ line += '<a style="max-width: 30px" class="btn-floating btn-small waves-effect waves-light blue oid-select" data-index="' + v + '" data-name="' + names[i].name + '">...</a>'
2018
+ } else {
2019
+ line += '<button style="max-width: 30px" class="oid-select" data-index="' + v + '" data-name="' + names[i].name + '">...</button>'
2020
+ }
2021
+ line += '</div>';
2022
+ } else if (names[i].type.substring(0, 6) === 'select') {
2023
+ line += (names[i].type.substring(7, 16) === 'multiple' ? '<select multiple style="' : '<select style="') + (names[i].style ? names[i].style : 'width: 100%') + '" class="values-input" data-index="' + v + '" data-name="' + names[i].name + '">';
2024
+ var options;
2025
+ if (names[i].name === 'room') {
2026
+ options = $table.data('rooms');
2027
+ } else if (names[i].name === 'func') {
2028
+ options = $table.data('functions');
2029
+ if (names[i].type === 'select multiple') {
2030
+ delete options[_('none')];
2031
+ }
2032
+ } else {
2033
+ options = names[i].options;
2034
+ }
2035
+
2036
+ var val = (values[v][names[i].name] === undefined ? '' : values[v][names[i].name]);
2037
+ if (typeof val !== 'object') {
2038
+ val = [val];
2039
+ }
2040
+ for (var p in options) {
2041
+ line += '<option value="' + p + '" ' + (val.indexOf(p) !== -1 ? ' selected' : '') + '>' + options[p] + '</option>';
2042
+ }
2043
+ line += '</select>';
2044
+ } else {
2045
+ line += '<input class="values-input" style="' + (names[i].style ? names[i].style : 'width: 100%') + '" type="' + names[i].type + '" data-index="' + v + '" data-name="' + names[i].name + '"/>';
2046
+ }
2047
+ }
2048
+
2049
+ if (buttons[i]) {
2050
+ style = 'text-align: center; white-space: nowrap;';
2051
+ for (var b = 0; b < buttons[i].length; b++) {
2052
+ if ((!v && buttons[i][b] === 'up') || (v === values.length - 1 && buttons[i][b] === 'down')) {
2053
+ if (isMaterialize) {
2054
+ line += '<a data-command="' + buttons[i][b] + '" class="values-buttons btn-floating btn-small waves-effect waves-light disabled"><i class="material-icons">add</i></a>';
2055
+ } else {
2056
+ line += '<button data-command="' + buttons[i][b] + '" class="values-buttons" disabled>&nbsp;</button>';
2057
+ }
2058
+ } else {
2059
+ if (isMaterialize) {
2060
+ line += '<a data-index="' + v + '" data-command="' + buttons[i][b] + '" class="values-buttons btn-floating btn-small waves-effect waves-light"><i class="material-icons">add</i></a>';
2061
+ } else {
2062
+ line += '<button data-index="' + v + '" data-command="' + buttons[i][b] + '" class="values-buttons"></button>';
2063
+ }
2064
+ }
2065
+ }
2066
+ }
2067
+ if (style.length || tdstyle.length) {
2068
+ text += ' style="' + style + tdstyle + '">' + line + '</td>';
2069
+ } else {
2070
+ text += '>' + line + '</td>';
2071
+ }
2072
+ }
2073
+
2074
+ text += '</tr>';
2075
+ }
2076
+
2077
+ var $lines = $div.find('.table-lines');
2078
+ if (!$lines.length) {
2079
+ $table.append('<tbody class="table-lines"></tbody>');
2080
+ $lines = $div.find('.table-lines');
2081
+ }
2082
+
2083
+ $lines.html(text);
2084
+
2085
+ $lines.find('.values-input').each(function () {
2086
+ var $this = $(this);
2087
+ var type = $this.attr('type');
2088
+ var name = $this.data('name');
2089
+ var id = $this.data('index');
2090
+ $this.data('old-value', values[id][name]);
2091
+ if (type === 'checkbox') {
2092
+ $this.prop('checked', values[id][name]);
2093
+ } else {
2094
+ $this.val(values[id][name]);
2095
+ }
2096
+ });
2097
+ $lines.find('.values-buttons').each(function () {
2098
+ var command = $(this).data('command');
2099
+ if (command === 'copy') {
2100
+ if (!isMaterialize) {
2101
+ $(this).button({
2102
+ icons: {primary: 'ui-icon-copy'},
2103
+ text: false
2104
+ })
2105
+ .css({width: '1em', height: '1em'});
2106
+ } else {
2107
+ $(this).find('i').html('content_copy');
2108
+ }
2109
+
2110
+ $(this).on('click', function () {
2111
+ if (!$add.data('maxraw') || ($add.data('raw') < $add.data('maxraw'))) {
2112
+ var id = $(this).data('index');
2113
+ var elem = JSON.parse(JSON.stringify(values[id]));
2114
+ values.push(elem);
2115
+ onChange && onChange();
2116
+
2117
+ setTimeout(function () {
2118
+ if (typeof tableEvents === 'function') {
2119
+ tableEvents(values.length - 1, elem, 'add');
2120
+ }
2121
+
2122
+ values2table(divId, values, onChange, onReady);
2123
+ }, 100);
2124
+
2125
+ if ($add.data('maxraw')) {
2126
+ $add.data('raw', $add.data('raw') + 1);
2127
+ }
2128
+ }
2129
+ });
2130
+ } else
2131
+ if (command === 'delete') {
2132
+ if (!isMaterialize) {
2133
+ $(this).button({
2134
+ icons: {primary: 'ui-icon-trash'},
2135
+ text: false
2136
+ })
2137
+ .css({width: '1em', height: '1em'});
2138
+ } else {
2139
+ $(this).addClass('red').find('i').html('delete');
2140
+ }
2141
+
2142
+ $(this).on('click', function () {
2143
+ var id = $(this).data('index');
2144
+ var elem = values[id];
2145
+ values.splice(id, 1);
2146
+ onChange && onChange();
2147
+
2148
+ setTimeout(function () {
2149
+ if (typeof tableEvents === 'function') {
2150
+ tableEvents(id, elem, 'delete');
2151
+ }
2152
+
2153
+ values2table(divId, values, onChange, onReady);
2154
+ }, 100);
2155
+
2156
+ if ($add.data('maxraw')) {
2157
+ $add.data('raw', $add.data('raw') - 1);
2158
+ }
2159
+ });
2160
+ } else if (command === 'up') {
2161
+ if (!isMaterialize) {
2162
+ $(this).button({
2163
+ icons: {primary: 'ui-icon-triangle-1-n'},
2164
+ text: false
2165
+ })
2166
+ .css({width: '1em', height: '1em'})
2167
+ } else {
2168
+ $(this).find('i').html('arrow_upward');
2169
+ }
2170
+ $(this).on('click', function () {
2171
+ var id = $(this).data('index');
2172
+ var elem = values[id];
2173
+ values.splice(id, 1);
2174
+ values.splice(id - 1, 0, elem);
2175
+ onChange && onChange();
2176
+ setTimeout(function () {
2177
+ values2table(divId, values, onChange, onReady);
2178
+ }, 100);
2179
+ });
2180
+ } else if (command === 'down') {
2181
+ if (!isMaterialize) {
2182
+ $(this).button({
2183
+ icons: {primary: 'ui-icon-triangle-1-s'},
2184
+ text: false
2185
+ })
2186
+ .css({width: '1em', height: '1em'});
2187
+ } else {
2188
+ $(this).find('i').html('arrow_downward');
2189
+ }
2190
+ $(this).on('click', function () {
2191
+ var id = $(this).data('index');
2192
+ var elem = values[id];
2193
+ values.splice(id, 1);
2194
+ values.splice(id + 1, 0, elem);
2195
+ onChange && onChange();
2196
+ setTimeout(function () {
2197
+ values2table(divId, values, onChange, onReady);
2198
+ }, 100);
2199
+ });
2200
+ } else if (command === 'pair') {
2201
+ if (!isMaterialize) {
2202
+ $(this).button({
2203
+ icons: {primary: 'ui-icon-transferthick-e-w'},
2204
+ text: false
2205
+ })
2206
+ .css({width: '1em', height: '1em'});
2207
+ } else {
2208
+ $(this).find('i').html('leak_add');
2209
+ }
2210
+ $(this).on('click', function () {
2211
+ if (typeof tableEvents === 'function') {
2212
+ var id = $(this).data('index');
2213
+ var elem = values[id];
2214
+ tableEvents(id, elem, 'pair');
2215
+ }
2216
+ }).attr('title', _('pair'));
2217
+ } else if (command === 'unpair') {
2218
+ if (!isMaterialize) {
2219
+ $(this).button({
2220
+ icons: {primary: 'ui-icon-scissors'},
2221
+ text: false
2222
+ })
2223
+ .css({width: '1em', height: '1em'});
2224
+ } else {
2225
+ $(this).find('i').html('leak_remove');
2226
+ }
2227
+ $(this).on('click', function () {
2228
+ if (typeof tableEvents === 'function') {
2229
+ var id = $(this).data('index');
2230
+ var elem = values[id];
2231
+ tableEvents(id, elem, 'unpair');
2232
+ }
2233
+ }).attr('title', _('unpair'));
2234
+ } else if (command === 'edit') {
2235
+ if (!isMaterialize) {
2236
+ $(this).button({
2237
+ icons: {primary: 'ui-icon-pencil'},
2238
+ text: false
2239
+ })
2240
+ .css({width: '1em', height: '1em'});
2241
+ } else {
2242
+ $(this).find('i').html('edit');
2243
+ }
2244
+ $(this).on('click', function () {
2245
+ var id = $(this).data('index');
2246
+ if (typeof editLine === 'function') {
2247
+ setTimeout(function () {
2248
+ editLine(id, JSON.parse(JSON.stringify(values[id])), function (err, id, newValues) {
2249
+ if (!err) {
2250
+ if (JSON.stringify(values[id]) !== JSON.stringify(newValues)) {
2251
+ onChange && onChange();
2252
+ values[id] = newValues;
2253
+ values2table(divId, values, onChange, onReady);
2254
+ }
2255
+ }
2256
+ });
2257
+ }, 100);
2258
+ }
2259
+ });
2260
+ }
2261
+ });
2262
+ $lines.find('.oid-select').on('click', function () {
2263
+ var name = $(this).data('name');
2264
+ var index = $(this).data('index');
2265
+ var $input = $lines.find('.values-input[data-name="' + name + '"][data-index="' + index + '"]');
2266
+ var val = $input.val() || '';
2267
+ showSelectIdDialog(val, function (newValue, oldValue) {
2268
+ if (newValue !== oldValue) {
2269
+ $input.val(newValue).trigger('change');
2270
+ }
2271
+ });
2272
+ });
2273
+
2274
+ $lines.find('.values-input').on('change.adaptersettings', function () {
2275
+ if ($(this).attr('type') === 'checkbox') {
2276
+ if ($(this).prop('checked').toString() !== $(this).data('old-value')) {
2277
+ onChange();
2278
+ }
2279
+
2280
+ values[$(this).data('index')][$(this).data('name')] = $(this).prop('checked');
2281
+ } else {
2282
+ if ($(this).val() !== $(this).data('old-value')) {
2283
+ onChange();
2284
+ }
2285
+
2286
+ values[$(this).data('index')][$(this).data('name')] = $(this).val();
2287
+ }
2288
+ }).on('keyup', function () {
2289
+ $(this).trigger('change.adaptersettings');
2290
+ });
2291
+ }
2292
+ if (isMaterialize) {
2293
+ if (!divId) {
2294
+ M.updateTextFields();
2295
+ $('select').select();
2296
+ } else {
2297
+ M.updateTextFields('#' + divId);
2298
+ $('#' + divId).find('select').select();
2299
+ }
2300
+
2301
+ // workaround for materialize checkbox problem
2302
+ $div.find('input[type="checkbox"]+span').off('click').on('click', function () {
2303
+ var $input = $(this).prev();
2304
+ if (!$input.prop('disabled')) {
2305
+ $input.prop('checked', !$input.prop('checked')).trigger('change');
2306
+ }
2307
+ });
2308
+ }
2309
+ typeof onReady === 'function' && onReady();
2310
+ }
2311
+
2312
+ /**
2313
+ * Extract the values from table.
2314
+ *
2315
+ * This function extracts the values from edit table, that was generated with values2table function.
2316
+ *
2317
+ * @param {string} divId name of the html element (or nothing).
2318
+ * @return {object} array with values
2319
+ */
2320
+ function table2values(divId) {
2321
+ var $div;
2322
+ if (!divId) {
2323
+ $div = $('body');
2324
+ } else {
2325
+ $div = $('#' + divId);
2326
+ }
2327
+ var names = [];
2328
+ $div.find('.table-values th').each(function () {
2329
+ var name = $(this).data('name');
2330
+ if (name) {
2331
+ names.push(name);
2332
+ } else {
2333
+ names.push('___ignore___');
2334
+ }
2335
+ });
2336
+
2337
+ var values = [];
2338
+ var j = 0;
2339
+ $div.find('.table-lines tr').each(function () {
2340
+ values[j] = {};
2341
+
2342
+ $(this).find('td').each(function () {
2343
+ var $input = $(this).find('input');
2344
+ if ($input.length) {
2345
+ var name = $input.data('name');
2346
+ if (name) {
2347
+ if ($input.attr('type') === 'checkbox') {
2348
+ values[j][name] = $input.prop('checked');
2349
+ } else {
2350
+ values[j][name] = $input.val();
2351
+ }
2352
+ }
2353
+ }
2354
+ var $select = $(this).find('select');
2355
+ if ($select.length) {
2356
+ var name = $select.data('name');
2357
+ values[j][name] = $select.val() || '';
2358
+ }
2359
+ });
2360
+ j++;
2361
+ });
2362
+
2363
+ return values;
2364
+ }
2365
+
2366
+ /**
2367
+ * Decrypt the password/value with given key
2368
+ * Usage:
2369
+ * ```
2370
+ * function load(settings, onChange) {
2371
+ * if (settings.password) {
2372
+ * settings.password = decrypt(systemSecret, settings.password);
2373
+ * // same as
2374
+ * settings.password = decrypt(settings.password);
2375
+ * }
2376
+ * // ...
2377
+ * }
2378
+ * ```
2379
+ * @param {string} key - Secret key
2380
+ * @param {string} value - value to decrypt
2381
+ * @returns {string}
2382
+ */
2383
+ function decrypt(key, value) {
2384
+ if (value === undefined) {
2385
+ value = key;
2386
+ key = systemSecret;
2387
+ }
2388
+ var result = '';
2389
+ for(var i = 0; i < value.length; i++) {
2390
+ result += String.fromCharCode(key[i % key.length].charCodeAt(0) ^ value.charCodeAt(i));
2391
+ }
2392
+ return result;
2393
+ }
2394
+
2395
+ /**
2396
+ * Encrypt the password/value with given key
2397
+ * Usage:
2398
+ * ```
2399
+ * function save(callback) {
2400
+ * ...
2401
+ * if (obj.password) {
2402
+ * obj.password = encrypt(systemSecret, obj.password);
2403
+ * // same as
2404
+ * obj.password = decrypt(obj.password);
2405
+ * }
2406
+ * ...
2407
+ * }
2408
+ * ```
2409
+ * @param {string} key - Secret key
2410
+ * @param {string} value - value to encrypt
2411
+ * @returns {string}
2412
+ */
2413
+ function encrypt(key, value) {
2414
+ if (value === undefined) {
2415
+ value = key;
2416
+ key = systemSecret;
2417
+ }
2418
+ var result = '';
2419
+ for(var i = 0; i < value.length; i++) {
2420
+ result += String.fromCharCode(key[i % key.length].charCodeAt(0) ^ value.charCodeAt(i));
2421
+ }
2422
+ return result;
2423
+ }