PageSourceSearch

https://app.mycer.it/interfaces/core/js/hig.js

js mycer.it collected 2026-09-24 14:24:26 UTC 263,027 bytes, 7,306 lines download raw bytes

1
2/*
3 ┌──────────────────────────────────────────────────────┐
4 │█┌──────────────────────────────────────────────────┐█│
5 │█│  hig.js                                          │█│
6 │█│                                                  │█│
7 │█│  Higeco JS Framework.                            │█│
8 │█│  JavaScript and Node utilities.                  │█│
9 │█└──────────────────────────────────────────────────┘█│
10 └──────────────────────────────────────────────────────┘
11*/
12/* eslint-disable */
13(function () {
14  // --------------------------
15  //
16  // INIT
17  //
18  // --------------------------
19
20  // Establish the root object, `window` in the browser, or `exports` on the server.
21  const self = this;
22
23  // Save bytes in the minified (but not gzipped) version:
24  const ArrayProto = Array.prototype; const ObjProto = Object.prototype; const FuncProto = Function.prototype;
25
26  // Our Global Object
27  /**
28   * @module    * Higeco JS Framework.
29   * JavaScript and Node utilities.
30   */
31  HigJS = {};
32
33  // Export the Underscore object for **Node.js**, with
34  // backwards-compatibility for the old `require()` API. If we're in
35  // the browser, add `_` as a global object.
36  if (typeof exports !== 'undefined') {
37    exports.HigJS = HigJS;
38  }
39
40  /**
41   * HigJS Library version
42   * @memberof module:HigJS
43   * @property {string}  VERSION               - Main library version
44   */
45  HigJS.VERSION = '0.0.1';
46
47  HigJS.init = function () {
48    // Array Remove - By John Resig (MIT Licensed)
49    Array.prototype.remove = function (from, to) {
50      const rest = this.slice((to || from) + 1 || this.length);
51      this.length = from < 0 ? this.length + from : from;
52      return this.push.apply(this, rest);
53    };
54    Object.defineProperty && Object.defineProperty(Array.prototype, 'remove', { enumerable: false, writable: false });
55  };
56
57  HigJS.init();
58
59  // --------------------------
60  //
61  // HigJS FUNCTIONS
62  //
63  // --------------------------
64
65  // --------------------------
66  // String Functions
67  // --------------------------
68  /**
69   * String Functions
70   * @module string
71   */
72  HigJS.str = {};
73  /**
74   * String library version.
75   * @property {string} VERSION - String library version
76   */
77  HigJS.str.VERSION = '0.0.1';
78  /**
79   * Aggiunger un 'Padding' a sinistra della stringa, per portarla alla lunghezza desiderata.
80   * @memberof module:string
81   *
82   * @param {string} str - Stringa da allungare.
83   * @param {number} len - Lunghezza desiderata della stringa.
84   * @param {string} pad - Carattere di riempimento.
85   * @returns {string} Ritorna la stringa con il padding impostato.
86   */
87  HigJS.str.padLeft = function (str, len, pad) {
88    pad = (pad && pad[0]) || ' ';
89    str = String(str);
90    while (str.length < len) { str = pad + str; }
91    return str;
92  };
93  /**
94   * Aggiunger un 'Padding' a destra della stringa, per portarla alla lunghezza desiderata.
95   * @memberof module:string
96   *
97   * @param {string} str - Stringa da allungare.
98   * @param {number} len - Lunghezza desiderata della stringa.
99   * @param {string} pad - Carattere di riempimento.
100   * @returns {string} Ritorna la stringa con il padding impostato.
101   */
102  HigJS.str.padRight = function (str, len, pad) {
103    pad = (pad && pad[0]) || ' ';
104    str = String(str);
105    while (str.length < len) { str += pad; }
106    return str;
107  };
108  /**
109   * Trasforma una stringa json in un oggetto javascript.
110   * @memberof module:string
111   *
112   * @param {string} str - Stringa da trasformare.
113   * @returns {Object} Oggetto js. In caso di errore null.
114   */
115  HigJS.str.toObj = function (str) {
116    try { return JSON.parse(str); } catch (e) { return null; }
117  };
118
119  /**
120   * Trasforma una stringa json in un oggetto javascript.
121   * @memberof module:string
122   *
123   * @param {string} str - Stringa da trasformare.
124   * @returns {Object} Oggetto js. In caso di errore ritorna str.
125   */
126  HigJS.str.toObj2 = function (str) {
127    try { return JSON.parse(str) || str; } catch (e) { return str; }
128  };
129
130  /**
131   * Converts a string to lowercase letters.
132   * @memberof module:string
133   *
134   * @param {string} str - String to conver.
135   * @returns {string} Converted string.
136   */
137  HigJS.str.toLowerCase = function (str) {
138    return str && typeof str === 'string' ? str.toLowerCase() : '';
139  };
140
141  /**
142   * Converts a string to uppercase letters.
143   * @memberof module:string
144   *
145   * @param {string} str - String to conver.
146   * @returns {string} Converted string.
147   */
148  HigJS.str.toUpperCase = function (str) {
149    return str && typeof str === 'string' ? str.toUpperCase() : '';
150  };
151
152  /**
153   * Check if the first string contain the second.
154   * @memberof module:string
155   *
156   * @param {string} str1 - Main string.
157   * @param {string} str2 - String to check.
158   * @returns {boolean} True if the first string contain the second, otherwise false.
159  */
160  HigJS.str.containString = function (str1, str2) {
161    if (!str1 || !str2 || str1 == null || str2 == null) return false;
162    return HigJS.str.toLowerCase(str1).indexOf(str2) >= 0;
163  };
164
165  /**
166   * Remove illegal characters from file name string.
167   * @memberof module:string
168   *
169   * @param {string} fileName - File name.
170   * @returns {string} File name without illegal characters.
171  */
172  HigJS.str.cleanFileName = function (fileName) {
173    return fileName.replace(/[(){}%&#$`'=@<>:"\/\\|?*]+/g, '').replace(/ /g, '_');
174  };
175
176  /**
177   * Replace all characters whith "" except numbers and letters.
178   * @memberof module:string
179   *
180   * @param {string} str - String.
181   * @returns {string} String without illegal characters.
182  */
183  HigJS.str.cleanString = function (str) {
184    str = str.replace(/\t/, '');
185    str = str.replace(/\n/, '');
186    str = str.replace(/\r/, '');
187    str = str.replace(/\b/, '');
188    str = str.replace(/\f/, '');
189    return str.replace(/[^a-zA-Z0-9]+$/, '');
190  };
191
192  /**
193  * Data una stringa controlla che sia un indirizzo ip V4.
194  * @memberof module:string
195  *
196  * @param {string} ipaddr - Indirizzo ip.
197  * @returns {boolean} Ritorna true se è un indirizzo ip, altrimenti false.
198  */
199  HigJS.str.validateIPAddress = function (ipaddr) {
200    if (!ipaddr) return false;
201    // Remember, this function will validate only Class C IP.
202    // change to other IP Classes as you need
203    ipaddr = ipaddr.replace(/\s/g, ''); // remove spaces for checking
204    const re = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/; // regex. check for digits and in
205    // all 4 quadrants of the IP
206    if (re.test(ipaddr)) {
207      // split into units with dots "."
208      const parts = ipaddr.split('.');
209      // if the first unit/quadrant of the IP is zero
210      if (parseInt(parseFloat(parts[0])) == 0) {
211        return false;
212      }
213      if (parts.length != 4) { return false; }
214      // if the fourth unit/quadrant of the IP is zero
215      // if (parseInt(parseFloat(parts[3])) == 0) {
216      //     return false;
217      // }
218      // if any part is greater than 256
219      for (let i = 0; i < parts.length; i++) {
220        if (parseInt(parseFloat(parts[i])) > 256) {
221          return false;
222        }
223      }
224      return true;
225    } else {
226      return false;
227    }
228  };
229
230  HigJS.str.validateEmail = function (str) {
231    const re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
232    return re.test(str);
233  };
234
235  HigJS.str.removeSpaces = function (str) {
236    if (!str) return '';
237    typeof str !== 'string' && str.toString && (str = str.toString());
238    return str.replace(/\s+/g, '');
239  };
240
241  HigJS.str.checkPkgVersion = function (pkgVer1, pkgVer2, equal) {
242    if (!pkgVer1) return true;
243    if (!pkgVer2) return false;
244
245    if (equal && pkgVer1 === pkgVer2) { return true; }
246
247    const gwcVer = pkgVer1.split('.'); let i;
248    const srvVer = pkgVer2.split('.');
249
250    for (i = 0; i < 3; i++) {
251      if (parseInt(gwcVer[i]) < parseInt(srvVer[i])) { return true; } else if (parseInt(gwcVer[i]) > parseInt(srvVer[i])) { return false; }
252    }
253    return false;
254  };
255
256  HigJS.str.capitalizeFirst = function (string) {
257    if (typeof string !== 'string') return string;
258    return string.charAt(0).toUpperCase() + string.slice(1);
259  };
260
261  /**
262  * Rimpiazza un carattere in una stringa.
263  * @memberof module:string
264  *
265  * @param {string} str       - Stringa.
266  * @param {number} index     - Posizione in cui sostituire il carattere.
267  * @param {string} character - Carattere da inserire nella stringa.
268  * @returns {string} Ritorna la stringa modificata.
269  */
270  HigJS.str.replaceAt = function (str, index, character) {
271    return str.substr(0, index) + character + str.substr(index + character.length);
272  };
273
274  HigJS.str.substring = function (str, from, to) {
275    return typeof str === 'string' ? str.substring(from, to) : str;
276  };
277
278  HigJS.str.capitelizeFirst = function (string) {
279    if (typeof string !== 'string') return string;
280    return string.charAt(0).toUpperCase() + string.slice(1);
281  };
282
283  HigJS.str.capitelizeAll = function (string) {
284    if (typeof string !== 'string') return string;
285    return string.toUpperCase();
286  };
287
288  HigJS.str.escapeHtml = function (string) {
289    if (typeof string !== 'string') return string;
290    return string.replace(/</g, '&lt;').replace(/>/g, '&gt;');
291  };
292
293  // --------------------------
294  // Errors Functions
295  // --------------------------
296  /**
297   * Errors Functions
298   * @module err
299   */
300  HigJS.err = {};
301  /**
302   * Object library version.
303   * @property {string}  VERSION               - Error library version
304   */
305  HigJS.err.VERSION = '0.0.1';
306  
307  HigJS.err = {};
308
309  /**
310   * Trasforma un oggetto javascript di errore in una stringa json.
311   * https://github.com/vkiryukhin/jsonfn
312   * 
313   * @memberof module:err
314   *
315   * @param {object} obj - Errore da trasformare.
316   * @returns {string}
316 Oggetto convertito a stringa. In caso di errore stringa vuota.
317   */
318  HigJS.err.toString = function (obj) {
319    try {
320      if (typeof obj === 'string') {
321        return obj;
322      }
323
324      return JSON.stringify(obj, function (key, value) {
325        if (value instanceof Error) {
326          const error = {};
327
328          Object.getOwnPropertyNames(value).forEach(function (key) {
329            error[key] = value[key];
330          });
331
332          return error;
333        }
334        return value;
335      });
336    } catch (e) { return ''; }
337  };
338
339  // --------------------------
340  // Objects Functions
341  // --------------------------
342  /**
343   * Objects Functions
344   * @module obj
345   */
346  HigJS.obj = {};
347  /**
348   * Object library version.
349   * @property {string}  VERSION               - Object library version
350   */
351  HigJS.obj.VERSION = '0.0.1';
352  /**
353   * Trasforma un oggetto javascript in una stringa json.
354   * https://github.com/vkiryukhin/jsonfn
355   * @memberof module:obj
356   *
357   * @param {object} obj - Oggetto javascript da trasformare.
358   * @returns {string} Oggetto convertito a stringa. In caso di errore stringa vuota.
359   */
360  HigJS.obj.toString = function (obj) {
361    try { return JSON.stringify(obj); } catch (e) { return ''; }
362  };
363
364  /**
365   * Clona un oggetto js.
366   * @memberof module:obj
367   *
368   * @param {object} source - Oggetto javascript da clonare.
369   * @returns {Object} Oggetto javascript clonato.
370   */
371  HigJS.obj.clone = function (obj, scope) {
372    return HigJS.str.toObj(HigJS.obj.toString(obj), scope);
373  };
374  /**
375   * Elimina i null da un oggetto. Può essere specificato un livello massimo di ricorsione.
376   * @memberof module:obj
377   *
378   * @param {Object}  source         Oggetto javascript dal quale rimuovere i null.
379   * @param {Number}  [recursion=0]  Maximum recursion level inside the `source` object.
380   */
381  HigJS.obj.removeNulls = function (obj, recursion = 0) {
382    for (const k in obj) {
383      if (obj[k] === null) {
384        delete obj[k];
385      } else if (recursion > 0 && HigJS.type.isObject(obj[k])) {
386        HigJS.obj.removeNulls(obj[k], recursion - 1);
387      }
388    }
389  };
390
391  /**
392  * Extends 2 objects and if rec is true removes null fields.
393  * @memberof module:obj
394  *
395  * @param {object} obj1 - Javascript destination object.
396  * @param {object} obj2 - Javascript source object.
397  * @param {number} rec  - If set removes null fields recursively "rec" times.
398  * @returns {Object} Extended object.
399  */
400  HigJS.obj.extendAdv = function (obj1, obj2, rec) {
401    rec && HigJS.obj.removeNulls(obj2, rec);
402    return HigJS.obj.extend(true, {}, obj1, obj2);
403  };
404
405  /**
406   * Extends 2 or more objects. Code from jQuery 2.1.3.
407   * @memberof module:obj
408   *
409   * @param {object} source - Oggetto javascript dal quale rimuovere i null.
410   * @returns {Object} Extended object.
411   */
412  HigJS.obj.extend = function () {
413    let options; let name; let src; let copy; let copyIsArray; let clone;
414    let target = arguments[0] || {};
415    let i = 1;
416    const length = arguments.length;
417    let deep = false;
418
419    // Handle a deep copy situation
420    if (typeof target === 'boolean') {
421      deep = target;
422
423      // Skip the boolean and the target
424      target = arguments[i] || {};
425      i++;
426    }
427
428    // Handle case when target is a string or something (possible in deep copy)
429    if (typeof target !== 'object' && !HigJS.type.isFunction(target)) {
430      target = {};
431    }
432
433    // Extend jQuery itself if only one argument is passed
434    if (i === length) {
435      target = this;
436      i--;
437    }
438
439    for (; i < length; i++) {
440      // Only deal with non-null/undefined values
441      if ((options = arguments[i]) != null) {
442        // Extend the base object
443        for (name in options) {
444          src = target[name];
445          copy = options[name];
446
447          // Prevent never-ending loop
448          if (target === copy) {
449            continue;
450          }
451
452          // Recurse if we're merging plain objects or arrays
453          // HigJS.type._sysIsObject DA NON SOSTITUIRE CON HigJS.type.isObject o HigJS.type.isPlainObj
454          if (deep && copy && (HigJS.type._sysIsObject(copy) || (copyIsArray = HigJS.type.isArray(copy)))) {
455            if (copyIsArray) {
456              copyIsArray = false;
457              clone = src && HigJS.type.isArray(src) ? src : [];
458            } else { // HigJS.type._sysIsObject DA NON SOSTITUIRE CON HigJS.type.isObject o HigJS.type.isPlainObj
459              clone = src && HigJS.type._sysIsObject(src) ? src : {};
460            }
461
462            // Never move original objects, clone them
463            target[name] = HigJS.obj.extend(deep, clone, copy);
464
465          // Don't bring in undefined values
466          } else if (copy !== undefined) {
467            target[name] = copy;
468          }
469        }
470      }
471    }
472
473    // Return the modified object
474    return target;
475  };
476
477  /**
478   * Ordina un oggetto javascritp. Funzione completamente inutile!!!
479   * @memberof module:obj
480   * @ignore
481   *
482   * @param {object}   obj - Oggetto javascript da ordinare.
483   * @param {Function} obj - (optional) Funzione che ordina.
484   * @returns {Object} Oggetto ordinato.
485   */
486  HigJS.obj.sort = function (obj, func) {
487    let i; let key; const sortable = []; const newObj = {};
488
489    for (key in obj) { sortable.push([key, obj[key]]); }
490
491    if (func) { sortable.sort(func); } else { sortable.sort(function (a, b) { return a[1] - b[1]; }); }
492
493    for (i = 0; i < sortable.length; i++) { newObj[sortable[i][0]] = sortable[i][1]; }
494    return newObj;
495  };
496
497  /**
498   * Returns the size of a object
499   * @memberof module:obj
500   *
501   * @param {object} opt - Object
502   * @returns {number} Object size.
503   */
504  HigJS.obj.objectSize = function (obj) {
505    let size = 0; let key;
506    for (key in obj) {
507      if (obj.hasOwnProperty(key) && typeof obj[key] !== 'function') { size++; }
508    }
509    return size;
510  };
511
512  // --------------------------
513  // Numeric Functions
514  // --------------------------
515  /**
516   * Number Functions
517   * @module num
518   */
519  HigJS.num = {};
520  /**
521   * Number library version.
522   * @property {string}  VERSION               - Nmeber library version
523   */
524  HigJS.num.VERSION = '0.0.1';
525  /**
526   * Dato un input controlla che sia un numero.
527   *
528   * REGEX: /^(\-|)([1-9]\d{0,2}(\.\d{3})*|([0-9]\d*))(\.\d{0,20})?$/
529   *
530   *  - Testa primo carattere se numerico, + o - (segno)
531   *  - il resto del numero è composto da cifre e un solo punto o virgola
532   *
533   * @memberof module:num
534   * @param {object}       opt             Oggetto di configurazione. oppure numero da testare
535   * @param {object}       [opt.val]       Se opt è un oggetto, qui metto il valore numerico da verificare
536   * @returns {number|boolean} Ritorna il numero (in formato stringa) con il punto (se decimale).
537   */
538  HigJS.num.isNum = function (opt) {
539    if (typeof opt === 'undefined' || opt === null) { return false; }
540    if (typeof opt === 'object') {
541      if (opt.val === null || typeof opt.val === 'undefined') { return false; } else { val = opt.val; }
542    } else { val = opt; }
543
544    if (val === false || val === true) { return false; }
545    if (typeof val !== 'string') { val = val.toString(); }
546
547    val = val.replace(',', '.').replace(/ /g, '');
548
549    if (val === 0 || val === '0') return val;
550
551    // var validNum = /^-?(\d+.?\d*)$|(\d*.?\d+)\g$/;
552    const validNum = /^(\-|)([1-9]\d{0,2}(\.\d{3})*|([0-9]\d*))(\.\d{0,20})?$/;
553    if (validNum.test(val)) { return val; }
554
555    return false;
556  };
557  /**
558   * Verifica se il numero è un intero
559   * @memberof module:num
560   *
561   * @param  {number}  n Valore da verificare se è un numero intero oppure no.
562   * @returns {boolean}  true se il numero è un intero
563   */
564  HigJS.num.isInt = function (n) { return n % 1 === 0; };
565
566  HigJS.num.toColumnName = function (num) {
567    for (var ret = '', a = 1, b = 26; (num -= a) >= 0; a = b, b *= 26) {
568      ret = String.fromCharCode(parseInt((num % b) / a) + 65) + ret;
569    }
570    return ret;
571  };
572
573  /**
574   * Genera una numero random.
575   * @memberof module:num
576   *
577   * @param {object}      opt     Oggetto di configurazione.
578   * @param {number}      opt.max Valore massimo del numero random. Default 1000.
579   * @returns {number} Numero casuale.
580   */
581  HigJS.num.genNum = function (opt) {
582    !opt && (opt = { max: 1000 });
583    return Math.floor(Math.random() * (opt.max + 1));
584  };
585
586  /**
587  * Change number size and set a new unit if the size is bigger than the size specified.
588  * @memberof module:num
589  *
590  * @param {object}       opt             Configuration object.
591  * @param {object}       opt.value       Value.
592  * @param {object}       opt.um          Unit.
593  * @param {object}       opt.numLength   Maximum number length.
594  * return {Object}       New number and new unit.
595  */
596  HigJS.num.autoSizeNum = function (opt) {
597    // try {
598    const units = [
599      { sym: '', molt: 1, nDec: 1, nextSym: 'k' },
600      { sym: 'k', molt: 1000, nDec: 1, nextSym: 'M' },
601      { sym: 'M', molt: 1000000, nDec: 2, nextSym: 'G' },
602      { sym: 'G', molt: 1000000000, nDec: 2, nextSym: 'T' },
603      { sym: 'T', molt: 1000000000000, nDec: 2 }
604    ]; let i; const unitsObj = { '': units[0], k: units[1], M: units[2], G: units[3], T: units[4] }; const originalValue = opt.value;
605    let nDecObj = opt.nDec;
606
607    // Controllo che nDec sia un valore o un oggetto del tipo { "k": 1, "M": 2 }
608    if (opt.nDecObj) {
609      nDecObj = opt.nDecObj;
610    }
611
612    if (HigJS.type.isNumber(nDecObj)) {
613      for (i = 0; i < units.length; i++) {
614        units[i].nDec = nDecObj;
615      }
616    } else if (nDecObj) {
617      for (i = 0; i < units.length; i++) {
618        typeof nDecObj[units[i].sym] !== 'undefined' && (units[i].nDec = nDecObj[units[i].sym]);
619      }
620    }
621
622    opt.value = parseFloat(opt.value).toFixed(unitsObj[opt.um[0]] && unitsObj[opt.um[0]].nDec ? unitsObj[opt.um[0]].nDec : unitsObj[''].nDec);
623
624    if (opt.value.length < opt.numLength) {
625      return opt;
626    } else {
627      opt.value = HigJS.num.toString(originalValue);
628    }
629
630    // var counter = 0, i;
631    while (opt.value.length > opt.numLength) {
632      if (!unitsObj[opt.um[0]]) {
633        opt.um = 'k' + opt.um;
634      } else if (unitsObj[opt.um[0]].nextSym) {
635        opt.um = HigJS.str.replaceAt(opt.um, 0, unitsObj[opt.um[0]].nextSym);
636      } else {
637        return opt;
638      }
639      opt.value = (parseFloat(opt.value) / 1000).toFixed(unitsObj[opt.um[0]] && unitsObj[opt.um[0]].nDec ? unitsObj[opt.um[0]].nDec : unitsObj[''].nDec);
640    }
641
642    return opt;
643  };
644
645  /**
646   * Given a byte number (or multiple) makes it human readable
647   *
648   * @param      {number}  bytes   The bytes counter
649   * @param      {string}  um      Measure unit:
650   *                                 - B     => Bytes
651   *                                 - KiB   => Kibibytes ( 1024   B )
652   *                                 - MiB   => Mebibytes ( 1024 KiB )
653   *                                 - GiB   => Gibibytes ( 1024 MiB )
654   *                                 - TiB   => Tebibytes ( 1024 GiB )
655   *                                 - PiB   => Pebibytes ( 1024 TiB )
656   *                                 - EiB   => Exbibytes ( 1024 PiB )
657   *                                 - ZiB   => Zebibytes ( 1024 EiB )
658   *                                 - YiB   => Yobibytes ( 1024 ZiB )
659   * @returns      {string}  String representation of the converted um
660   * @returns      {string}  Empty string in case of error or negative number
661   */
662  HigJS.num.bytesToHuman = function (bytes, um) {
663    bytes = parseFloat(bytes);
664    if (isNaN(bytes) || bytes < 0) { return ''; }
665
666    const ums = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
667    const uidx = ums.indexOf(String(um).toUpperCase().replace('I', 'i'));
668
669    if (uidx < 0) { return null; }
670    if (bytes > 1024 && (uidx < ums.length - 1)) {
671      return HigJS.num.bytesToHuman(bytes / 1024, ums[uidx + 1]);
672    }
673
674    return String(bytes.toFixed(1) + ' ' + um);
675  };
676
677  /**
678   * Converte un decimale in un esadecimale
679   * @memberof module:num
680   *
681   * @param  {number}  d Decimale.
682   * @returns {string}  Valore esadecimale.
683   */
684  HigJS.num.dec2hex = function (d) { return d.toString(16); };
685  /**
686   * Converte un esadecimale in un decimale
687   * @memberof module:num
688   *
689   * @param  {string}  d Decimale.
690   * @returns {number}  Valore decimale.
691   */
692  HigJS.num.hex2dec = function (h) { return parseInt(h, 16); };
693  HigJS.num.toString = function (num) { try { return num.toString(); } catch (e) { return ''; } };
694
695  /**
696   * @function
697   * @description Converte un valore esadecimale in un binario.
698   * @param {string}      h       Stringa in esadecimale.
699   * @param {number}      opt     Se 1
700   * @return Stringa binaria composta da 16 cifre.
701   */
702  HigJS.num.hex2bin = function (h, opt) {
703    if (h == null || isNaN('0x' + h)) h=0;
704
705    const binStr = parseInt(h, 16).toString(2).padStart(16, 0);
706    return opt == 1
707      ? binStr.split('').map(x => parseInt(x))
708      : binStr;
709  };
710
711
712  /**
713   * @description Dato un valore in secondi restituisce una stringa gg/ore/min/sec.
714   * @param {jSon}        opt             Oggetto jSon di configurazione.
715   * @param {number}      opt.sec         Numero secondi.
716   * @param {boolean}     opt.disableSec  Disabilita la visualizzazione dei secondi.
717   * @return Stringa gg/ore/min/sec.
718   */
719  HigJS.num.secToStr = function (opt) {
720    if (opt.sec == '---')
721      return '---';
722
723    let seconds = parseInt(opt.sec, 10);
724    if (isNaN(seconds)) return '---';
725
726    // Always return an empty string if no seconds
727    // or seconds are disabled
728    if (seconds <= 0 || (opt.disableSec && seconds < 60)) {
729      return ''
730    };
731
732    const duration = {
733      seconds: 0,
734      minutes: 0,
735      hours:   0,
736      days:    0,
737    };
738
739    duration.seconds = seconds % 60;
740    seconds -= duration.seconds;
741    duration.minutes = parseInt(seconds % 3600 / 60);
742    seconds -= duration.minutes * 60;
743    duration.hours = parseInt((seconds % 86400) / 3600);
744    seconds -= duration.hours * 3600;
745    duration.days = parseInt(seconds / 86400);
746
747    if (duration.days === 0) {
748      delete duration.days;
749    }
750    if (duration.hours === 0) {
751      delete duration.hours;
752    }
753    if (duration.minutes === 0) {
754      delete duration.minutes;
755    }
756
757    // We remove seconds if disableSec is true or if 0, but only if there are other fields
758    // visible, to avoid returning an empty string
759    if (opt.disableSec || duration.seconds === 0) {
760      delete duration.seconds;
761    }
762
763    try {
764      const lang = global?.gwc?.lang?.toLowerCase?.() ?? 'en';
765      const df = new Intl.DurationFormat(lang, { style: 'narrow' }).format(duration);
766      return df;
767    } catch(e) {
768      console.debug('Intl.DurationFormat unsupported, using legacySecToStr');
769
770      const localEdw = HigJS.diz?.edw ?? function(key) { return key };
771      // Legacy solution
772      let timeStrArray = [];
773      if (duration.days) {
774        timeStrArray.push(`${Math.floor(duration.days)} ${localEdw('days')}`);
775      }
776      if (duration.hours) {
777        timeStrArray.push(`${Math.floor(duration.hours)} ${localEdw('hours')}`);
778      }
779      if (duration.minutes) {
780        timeStrArray.push(`${Math.floor(duration.minutes)} ${localEdw('min')}`);
781      }
782      if (duration.seconds) {
783        timeStrArray.push(`${Math.floor(duration.seconds)} ${localEdw('sec')}`);
784      }
785
786      return timeStrArray.join(', ');
787    }
788  }
789
790  // --------------------------
791  // Array Functions
792  // --------------------------
793  /**
794   * Array Functions
795   * @module array
796   */
797  HigJS.array = {};
798  /**
799   * Array library version.
800   * @property {string}  VERSION               - Array library version
801   */
802  HigJS.array.VERSION = '0.0.1';
803  /**
804   * Clona un Array js.
805   * @memberof module:array
806   *
807   * @param {Array}  source  Array javascript da clonare.
808   * @returns {Array} Array javascript clonato.
809   */
810  HigJS.array.clone = function (array) { return array.slice(0); };
811
812  /**
813   * Concatena due array senza creare in memoria un'ulteriore copia.
814   * @memberof module:array
815   *
816   * @param {Array}  a  Array in cui viene concatenato l'altro array.
817   * @param {Array}  b  Array da concatenare.
818   */
819  HigJS.array.merge = function (a, b) {
820    if (a.reduce) {
821      a = b.reduce(function (coll, item) {
822        coll.push(item);
823        return coll;
824      }, a);
825    } else {
826      a.push.apply(a, b);
827    }
828  };
829
830  HigJS.array.sortByKey = function (a, b) {
831    let mode, options, key, object, r;
832    mode = '';
833
834    if (arguments.length > 2) {
835      if (typeof arguments[2] === 'string') {
836        key = arguments[2];
837        options = arguments[3] || {};
838        mode = 'key';
839      } else {
840        options = arguments[2] || {};
841      }
842      object = options.obj;
843      object && (mode += 'obj');
844      if (!options.hasOwnProperty('direction')) {
845        options.direction = true;
846      } else {
847        options.direction = options.direction == 'ASC' ? 1 : options.direction == 'DESC' ? -1 : 1;
848      }
849    }
850
851    switch (mode) {
852      case 'key':
853        a = HigJS.obj.getObjDeep({ target: a, key: key });
854        b = HigJS.obj.getObjDeep({ target: b, key: key });
855        break;
856      case 'obj':
857        a = HigJS.obj.getObjDeep({ target: object, key: a });
858        b = HigJS.obj.getObjDeep({ target: object, key: b });
859        break;
860      case 'keyobj':
861        a = HigJS.obj.getObjDeep({ target: object, key: a + '.' + key });
862        b = HigJS.obj.getObjDeep({ target: object, key: b + '.' + key });
863        break;
864      default:
865        !options && (options = {});
866        options.direction = true;
867    }
868
869    if (options.lexicon && typeof options.lexicon === 'function') { a = options.lexicon(a); b = options.lexicon(b); }
870    if (options.number) { a = +a; b = +b; } else { a = a && a.toString().toLowerCase(); b = b && b.toString().toLowerCase(); }
871
872    r = a > b ? 1 : a < b ? -1 : 0;
873    return options.direction ? r : -r;
874  };
875
876  /**
877   * Ordina un array sempice o un array di oggetti. Se le stringhe contiene dei numeri lo ordina correttamente.
878   * @memberof module:array
879   * 
880   * @example
881   * var array = [{ name: "002goo" }, {name: "001foo"}];
882   * HigJS.array.sort( array, "name");
883   * // result => [{ name: "001goo" }, {name: "002foo"}];
884   *  
885   * @example
886   * var array = [4,2,5,61,9];
887   * HigJS.array.sort( array, null, true);
888   *
889   * @param {array}  array - Array da ordinare.
890   * @param {string} key   - Chiave su cui ordinare l'array.
891   * @param {boolean=} simple - Se true ordina un array semplice
892   * @param {boolean=} reverse - Se true ordina in modo inverso l'array
893   */
894  HigJS.array.sort = function (_array, key, simple, reverse) {
895    const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });
896    if (!simple) {
897      _array.sort(function (a, b) {
898        return collator.compare(a[key], b[key]);
899      });
900    } else {
901      _array.sort(function (a, b) {
902        return collator.compare(a, b);
903      });
904    }
905
906    if (reverse) {
907      _array.reverse();
908    }
909  };
910
911  // --------------------------
912  // Type Functions
913  // --------------------------
914  /**
915   * Type's Functions
916   * @module type
917   */
918  HigJS.type = {};
919  /**
920   * Type library version.
921   * @property {string}  VERSION               - Type library version
922   */
923  HigJS.type.VERSION = '0.0.1';
924  /**
925   * Controlla che l'input sia una funzione.
926   * @memberof module:type
927   *
928   * @param  {Function}  target Target da controllare.
929   * @returns {number}  Valore decimale.
930   */
931  HigJS.type.isFunction = function (target) { return typeof target === 'function'; };
932  /**
933   * Controlla che l'input sia un numero.
934   * @memberof module:type
935   *
936   * @param  {number}  target Target da controllare.
937   * @returns {boolean} True se il tipo è corretto, altrimenti false.
938   */
939  HigJS.type.isNumber = function (target) {
940    if (typeof target === 'object') return false;
941    return HigJS.num.isNum(target) !== false;
942  };
943  /**
944   * Controlla che l'input sia un array.
945   * @memberof module:type
946   *
947   * @param  {Array}  target Target da controllare.
948   * @returns {boolean} True se il tipo è corretto, altrimenti false.
949   */
950  HigJS.type.isArray = function (target) { return !!(target && Array.isArray(target)); };
951  /**
952   * Controlla che l'input sia una stringa.
953   * @memberof module:type
954   *
955   * @param  {string}  target Target da controllare.
956   * @returns {boolean} True se il tipo è corretto, altrimenti false.
957   */
958  HigJS.type.isString = function (target) { return typeof target === 'string'; };
959
960  HigJS.type.isPlainObj = function (target) {
961    return !!((target && typeof target === 'object' && !Array.isArray(target) && Object.prototype.toString.call(target) === '[object Object]'));
962  };
963  /**
964   * Controlla che l'input sia un oggetto javascript.
965   * Sono validi oggetti con diverso costruttore
966   * @memberof module:type
967   *
968   * @param  {Object}  target Target da controllare.
969   * @returns {boolean} True se il tipo è corretto, altrimenti false.
970   */
971  HigJS.type.isObject = function (target) {
972    return !!((target && typeof target === 'object' && !Array.isArray(target) && typeof target.lookupNamespaceURI !== 'function'));
973  };
974
975  // Utilizzata esclusivamente in HigJS.obj.extend(). DA NON SOSTITUIRE CON HigJS.type.isObject o HigJS.type.isPlainObj
976  // HigJS.type._sysIsObject = function( target ){
977  //   if( !target || typeof target !== "object" || target === target.window ){ return false; }
978  //   if( !( target.constructor && target.constructor === Object ) ){ return false; }
979
980  //   return true;
981  // };
982  HigJS.type._sysIsObject = function (target) {
983    if (!target || typeof target !== 'object' || target === target.window) { return false; }
984    // if( !( target.constructor && target.constructor === Object ) ){ return false; }  <--- riga non funziona come in jQuery
985
986    // return true;
987
988    // Versione Jquery
989    let proto; let Ctor;
990    const class2type = {};
991    const ObjectFunctionString = class2type.hasOwnProperty.toString.call(Object);
992
993    // Detect obvious negatives
994    // Use toString instead of jQuery.type to catch host objects
995    if (!target || class2type.toString.call(target) !== '[object Object]') {
996      return false;
997    }
998
999    proto = Object.getPrototypeOf(target);
1000
1001    // Objects with no prototype (e.g., `Object.create( null )`) are plain
1002    if (!proto) {
1003      return true;
1004    }
1005
1006    // Objects with prototype are plain iff they were constructed by a global Object function
1007    Ctor = class2type.hasOwnProperty.call(proto, 'constructor') && proto.constructor;
1008    return typeof Ctor === 'function' && class2type.hasOwnProperty.toString.call(Ctor) === ObjectFunctionString;
1009  };
1010  /**
1011   * Controlla che l'input sia un oggetto del DOM.
1012   * @memberof module:type
1013   *
1014   * @param  {Object}  target Target da controllare.
1015   * @returns {number}  True se il tipo è corretto, altrimenti false.
1016   */
1017  HigJS.type.isDOM = function (target) { return !!((target && typeof target.lookupNamespaceURI === 'function')); };
1018
1019  // --------------------------
1020  // Debug Functions
1021  // --------------------------
1022  /**
1023   * Debug Functions and Settings.
1024   * @module debug
1025   */
1026  HigJS.debug = {};
1027
1028  /**
1029   * Debug library version.
1030   * @property {string}  VERSION               - Debug library version
1031   */
1032  HigJS.debug.VERSION = '0.0.1';
1033  /**
1034   * Debug status, if true enable debug functions.
1035   * @property {string}  enable               - Enable debug mode
1036   */
1037  HigJS.debug.enable = false;
1038
1039  /**
1040   * Prints a string only if debug is enabled.
1041   * @memberof module:debug
1042   *
1043   * @param {string} txt String to be printed
1044   */
1045  HigJS.debug.print = function (txt) {
1046    HigJS.debug.enable && console.log(txt);
1047  };
1048
1049  /**
1050   * Alias for print.
1051   * @memberof module:debug
1052   *
1053   * @param {string} txt String to be printed.
1054   */
1055  HigJS.debug.log = HigJS.debug.print;
1056
1057  /**
1058   * Prints an error only if debug is enabled.
1059   * @memberof module:debug
1060   *
1061   * @param {string} txt Error String
1062   */
1063  HigJS.debug.error = function (txt) {
1064    HigJS.debug.enable && console.error(txt);
1065  };
1066
1067  // --------------------------
1068  // Date Functions
1069  // --------------------------
1070  /**
1071   * Date tools.
1072   * @module date
1073   */
1074  HigJS.date = {};
1075
1076  /**
1077   * Date library version.
1078   * @property {string}  VERSION               - Date library version
1079   */
1080  HigJS.date.VERSION = '0.0.1';
1081
1082  /**
1083   * Numbers of day in a Month.
1084   * @memberof module:date
1085   *
1086   * @param {number} month Month.
1087   * @param {number} year Year.
1088   * @returns {number} Number of days.
1089   */
1090  HigJS.date.daysInMonth = function (month, year) {
1091    return (new Date(year, month + 1, 0)).getDate() + 1;
1092  };
1093
1094  HigJS.date.daysInMonth2 = function (month, year) {
1095    return (new Date(year, month, 0)).getDate();
1096  };
1097  /**
1098   * Numbers of day in a year.
1099   * @memberof module:date
1100   *
1101   * @param {number} year Year.
1102   * @returns {number} Number of days.
1103   */
1104  HigJS.date.daysInYear = function (year) {
1105    return HigJS.date.isLeapYear(year) ? 366 : 365;
1106  };
1107  /**
1108   * Is leap year? (bisestile).
1109   * @memberof module:date
1110   *
1111   * @param {number} year Year.
1112   * @returns {number} True || false.
1113   */
1114  HigJS.date.isLeapYear = function (year) {
1115    return year % 400 === 0 || (year % 100 !== 0 && year % 4 === 0);
1116  };
1117
1118  /**
1119   * Week number of a specific day - month - year
1120   * @memberof module:date
1121   *
1122   * @param {number} year Year.
1123   * @param {number} month Month.
1124   * @param {number} day Day.
1125   * @returns {number} Week number.
1126   */
1127  HigJS.date.weekNumber = function (year, month, day) {
1128    const d = new Date(year, month, day);
1129    d.setHours(0, 0, 0);
1130    // Set to nearest Thursday: current date + 4 - current day number
1131    // Make Sunday's day number 7
1132    d.setDate(d.getDate() + 4 - (d.getDay() || 7));
1133    // Get first day of year
1134    const yearStart = new Date(d.getFullYear(), 0, 1);
1135    // Calculate full weeks to nearest Thursday
1136    const weekNo = Math.ceil((((d - yearStart) / 86400000) + 1) / 7);
1137    // Return array of year and week number
1138    return weekNo;
1139  };
1140
1141  /**
1142   * Returns the Date object for a specific year-week-date
1143   *
1144   *  - Date starts from 1 to 7
1145   *   - Week starts from 1
1146   * @memberof module:date
1147   *
1148   * @param {number} year Year.
1149   * @param {number} week Month.
1150   * @param {number} date Day.
1151   * @returns {Object} Date object.
1152   */
1153  HigJS.date.weeksToDate = function (year, week, date) {
1154    year = parseInt(year); week = parseInt(week); date = parseInt(date);
1155    const simple = new Date(year, 0, (week - 1) * 7);
1156    if (simple.getDay() < 4) { simple.setDate(simple.getDate() - simple.getDay() + date); } else { simple.setDate(simple.getDate() + 7 - simple.getDay() + date); }
1157    return simple;
1158  };
1159
1160  HigJS.date.getTodayDate = function (offset) {
1161    !offset && (offset = 0);
1162    return HigJS.num.formatDate({ utc: parseInt((new Date()).getTime() / 1000) + (offset * 86400), date: true, time: false });
1163  };
1164
1165  HigJS.date.getYesterdayDate = function () {
1166    const now = new Date();
1167    return HigJS.num.formatDate({ utc: parseInt((new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1, now.getHours(), 0, 0)).getTime() / 1000), date: true, time: false });
1168  };
1169
1170  HigJS.date.UTCtoExcel = function (utc) {
1171    return utc ? (utc / 86400) + 25569 : 0;
1172  };
1173
1174  HigJS.date.getTimeIntervalMil = function (str) {
1175    let interval = [0, 0]; const now = new Date();
1176    if (str == 'today') {
1177      interval = [
1178        Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 0, 0, 0),
1179        Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 23, 59, 59)
1180      ];
1181    } else if (str == 'last24') {
1182      interval[1] = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds());
1183      interval[0] = interval[1] - 86400000;
1184    } else if (str == 'lastWeek') {
1185      interval[1] = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds());
1186      interval[0] = interval[1] - 604800000;
1187    } else if (str == 'lastMonth') {
1188      interval[1] = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds());
1189      interval[0] = interval[1] - 2592000000;
1190    } else if (str == 'currentMonth') {
1191      interval[0] = Date.UTC(now.getFullYear(), now.getMonth(), 1, 0, 0, 0);
1192      interval[1] = Date.UTC(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 0);
1193    } else if (str == 'lastYear') {
1194      interval[0] = Date.UTC(now.getUTCFullYear() - 1, now.getUTCMonth());
1195      interval[1] = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds());
1196    } else if (str == 'currentYear') {
1197      interval[0] = Date.UTC(now.getFullYear(), 0);
1198      interval[1] = Date.UTC(now.getFullYear() + 1, 0, 1);
1199    }
1200    return interval;
1201  };
1202
1203  HigJS.date.getCurrentWeek = function (startOnMonday) {
1204    const curr = new Date(); // get current date
1205    const first = curr.getDate() - curr.getDay() + (startOnMonday ? 1 : 0); // First day is the day of the month - the day of the week
1206    return { start: parseInt(Date.UTC(curr.getUTCFullYear(), curr.getUTCMonth(), first, 0, 0, 0) / 1000), stop: parseInt(Date.UTC(curr.getUTCFullYear(), curr.getUTCMonth(), first + 6, 0, 0, 0) / 1000) };
1207  };
1208
1209  HigJS.date.getTimeInterval = function (str) {
1210    const interval = HigJS.date.getTimeIntervalMil(str);
1211    return [parseInt(interval[0] / 1000), parseInt(interval[1] / 1000)];
1212  };
1213
1214  HigJS.date.getCustomInterval = function (date) {
1215    const type = date.interval;
1216    const dateObj = date.selection;
1217    const interval = [0, 0];
1218
1219    for (const id in dateObj) {
1220      dateObj[id] = (dateObj[id] == null) ? null : +dateObj[id]; // convert all the fields to number so there are non problems during adding operations
1221    }
1222
1223    if (type == 'year') {
1224      interval[0] = Date.UTC(dateObj.y, 0, 1);
1225      interval[1] = Date.UTC(dateObj.y + 1, 0, 1);
1226    } else if (type == 'month') {
1227      interval[0] = Date.UTC(dateObj.y, dateObj.m, 1);
1228      interval[1] = Date.UTC(dateObj.y, dateObj.m + 1, 1);
1229    } else if (type == 'day') {
1230      interval[0] = Date.UTC(dateObj.y, dateObj.m, dateObj.d);
1231      interval[1] = Date.UTC(dateObj.y, dateObj.m, dateObj.d + 1);
1232    }
1233    return [parseInt(interval[0] / 1000), parseInt(interval[1] / 1000)];
1234  };
1235
1236  HigJS.date.isHoliday = function () {
1237    let date;
1238    if (arguments.length == 1) {
1239      date = new Date(arguments[0]);
1240    } else if (arguments.length == 3) {
1241      date = new Date(arguments[0], arguments[1], arguments[2]);
1242    } else {
1243      throw new Error('Invalid input');
1244    }
1245
1246    date = { weekday: date.getDay(), year: date.getFullYear(), month: date.getMonth(), day: date.getDate() };
1247
1248    if (HigJS.date.isHoliday.HOLIDAYS.has(date.weekday)) return true;
1249    for (const f of HigJS.date.isHoliday.FIXED_HOLIDAY) {
1250      if (f[0] == date.month && f[1] == date.day) return true;
1251    }
1252    date.eastermonday = HigJS.date.getEasterMonday(date.year);
1253    if (date.eastermonday[0] == date.month && date.eastermonday[1] == date.day) return true;
1254    return false;
1255  };
1256
1257  HigJS.date.isHoliday.HOLIDAYS = new Set([6, 0]);
1258  HigJS.date.isHoliday.FIXED_HOLIDAY = new Set([
1259    [0, 1], [0, 6], [3, 25], [4, 1], [5, 2], [7, 15], [10, 1], [11, 8], [11, 25], [11, 26]
1260  ]);
1261
1262  HigJS.date.isHoliday.EASTERMONDAY_BY_YEAR = {};
1263
1264  HigJS.date.getEasterMonday = function (Y) {
1265    if (HigJS.date.isHoliday.EASTERMONDAY_BY_YEAR.hasOwnProperty(Y)) {
1266      return HigJS.date.isHoliday.EASTERMONDAY_BY_YEAR[Y];
1267    }
1268    let a, b, c, d, e, M, N, day, month, date;
1269    M = 24;
1270    N = 5;
1271    a = Y % 19;
1272    b = Y % 4;
1273    c = Y % 7;
1274    d = ((19 * a) + M) % 30;
1275    e = ((2 * b) + (4 * c) + (6 * d) + N) % 7;
1276
1277    if (d + e < 10) {
1278      day = d + e + 22;
1279      month = 3;
1280    } else {
1281      day = d + e - 9;
1282      month = 4;
1283    }
1284
1285    if (day == 26 && month == 4) {
1286      day = 19;
1287      month = 4;
1288    }
1289
1290    if (day == 25 && month == 4 && d == 28 && e == 6 && a > 10) {
1291      day = 18;
1292      month = 4;
1293    }
1294
1295    date = new Date(Y, month - 1, day + 1);
1296
1297    return HigJS.date.isHoliday.EASTERMONDAY_BY_YEAR[Y] = [date.getMonth(), date.getDate()];
1298  };
1299
1300  /**
1301    * Dig deep into an object to get one of its properties in a simple way.
1302    * @param   {object}         opt              Options object.
1303    * @param   {string}         [opt.key]        The point-separated properties to descend in the object tree.
1304    * @param   {object|string}  [opt.target]     The targeted object to dig in search of the desired properties .
1305    * @param   {object}         [opt.context]    The context where to find the targeted object if opt.target is a string, defaults to Window.
1306    * @param   {boolean}        [opt.makeCopy]   Simple flag to return a copy of the properties instead of a pointer.
1307    * @returns  {object}                           Returns the desired object or undefined if the properties is not reachable.
1308  */
1309
1310  HigJS.obj.getObjDeep = function (opt) {
1311    let parsedObj, tmp;
1312    tmp = Array.prototype.slice.call(arguments);
1313    if (tmp.length > 1 && typeof arguments[1] === 'string') {
1314      opt = { target: arguments[0], key: arguments[1] };
1315      tmp.length == 3 && Object.assign(opt, arguments[2]);
1316    }
1317
1318    if (!(opt && opt.hasOwnProperty('key') && opt.hasOwnProperty('target'))) {
1319      return;
1320    }
1321
1322    if (HigJS.type.isString(opt.target)) {
1323      parsedObj = opt.context ? opt.context[opt.target] : window[opt.target];
1324    } else {
1325      parsedObj = opt.target;
1326    }
1327
1328    if (HigJS.type.isString(opt.key)) {
1329      opt.key = opt.key.split('.');
1330      const l = opt.key.length;
1331      for (let i = 0; i < l; i++) {
1332        if (opt.key[i].replace(/\s+/g, '') != '') {
1333          try {
1334            tmp = opt.key[i].split('\\');
1335            if (tmp.length == 2) {
1336              if (tmp[0] !== '') {
1337                parsedObj = parsedObj[opt.key[i]];
1338              } else {
1339                switch (tmp[1]) {
1340                  case 'LAST':
1341                    if (Array.isArray(parsedObj)) {
1342                      tmp = parsedObj.length - 1;
1343                      (tmp >= 0) && (parsedObj = parsedObj[tmp]);
1344                    }
1345                    break;
1346                  default:
1347                    parsedObj = parsedObj[opt.key[i]];
1348                }
1349              }
1350            } else {
1351              parsedObj = parsedObj[opt.key[i]];
1352            }
1353          } catch (e) {
1354            // sysConf && sysConf.debug && console.info(e);
1355            // console.info('Failed to parse ' + opt.key[i] + ' property');
1356            return;
1357          }
1358        }
1359      }
1360    } else {
1361      return;
1362    }
1363
1364    if (opt.makeCopy) { return HigJS.obj.advClone(parsedObj, opt.context || undefined); }
1365
1366    return parsedObj;
1367  };
1368
1369  HigJS.obj.customHasOwnProperty = function (opt) {
1370    let returnValue = true;
1371    let tmpTarget = opt.target;
1372    if (opt && opt.target && opt.key) {
1373      const splitted = opt.key.split('.');
1374      const howDeep = splitted.length;
1375      for (let i = 0; i < howDeep; i++) {
1376        const spl = splitted[i].replace(/\s+/g, '');
1377        if (spl != '' && tmpTarget.hasOwnProperty(spl)) {
1378          try {
1379            tmpTarget = tmpTarget[spl];
1380          } catch (e) {
1381            // sysConf && sysConf.debug && console.info(e);
1382            // console.info('Failed to parse ' + opt.key[i] + ' property');
1383            return false;
1384          }
1385        } else {
1386          returnValue = false;
1387          break;
1388        }
1389      }
1390    } else {
1391      returnValue = false;
1392    }
1393    return returnValue;
1394  };
1395
1396  HigJS.obj.checkObjStructValidity = function (obj, checklist, inferType) {
1397    // check inputs
1398    let r, c, i, tmp;
1399    if (obj == null) return false;
1400    if (checklist == null) return true;
1401
1402    if (Array.isArray(checklist)) {
1403      checklist = checklist.reduce(function (cml, key) {
1404        cml[key] = '_e_';
1405        return cml;
1406      }, {});
1407    }
1408
1409    tmp = {};
1410    for (c in checklist) {
1411      tmp.type = checklist[c];
1412      tmp.own = HigJS.obj.customHasOwnProperty({
1413        key: c,
1414        target: obj
1415      });
1416
1417      tmp.val = tmp.own ? HigJS.obj.getObjDeep({ key: c, target: obj }) : undefined;
1418
1419      if (!inferType) {
1420        tmp.type = tmp.type.split('|');
1421      } else {
1422        tmp.type = [tmp.type];
1423      }
1424
1425      for (i = 0; i < tmp.type.length; i++) {
1426        switch (tmp.type[i]) {
1427          case '_e_':
1428            r = tmp.own;
1429            break;
1430          case 'array':
1431            r = Array.isArray(tmp.val);
1432            break;
1433          case 'NaN':
1434            r = isNaN(tmp.val);
1435            break;
1436          default:
1437            r = (typeof tmp.val === (inferType ? typeof tmp.type[i] : tmp.type[i]));
1438        }
1439        if (r) break;
1440      }
1441      if (!r) return false;
1442    }
1443    return true;
1444  };
1445
1446  /**
1447   * Determines if empty.
1448   *
1449   * @param      {object}   obj     The object
1450   * @returns     {boolean}  True if empty, False otherwise.
1451   */
1452  HigJS.obj.isEmpty = function (obj) {
1453    for (const k in obj) {
1454      if (obj.hasOwnProperty(k)) {
1455        return false;
1456      }
1457    }
1458    return true;
1459  };
1460
1461  HigJS.date.getStartStopFromInterval = function (opt) {
1462    if (!HigJS.type.isObject(opt)) {
1463      return {};
1464    }
1465
1466    let interval = [];
1467    let period; const now = new Date();
1468    let incrPeriod;
1469
1470    if (HigJS.type.isString(opt.interval)) { interval = HigJS.date.getTimeInterval(opt.interval); }
1471
1472    if (opt.interval === 'all' || (HigJS.type.isNumber(opt.startTime) && HigJS.type.isNumber(opt.stopTime))) {
1473      interval[0] = opt.startTime || 0;
1474      interval[1] = opt.stopTime || (Date.UTC(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds()) / 1000);
1475    }
1476
1477    // Checking interval bounds were properly computed
1478    if (interval.length !== 2 && HigJS.type.isNumber(interval[0]) && HigJS.type.isNumber(interval[1])) {
1479      return {};
1480    }
1481
1482    const elapsed = interval[1] - interval[0];
1483    period = parseInt(elapsed / 10000);
1484    incrPeriod = 86400;
1485
1486    // Adjusting incrPeriod
1487    if (elapsed < 86400) { incrPeriod = 3600; } // colonne di un ora su una giornata
1488    else if (elapsed < 604800) { incrPeriod = 86400; } // colonne di un giorno
1489    else if (elapsed < 3024000) { incrPeriod = 86400; } else if (elapsed > 31536000) { incrPeriod = 2592000; }
1490
1491    return { startTime: interval[0], stopTime: interval[1], period: period, incrPeriod: incrPeriod };
1492  };
1493
1494  function ZipJson () {
1495    const self = this;
1496
1497    const UNDEFINED_STRING = 'Ø';
1498
1499    /**
1500     *  Sets difference.
1501     *  @param {object}       opts         - Options.
1502     *  @param {array[]}      opts.lists   - List of list to intersept.
1503     *  @param {object[]}     opts.lists[] - List of object: numbers and string
1504     *
1505     *  @example
1506     *  setDifference({lists: [ [1,2,3,4,5,6,7,8,9], [34, 2,4,6,8] }) --> [1, 3, 5, 7, 9]
1507     */
1508    function setDifference (opts) {
1509      let a, b, _objA;
1510
1511      a = opts.lists[0];
1512      b = opts.lists[1];
1513      _objA = {};
1514
1515      for (var i = 0; i < a.length; i++) { _objA[a[i]] = true; }
1516
1517      for (i = 0; i < b.length; i++) { if (_objA[b[i]]) delete _objA[b[i]]; }
1518
1519      return Object.keys(_objA);
1520    }
1521
1522    /**
1523     *
1524     */
1525    function addNewFields (current, newFields) {
1526      const diff = setDifference({ lists: [newFields, current.map(f => (f.hasOwnProperty('name') ? f.name : f))] });
1527      return current = current.concat(diff);
1528    }
1529
1530    isObject = (o) => (o != null && typeof o === 'object' && !Array.isArray(o));
1531    isArray = (o) => (o != null && typeof o === 'object' && Array.isArray(o));
1532    isString = (o) => (o != null && typeof o === 'string');
1533
1534    /**
1535     *  Zip a json object.
1536     *  @param {object}                 opts        - Function options
1537     *  @param {array|object}           opts.data   - list of objects
1538     *  @param {number=}                opts.level  - number of level of zipping.
1539     *  @param {object|string=}       opts.fields - String that replace the undefined symbol.
1540     */
1541    function zip (opts) {
1542      let data, fields, res, level, hfields;
1543
1544      data = opts.data;
1545      hfields = opts.fields;
1546      level = opts.level;
1547      res = [];
1548
1549      if (level == 0) return { data: data, _zipped: false };
1550
1551      // è un oggetto, ciclo su tutti i campi e chiamo zip di ciascun valore.
1552      if (isObject(data)) {
1553        const keys = Object.keys(data); let tmp;
1554        fields === undefined && (fields = []);
1555
1556        // nel caso hfield è definito significa che siamo già dentro l'oggetto quindi sostituisco la string con un oggetto
1557        if (hfields != null && isString(hfields)) hfields = { name: hfields, _fields: [] };
1558        if (isObject(hfields) && hfields._fields) fields = hfields._fields;
1559        if (isArray(hfields)) fields = hfields;
1560
1561        const diff = fields.length;
1562        // prendo i campi ereditati da prec oggetti nella stessa posizione e aggiungo (se ci sono) quelli nuovi.
1563        fields = addNewFields(fields, keys);
1564
1565        if (fields.length - diff > 0) { (isObject(hfields) && hfields.hasOwnProperty('name') ? hfields._fields = fields : hfields = fields); }
1566
1567        // ciclo su ogni campo e tratto i singoli valori
1568        fields.forEach(function (f, pos, list) {
1569          _f = (isObject(f) ? f.name : f);
1570
1571          if (data[_f] === undefined) {
1572            res.push(UNDEFINED_STRING);
1573          } else {
1574            // calcolo ricorsivo
1575            tmp = zip({ data: data[_f], fields: f, level: level - 1 });
1576
1577            // integrazione del risoltato
1578            res.push(tmp.data);
1579
1580            // aggiornamento della definizione dei campi
1581            tmp._fields && (list[pos] = tmp._fields);
1582          }
1583        });
1584
1585        if (isObject(hfields)) hfields._fields = fields;
1586
1587        return { data: res, _zipped: true, _fields: (hfields || fields) };
1588      } else if (isArray(data)) {
1589        fields = { a: null };
1590
1591        // nel caso hfield è definito significa che siamo già dentro l'oggetto quindi sostituisco la string con un oggetto
1592        if (hfields != null && isString(hfields)) hfields = { name: hfields, _fields: fields };
1593        if (isObject(hfields) && hfields._fields) fields = hfields._fields;
1594
1595        data.forEach(function (el, pos) {
1596          if (isObject(el)) {
1597            const tmp = zip({ data: el, level: level - 1, fields: fields.a });
1598
1599            res.push(tmp.data);
1600            tmp._fields && (fields.a = tmp._fields);
1601          } else res.push(el);
1602        });
1603
1604        return { data: res, _zipped: true, _fields: (hfields || fields) };
1605      } else {
1606        // all other types: numbers, strings...
1607        return { data: data, _zipped: false };
1608      }
1609    }
1610
1611    /**
1612     *  Unzip a zipped object.
1613     *  @param {object}                 opts         - Function options
1614     *  @param {array|abject}           opts.data    - list of objects
1615     *  @param {array|string=}          opts._fields - number of level of masking.
1616     *  @param {boolean}                opts._zipped - If it is masked or not.
1617     */
1618    function unZip (opts) {
1619      let fields, data, res;
1620      data = opts.data;
1621      if (data === UNDEFINED_STRING) { return data; }
1622
1623      if (!opts._zipped) {
1624        return data;
1625      } else {
1626        fields = opts._fields;
1627
1628        if (!isArray(data) && isArray(fields)) { return data; }
1629
1630        if (isObject(fields) && fields.hasOwnProperty('a')) {
1631          res = [];
1632          // we have an array
1633          data.forEach(function (el) {
1634            const tmp = unZip({ data: el, _fields: fields.a, _zipped: (fields.a != null) });
1635            res.push(tmp);
1636          });
1637          return res;
1638        } else if (isArray(fields)) {
1639          // we have an object
1640          res = {};
1641          fields.forEach(function (f, pos) {
1642            if (pos >= data.length) return;
1643            const _f = (isObject(f) ? f.name : f);
1644            const tmp = unZip({ data: data[pos], _fields: (isObject(f) ? f._fields : null), _zipped: (!isString(f)) });
1645            if (tmp !== UNDEFINED_STRING) { res[_f] = tmp; }
1646          });
1647          return res;
1648        } else {
1649          console.log('ups');
1650          console.log(fields);
1651        }
1652        return null;
1653      }
1654    }
1655
1656    this.zip = zip;
1657    this.unZip = unZip;
1658  }
1659
1660  HigJS.ZipJson = ZipJson;
1661  HigJS.zipJson = new ZipJson();
1662
1663  HigJS.obj.JSONzip = function (opt) {
1664    return HigJS.zipJson.zip(opt);
1665  };
1666
1667  HigJS.obj.JSONunZip = function (opt) {
1668    return HigJS.zipJson.unZip(opt);
1669  };
1670}.call(this));
1671
1672
1673/* eslint-disable */
1674
1675/*
1676 ┌──────────────────────────────────────────────────────┐
1677 │█┌──────────────────────────────────────────────────┐█│
1678 │█│  hih-dom.js                                      │█│
1679 │█│                                                  │█│
1680 │█│  Higeco JS Framework.                            │█│
1681 │█│  JavaScript and utilities.                       │█│
1682 │█└──────────────────────────────────────────────────┘█│
1683 └──────────────────────────────────────────────────────┘
1684*/
1685
1686(function () {
1687  // --------------------------
1688  //
1689  // INIT
1690  //
1691  // --------------------------
1692
1693  // Establish the root object, `window` in the browser, or `exports` on the server.
1694  const self = this;
1695
1696  // Save bytes in the minified (but not gzipped) version:
1697  const ArrayProto = Array.prototype; const ObjProto = Object.prototype; const FuncProto = Function.prototype;
1698
1699  if (typeof HigJS === void 0 || !HigJS) {
1700    console.error("Missing HigJS base library. Include 'hig.js'");
1701    return null;
1702  }
1703  // --------------------------
1704  //
1705  // diz Only extensions to HigJS
1706  //
1707  // --------------------------
1708
1709  // Our Global Object
1710  const _diz = HigJS.diz = {};
1711
1712  // Current version.
1713  _diz.VERSION = '0.0.1';
1714  _diz.enable = false;
1715
1716  _diz.edw = function (opt) {
1717    let myDiz = typeof diz !== 'undefined' ? diz : {};
1718
1719    if (typeof opt === 'undefined') { opt = 'undefined'; }
1720
1721    !opt && (opt = '');
1722
1723    if (window.diz) {
1724      myDiz = window.diz;
1725    } else if (HigJS.dictionary) {
1726      myDiz = HigJS.dictionary;
1727    }
1728
1729    if (typeof opt === 'string') { opt = { word: opt, diz: myDiz }; }
1730
1731    if (typeof sysConf !== 'undefined' && sysConf.showDizId) {
1732      return opt.word;
1733    }
1734
1735    try {
1736      if (opt.diz[opt.word]) { return opt.diz[opt.word]; } else { return opt.word; }
1737    } catch (e) {
1738      HigJS.debug.error("Unable to load the word with id '" + opt.word + "' from diz");
1739      return opt.word;
1740    }
1741  };
1742
1743  HigJS.diz.decodeDizIdFromString = function (str) {
1744    if (str && str[0] == '{' && str[str.length - 1] == '}') { return str.substring(1, str.length - 1); } else { return str; }
1745  };
1746
1747  HigJS.diz.encodeDizIdFromString = function (str) {
1748    if (str) { return '{' + str + '}'; } else { return str; }
1749  };
1750
1751  HigJS.diz.isCustomWord = function (str) {
1752    if (str && str[0] == '{' && str[str.length - 1] == '}') { return true; }
1753    return false;
1754  };
1755
1756  HigJS.diz.edwCustom = function (opt) {
1757    if (typeof opt === 'undefined') { opt = 'undefined'; }
1758
1759    if (typeof opt === 'string') { opt = { word: opt, alt: '' }; }
1760
1761    if (!opt.diz && HigJS.userDiz) {
1762      opt.diz = HigJS.userDiz;
1763    } else {
1764      opt.diz = {};
1765    }
1766
1767    if (opt.word == ' ' || opt.word == '') { return opt.word; }
1768
1769    try {
1770      if (HigJS.diz.isCustomWord(opt.word) || opt.diz[HigJS.diz.decodeDizIdFromString(opt.word)]) {
1771        return opt.diz[HigJS.diz.decodeDizIdFromString(opt.word)][userConf.langId] || opt.alt || '';
1772      } else {
1773        if( !opt.word.match(/\d{5,}/) ){ //Se la stringa non contiene un timestamp ritorna la stringa stessa. A volte viene passata una stringa già tradotta.
1774          return opt.word;
1775        }
1776        return '';
1777      }
1778    } catch (e) {
1779      HigJS.debug.error("Unable to load the custom word with id '" + opt.word + "' from diz");
1780      if (typeof opt.alt !== 'undefined' && opt.diz) {
1781        opt.diz[HigJS.diz.decodeDizIdFromString(opt.word)] = {};
1782        opt.diz[HigJS.diz.decodeDizIdFromString(opt.word)][userConf.langId] = opt.alt;
1783      }
1784      return typeof opt.alt !== 'undefined' ? opt.alt : '';
1785    }
1786  };
1787
1788  HigJS.diz.addCustom = function (opt) {
1789    !opt.id && (opt.id = HigJS.diz.encodeDizIdFromString('word_' + parseInt(new Date().getTime() / 1000) + HigJS.num.genNum()));
1790    !opt.diz[HigJS.diz.decodeDizIdFromString(opt.id)] && (opt.diz[HigJS.diz.decodeDizIdFromString(opt.id)] = {});
1791    opt.diz[HigJS.diz.decodeDizIdFromString(opt.id)][opt.lang] = opt.word || '';
1792    return opt;
1793  };
1794
1795  HigJS.num.formatDate = function (opt) {
1796    let whatFuse, myDate;
1797    if (HigJS.type.isNumber(opt)) { opt = { utc: opt, date: true, time: true, local: false }; }
1798
1799    if (opt.utc == '---' || !opt.utc) { return '---'; }
1800
1801    myDate = new Date(parseInt(opt.utc) * 1000), str = '';
1802    whatFuse = opt.local ? '' : 'UTC';
1803    if (opt.date) {
1804      let day = myDate['get' + whatFuse + 'Date']();
1805      let month = opt.months ? ' ' + opt.months[myDate['get' + whatFuse + 'Month']()] + ' ' : myDate['get' + whatFuse + 'Month']() + 1;
1806      const year = myDate['get' + whatFuse + 'FullYear']();
1807      if (day < 10) { day = `0${day}`; }
1808      if (month < 10 && !opt.months) { month = `0${month}`; }
1809      if (opt.xml) {
1810        str = `${year}-${month}-${day}`;
1811      } else {
1812        if (userConf.dateFormat == 'DD_MM_YY_HH_MM_SS_SINGLE_POINT' || userConf.dateFormat == 'DD_MM_YY_HH_MM_SS_DOUBLE_POINT') {
1813          str = `${day}/${month}/${year}`;
1814        } else if (userConf.dateFormat == 'YY_MM_DD_HH_MM_SS_SINGLE_POINT' || userConf.dateFormat == 'YY_MM_DD_HH_MM_SS_DOUBLE_POINT') {
1815          str = `${year}/${month}/${day}`;
1816        } else if (userConf.dateFormat == 'MM_DD_YY_HH_MM_SS_SINGLE_POINT' || userConf.dateFormat == 'MM_DD_YY_HH_MM_SS_DOUBLE_POINT') {
1817          str = `${month}/${day}/${year}`;
1818        } else {
1819          str = `${day}/${month}/${year}`;
1820        }
1821      }
1822    }
1823    if (opt.time) {
1824      let hours = myDate['get' + whatFuse + 'Hours']();
1825      let minutes = myDate['get' + whatFuse + 'Minutes']();
1826      let seconds = myDate['get' + whatFuse + 'Seconds']();
1827      if (hours < 10) { hours = `0${hours}`; }
1828      if (seconds < 10) { seconds = `0${seconds}`; }
1829      if (minutes < 10) { minutes = `0${minutes}`; }
1830      if (opt.xml) {
1831        str += `T${hours}:${minutes}:${seconds}.000`;
1832      } else if (userConf.dateFormat == 'DD_MM_YY_HH_MM_SS_SINGLE_POINT' || userConf.dateFormat == 'YY_MM_DD_HH_MM_SS_SINGLE_POINT' || userConf.dateFormat == 'MM_DD_YY_HH_MM_SS_SINGLE_POINT') {
1833        str += ` ${hours}.${minutes}.${seconds}`;
1834      } else if (userConf.dateFormat == 'DD_MM_YY_HH_MM_SS_DOUBLE_POINT' || userConf.dateFormat == 'YY_MM_DD_HH_MM_SS_DOUBLE_POINT' || userConf.dateFormat == 'MM_DD_YY_HH_MM_SS_DOUBLE_POINT') {
1835        str += ` ${hours}:${minutes}:${seconds}`;
1836      } else {
1837        str += ` ${hours}:${minutes}:${seconds}`;
1838      }
1839    }
1840
1841    if (opt.timezone) {
1842      str += ` ${opt.timezone}`;
1843    }
1844
1845    return str;/* 1981-12-11T11:11:11.000 */
1846  };
1847
1848  HigJS.date.getIntervalFromStrDate = function (day, local) {
1849    if (!day || typeof day !== 'string') return [0, 0];
1850    const days = day.split('/'); let start; let end;
1851
1852    if (!local) { // GMT
1853      if (userConf.dateFormat == 'DD_MM_YY_HH_MM_SS_SINGLE_POINT' || userConf.dateFormat == 'DD_MM_YY_HH_MM_SS_DOUBLE_POINT') {
1854        start = parseInt(Date.UTC(parseInt(days[2]), parseInt(days[1] - 1), parseInt(days[0]), 0, 0, 0) / 1000);
1855        end = parseInt(Date.UTC(parseInt(days[2]), parseInt(days[1] - 1), parseInt(days[0]), 23, 59, 59) / 1000);
1856      } else if (userConf.dateFormat == 'YY_MM_DD_HH_MM_SS_SINGLE_POINT' || userConf.dateFormat == 'YY_MM_DD_HH_MM_SS_DOUBLE_POINT') {
1857        start = parseInt(Date.UTC(parseInt(days[0]), parseInt(days[1] - 1), parseInt(days[2]), 0, 0, 0) / 1000);
1858        end = parseInt(Date.UTC(parseInt(days[0]), parseInt(days[1] - 1), parseInt(days[2]), 23, 59, 59) / 1000);
1859      } else if (userConf.dateFormat == 'MM_DD_YY_HH_MM_SS_SINGLE_POINT' || userConf.dateFormat == 'MM_DD_YY_HH_MM_SS_DOUBLE_POINT') {
1860        start = parseInt(Date.UTC(parseInt(days[2]), parseInt(days[0] - 1), parseInt(days[1]), 0, 0, 0) / 1000);
1861        end = parseInt(Date.UTC(parseInt(days[2]), parseInt(days[0] - 1), parseInt(days[1]), 23, 59, 59) / 1000);
1862      }
1863    } else { // Tempo locale
1864      if (userConf.dateFormat == 'DD_MM_YY_HH_MM_SS_SINGLE_POINT' || userConf.dateFormat == 'DD_MM_YY_HH_MM_SS_DOUBLE_POINT') {
1865        start = parseInt((new Date(parseInt(days[2]), parseInt(days[1] - 1), parseInt(days[0]), 0, 0, 0)).getTime() / 1000);
1866        end = parseInt((new Date(parseInt(days[2]), parseInt(days[1] - 1), parseInt(days[0]), 23, 59, 59)).getTime() / 1000);
1867      } else if (userConf.dateFormat == 'YY_MM_DD_HH_MM_SS_SINGLE_POINT' || userConf.dateFormat == 'YY_MM_DD_HH_MM_SS_DOUBLE_POINT') {
1868        start = parseInt((new Date(parseInt(days[0]), parseInt(days[1] - 1), parseInt(days[2]), 0, 0, 0)).getTime() / 1000);
1869        end = parseInt((new Date(parseInt(days[0]), parseInt(days[1] - 1), parseInt(days[2]), 23, 59, 59)).getTime() / 1000);
1870      } else if (userConf.dateFormat == 'MM_DD_YY_HH_MM_SS_SINGLE_POINT' || userConf.dateFormat == 'MM_DD_YY_HH_MM_SS_DOUBLE_POINT') {
1871        start = parseInt(new Date(parseInt(days[2]), parseInt(days[0] - 1), parseInt(days[1]), 0, 0, 0) / 1000);
1872        end = parseInt(new Date(parseInt(days[2]), parseInt(days[0] - 1), parseInt(days[1]), 23, 59, 59) / 1000);
1873      }
1874    }
1875    return [start, end];
1876  };
1877
1878  HigJS.num.format = function (val) {
1879    if (typeof val === 'boolean') { return '---'; }
1880
1881    if (typeof val === 'number') { val = val.toString(); }
1882
1883    if (!HigJS.num.isNum(val)) { return '---'; }
1884
1885    if (val == '---') { return val; }
1886
1887    let str = ' ';
1888    let dec = '.';
1889    let minus = '';
1890
1891    if (userConf.numFormat == '1 000 000.000') { str = ' '; dec = '.'; } else if (userConf.numFormat == '1,000,000.000') { str = ','; dec = '.'; } else if (userConf.numFormat == '1.000.000,000') { str = '.'; dec = ','; } else { str = ' '; dec = '.'; }
1892
1893    if (val[0] == '-') {
1894      minus = '-';
1895      val = val.split('-')[1];
1896    }
1897
1898    let tmpVal = [];
1899    if (val.indexOf(',') >= 0) tmpVal = val.split(',');
1900    else if (val.indexOf('.') >= 0) tmpVal = val.split('.');
1901    else { tmpVal[0] = val.slice(0); tmpVal[1] = ''; }
1902
1903    const output = [];
1904    for (var i = 0; i < tmpVal[0].length; i++) { output[i] = tmpVal[0][i]; }
1905
1906    if (output.length > 3) {
1907      for (var i = output.length - 3; i > 0; i -= 3) { output.splice(i, 0, str); }
1908    }
1909
1910    tmpVal[0] = '';
1911
1912    for (var i = 0; i < output.length; i++) { tmpVal[0] += output[i]; }
1913
1914    if (tmpVal[1] == '') { return minus + tmpVal[0]; }
1915    return minus + tmpVal[0] + dec + tmpVal[1];
1916  };
1917
1918  HigJS.num.unFormat = function (val) {
1919    if (typeof val === 'boolean' || val === '---') { return '---'; }
1920
1921    if (typeof val === 'number') val = val.toString();
1922
1923    let str = ' '; let dec = '.'; const dateNumFormat = 'UNI';
1924
1925    if (userConf.numFormat == '1 000 000.000') { str = ' '; dec = '.'; } else if (userConf.numFormat == '1,000,000.000') { str = ','; dec = '.'; } else if (userConf.numFormat == '1.000.000,000') { str = '.'; dec = ','; } else { str = ' '; dec = '.'; }
1926
1927    // val = val.replace(/ /g,'').split(str).join('').replace( new RegExp( dec, "g"),'.'); // sostituire dec = "\\."
1928    val = val.replace(/ /g, '').split(str).join('').replace(dec, '.'); // global substitution of str, before was only the first
1929    if (!HigJS.type.isNumber(val)) {
1930      return '---';
1931    }
1932
1933    return parseFloat(val);
1934  };
1935
1936  HigJS.num.formatValue = function (custom) {
1937    const def = {
1938      nDec: 1,
1939      type: 'ana',
1940      date: true,
1941      time: true
1942    };
1943
1944    const opt = HigJS.obj.extendAdv(def, custom);
1945
1946    if (opt.type == 'ana' || opt.type == 'Num') {
1947      if (!HigJS.type.isNumber(opt.value)) { return '---'; }
1948
1949      opt.value = parseFloat(opt.value);
1950      // typeof opt.gain == "number" && ( opt.value *= opt.gain );
1951      // typeof opt.offset == "number" && ( opt.value -= opt.offset );
1952      HigJS.type.isNumber(opt.gain) && (opt.value *= opt.gain);
1953      HigJS.type.isNumber(opt.offset) && (opt.value -= opt.offset);
1954
1955      return HigJS.num.format(parseFloat(opt.value).toFixed(opt.nDec));
1956    } else if (opt.type == 'str') {
1957      return opt.value;
1958    } else if (opt.type == 'utc') {
1959      return HigJs.num.formatDate({ utc: opt.value, date: opt.date, time: opt.time });
1960    } else if (opt.type === 'Bool') {
1961      return parseInt(opt.value) ? HigJS.diz.edw('on') : HigJS.diz.edw('off');
1962    }
1963
1964    return opt.value;
1965  };
1966
1967  !HigJS.cns && (HigJS.cns = {});
1968
1969  HigJS.cns.checkPkg = function (pkgId) {
1970    return !!userConf.pkgListByType[pkgId];
1971  };
1972
1973  HigJS.cns.checkMCC = function (checks, style) {
1974    let flag = false;
1975
1976    switch (style) {
1977      case '|':
1978      case 'or':
1979      case 'OR':
1980        style = 'some';
1981        break;
1982      default:
1983        style = 'every';
1984    }
1985
1986    if (typeof checks === 'string') {
1987      checks = checks.replace(/ +/g, '').split(',');
1988    } else if (!Array.isArray(checks)) {
1989      checks = HigJS.cns.MCC_PLUGINS;
1990    }
1991
1992    if (userConf && userConf.pkgListByType && HigJS.obj.objectSize(userConf.pkgListByType)) {
1993      flag = Array.prototype[style].call(checks, function (plname) {
1994        return userConf.pkgListByType.hasOwnProperty(plname);
1995      });
1996    }
1997
1998    return flag;
1999  };
2000
2001  HigJS.cns.MCC_PLUGINS = ['mccCorePl', 'mccDriverPl', 'mccKPIPl', 'pvManagerPl'];
2002
2003  HigJS.cns.checkRights = function (opt) {
2004    if (opt.taskId == 'singleUserPage' && userConf.userType == 'admin') return false;
2005    if (userConf.userType == 'superadmin' || userConf.userType == 'admin') return true;
2006
2007    if (!userConf.tasksById || !userConf.tasksByCode) {
2008      userConf.tasksById = {};
2009      userConf.tasksByName = {};
2010      userConf.tasksByCode = {};
2011      if (Array.isArray(userConf.tasks)) {
2012        for (let i = 0; i < userConf.tasks.length; i++) {
2013          userConf.tasksById[userConf.tasks[i].taskId] = userConf.tasks[i];
2014          userConf.tasks[i].taskName && (userConf.tasksByName[userConf.tasks[i].taskName] = userConf.tasks[i]);
2015          userConf.tasks[i].taskCode && (userConf.tasksByCode[userConf.tasks[i].taskCode] = userConf.tasks[i]);
2016        }
2017      } else {
2018        userConf.tasksById = userConf.tasks;
2019      }
2020    }
2021
2022    if (userConf.tasksById[opt.taskId] || userConf.tasksByName[opt.taskName] || userConf.tasksByCode[opt.taskCode]) {
2023      return true;
2024    } else {
2025      return false;
2026    }
2027  };
2028
2029  !HigJS.cfg && (HigJS.cfg = {});
2030
2031  /**
2032   * Combine all the configurations requested from the db to return a single object.
2033   * @param {Array|Object} opt Array of Objects or single Object composed like { pageId: 'value', nodeId: 'value', nodeTypeId: 'value' }
2034   * @returns {Object} the final object obtained after combining the configurations in the same order as they arrived.
2035   */
2036  HigJS.cfg.loadConfigs = function (opt) {
2037    if (!Array.isArray(opt)) opt = [opt];
2038    const filteredOpt = opt.filter(el => {
2039      if (!el || !typeof el === 'object') return false;
2040      if (el.pageId) return true;
2041      return false;
2042    })
2043
2044    return new Promise((resolve, reject) => {
2045      const reqs = [];
2046      filteredOpt.forEach((filter) => {
2047        const req = {
2048          act: 'pagesConfigsCRUD',
2049          idReq: 'pagesConfigsCRUD_' + filter.pageId,
2050          data: {
2051            act: 'read',
2052            pageId: filter.pageId,
2053            nodeId: filter.nodeId,
2054            nodeTypeId: filter.nodeTypeId
2055          }
2056        };
2057        reqs.push(req);
2058      });
2059      if (!reqs.length) return reject('Invalid format of requests.');
2060
2061      HigJS.ajax.request({
2062        reqs: reqs,
2063        ids: userConf.ids,
2064        nodeJS: true,
2065        onSuccess: function (msg) {
2066          if (!msg.DATI.length) {
2067            if (!HigJS.ajax.checkResponse(msg).ok) {
2068              return reject(HigJS.ajax.checkResponse(msg).errMsg);
2069            }
2070          }
2071
2072          let conf = {};
2073          for (let i = 0; i < msg.DATI.length; i++) {
2074            if (msg.DATI[i].ERR) continue;
2075
2076            for (let k = 0; k < msg.DATI[i].DATI.length; k++) {
2077              let tempEval = {};
2078              try {
2079                tempEval = eval(msg.DATI[i].DATI[k].config);
2080              } catch (e) {
2081                console.error('Error reading configuration: ' + msg.DATI[i].DATI[k].label + '.\n' + e);
2082              }
2083              conf = HigJS.obj.extendAdv(conf, tempEval);
2084            }
2085          }
2086
2087          resolve(conf);
2088        },
2089        onError: reject,
2090        url: '/node'
2091      });
2092    });
2093  };
2094}.call(this));
2095
2096
2097/*
2098 ┌──────────────────────────────────────────────────────┐
2099 │█┌──────────────────────────────────────────────────┐█│
2100 │█│  hig-ajax.js                                     │█│
2101 │█│                                                  │█│
2102 │█│  Higeco JS Framework.                            │█│
2103 │█│  JavaScript and ajax utilities.                  │█│
2104 │█└──────────────────────────────────────────────────┘█│
2105 └──────────────────────────────────────────────────────┘
2106*/
2107
2108(function () {
2109  // --------------------------
2110  //
2111  // INIT
2112  //
2113  // --------------------------
2114
2115  // Establish the root object, `window` in the browser, or `exports` on the server.
2116  const self = this;
2117
2118  // Save bytes in the minified (but not gzipped) version:
2119  const ArrayProto = Array.prototype; const ObjProto = Object.prototype; const FuncProto = Function.prototype;
2120
2121  if (typeof HigJS === void 0 || !HigJS) {
2122    console.error("Missing HigJS base library. Include 'hig.js'");
2123    return null;
2124  }
2125
2126  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
2127  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
2128  /*  Block TEA (xxtea) Tiny Encryption Algorithm implementation in JavaScript                      */
2129  /*     (c) Chris Veness 2002-2012: www.movable-type.co.uk/tea-block.html                          */
2130  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
2131
2132  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
2133  /*  Algorithm: David Wheeler & Roger Needham, Cambridge University Computer Lab                   */
2134  /*             http://www.cl.cam.ac.uk/ftp/papers/djw-rmn/djw-rmn-tea.html (1994)                 */
2135  /*             http://www.cl.cam.ac.uk/ftp/users/djw3/xtea.ps (1997)                              */
2136  /*             http://www.cl.cam.ac.uk/ftp/users/djw3/xxtea.ps (1998)                             */
2137  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
2138
2139  /**
2140   * TEA Functions
2141   * @module tea
2142  */
2143  HigJS.Tea = {};
2144
2145  /**
2146   * encrypt text using Corrected Block TEA (xxtea) algorithm
2147   * 
2148   * @memberof module:tea
2149   *
2150   * @param {string} plaintext - byte safe)
2151   * @param {string} password  - Password to be used for encryption (1st 16 chars)
2152   * @returns {string} encrypted text
2153   */
2154  HigJS.Tea.encrypt = function (plaintext, password) {
2155    if (plaintext.length == 0) return (''); // nothing to encrypt
2156
2157    // convert string to array of longs after converting any multi-byte chars to UTF-8
2158    const v = HigJS.Tea.strToLongs(HigJS.Utf8.encode(plaintext));
2159    if (v.length <= 1) v[1] = 0; // algorithm doesn't work for n<2 so fudge by adding a null
2160    // simply convert first 16 chars of password as key
2161    const k = HigJS.Tea.strToLongs(HigJS.Utf8.encode(password).slice(0, 16));
2162    const n = v.length;
2163
2164    // ---- <TEA coding> ----
2165
2166    let z = v[n - 1]; let y = v[0]; const delta = 0x9E3779B9;
2167    let mx; let e; let q = Math.floor(6 + 52 / n); let sum = 0;
2168
2169    while (q-- > 0) { // 6 + 52/n operations gives between 6 & 32 mixes on each word
2170      sum += delta;
2171      e = sum >>> 2 & 3;
2172      for (let p = 0; p < n; p++) {
2173        y = v[(p + 1) % n];
2174        mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
2175        z = v[p] += mx;
2176      }
2177    }
2178
2179    // ---- </TEA> ----
2180
2181    const ciphertext = HigJS.Tea.longsToStr(v);
2182
2183    return HigJS.Base64.encode(ciphertext);
2184  };
2185
2186  /**
2187   * decrypt text using Corrected Block TEA (xxtea) algorithm
2188   * @memberof module:tea
2189   *
2190   * @param {string} ciphertext - String to be decrypted
2191   * @param {string} password   - Password to be used for decryption (1st 16 chars)
2192   * @returns {string} decrypted text
2193   */
2194  HigJS.Tea.decrypt = function (ciphertext, password) {
2195    if (ciphertext.length == 0) return ('');
2196    const v = HigJS.Tea.strToLongs(HigJS.Base64.decode(ciphertext));
2197    const k = HigJS.Tea.strToLongs(HigJS.Utf8.encode(password).slice(0, 16));
2198    const n = v.length;
2199
2200    // ---- <TEA decoding> ----
2201
2202    let z = v[n - 1]; let y = v[0]; const delta = 0x9E3779B9;
2203    let mx; let e; const q = Math.floor(6 + 52 / n); let sum = q * delta;
2204
2205    while (sum != 0) {
2206      e = sum >>> 2 & 3;
2207      for (let p = n - 1; p >= 0; p--) {
2208        z = v[p > 0 ? p - 1 : n - 1];
2209        mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
2210        y = v[p] -= mx;
2211      }
2212      sum -= delta;
2213    }
2214
2215    // ---- </TEA> ----
2216
2217    let plaintext = HigJS.Tea.longsToStr(v);
2218
2219    // strip trailing null chars resulting from filling 4-char blocks:
2220    plaintext = plaintext.replace(/\0+$/, '');
2221
2222    return HigJS.Utf8.decode(plaintext);
2223  };
2224
2225  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
2226
2227  // supporting functions
2228
2229  HigJS.Tea.strToLongs = function (s) { // convert string to array of longs, each containing 4 chars
2230    // note chars must be within ISO-8859-1 (with Unicode code-point < 256) to fit 4/long
2231    const l = new Array(Math.ceil(s.length / 4));
2232    for (let i = 0; i < l.length; i++) {
2233      // note little-endian encoding - endianness is irrelevant as long as
2234      // it is the same in longsToStr()
2235      l[i] = s.charCodeAt(i * 4) + (s.charCodeAt(i * 4 + 1) << 8) +
2236                 (s.charCodeAt(i * 4 + 2) << 16) + (s.charCodeAt(i * 4 + 3) << 24);
2237    }
2238    return l; // note running off the end of the string generates nulls since
2239  }; // bitwise operators treat NaN as 0
2240
2241  HigJS.Tea.longsToStr = function (l) { // convert array of longs back to string
2242    const a = new Array(l.length);
2243    for (let i = 0; i < l.length; i++) {
2244      a[i] = String.fromCharCode(l[i] & 0xFF, l[i] >>> 8 & 0xFF,
2245        l[i] >>> 16 & 0xFF, l[i] >>> 24 & 0xFF);
2246    }
2247    return a.join(''); // use Array.join() rather than repeated string appends for efficiency in IE
2248  };
2249
2250  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
2251  /*  Base64 class: Base 64 encoding / decoding (c) Chris Veness 2002-2012                          */
2252  /*    note: depends on Utf8 class                                                                 */
2253  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
2254  /**
2255   * Base64 Functions
2256   * @module Base64
2257  */
2258  HigJS.Base64 = {};
2259  HigJS.Base64.code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
2260
2261  /**
2262   * Encode string into Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648]
2263   * (instance method extending String object). As per RFC 4648, no newlines are added.
2264   * @memberof module:Base64
2265   *
2266   * @param {string} str - The string to be encoded as base-64
2267   * @param {boolean} [utf8encode=false] - Flag to indicate whether str is Unicode string to be encoded to UTF8 before conversion to base64; otherwise string is assumed to be 8-bit characters
2268   * @returns {string} Base64-encoded string
2269   */
2270  HigJS.Base64.encode = function (str, utf8encode) { // http://tools.ietf.org/html/rfc4648
2271    utf8encode = (typeof utf8encode === 'undefined') ? false : utf8encode;
2272    let o1; let o2; let o3; let bits; let h1; let h2; let h3; let h4; const e = []; let pad = ''; let c; let plain; let coded;
2273    const b64 = HigJS.Base64.code;
2274
2275    plain = utf8encode ? HigJS.Utf8.encode(str) : str;
2276
2277    c = plain.length % 3; // pad string to length of multiple of 3
2278    if (c > 0) { while (c++ < 3) { pad += '='; plain += '\0'; } }
2279    // note: doing padding here saves us doing special-case packing for trailing 1 or 2 chars
2280
2281    for (c = 0; c < plain.length; c += 3) { // pack three octets into four hexets
2282      o1 = plain.charCodeAt(c);
2283      o2 = plain.charCodeAt(c + 1);
2284      o3 = plain.charCodeAt(c + 2);
2285
2286      bits = o1 << 16 | o2 << 8 | o3;
2287
2288      h1 = bits >> 18 & 0x3f;
2289      h2 = bits >> 12 & 0x3f;
2290      h3 = bits >> 6 & 0x3f;
2291      h4 = bits & 0x3f;
2292
2293      // use hextets to index into code string
2294      e[c / 3] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
2295    }
2296    coded = e.join(''); // join() is far faster than repeated string concatenation in IE
2297
2298    // replace 'A's from padded nulls with '='s
2299    coded = coded.slice(0, coded.length - pad.length) + pad;
2300
2301    return coded;
2302  };
2303
2304  /**
2305   * Decode string from Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648]
2306   * (instance method extending String object). As per RFC 4648, newlines are not catered for.
2307   * @memberof module:Base64
2308   *
2309   * @param {string}  str                - The string to be decoded from base-64
2310   * @param {boolean} [utf8decode=false] - Flag to indicate whether str is Unicode string to be decoded from UTF8 after conversion from base64
2311   * @returns {string} decoded string
2312   */
2313  HigJS.Base64.decode = function (str, utf8decode) {
2314    utf8decode = (typeof utf8decode === 'undefined') ? false : utf8decode;
2315    let o1; let o2; let o3; let h1; let h2; let h3; let h4; let bits; const d = []; let plain; let coded;
2316    const b64 = HigJS.Base64.code;
2317
2318    coded = utf8decode ? HigJS.Utf8.decode(str) : str;
2319
2320    for (let c = 0; c < coded.length; c += 4) { // unpack four hexets into three octets
2321      h1 = b64.indexOf(coded.charAt(c));
2322      h2 = b64.indexOf(coded.charAt(c + 1));
2323      h3 = b64.indexOf(coded.charAt(c + 2));
2324      h4 = b64.indexOf(coded.charAt(c + 3));
2325
2326      bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
2327
2328      o1 = bits >>> 16 & 0xff;
2329      o2 = bits >>> 8 & 0xff;
2330      o3 = bits & 0xff;
2331
2332      d[c / 4] = String.fromCharCode(o1, o2, o3);
2333      // check for padding
2334      if (h4 == 0x40) d[c / 4] = String.fromCharCode(o1, o2);
2335      if (h3 == 0x40) d[c / 4] = String.fromCharCode(o1);
2336    }
2337    plain = d.join(''); // join() is far faster than repeated string concatenation in IE
2338
2339    return utf8decode ? HigJS.Utf8.decode(plain) : plain;
2340  };
2341
2342  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
2343  /*  Utf8 class: encode / decode between multi-byte Unicode characters and UTF-8 multiple          */
2344  /*              single-byte character encoding (c) Chris Veness 2002-2012                         */
2345  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
2346  /**
2347   * Utf8 Functions
2348   * @module Utf8
2349  */
2350  HigJS.Utf8 = {}; // Utf8 namespace
2351
2352  /**
2353   * Encode multi-byte Unicode string into utf-8 multiple single-byte characters
2354   * (BMP / basic multilingual plane only)
2355   *
2356   * Chars in range U+0080 - U+07FF are encoded in 2 chars, U+0800 - U+FFFF in 3 chars
2357   * 
2358   * @memberof module:Utf8
2359   *
2360   * @param {string} strUni - Unicode string to be encoded as UTF8
2361   *
2362   * @returns {string} encoded - string
2363   */
2364  HigJS.Utf8.encode = function (strUni) {
2365    // use regular expressions & String.replace callback function for better efficiency
2366    // than procedural approaches
2367    let strUtf = strUni.replace(
2368      /[\u0080-\u07ff]/g, // U+0080 - U+07FF => 2 bytes 110yyyyy, 10zzzzzz
2369      function (c) {
2370        const cc = c.charCodeAt(0);
2371        return String.fromCharCode(0xc0 | cc >> 6, 0x80 | cc & 0x3f);
2372      }
2373    );
2374    strUtf = strUtf.replace(
2375      /[\u0800-\uffff]/g, // U+0800 - U+FFFF => 3 bytes 1110xxxx, 10yyyyyy, 10zzzzzz
2376      function (c) {
2377        const cc = c.charCodeAt(0);
2378        return String.fromCharCode(0xe0 | cc >> 12, 0x80 | cc >> 6 & 0x3F, 0x80 | cc & 0x3f);
2379      }
2380    );
2381    return strUtf;
2382  };
2383
2384  /**
2385   * Decode utf-8 encoded string back into multi-byte Unicode characters
2386   * @memberof module:Utf8
2387   *
2388   * @param {string} strUtf - UTF-8 string to be decoded back to Unicode
2389   *
2390   * @returns {string} decoded - string
2391   */
2392  HigJS.Utf8.decode = function (strUtf) {
2393    // note: decode 3-byte chars first as decoded 2-byte strings could appear to be 3-byte char!
2394    let strUni = strUtf.replace(
2395      /[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars
2396      function (c) { // (note parentheses for precence)
2397        const cc = ((c.charCodeAt(0) & 0x0f) << 12) | ((c.charCodeAt(1) & 0x3f) << 6) | (c.charCodeAt(2) & 0x3f);
2398        return String.fromCharCode(cc);
2399      }
2400    );
2401    strUni = strUni.replace(
2402      /[\u00c0-\u00df][\u0080-\u00bf]/g, // 2-byte chars
2403      function (c) { // (note parentheses for precence)
2404        const cc = (c.charCodeAt(0) & 0x1f) << 6 | c.charCodeAt(1) & 0x3f;
2405        return String.fromCharCode(cc);
2406      }
2407    );
2408    return strUni;
2409  };
2410
2411  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
2412  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
2413
2414  /**
2415   * ajax Functions
2416   * @module ajax
2417  */
2418
2419  // Our Global Object
2420  HigJS.ajax = {};
2421
2422  // Current version.
2423  HigJS.ajax.VERSION = '0.0.1';
2424
2425  // --------------------------
2426  //
2427  // ajax Only extensions to HigJS
2428  //
2429  // --------------------------
2430
2431  HigJS.ajax.post = function (opt) {
2432    const request = new window.XMLHttpRequest();
2433    // request.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
2434    request.open('POST', opt.url, true);
2435    // request.onreadystatechange = opt.onSuccess;
2436    request.onload = function () {
2437      let response;
2438      if (!request.readyState == XMLHttpRequest.DONE) {
2439        return;
2440      } else if (request.status !== 200) {
2441        opt.onError && opt.onError(request);
2442        return;
2443      }
2444
2445      if (opt.forceTeaEncryption && typeof request.responseText === 'string') {
2446        let msgTmp = HigJS.Tea.decrypt(request.responseText, 'SR0cM+3pitFygtrA');
2447        msgTmp = HigJS.str.toObj(msgTmp);
2448        msgTmp && (response = msgTmp);
2449        try { typeof sysConf !== 'undefined' && sysConf.debug && console.log(response); } catch (e) {}
2450      } else {
2451        response = HigJS.str.toObj(request.responseText) || request.responseText;
2452      }
2453
2454      try {
2455        if (response.DATI[0].ERR == 401) {
2456          alert(HigJS.diz ? HigJS.diz.edw('sessionExpired') : 'Session expired');
2457          window.top.location.reload();
2458        }
2459      } catch (e) {
2460        console.error('Session expired error');
2461      }
2462
2463      opt.onSuccess && opt.onSuccess(response);
2464    };
2465    request.ontimeout = function () {
2466      if (opt.onTimeout) {
2467        opt.onTimeout();
2468      } else if (opt.onError) {
2469        opt.onError();
2470      }
2471    };
2472    request.setRequestHeader('Accept', 'application/json, text/javascript, */*; q=0.01');
2473    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
2474    request.onerror = opt.onError;
2475    request.onloadend = opt.onComplete;
2476    request.onabort = opt.onAbort;
2477    request.onprogress = opt.onProgress;
2478    request.upload.onprogress = opt.onUploadProgress;
2479    opt.timeout && (request.timeout = opt.timeout);
2480    request.send(opt.data);
2481    return request;
2482  };
2483
2484  HigJS.ajax.request = function (opt) {
2485    if (!opt.reqs) {
2486      opt.reqs = [{
2487        act: opt.act,
2488        idReq: opt.idReq || 1,
2489        data: opt.data || {}
2490      }];
2491    }
2492
2493    const objJson = []; var i; let datiPost;
2494    for (var i = 0; i < opt.reqs.length; i++) {
2495      opt.reqs[i].idReq = opt.reqs[i].idReq ? opt.reqs[i].idReq : opt.reqs[i].act;
2496      opt.reqs[i].ids = opt.reqs[i].ids ? opt.reqs[i].ids : opt.ids;
2497      opt.reqs[i].DATI = opt.reqs[i].data;
2498      delete opt.reqs[i].data;
2499      objJson.push(opt.reqs[i]);
2500    }
2501
2502    datiPost = 'query=' + encodeURIComponent(HigJS.obj.toString(objJson));
2503
2504    if (opt.forceTeaEncryption) {
2505      try { typeof sysConf !== 'undefined' && sysConf.debug && console.log(HigJS.str.toObj(decodeURIComponent(datiPost).split('query=')[1])); } catch (e) {}
2506      opt.data = HigJS.Tea.encrypt(datiPost, 'SR0cM+3pitFygtrA');
2507    } else {
2508      opt.data = datiPost;
2509    }
2510
2511    return HigJS.ajax.post(opt);
2512  };
2513
2514  /**
2515   * Controlla che l'input sia una funzione.
2516   * @memberof module:ajax
2517   *
2518   * @param {Object}      opt             - Oggetto di configurazione.
2519   * @param {string}      opt.reqs        - Array delle richieste. Es: [{act:"act1",idReq:"idReq",data:{ value: 1 },sn:"GWC-SERIAL"}].
2520   * @param {string}      opt.act         - Url della cgi via server.
2521   * @param {string}      opt.idReq       - (optional) Id richiesta.
2522   * @param {string}      opt.data        - Dati da inviare.
2523   * @param {string}      [opt.sn=gwc.sn] - (optional) Url della cgi via server.
2524   * @param {string}      opt.phpFile     - Url della cgi via server.
2525   * @param {string}      opt.cgi         - Url della cgi in locale.
2526   * @param {string}      opt.source      - Sorgente della richiesta ( gwc/server )
2527   * @param {Function}    opt.onSuccess   - Funzione che viene eseguita in caso di successo.
2528   * @param {Function}    opt.onError     - Funzione che viene eseguita in caso d'errore.
2529   */
2530  HigJS.ajax.gwcRequest = function (opt) {
2531    if (!opt.reqs) {
2532      opt.reqs = [{
2533        act: opt.act,
2534        idReq: opt.idReq || 1,
2535        data: opt.data || {},
2536        sn: opt.sn
2537      }];
2538    }
2539    !opt.phpFile && (opt.phpFile = '/phpScript/deviceServerCgi.php');
2540    !opt.source && (opt.source = 'server');
2541
2542    const objJson = []; let i; let datiPost; let objJsonSer;
2543    for (i = 0; i < opt.reqs.length; i++) {
2544      opt.reqs[i].act == 'getStatus' && (opt.reqs[i].data.localGMT = 1);
2545      objJson.push({ act: opt.reqs[i].act, idReq: opt.reqs[i].idReq, sn: opt.reqs[i].sn || opt.sn || opt.sn, DATI: opt.reqs[i].data });
2546    }
2547
2548    if (HigJS.str.toLowerCase(opt.source) === 'gwc') {
2549      objJsonSer = [{ act: 'getFromGWC', sn: opt.sn, idReq: 'getFromGWC', ids: opt.ids, DATI: { cgi: opt.cgi, queryCgi: objJson } }];
2550      datiPost = 'query=' + encodeURIComponent(HigJS.obj.toString(objJsonSer));
2551      opt.url = '/GWC_V200' + opt.phpFile;
2552      opt.data = datiPost;
2553      return HigJS.ajax.post(opt);
2554    }
2554 else if (HigJS.str.toLowerCase(opt.source) === 'server') {
2555      datiPost = 'query=' + encodeURIComponent(HigJS.obj.toString(objJson));
2556      opt.url = '/GWC_V200' + opt.phpFile;
2557      opt.data = datiPost;
2558      return HigJS.ajax.post(opt);
2559    }
2560  };
2561
2562  HigJS.ajax.formRequest = function (opt) {
2563    if (!opt.reqs) {
2564      opt.reqs = [{
2565        act: opt.act,
2566        idReq: opt.idReq || 1,
2567        data: opt.data || {}
2568      }];
2569    }
2570
2571    const objJson = []; let datiPost;
2572    for (let i = 0; i < opt.reqs.length; i++) {
2573      opt.reqs[i].idReq = opt.reqs[i].idReq ? opt.reqs[i].idReq : opt.reqs[i].act;
2574      opt.reqs[i].ids = opt.reqs[i].ids ? opt.reqs[i].ids : opt.ids;
2575      opt.reqs[i].DATI = opt.reqs[i].data;
2576      delete opt.reqs[i].data;
2577      objJson.push(opt.reqs[i]);
2578    }
2579
2580    const $form = $('<form/>', {
2581      action: opt.url,
2582      target: opt.frameId || 'fakeFrame',
2583      method: 'post',
2584      enctype: 'text/plain'
2585    }).appendTo($('body'));
2586
2587    if (opt.forceTeaEncryption) {
2588      datiPost = 'query=' + encodeURIComponent(HigJS.obj.toString(objJson));
2589      try { typeof sysConf !== 'undefined' && sysConf.debug && console.log(HigJS.str.toObj(decodeURIComponent(datiPost).split('query=')[1])); } catch (e) {}
2590      opt.data = HigJS.Tea.encrypt(datiPost, 'SR0cM+3pitFygtrA');
2591      $('<input/>', { type: 'hidden', name: 'encryptData', value: opt.data, id: 'encryptData' }).appendTo($form);
2592    } else {
2593      datiPost = encodeURIComponent(HigJS.obj.toString(objJson));
2594      $('<input/>', { type: 'hidden', name: 'query', value: datiPost, id: 'query' }).appendTo($form);
2595    }
2596
2597    $form.submit();
2598  };
2599
2600  HigJS.ajax.getFile = function (opt) {
2601    const request = new window.XMLHttpRequest();
2602    request.open('GET', opt.url, true);
2603    opt.timeout && (request.timeout = opt.timeout);
2604    request.onerror = opt.onError;
2605    request.onloadend = opt.onComplete;
2606    request.onload = function () {
2607      if (request.status !== 200) {
2608        opt.onError && opt.onError(request);
2609        return;
2610      }
2611      const response = HigJS.str.toObj(request.responseText) || request.responseText;
2612      opt.onSuccess && opt.onSuccess(response);
2613    };
2614    request.send();
2615  };
2616
2617  HigJS.ajax.checkResponse = function (msg) {
2618    try {
2619      if (!msg) { return { ok: false, errMsg: 'no msg' }; }
2620      if (msg.ERR != 0) {
2621        return { ok: false, errMsg: msg.STRERR };
2622      }
2623      if (HigJS.type.isArray(msg.DATI)) {
2624        for (let i = 0; i < msg.DATI.length; i++) {
2625          if (msg.DATI[i].ERR != 0) {
2626            return { ok: false, errMsg: msg.DATI[i].STRERR };
2627          }
2628        }
2629      }
2630      return { ok: true };
2631    } catch (e) {
2632      return { ok: false, errMsg: 'undefined error' };
2633    }
2634  };
2635
2636  HigJS.ajax.uploadFiles = function (opt, scope) {
2637    let xhr, data, postData;
2638    !scope && (scope = window);
2639    data = new scope.FormData();
2640    xhr = new scope.XMLHttpRequest();
2641
2642    xhr.onload = function () {
2643      let response;
2644      if (!xhr.readyState == XMLHttpRequest.DONE) {
2645        return;
2646      } else if (xhr.status !== 200) {
2647        opt.onError && opt.onError(xhr);
2648        return;
2649      }
2650
2651      if (opt.forceTeaEncryption && typeof xhr.responseText === 'string') {
2652        let msgTmp = HigJS.Tea.decrypt(xhr.responseText, 'SR0cM+3pitFygtrA');
2653        msgTmp = HigJS.str.toObj(msgTmp);
2654        msgTmp && (response = msgTmp);
2655        try { typeof sysConf !== 'undefined' && sysConf.debug && console.log(response); } catch (e) {}
2656      } else {
2657        response = HigJS.str.toObj(xhr.responseText) || xhr.responseText;
2658      }
2659
2660      try {
2661        if (response.DATI[0].ERR == 401) {
2662          alert(HigJS.diz ? HigJS.diz.edw('sessionExpired') : 'Session expired');
2663          scope.top.location.reload();
2664        }
2665      } catch (e) {
2666        console.error('Session expired error');
2667      }
2668
2669      opt.onSuccess && opt.onSuccess(response);
2670    };
2671
2672    xhr.ontimeout = function () {
2673      if (opt.onTimeout) {
2674        opt.onTimeout();
2675      } else if (opt.onError) {
2676        opt.onError();
2677      }
2678    };
2679
2680    xhr.upload.onerror = opt.onUploadError || opt.onError;
2681    xhr.upload.onloadend = opt.onUploadComplete;
2682    xhr.upload.onabort = opt.onAbort;
2683    xhr.upload.onprogress = opt.onUploadProgress;
2684    opt.timeout && (xhr.timeout = opt.timeout);
2685
2686    if (!opt.reqs) {
2687      opt.reqs = [{
2688        act: opt.act,
2689        idReq: opt.idReq || 1,
2690        data: opt.data || {}
2691      }];
2692    }
2693    postData = [];
2694    for (var i = 0; i < opt.reqs.length; i++) {
2695      opt.reqs[i].idReq = opt.reqs[i].idReq ? opt.reqs[i].idReq : opt.reqs[i].act;
2696      opt.reqs[i].ids = opt.reqs[i].ids ? opt.reqs[i].ids : opt.ids;
2697      opt.reqs[i].DATI = opt.reqs[i].data;
2698      delete opt.reqs[i].data;
2699      postData.push(opt.reqs[i]);
2700    }
2701    postData = 'query=' + encodeURIComponent(HigJS.obj.toString(postData));
2702    if (opt.forceTeaEncryption) {
2703      try {
2704        typeof sysConf !== 'undefined' && sysConf.debug && console.log(HigJS.str.toObj(decodeURIComponent(postData).split('query=')[1]));
2705      } catch (e) {}
2706
2707      postData = HigJS.Tea.encrypt(postData, 'SR0cM+3pitFygtrA');
2708    }
2709
2710    data.append('query', postData);
2711
2712    if (opt.files) {
2713      !(scope.Array.isArray(opt.files) || opt.files instanceof scope.FileList) && (opt.files = [opt.files]);
2714      for (var i = 0; i < opt.files.length; i++) {
2715        data.append('file_' + i, opt.files[i]);
2716      }
2717    }
2718
2719    xhr.open('POST', opt.url, true);
2720    xhr.send(data);
2721    return xhr;
2722  };
2723
2724  HigJS.ajax.downloadFile = function (opt, scope) {
2725    let xhr, ERR_CTYPES;
2726    ERR_CTYPES = /^ *$|undefined|null|false|^text\/?/i;
2727    !scope && (scope = window);
2728    if (!opt.reqs) {
2729      opt.reqs = [{
2730        act: opt.act,
2731        idReq: opt.idReq || 1,
2732        data: opt.data || {}
2733      }];
2734    }
2735    opt.fileName = opt.fileName || 'download';
2736
2737    if (!opt.ids) opt.ids = window?.userConf?.ids;
2738
2739    const objJson = []; var i; let datiPost;
2740    for (var i = 0; i < opt.reqs.length; i++) {
2741      opt.reqs[i].idReq = opt.reqs[i].idReq ? opt.reqs[i].idReq : opt.reqs[i].act;
2742      opt.reqs[i].ids = opt.reqs[i].ids ? opt.reqs[i].ids : opt.ids;
2743      opt.reqs[i].DATI = opt.reqs[i].data;
2744      delete opt.reqs[i].data;
2745      objJson.push(opt.reqs[i]);
2746    }
2747
2748    datiPost = 'query=' + encodeURIComponent(HigJS.obj.toString(objJson));
2749
2750    if (opt.forceTeaEncryption) {
2751      try { typeof sysConf !== 'undefined' && sysConf.debug && console.log(HigJS.str.toObj(decodeURIComponent(datiPost).split('query=')[1])); } catch (e) {}
2752      opt.data = HigJS.Tea.encrypt(datiPost, 'SR0cM+3pitFygtrA');
2753    } else {
2754      opt.data = datiPost;
2755    }
2756
2757    xhr = new scope.XMLHttpRequest();
2758
2759    xhr.responseType = 'arraybuffer';
2760
2761    opt.timeout && (xhr.timeout = opt.timeout);
2762
2763    xhr.ontimeout = function (e) {
2764      if (opt.onTimeout) return opt.onTimeout();
2765      else opt.onError && opt.onError();
2766    };
2767
2768    xhr.onreadystatechange = function (e) {
2769      if (this.readyState == XMLHttpRequest.DONE) {
2770        if (this.status != 200) {
2771          opt.onError && opt.onError(this);
2772        } else {
2773          let blob, link, ctype;
2774          ctype = String(this.getResponseHeader('content-type'));
2775          if (!ERR_CTYPES.test(ctype)) {
2776            blob = new Blob([this.response], {});
2777            link = document.createElement('a');
2778            link.setAttribute('href', URL.createObjectURL(blob));
2779            let filename;
2780            filename = String(this.getResponseHeader('content-disposition'));
2781            filename = filename.match(/filename=(["'])(.*)\1/i);
2782            filename = (filename && filename.length == 3) ? filename[2] : opt.fileName;
2783            link.download = filename;
2784            link.style.display = 'none';
2785            document.body.append(link);
2786            link.click();
2787            opt.onSuccess && opt.onSuccess();
2788            if (link.remove) {
2789              link.remove();
2790            } else {
2791              link.parentNode && link.parentNode.removeChild(link);
2792            }
2793          } else {
2794            let response;
2795            response = decodeArrayBuffer(this.response);
2796            if (opt.forceTeaEncryption) {
2797              let msgTmp = HigJS.Tea.decrypt(response, 'SR0cM+3pitFygtrA');
2798              msgTmp = HigJS.str.toObj(msgTmp);
2799              msgTmp && (response = msgTmp);
2800              try { typeof sysConf !== 'undefined' && sysConf.debug && console.log(response); } catch (e) {}
2801            } else {
2802              response = HigJS.str.toObj(xhr.responseText) || xhr.responseText;
2803            }
2804            opt.onError && opt.onError(response);
2805          }
2806        }
2807        opt.onComplete && opt.onComplete(this);
2808      }
2809    };
2810
2811    xhr.onprogress = function (e) {
2812      if (e.lengthComputable && opt.onProgress) {
2813        let progress;
2814        progress = e.loaded / e.total * 100;
2815        opt.onProgress && opt.onProgress(progress);
2816      }
2817    };
2818
2819    xhr.onerror = opt.onError;
2820    xhr.onabort = opt.onAbort;
2821
2822    xhr.open('POST', opt.url);
2823    xhr.send(opt.data);
2824    return xhr;
2825    function decodeArrayBuffer (buf) {
2826      let string, dView;
2827
2828      if (TextDecoder) {
2829        dView = new DataView(buf);
2830        string = (new TextDecoder('utf-8')).decode(dView);
2831      } else {
2832        string = String.fromCharCode.apply(null, new Uint8Array(buf));
2833      }
2834
2835      return string;
2836    }
2837  };
2838
2839  HigJS.ajax.downloadFileWithToken = function (opts) {
2840    return HigJS.ajax.request({
2841      reqs: HigJS.obj.clone(opts.statusReqs),
2842      ids: userConf.ids,
2843      url: opts.url,
2844      onSuccess: function (msg) {
2845        let error;
2846        error = HigJS.ajax.checkResponse(msg).ok;
2847
2848        if (!error) {
2849          HigJS.debug.error(error);
2850          typeof opts.onError === 'function' && opts.onError(error);
2851        }
2852
2853        msg = (msg && msg.DATI && msg.DATI[0] && msg.DATI[0].DATI) || {};
2854
2855        if (msg.status) {
2856          if (!msg.status.complete) {
2857            typeof opts.onStatusProgress === 'function' && opts.onStatusProgress(msg);
2858            setTimeout(function () { HigJS.ajax.downloadFileWithToken(opts); }, opts.statusTimeout || 1000);
2859          } else if (msg.status.complete && !msg.status.fail) {
2860            typeof opts.onStatusProgress === 'function' && opts.onStatusProgress(msg);
2861            HigJS.ajax.downloadFile(opts);
2862          } else {
2863            HigJS.debug.error(msg.status.err);
2864            typeof opts.onError === 'function' && opts.onError(msg.status.err);
2865          }
2866        } else {
2867          typeof opts.onError === 'function' && opts.onError('impossibleToRetrieveData');
2868        }
2869      },
2870      onError: function (err) {
2871        typeof opts.onError === 'function' && opts.onError(err);
2872      }
2873    });
2874  };
2875
2876  HigJS.ajax.execCgi = function (opts, callback) {
2877    return new Promise(function (res, rej) {
2878      HigJS.forms.startLoader({ imgPath: pageConf.imgPath, appendTo: $('body'), zIndex: 5000 });
2879      HigJS.ajax.request({
2880        reqs: opts.req,
2881        ids: userConf.ids,
2882        onSuccess: function (msg) {
2883          HigJS.forms.stopLoader();
2884          (typeof (callback) === 'function') && callback(msg);
2885          return res(msg);
2886        },
2887        onError: function (msg) {
2888          HigJS.forms.stopLoader();
2889          return rej(msg);
2890        },
2891        url: opts.target
2892      });
2893    });
2894  };
2895
2896  HigJS.ajax.getConfigJSON = function (url, backurl) {
2897    return new Promise(function (rs, rj) {
2898      let xhr;
2899      xhr = new XMLHttpRequest();
2900      xhr.open('GET', url);
2901      xhr.responseType = 'json';
2902
2903      xhr.onreadystatechange = function (e) {
2904        if (this.readyState == XMLHttpRequest.DONE) {
2905          if (this.status != 200) {
2906            rj(e);
2907          } else {
2908            rs(this.response);
2909          }
2910        }
2911      };
2912
2913      xhr.addEventListener('timeout', rj);
2914      xhr.addEventListener('error', rj);
2915      xhr.send();
2916    }).then(function (config) {
2917      if (config === null) {
2918        if (backurl) {
2919          console.warn('Invalid configuration JSON! Falling back to default config in ' + backurl + '...');
2920          return HigJS.ajax.getConfigJSON(backurl);
2921        } else {
2922          return Promise.reject('Invalid JSON, no fallback!');
2923        }
2924      } else {
2925        return config;
2926      }
2927    }).catch(function (err) {
2928      if (backurl) {
2929        console.warn('Error retrieving configuration JSON! Falling back to default config in ' + backurl + '...');
2930        return HigJS.ajax.getConfigJSON(backurl);
2931      } else {
2932        return Promise.reject(err);
2933      }
2934    });
2935  };
2936
2937  HigJS.ajax.loadDiz = function (ids) {
2938    return new Promise(function (resolve, reject) {
2939      !Array.isArray(ids) && (ids = [ids]);
2940      const reqs = [];
2941
2942      ids.length && ids.forEach(function (id) {
2943        if (typeof id === 'string' && !sysConf.diz[id]) {
2944          reqs.push({ act: 'readDiz', idReq: id, data: { langId: userConf.langId, groupId: id } });
2945        }
2946      });
2947
2948      if (reqs.length) {
2949        HigJS.ajax.request({
2950          reqs: reqs,
2951          ids: userConf.ids,
2952          onSuccess: function (msg) {
2953            if (!HigJS.ajax.checkResponse(msg).ok) {
2954              HigJS.debug.error(HigJS.ajax.checkResponse(msg).errMsg);
2955              HigJS.DOM.alert(edw('errorOnReadData'));
2956              return reject(HigJS.ajax.checkResponse(msg).errMsg);
2957            }
2958            let tmp;
2959            for (let i = 0; i < msg.DATI.length; i++) {
2960              if (msg.DATI[i].act == 'readDiz') {
2961                !msg.DATI[i].DATI.langs[userConf.langId][msg.DATI[i].idReq] && (msg.DATI[i].DATI.langs[userConf.langId][msg.DATI[i].idReq] = {});
2962                sysConf.diz[msg.DATI[i].idReq] = msg.DATI[i].DATI.langs[userConf.langId][msg.DATI[i].idReq];
2963              }
2964            }
2965
2966            ids.length && ids.forEach(function (id) {
2967              if (typeof id === 'string' && sysConf.diz[id]) {
2968                diz = HigJS.obj.extendAdv(diz, sysConf.diz[id]);
2969              }
2970            });
2971
2972            resolve();
2973          },
2974          url: '/PHP/phpScript/user.php'
2975        });
2976      } else {
2977        ids.length && ids.forEach(function (id) {
2978          if (typeof id === 'string' && sysConf.diz[id]) {
2979            diz = HigJS.obj.extendAdv(diz, sysConf.diz[id]);
2980          }
2981        });
2982        resolve();
2983      }
2984    });
2985  };
2986}.call(this));
2987
2988
2989/*
2990 ┌──────────────────────────────────────────────────────┐
2991 │█┌──────────────────────────────────────────────────┐█│
2992 │█│  hih-dom.js                                      │█│
2993 │█│                                                  │█│
2994 │█│  Higeco JS Framework.                            │█│
2995 │█│  JavaScript and DOM utilities.                   │█│
2996 │█└──────────────────────────────────────────────────┘█│
2997 └──────────────────────────────────────────────────────┘
2998*/
2999
3000(function () {
3001  // --------------------------
3002  //
3003  // INIT
3004  //
3005  // --------------------------
3006
3007  // Establish the root object, `window` in the browser, or `exports` on the server.
3008  const self = this;
3009
3010  // Save bytes in the minified (but not gzipped) version:
3011  const ArrayProto = Array.prototype; const ObjProto = Object.prototype; const FuncProto = Function.prototype;
3012
3013  if (typeof HigJS === void 0 || !HigJS) {
3014    console.error("Missing HigJS base library. Include 'hig.js'");
3015    return null;
3016  }
3017
3018  // Our Global Object
3019  HigJS.DOM = {};
3020
3021  // Current version.
3022  HigJS.DOM.VERSION = '0.0.1';
3023
3024  // --------------------------
3025  //
3026  // DOM Only extensions to HigJS
3027  //
3028  // --------------------------
3029
3030  // --------------------------
3031  // Object create Functions
3032  // --------------------------
3033
3034  /**
3035   * Create a DOM object.
3036   * @param   {object}  opt         Options object.
3037   * @param   {string}  [opt.type]  Type of object to create.
3038   * @param   {object}  [opt.set]   HTML Properties to be set.
3039   * @return  {object}  Returns the DOM object created.
3040   */
3041  HigJS.DOM.create = function (opt) {
3042    if (!(HigJS.type.isObject(opt) && HigJS.type.isString(opt.type))) { return false; }
3043    const newDOM = document.createElement(opt.type);
3044
3045    if (opt.type === 'table') {
3046      const tbl = newDOM; let row; let cell; let i; let j;
3047      for (j = 0; j < opt.rows; j++) {
3048        row = tbl.insertRow(j);
3049        for (i = 0; i < opt.cells; i++) { cell = row.insertCell(i); }
3050      }
3051    } else if (opt.type === 'iframe') {
3052      // translateZ(0) is suggested to turn on GPU rendering on supported hw
3053      // supposed to avoid scrolling slowdown
3054      opt.set = HigJS.obj.extendAdv({
3055        frameborder: 0,
3056        style: {
3057          width: '100%',
3058          height: '100%',
3059          margin: 0,
3060          overflow: 'auto',
3061          webkitTransform: 'translateZ(0)',
3062          mozTransform: 'translateZ(0)',
3063          transform: 'translateZ(0)',
3064          webkitBackfaceVisibility: 'hidden',
3065          mozBackfaceVisibility: 'hidden',
3066          backfaceVisibility: 'hidden',
3067          webkitPerspective: 1000,
3068          mozPerspective: 1000,
3069          perspective: 1000
3070        }
3071      }, opt.set || {});
3072    }
3073
3074    HigJS.type.isObject(opt.set) && HigJS.DOM.setProperties(newDOM, opt.set);
3075
3076    return newDOM;
3077  };
3078
3079  /**
3080   * Sets html properties of a DOM element
3081   * Some attributes need to be setted with .setAttribute():
3082   *   • name
3083   *   • frameborder
3084   * @param   {object}  [el]      DOM element.
3085   * @param   {object}  [props]   HTML Properties object.
3086   */
3087  HigJS.DOM.setProperties = function (el, props) {
3088    if (!el) { return; }
3089    for (const k in props) {
3090      if (HigJS.type.isObject(props[k])) { HigJS.DOM.setProperties(el[k], props[k]); continue; }
3091      // Some properties need to be set with .setAttribute
3092      (k === 'name' || k === 'frameborder' || k === 'class') ? el.setAttribute(k, props[k]) : (el[k] = props[k]);
3093    }
3094  };
3095
3096  /**
3097   * Alias for HigJS.DOM.setProperties
3098   */
3099  HigJS.DOM.set = HigJS.DOM.setProperties;
3100
3101  /**
3102   * Remove all content ans children of a DOM element
3103   * @param   {Object}  element  DOM element to empty
3104   */
3105  HigJS.DOM.empty = function (element) {
3106    if (!HigJS.type.isDOM(element)) { return; }
3107    while (element.firstChild) { element.removeChild(element.firstChild); }
3108  };
3109
3110  /**
3111   * Remove the selected DOM element from is parent
3112   * @param   {Object}  element  DOM element to empty
3113   */
3114  HigJS.DOM.remove = function (element) {
3115    HigJS.type.isDOM(element) && element.parentElement && element.parentElement.removeChild(element);
3116  };
3117
3118  /**
3119   * Create a customized alert window.
3120   * @param   {string}  msg  Text to show on the alert box.
3121   */
3122  HigJS.DOM.alert = function (msg) {
3123    return alert(msg);
3124  };
3125
3126  /**
3127   * Create a customized confirm window.
3128   * @param   {string}    msg  Text to show on the confirm box.
3129   * @return  {boolean}   Returns the responce.
3130   */
3131  HigJS.DOM.confirm = function (msg) {
3132    return confirm(msg);
3133  };
3134
3135  /**
3136   * Create a customized confirm window.
3137   * @param   {objesct}   sheet     Stylesheet to modify.
3138   * @param   {string}    selector  CSS selector.
3139   * @param   {string}    rules     CSS rules to add.
3140   * @param   {number}    index     index.
3141   * @return  {object}   Returns stylesheet.
3142   */
3143  HigJS.DOM.addCSSRule = function (opt) {
3144    !opt.sheet && (opt.sheet = HigJS.DOM.createStylesheet(opt.document));
3145    // !opt.index && ( opt.index = -1);
3146    if ('insertRule' in opt.sheet) {
3147      opt.sheet.insertRule(opt.selector + '{' + opt.rules + '}', opt.index);
3148    } else if ('addRule' in opt.sheet) {
3149      opt.sheet.addRule(opt.selector, opt.rules, opt.index);
3150    }
3151    return opt.sheet;
3152  };
3153
3154  HigJS.DOM.createStylesheet = function (_document) {
3155    !_document && (_document = document);
3156    const style = _document.createElement('style');
3157    // Add a media (and/or media query) here if you'd like!
3158    // style.setAttribute("media", "screen")
3159    // style.setAttribute("media", "only screen and (max-width : 1024px)")
3160
3161    // WebKit hack :(
3162    style.appendChild(_document.createTextNode(''));
3163    // Add the <style> element to the page
3164    _document.head.appendChild(style);
3165    return style.sheet;
3166  };
3167
3168  HigJS.DOM.loadCss = function (opt) {
3169    const fileref = document.createElement('link');
3170    fileref.setAttribute('rel', 'stylesheet');
3171    fileref.setAttribute('type', 'text/css');
3172    fileref.setAttribute('href', opt.fileName);
3173
3174    fileref.onload = opt.onload;
3175    document.getElementsByTagName('head')[0].appendChild(fileref);
3176  };
3177
3178  HigJS.DOM.isDOMElement = function (obj) {
3179    try {
3180      // Using W3 DOM2 (works for FF, Opera and Chrome)
3181      return obj instanceof HTMLElement;
3182    } catch (e) {
3183      // Browsers not supporting W3 DOM2 don't have HTMLElement and
3184      // an exception is thrown and we end up here. Testing some
3185      // properties that all elements have (works on IE7)
3186      return (typeof obj === 'object') &&
3187        (obj.nodeType === 1) && (typeof obj.style === 'object') &&
3188        (typeof obj.ownerDocument === 'object');
3189    }
3190  };
3191
3192  // Our Global Object
3193  const _browser = HigJS.browser = {};
3194
3195  // Current version.
3196  HigJS.browser.VERSION = '0.0.1';
3197
3198  HigJS.browser.isIe = function (opt) {
3199    !opt && (opt = {});
3200
3201    // Per versioni sucessive a IE11
3202    if (navigator.appName == 'Netscape' && navigator.userAgent.indexOf('Trident') > 0 && (opt.version == 11 || !opt.version)) { return true; }
3203
3204    // Per versioni precendeti a IE11
3205    let rv = -1; // Return value assumes failure.
3206    if (navigator.appName == 'Microsoft Internet Explorer') {
3207      const ua = navigator.userAgent;
3208      const re = new RegExp('MSIE ([0-9]{1,}[\.0-9]{0,})');
3209      if (re.exec(ua) != null) { rv = parseFloat(RegExp.$1); }
3210    }
3211
3212    if (opt.version && opt.version == rv) { return true; }
3213
3214    return rv === -1 ? false : rv;
3215  };
3216
3217  HigJS.browser.isMobile = function () {
3218    const agent = navigator.userAgent || navigator.vendor || window.opera;
3219    if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(agent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|
3219sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(agent.substr(0, 4))) { return true; }
3220
3221    const testExp = new RegExp('Android|webOS|iPhone|iPad|BlackBerry|Windows Phone|Opera Mini|IEMobile|Mobile', 'i');
3222    if (testExp.test(navigator.userAgent)) { return true; }
3223
3224    return false;
3225  };
3226
3227  /**
3228   * Extract from the location bar the pairs parameters given, the ones after the '?' sign, as given by window.location.search property
3229   * Exampe: http://localhost/page.html?pluto="minnie"&ids=4&mary="CABLE"
3230   *         { pluto: "minnie", ids: "4", mary: "CABLE" }
3231   * @Note   Actually basic type conversion is supported. The following types are automagically converted:
3232   *          - Number
3233   *          - Object
3234   *          - Array
3235   *
3236   * @param  {string}  str Stringa da trasformare.
3237   * @return object containing key-value pairs read from the url
3238   */
3239  HigJS.browser.getUrlParams = function () {
3240    let urlVars = [];
3241    const params = {};
3242
3243    try { urlVars = (decodeURIComponent(window.location.search).substring(1) || '').split('&'); } catch (e) { HigJS.debug.log('[HigJS.browser.getUrlParams] Failed decoding url search: ' + e.toString()); }
3244
3245    for (let i = 0; i < urlVars.length; i++) {
3246      const strElem = urlVars[i].split('=');
3247      if (strElem.length != 2) { continue; }
3248
3249      let val = strElem[1] || null;
3250      if (HigJS.type.isNumber(val)) { val = Number(val); } else if (HigJS.type.isObject(HigJS.str.toObj(val))) { val = HigJS.str.toObj(val); }
3251
3252      params[strElem[0]] = val;
3253    }
3254
3255    return params;
3256  };
3257
3258  //
3259  // Dom
3260  //
3261
3262  /**
3263   * @function
3264   * @description Dato un colore in hex lo converte in rgb.
3265   * @param {string}      format  Colore espresso in hex.
3266   * @return Oggetto contenente i tre canali rgb.
3267   */
3268  HigJS.str.hexToRgb = function (hex) {
3269    const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
3270    return result
3271      ? {
3272          r: parseInt(result[1], 16),
3273          g: parseInt(result[2], 16),
3274          b: parseInt(result[3], 16)
3275        }
3276      : {
3277          r: parseInt(0, 16),
3278          g: parseInt(0, 16),
3279          b: parseInt(0, 16)
3280        };
3281  };
3282
3283  /**
3284   * Trasforma una stringa json in un oggetto javascript mantenendo le funzioni.
3285   * https://github.com/vkiryukhin/jsonfn
3286   * @param {string}  str Stringa da trasformare.
3287   * @return Oggetto js. In caso di errore null.
3288   */
3289  HigJS.str.parse = function (str, scope, date2obj) {
3290    try {
3291      !scope && (scope = window);
3292
3293      const iso8061 = date2obj ? /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/ : false;
3294      return scope.JSON.parse(str, function (key, value) {
3295        let prefix;
3296
3297        if (typeof value !== 'string') {
3298          return value;
3299        }
3300        if (value.length < 8) {
3301          return value;
3302        }
3303
3304        prefix = value.substring(0, 8);
3305
3306        if (iso8061 && value.match(iso8061)) {
3307          return new scope.Date(value);
3308        }
3309        if (prefix === 'function') {
3310          try {
3311            return scope.eval('(' + value + ')');
3312          } catch (e) { // the eval could fail if the string starts with `function` but is not a js one
3313            return value;
3314          }
3315        }
3316        if (prefix === '_PxEgEr_') {
3317          return scope.eval(value.slice(8));
3318        }
3319
3320        return value;
3321      });
3322    } catch (e) { return null; }
3323  };
3324
3325  /**
3326   * Trasforma un oggetto javascript in una stringa json mantenendo le funzioni.
3327   * https://github.com/vkiryukhin/jsonfn
3328   * @param {object}  obj Oggetto javascript trasformare.
3329   * @return Stringa. In caso di errore stringa vuota.
3330   */
3331  HigJS.obj.stringify = function (obj) {
3332    try {
3333      return JSON.stringify(obj, function (key, value) {
3334        if (value instanceof Function || typeof value === 'function') {
3335          return value.toString();
3336        }
3337        if (value instanceof RegExp) {
3338          return '_PxEgEr_' + value;
3339        }
3340        return value;
3341      });
3342    } catch (e) { return ''; }
3343  };
3344
3345  HigJS.obj.advClone = function (obj, scope) {
3346    !scope && (scope = window);
3347    return HigJS.str.parse(HigJS.obj.stringify(obj), scope);
3348  };
3349
3350  HigJS.obj.removeDomObj = function (obj) {
3351    for (const key in obj) {
3352      if (!obj[key]) { continue; }
3353
3354      if (obj[key].jquery || obj[key].tagName || obj[key].nodeName || key == '$button' || 
3354key == 'pageObj') { delete obj[key]; } else if (typeof obj[key] === 'object') {
3355        HigJS.obj.removeDomObj(obj[key]);
3356      }
3357    }
3358  };
3359}.call(this));
3360
3361
3362/*
3363 ┌──────────────────────────────────────────────────────┐
3364 │█┌──────────────────────────────────────────────────┐█│
3365 │█│  hih-dom.js                                      │█│
3366 │█│                                                  │█│
3367 │█│  Higeco JS Framework.                            │█│
3368 │█│  JavaScript and DOM utilities.                   │█│
3369 │█└──────────────────────────────────────────────────┘█│
3370 └──────────────────────────────────────────────────────┘
3371*/
3372
3373(function () {
3374  // --------------------------
3375  //
3376  // INIT
3377  //
3378  // --------------------------
3379
3380  // Establish the root object, `window` in the browser, or `exports` on the server.
3381  const self = this;
3382
3383  // Save bytes in the minified (but not gzipped) version:
3384  const ArrayProto = Array.prototype; const ObjProto = Object.prototype; const FuncProto = Function.prototype;
3385
3386  if (typeof HigJS === void 0 || !HigJS) {
3387    console.error("Missing HigJS base library. Include 'hig.js'");
3388    return null;
3389  }
3390
3391  // Our Global Object
3392  if (!HigJS.DOM) {
3393    HigJS.DOM = {};
3394    // Current version.
3395    HigJS.DOM.VERSION = '0.0.1';
3396  }
3397}.call(this));
3398
3399
3400/*
3401 ┌──────────────────────────────────────────────────────┐
3402 │█┌──────────────────────────────────────────────────┐█│
3403 │█│  hih-forms.js                                    │█│
3404 │█│                                                  │█│
3405 │█│  Higeco JS Framework.                            │█│
3406 │█│  JavaScript and forms utilities.                 │█│
3407 │█└──────────────────────────────────────────────────┘█│
3408 └──────────────────────────────────────────────────────┘
3409*/
3410
3411(function () {
3412  // --------------------------
3413  //
3414  // INIT
3415  //
3416  // --------------------------
3417
3418  // Establish the root object, `window` in the browser, or `exports` on the server.
3419  const self = this;
3420
3421  // Save bytes in the minified (but not gzipped) version:
3422  const ArrayProto = Array.prototype; const ObjProto = Object.prototype; const FuncProto = Function.prototype;
3423
3424  if (typeof HigJS === void 0 || !HigJS) {
3425    console.error("Missing HigJS base library. Include 'hig.js'");
3426    return null;
3427  }
3428
3429  // Our Global Object
3430  HigJS.forms = {};
3431
3432  // Current version.
3433  HigJS.forms.VERSION = '0.0.1';
3434
3435  // --------------------------
3436  //
3437  // forms Only extensions to HigJS
3438  //
3439  // --------------------------
3440
3441  // --------------------------
3442  // Object create Functions
3443  // --------------------------
3444
3445  /**
3446   * Create a forms object.
3447   * @param   {object}  opt         Options object.
3448   * @param   {string}  [opt.type]  Type of object to create.
3449   * @param   {object}  [opt.set]   HTML Properties to be set.
3450   * @return  {object}  Returns the forms object created.
3451   */
3452  HigJS.forms.create = function (opt) {
3453    if (!(HigJS.type.isObject(opt) && HigJS.type.isString(opt.type))) { return false; }
3454    const newforms = document.createElement(opt.type);
3455
3456    if (opt.type === 'table') {
3457      const tbl = newforms; let row; let cell; let i; let j;
3458      for (j = 0; j < opt.rows; j++) {
3459        row = tbl.insertRow(j);
3460        for (i = 0; i < opt.cells; i++) { cell = row.insertCell(i); }
3461      }
3462    } else if (opt.type === 'iframe') {
3463      // translateZ(0) is suggested to turn on GPU rendering on supp
3463orted hw
3464      // supposed to avoid scrolling slowdown
3465      opt.set = HigJS.obj.extendAdv({
3466        frameborder: 0,
3467        style: {
3468          width: '100%',
3469          height: '100%',
3470          margin: 0,
3471          overflow: 'auto',
3472          webkitTransform: 'translateZ(0)',
3473          mozTransform: 'translateZ(0)',
3474          transform: 'translateZ(0)',
3475          webkitBackfaceVisibility: 'hidden',
3476          mozBackfaceVisibility: 'hidden',
3477          backfaceVisibility: 'hidden',
3478          webkitPerspective: 1000,
3479          mozPerspective: 1000,
3480          perspective: 1000
3481        }
3482      }, opt.set || {});
3483    }
3484
3485    HigJS.type.isObject(opt.set) && HigJS.forms.setProperties(newforms, opt.set);
3486
3487    return newforms;
3488  };
3489
3490  HigJS.forms.optionsConstructor = function (optGen) {
3491    const self = this;
3492
3493    this.init = function (customOpt) {
3494      const defaultOpt = {
3495        optionsTypes: {},
3496        inpWdt: 140,
3497        txtWdt: 140,
3498        inpWdtHalf: 69,
3499        txtWdtHalf: 68,
3500        draw: true,
3501        objAlign: 'left'
3502      };
3503
3504      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
3505      this.options.optionsTypes = customOpt.optionsTypes;
3506      this.options.userDiz = customOpt.userDiz;
3507      this.options.draw && this.draw();
3508      return this;
3509    };
3510
3511    this.draw = function () {
3512      this.$div = $('<div/>', { id: 'div.optionsConstructor' }).appendTo(this.options.appendTo).css({ 'text-align': 'center' });
3513      this.$container = $('<div/>', { id: 'container.optionsConstructor' }).appendTo(this.$div)
3514        .css({ display: 'inline-block', 'text-align': this.options.objAlign, margin: 'auto', width: this.options.width });
3515      this.drawOptFieldsObjects();
3516    };
3517
3518    this.drawOptFieldsObjects = function (opt) {
3519      const optTypes = this.options.optionsTypes; let field; let i;
3520      for (i = 0; i < optTypes.length; i++) {
3521        if (optTypes[i].type === 'sectionTitle') {
3522          this.addSectionTitle(optTypes[i]);
3523        } else if (optTypes[i].type === 'text') {
3524          this.addTextInput(optTypes[i]);
3525        } else if (optTypes[i].type === 'checkbox') {
3526          this.addCheckbox(optTypes[i]);
3527        } else if (optTypes[i].type === 'dizText') {
3528          this.addDizTextInput(optTypes[i]);
3529        } else if (optTypes[i].type === 'select') {
3530          this.addSelect(optTypes[i]);
3531        } else if (optTypes[i].type === 'button') {
3532          this.addButton(optTypes[i]);
3533        } else if (optTypes[i].type == 'valueOptionsChooser') {
3534          this.addValOptChooser(optTypes[i]);
3535        } else if (optTypes[i].type == 'dateTimePicker') {
3536          this.addDateTimePicker(optTypes[i]);
3537        } else if (optTypes[i].type == 'timePicker') {
3538          this.addTimePicker(optTypes[i]);
3539        } else if (optTypes[i].type == 'uploadFile') {
3540          this.uploadFile(optTypes[i]);
3541        }
3542      }
3543
3544      this.options.optionsTypes.update && this.options.optionsTypes.update();
3545    };
3546
3547    this.addSectionTitle = function (opt) {
3548      opt.confObj = { $div: $('<div/>') };
3549      opt.confObj.$div.appendTo(this.$container)
3550        .addClass('optionsGrpTitle')
3551        .text(opt.label)
3552        .css(opt.css || {});
3553    };
3554
3555    this.addTextInput = function (opt) {
3556      opt.confObj = new HigJS.forms.inputText({
3557        itemCfg: {
3558          label: opt.label,
3559          key: opt.key,
3560          inpWdt: opt.inpWdt || (opt.grp ? this.options.inpWdtHalf : this.options.inpWdt),
3561          txtWdt: opt.txtWdt || (opt.grp ? this.options.txtWdtHalf : this.options.txtWdt),
3562          readOnly: opt.readOnly,
3563          timeout: opt.timeout,
3564          number: opt.number,
3565          upperLbl: opt.upperLbl,
3566          textarea: opt.textarea || false,
3567          rows: opt.rows,
3568          cols: opt.cols,
3569          maxlength: opt.maxlength,
3570          maxVal: opt.maxVal,
3571          minVal: opt.minVal,
3572          dataList: opt.dataList
3573        },
3574        saveTo: opt.saveTo,
3575        imgPath: opt.imgPath || this.options.imgPath,
3576        appendTo: $('<div/>').appendTo(this.$container).addClass('optionField'),
3577        onChange: opt.onChange,
3578        checkInput: opt.checkInput,
3579        onEnter: opt.onEnter,
3580        onSave: opt.onSave || function (val) { return val; }
3581      });
3582    };
3583
3584    this.addDizTextInput = function (opt) {
3585      const options = this.options;
3586
3587      opt.saveTo[opt.key] = opt.saveTo[opt.key] || HigJS.diz.encodeDizIdFromString(opt.key + '_' + parseInt(new Date().getTime() / 1000) + HigJS.num.genNum());
3588      opt.confObj = new HigJS.forms.inputText({
3589        itemCfg: {
3590          label: opt.label,
3591          key: opt.key,
3592          inpWdt: opt.grp ? options.inpWdtHalf : options.inpWdt,
3593          txtWdt: opt.grp ? options.txtWdtHalf : options.txtWdt,
3594          upperLbl: opt.upperLbl,
3595          timeout: opt.timeout,
3596          readOnly: opt.readOnly
3597        },
3598        saveTo: opt.saveTo,
3599        langs: options.langs,
3600        langsLbl: options.langsLbl,
3601        defLang: options.defLang,
3602        diz: options.userDiz,
3603        imgPath: options.imgPath,
3604        appendTo: $('<div/>').appendTo(this.$container).addClass('optionField'),
3605        onChange: opt.onChange
3606      });
3607    };
3608
3609    this.addCheckbox = function (opt) {
3610      opt.confObj = new HigJS.forms.checkBox({
3611        itemCfg: {
3612          label: opt.label,
3613          key: opt.key,
3614          inpWdt: opt.inpWdt || (opt.grp ? this.options.inpWdtHalf : this.options.inpWdt),
3615          txtWdt: opt.txtWdt || (opt.grp ? this.options.txtWdtHalf : this.options.txtWdt),
3616          position: opt.position || false,
3617          readOnly: opt.readOnly,
3618          upperLbl: opt.upperLbl
3619        },
3620        saveTo: opt.saveTo,
3621        appendTo: $('<div/>').appendTo(this.$container).addClass('optionField'),
3622        onChange: opt.onChange
3623      });
3624    };
3625
3626    this.addSelect = function (opt) {
3627      opt.confObj = new HigJS.forms.menuSel({
3628        itemCfg: {
3629          label: opt.label,
3630          key: opt.key,
3631          items: opt.items,
3632          itemsId: opt.itemsId,
3633          categories: opt.categories,
3634          inpWdt: opt.inpWdt || (opt.grp ? this.options.inpWdtHalf : this.options.inpWdt),
3635          txtWdt: opt.txtWdt || (opt.grp ? this.options.txtWdtHalf : this.options.txtWdt),
3636          readOnly: opt.readOnly,
3637          upperLbl: opt.upperLbl
3638        },
3639        saveTo: opt.saveTo,
3640        appendTo: $('<div/>').appendTo(this.$container).addClass('optionField'),
3641        onChange: opt.onChange
3642      });
3643    };
3644
3645    this.addButton = function (opt) {
3646      opt.confObj = new HigJS.forms.button({
3647        itemCfg: {
3648          label: opt.label,
3649          width: opt.width || this.options.inpWdt,
3650          height: opt.height || 'auto'
3651        },
3652        onClick: opt.onClick || function () { },
3653        appendTo: $('<div/>').appendTo(this.$container).addClass('optionField')
3654      });
3655    };
3656
3657    this.addValOptChooser = function (opt) { // Selezione grandezza
3658      opt.key && !opt.saveTo[opt.key] && (opt.saveTo[opt.key] = {});
3659      opt.confObj = new HigJS.forms.grOptionsChooser({
3660        itemCfg: {
3661          label: opt.label,
3662          disablePlantSel: opt.disablePlantSel,
3663          pluginOnly: opt.pluginOnly,
3664          readOnly: opt.readOnly,
3665          noItems: opt.noItems,
3666          deviceOnly: opt.deviceOnly,
3667          plantId: opt.plantId,
3668          noDevs: opt.noDevs,
3669          idKey: opt.idKey,
3670          umKey: opt.umKey,
3671          offsetKey: opt.offsetKey,
3672          gainKey: opt.gainKey,
3673          nDecKey: opt.nDecKey,
3674          inpWdt: opt.grp ? this.options.inpWdtHalf : this.options.inpWdt,
3675          txtWdt: opt.grp ? this.options.txtWdtHalf : this.options.txtWdt,
3676          umFilter: opt.um
3677        },
3678        lastSelection: opt.lastSelection,
3679        plants: this.options.plants,
3680        onChange: opt.onChange,
3681        saveTo: opt.key ? opt.saveTo[opt.key] : opt.saveTo,
3682        appendTo: $('<div/>').appendTo(this.$container)
3683      });
3684    };
3685
3686    this.addDateTimePicker = function (opt) {
3687      opt.confObj = new HigJS.forms.dateTimePicker({
3688        itemCfg: {
3689          dateLabel: opt.dateLabel,
3690          timeLabel: opt.timeLabel,
3691          key: opt.key,
3692          date: opt.date,
3693          time: opt.time,
3694          localTime: opt.localTime,
3695          inpWdt: opt.grp ? this.options.inpWdtHalf : this.options.inpWdt,
3696          txtWdt: opt.grp ? this.options.txtWdtHalf : this.options.txtWdt
3697        },
3698        saveTo: opt.saveTo,
3699        onChange: opt.onChange,
3700        appendTo: $('<div/>').appendTo(this.$container)
3701      });
3702    };
3703
3704    this.addTimePicker = function (opt) {
3705      opt.confObj = new HigJS.forms.timeSelect({
3706        itemCfg: {
3707          label: opt.label,
3708          key: opt.key,
3709          inpWdt: opt.grp ? this.options.inpWdtHalf : this.options.inpWdt,
3710          txtWdt: opt.grp ? this.options.txtWdtHalf : this.options.txtWdt
3711        },
3712        saveTo: opt.saveTo,
3713        onChange: opt.onChange,
3714        appendTo: $('<div/>').appendTo(this.$container).addClass('optionField')
3715      });
3716    };
3717
3718    this.uploadFile = function (opt) {
3719      opt.confObj = new HigJS.forms.uploadFileForm({
3720        itemCfg: {
3721          label: opt.label,
3722          key: opt.key,
3723          upperLbl: opt.upperLbl,
3724          buttonLbl: opt.buttonLbl,
3725          phpFile: opt.phpFile,
3726          req: opt.req,
3727          inpWdt: opt.grp ? this.options.inpWdtHalf : this.options.inpWdt,
3728          txtWdt: opt.grp ? this.options.txtWdtHalf : this.options.txtWdt
3729        },
3730        saveTo: opt.saveTo,
3731        onClick: opt.onClick,
3732        onSubmit: opt.onSubmit,
3733        appendTo: $('<div/>').appendTo(this.$container).addClass('optionField')
3734      });
3735    };
3736
3737    optGen && this.init(optGen);
3738  };
3739
3740  HigJS.forms.inputText = function (mainOpt) {
3741    const self = this;
3742
3743    this.init = function (customOpt) {
3744      const defaultOpt = {
3745        itemCfg: {
3746          inpWdt: 100,
3747          inpHgt: 20,
3748          txtWdt: 100,
3749          txtHgt: 20,
3750          timeout: 1, // Permette di eseguire la funzione onChange solo ogni "timeout" millisecondi
3751          maxlength: 50,
3752          readOnly: false,
3753          valueId: false, // Id dizionario
3754          upperLbl: false,
3755          password: false,
3756          cols: 30,
3757          rows: 3,
3758          id: HigJS.num.genNum(),
3759          upperLblFont: { 'font-size': 12 },
3760          autocomplete: false,
3761          allowedChars: ''
3762        },
3763        dizPage: false, // Id pagina dizionario
3764        diz: false,
3765        langs: [], // Lista lingue
3766        langsLbl: [], // Lista lingue
3767        imgPath: 'img/',
3768        onSave: function (val) {
3769          // self.options.itemCfg.number && val && ( val = parseFloat(val) );
3770          return val;
3771        },
3772        onShow: function (val) { return val; },
3773        onEnter: false, // Funzione da eseguire alla pressione del tasto enter
3774        checkInput: function (val) { return true; },
3775        draw: true
3776      };
3777
3778      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
3779
3780      if (customOpt.diz) {
3781        this.options.diz = customOpt.diz;
3782        const dizId = HigJS.diz.decodeDizIdFromString(this.options.saveTo[this.options.itemCfg.key]);
3783        if (!this.options.diz[dizId]) {
3784          this.options.diz[dizId] = {};
3785          for (let i = 0; i < this.options.langs.length; i++) { this.options.diz[dizId][this.options.langs[i]] = ''; }
3786        }
3787        this.values = this.options.diz[dizId];
3788      }
3789
3790      this.options.saveTo = customOpt.saveTo;
3791      this.options.draw && this.draw();
3792      return this;
3793    };
3794
3795    this.draw = function () {
3796      const options = this.options; const itemCfg = this.options.itemCfg; let value;
3797
3798      if (!this.$div) {
3799        this.$div = $('<div/>').appendTo(options.appendTo)
3800          .addClass('inputText2')
3801          .css({ 'text-align': 'left' });
3802      } else { this.$div.empty(); }
3803
3804      if (itemCfg.upperLbl) {
3805        this.$label = $('<label/>', { for: itemCfg.id }).appendTo($('<div/>').appendTo(this.$div).css({ 'text-align': 'left' }))
3806          .css(itemCfg.upperLblFont || {})
3807          .text(itemCfg.label);
3808      } else {
3809        this.$label = $('<div/>', { id: 'label' }).appendTo(this.$div)
3810          .text(itemCfg.label);
3811      }
3812
3813      if (itemCfg.txtWdt === 0) { this.$label.css({ display: 'none' }); }
3814
3815      value = options.onShow ? options.onShow(options.saveTo[itemCfg.key]) : options.saveTo[itemCfg.key];
3816      value = options.diz ? HigJS.diz.edwCustom({ word: options.saveTo[itemCfg.key], alt: '---' }) : options.onShow(options.saveTo[itemCfg.key]);
3817      if (itemCfg.password) {
3818        this.$input = $('<input/>', { type: 'password' });
3819      } else if (itemCfg.textarea) {
3820        this.$input = $('<textarea/>').css({ resize: 'none' })
3821          .text(value);
3822      } else {
3823        this.$input = $('<input/>', { type: 'text' });
3824      }
3825
3826      if (itemCfg.dataList) {
3827        this.$input.attr({ list: itemCfg.dataList.id, type: 'search' });
3828        this.$dataList = dl = $('<datalist/>', { id: itemCfg.dataList.id });
3829        itemCfg.dataList.options.forEach(function (o) {
3830          $('<option/>', { value: o }).appendTo(dl);
3831        });
3832      }
3833
3834      this.$input.attr({
3835        // value: itemCfg.textarea ? "" : value,
3836        value: value,
3837        cols: itemCfg.cols,
3838        rows: itemCfg.rows,
3839        maxlength: itemCfg.maxlength,
3840        readonly: itemCfg.readOnly,
3841        id: itemCfg.id,
3842        name: itemCfg.id,
3843        autocomplete: itemCfg.autocomplete ? 'on' : 'off'
3844      }).appendTo(this.$div)
3845        .css({ width: options.diz ? itemCfg.inpWdt - 30 : itemCfg.inpWdt })
3846        .on('keyup cut paste change', function (event) {
3847          self.txtChange();
3848          // Funzione da eseguire al press del tasto Enter
3849          if (options.onEnter) {
3850            if (event.keyCode === 13) {
3851              options.onEnter();
3852              event.preventDefault();
3853            }
3854          }
3855        });
3856
3857      if (this.$dataList) this.$dataList.appendTo(this.$div);
3858
3859      // Aggiungo l'icona per la modifica del dizionario e configuro la finestra di modifica
3860      if (options.diz) {
3861        new HigJS.forms.image({
3862          itemCfg: {
3863            src: options.imgPath + 'books.png', mouseOver: true, height: itemCfg.inpHgt
3864          },
3865          appendTo: $('<div/>', { id: 'img' }).appendTo(this.$div),
3866          onClick: function () {
3867            self.drawLanguageWindow();
3868          }
3869        });
3870      }
3871
3872      this.setSize({ txtWdt: itemCfg.txtWdt, inpWdt: itemCfg.inpWdt });
3873
3874      return this;
3875    };
3876
3877    this.getValue = function () {
3878      let value;
3879      if (this.options.itemCfg.textarea) {
3880        value = this.$input.val();
3881      } else {
3882        value = this.$input[0].value;
3883      }
3884
3885      if (self.options.itemCfg.number) {
3886        // Sostituisco le "," con i "."
3887        // typeof value !== "string" && ( value = value.toString() );
3888        value && (value = value.replace(/,/g, '.'));
3889      }
3890      return value;
3891    };
3892
3893    this.setValue = function (value, opt) {
3894      !opt && (opt = { skipOnChange: 0 });
3895      if (this.options.itemCfg.textarea) {
3896        this.$input.val(value);
3897      } else {
3898        this.$input[0].value = value;
3899      }
3900      this.txtChange({}, opt.skipOnChange);
3901    };
3902
3903    this.txtChange = function (event, skipOnChange) {
3904      let timeout = 0;
3905      if (event && event.type !== 'keyup') {
3906        timeout = 10;
3907      }
3908
3909      // Timeout per salvare il testo inserito con l'incolla da mouse
3910      setTimeout(function () {
3911        const value = self.getValue();
3912        // Nel caso non sia abilitata la gestione del dizionario
3913        if (!self.options.diz) {
3914          self.options.saveTo[self.options.itemCfg.key] = self.options.onSave(value);
3915        } else { // Salvo direttamente nell'oggetto del dizionario
3916          self.values._modified = true;
3917          self.values[self.options.defLang] = self.options.onSave(value);
3918        }
3919
3920        clearTimeout(self.lastSearchTimer);
3921        self.lastSearchTimer = setTimeout(function () {
3922          self.check();
3923          !skipOnChange && self.options.onChange && self.options.onChange(value);
3924        }, self.options.itemCfg.timeout);
3925      }, timeout);
3926    };
3927
3928    this.updateValue = function (value) { this.$input[0].value = value; };
3929
3930    this.setLabel = function (label) {
3931      this.$label.text(label);
3932      this.options.itemCfg.label = label;
3933    };
3934
3935    this.setSize = function (opt) {
3936      const itemCfg = this.options.itemCfg; let inpWdt = itemCfg.inpWdt; let txtWdt = itemCfg.txtWdt; let width;
3937
3938      if (opt.txtWdt || opt.inpWdt) {
3939        inpWdt = parseInt(opt.inpWdt) || itemCfg.inpWdt;
3940        txtWdt = parseInt(opt.txtWdt) || itemCfg.txtWdt;
3941        width = itemCfg.upperLbl ? inpWdt : inpWdt + txtWdt;
3942      } else if (opt.width && itemCfg.upperLbl) {
3943        inpWdt = parseInt(opt.width);
3944        txtWdt = parseInt(opt.width);
3945        width = parseInt(opt.width);
3946      } else if (opt.width && !itemCfg.upperLbl) {
3947        inpWdt = parseInt(opt.width / 2);
3948        txtWdt = parseInt(opt.width / 2);
3949        width = parseInt(opt.width);
3950      }
3951
3952      width = this.options.diz ? width + 32 : width;
3953
3954      this.$label.css({ width: txtWdt });
3955      this.$input.css({ width: inpWdt });
3956      this.$div.css({ width: width });
3957
3958      itemCfg.txtWdt = parseInt(txtWdt);
3959      itemCfg.inpWdt = parseInt(inpWdt);
3960      itemCfg.width = parseInt(width);
3961      return this;
3962    };
3963
3964    this.getSize = function (key) {
3965      const itemCfg = this.options.itemCfg;
3966      if (!key) {
3967        return {
3968          width: itemCfg.upperLbl ? parseInt(itemCfg.inpWdt) : parseInt(itemCfg.txtWdt) + parseInt(itemCfg.inpWdt),
3969          height: 'auto',
3970          txtWdt: parseInt(itemCfg.txtWdt),
3971          inpWdt: parseInt(itemCfg.inpWdt)
3972        };
3973      } else if (key === 'txt') {
3974        return { width: itemCfg.txtWdt, height: 'auto', txtWdt: itemCfg.txtWdt, inpWdt: itemCfg.inpWdt };
3975      } else if (key === 'inp') {
3976        return { width: itemCfg.inpWdt, height: 'auto', txtWdt: itemCfg.txtWdt, inpWdt: itemCfg.inpWdt };
3977      }
3978    };
3979
3980    this.drawLanguageWindow = function () {
3981      const options = this.options; const box = new HigJS.forms.overlayBox({ itemCfg: { small: true } });
3982
3983      const langTable = HigJS.DOM.create({ type: 'table', rows: options.langs.length + 1, cells: 2 });
3984      $(langTable.rows[0]).addClass('titleRow');
3985      $(langTable.rows[0].cells[0]).text(edw('langs'));
3986      $(langTable.rows[0].cells[1]).text(edw('translation'));
3987
3988      box.$container.append(langTable);
3989
3990      for (let i = 0; i < options.langs.length; i++) {
3991        $(langTable.rows[i + 1].cells[0]).text(options.langsLbl[i]);
3992        $(langTable.rows[i + 1]).addClass(i % 2 ? 'oddRow' : 'evenRow');
3993
3994        $('<input/>', { type: 'text', value: self.values[options.langs[i]] }).appendTo(langTable.rows[i + 1].cells[1])
3995          .on('keyup cut paste', (function (i) {
3996            return function () {
3997              self.values[options.langs[i]] = this.value;
3998              self.values._modified = true;
3999              options.langs[i] == options.defLang && (self.setValue(this.value));
4000            };
4001          }(i)));
4002      }
4003
4004      box.$container.append('<br>');
4005      new HigJS.forms.button({
4006        itemCfg: { label: HigJS.diz.edw('OK') },
4007        appendTo: $('<div/>').appendTo(box.$container).css({ 'text-align': 'center' }),
4008        onClick: function () {
4009          box.$div.remove();
4010        }
4011      });
4012    };
4013
4014    // Abilito/Disabilito la proprietà readonly della casella di testo
4015    this.setReadOnly = function (bool) { self.$input.attr({ readonly: bool }); };
4016
4017    // Ritorno Vero/falso in base alla funzione checkinput
4018    this.check = function () {
4019      const options = this.options; let flag = true;
4020      const itemCfg = this.options.itemCfg;
4021      value = this.getValue();
4022
4023      // Funzione che se ritorna true ha la precedenza su tutti gli altri check
4024      if (options.forceValid && options.forceValid(value)) {
4025        self.setStatus(0);
4026        return true;
4027      }
4028
4029      // Funzione che se ritorna false ha la precedenza su tutti gli altri check
4030      if (options.forceInvalid && !options.forceInvalid(value)) { flag = false; }
4031
4032      if (HigJS.str.removeSpaces(value) === '') { return true; }
4033
4034      // Controllo i valori inseriti solo se sono specificati
4035      if (!(itemCfg.allowedChars === '')) {
4036        for (let i = 0; i < value.length; i++) {
4037          if (itemCfg.allowedChars.indexOf(value[i]) < 0) {
4038            flag = false;
4039            break;
4040          }
4041        }
4042      }
4043
4044      // Controllo il valore dell'input in base alla funzione specificata dall'utente
4045      options.checkInput && !options.checkInput(value) && (flag = false);
4046      if (itemCfg.number) {
4047        HigJS.num.isNum(value) === false && (flag = false);
4048        HigJS.num.isNum(itemCfg.minVal) !== false && parseFloat(value) < parseFloat(itemCfg.minVal) && (flag = false);
4049        HigJS.num.isNum(itemCfg.maxVal) !== false && parseFloat(value) > parseFloat(itemCfg.maxVal) && (flag = false);
4050      }
4051
4052      HigJS.num.isNum(itemCfg.minLength) !== false && itemCfg.minLength > value.length && (flag = false);
4053      HigJS.num.isNum(itemCfg.maxLength) !== false && itemCfg.maxLength < value.length && (flag = false);
4054      itemCfg.ipAddress && !HigJS.str.validateIPAddress(value) && (flag = false);
4055      itemCfg.email && !HigJS.str.validateEmail(value) && (flag = false);
4056
4057      if (!flag) {
4058        self.setStatus(1);
4059        return false;
4060      }
4061
4062      // self.$input.removeClass("errorBox");
4063      self.setStatus(0);
4064      return true;
4065    };
4066
4067    /* Da togliere nella prossima versione */
4068    this.setErr = function (flag) {
4069      flag ? self.$input.addClass('errorBox') : self.$input.removeClass('errorBox');
4070    };
4071
4072    this.setStatus = function (flag) {
4073      flag ? self.$input.addClass('errorBox') : self.$input.removeClass('errorBox');
4074    };
4075
4076    mainOpt && this.init(mainOpt);
4077    return this;
4078  };
4079
4080  HigJS.forms.button = function (opt) {
4081    const self = this;
4082    const defcss = 'bottone';
4083
4084    this.init = function (customOpt) {
4085      const defaultOpt = {
4086        itemCfg: {
4087          width: 100,
4088          height: 'auto',
4089          label: 'button',
4090          id: HigJS.num.genNum()
4091        },
4092        cssClass: defcss,
4093        onClick: function (val) { },
4094        draw: true
4095      };
4096
4097      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
4098      this.options.draw && this.draw();
4099      return this;
4100    };
4101
4102    this.draw = function () {
4103      const options = this.options; const itemCfg = this.options.itemCfg; let inpWdt; let value;
4104
4105      this.$button = $('<button/>').appendTo(options.appendTo)
4106        .attr('id', itemCfg.id)
4107        .addClass(options.cssClass)
4108        .css({ width: itemCfg.width, height: itemCfg.height })
4109        .text(itemCfg.label)
4110        .on('click', function (e) {
4111          options.onClick(e);
4112        });
4113
4114      if (options.cssClass === defcss) {
4115        this.$button.hover(function () {
4116          $(this).removeClass(defcss);
4117          $(this).addClass('bottoneSel');
4118        }, function () {
4119          $(this).addClass(defcss);
4120          $(this).removeClass('bottoneSel');
4121        });
4122      }
4123
4124      return this;
4125    };
4126
4127    this.setLabel = function (label) {
4128      this.$button.text(label);
4129      this.options.itemCfg.label = label;
4130    };
4131
4132    this.setSize = function (opt) {
4133      this.$button.css({ width: opt.width, height: opt.height });
4134      return this;
4135    };
4136
4137    this.getSize = function (key) {
4138      const itemCfg = this.options.itemCfg;
4139      return { width: itemCfg.width, height: itemCfg.height };
4140    };
4141
4142    this.setValue = function (value) {
4143      return this;
4144    };
4145
4146    this.updateValue = function (value) {
4147      return this;
4148    };
4149
4150    opt && this.init(opt);
4151    return this;
4152  };
4153
4154  HigJS.forms.shortListOfObjects = function (mainOpt) {
4155    const self = this;
4156
4157    this.init = function (customOpt) {
4158      const defaultOpt = {
4159        columnWidth: [], // Larghezza colonne
4160        columnLabels: [], // Label colonne
4161        enableSearch: true, // Abilita ricerca
4162        appendSearchTo: false, // Oggetto in cui appendere il campo ricerca
4163        searchFields: [], // Colonne su cui eseguire la ricerca
4164        columnToOrder: [], // Colonne su cui abilitare l'ordinamento
4165        dataList: [], // Dati da passare all'oggetto riga
4166        objName: '', // Nome dell'oggetto riga
4167        listClass: ['evenRow', 'oddRow'], // Classi delle righe pari e dispari
4168        titleClass: 'titleRow', // Classe dei titole della tabella
4169        titleLabelsAlign: 'center',
4170        appendTo: false, // Oggetto a cui appendere la tabella
4171        enableAddItem: true, // Abilita pulsante aggiungi
4172        appendAddItemTo: false, // Oggetto in cui inserire il pulsante aggiungi
4173        enableRemoveItem: true, // Abilita pulsante rimuovi
4174        appendRemoveItemTo: false, // Oggetto in cui inserire il pulsante rimuovi
4175        noItemLabel: 'menuSelnoItems', // Stringa in caso di tabella vuota
4176        removeLbl: 'remove', // Label pulsante rimuovi item
4177        addLbl: 'add', // Label pulsante aggiungi item
4178        emptyNewConfig: {}, // Configurazione standard per il nuovo oggetto
4179        imgPath: '../img', // Cartella con le immagini
4180        elValfunc: function (valOpt) { return valOpt.val; }, // Funzione che elabora il valore della cella prima di essere ordinato o filtrato
4181        onDraw: function () { }, // Funzione che viene eseguita alla fine della creazione della tabella
4182        disableCloneList: false,
4183        draw: true,
4184        tableWidth: 0,
4185        minObjToDraw: 50
4186      };
4187
4188      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt);
4189      this.options.id = new Date().getTime();
4190
4191      for (var i = 0; i < this.options.columnWidth.length; i++) { this.options.tableWidth += this.options.columnWidth[i]; }
4192
4193      if (customOpt.containerObj) {
4194        this.options.scrollDiv = customOpt.containerObj.div;
4195        this.options.appendTo = customOpt.containerObj.div;
4196        this.containerObj = customOpt.containerObj;
4197      }
4198
4199      const listCfg = this.options; var i;
4200      // Array di configurazione delle righe
4201      if (this.options.disableCloneList) {
4202        this.itemsList = listCfg.dataList;
4203      } else {
4204        this.itemsList = HigJS.obj.clone(listCfg.dataList);
4205      }
4206
4207      for (i = 0; i < this.itemsList.length; i++) {
4208        // Se l'elemento è un array inserisco iterfaceTableId come ultimo elemento dell'array
4209        if (Array.isArray && Array.isArray(this.itemsList[i])) { this.itemsList[i].push(this.getNewId()); } else { this.itemsList[i].interfaceTableId = this.getNewId(); }
4210      }
4211
4212      this.removedItems = [];
4213
4214      if (this.options.draw) { this.draw(); }
4215    };
4216
4217    this.draw = function () {
4218      const listCfg = this.options; let i;
4219
4220      this.$div = $('<div/>').appendTo(listCfg.appendTo);
4221      this.$titleTableDiv = $('<div/>').appendTo(this.$div);
4222      this.$tableDiv = $('<div/>').appendTo(this.$div);
4223
4224      if (listCfg.enableSearch) {
4225        this.$searchTxt = $('<input/>', { type: 'text', class: 'searchInput' })
4226          .on('keyup paste cut', function (event) {
4227            self.searchWord = this.value;
4228            if (!listCfg.searchFields.length) { return; }
4229
4230            if (event.type == 'paste' || event.type == 'cut') {
4231              const This = this;
4232              setTimeout(function () {
4233                HigJS.forms.filterData({ fields: listCfg.searchFields, data: self.itemsList, searchWord: This.value, func: function (toShow) { self.drawTable(toShow); }, elValfunc: listCfg.elValfunc, searchId: self.options.id });
4234              }, 100);
4235            } else { HigJS.forms.filterData({ fields: listCfg.searchFields, data: self.itemsList, searchWord: this.value, func: function (toShow) { self.drawTable(toShow); }, elValfunc: listCfg.elValfunc, searchId: self.options.id }); }
4236          });
4237
4238        $('<div/>').appendTo(listCfg.appendSearchTo)
4239          .addClass('searchBox')
4240          .css({ 'margin-top': 5, 'margin-right': 5 })
4241          .append(this.$searchTxt)
4242          .append($('<img/>', { src: listCfg.imgPath + '/search.png', class: 'searchIcon' }));
4243      }
4244
4245      // Creazione pulsante remove
4246      if (listCfg.enableRemoveItem) {
4247        this.remButton = new HigJS.forms.button({
4248          itemCfg: {
4249            label: listCfg.removeLbl,
4250            width: 'auto'
4251          },
4252          cssClass: listCfg.buttonClass,
4253          appendTo: listCfg.appendRemoveItemTo,
4254          onClick: function () {
4255            let thisId;
4256            for (let i = 0; i < self.itemsObj.length; i++) {
4257              self.itemsObj[i].$tabDiv.removeClass(listCfg.listClass[0] + ' ' + listCfg.listClass[1])
4258                .addClass(i % 2 ? listCfg.listClass[0] : listCfg.listClass[1]);
4259
4260              if (Array.isArray && Array.isArray(self.itemsObj[i].options.itemCfg)) { thisId = self.itemsObj[i].options.itemCfg[self.itemsObj[i].options.itemCfg.length - 1]; } else { thisId = self.itemsObj[i].options.itemCfg.interfaceTableId; }
4261
4262              if (self.itemsObj[i].$selCkbox && self.itemsObj[i].$selCkbox.attr('checked')) {
4263                if (self.itemsObj[i].remove) {
4264                  if (self.itemsObj[i].remove()) {
4265                    self.removeItem(thisId);
4266                  }
4267                } else {
4268                  self.removeItem(thisId);
4269                }
4270              }
4271            }
4272
4273            self.drawTable(self.itemsList);
4274            listCfg.onRemove && listCfg.onRemove();
4275            self.containerObj && self.containerObj.update(0);
4276          }
4277        });
4278      }
4279      // Oggetto titolo tabella
4280      if (listCfg.columnLabels.length) {
4281        if (listCfg.titleObj) { titleRow = new listCfg.titleObj(); } else if (listCfg.titleObjName) { titleRow = new window[listCfg.titleObjName](); } else { titleRow = new HigJS.forms.simpleListTitleObj(); }
4282        titleRow.init({
4283          itemCfg: { labelsAlign: listCfg.titleLabelsAlign },
4284          appendTo: this.$titleTableDiv,
4285          columnWidth: listCfg.columnWidth,
4286          columnLabels: listCfg.columnLabels,
4287          fieldsId: listCfg.fieldsId,
4288          columnToOrder: listCfg.columnToOrder,
4289          titleClass: listCfg.titleClass,
4290          elValfunc: listCfg.elValfunc,
4291          tableWidth: listCfg.tableWidth,
4292          listObj: this
4293        });
4294      }
4295
4296      // Creazione pulsante aggiungi
4297      if (listCfg.enableAddItem) {
4298        this.addButton = new HigJS.forms.button({
4299          itemCfg: {
4300            label: listCfg.addLbl,
4301            width: 'auto'
4302          },
4303          cssClass: listCfg.buttonClass,
4304          appendTo: listCfg.appendAddItemTo,
4305          onClick: function () {
4306            self.addItem(listCfg.emptyNewConfig);
4307            listCfg.onAdd && listCfg.onAdd();
4308          }
4309        });
4310      }
4311      this.drawTable(this.itemsList);
4312    };
4313
4314    this.drawTable = function (toShow) {
4315      this.itemsObj = []; // Array contenete tutti gli oggetti riga
4316
4317      if (this.$searchTxt && this.$searchTxtFlag && this.$searchTxt.val() && !toShow) {
4318        this.$searchTxtFlag = false;
4319        this.$searchTxt.trigger('keyup');
4320        return;
4321      } else {
4322        this.$searchTxtFlag = true;
4323      }
4324
4325      toShow = toShow || this.itemsList;
4326
4327      const listCfg = this.options; let i; let nColumns; let fields; let j; let titleRow; let plantCounter; let scrolling = false;
4328      const nRow = toShow.length > listCfg.minObjToDraw && self.options.scrollDiv ? listCfg.minObjToDraw : toShow.length;
4329
4330      this.$tableDiv.empty(); this.$tableDiv[0].innerHTML = ''; // Chrome da problemi con empty
4331      this.toShow = toShow;
4332
4333      if (!toShow.length) {
4334        this.$tableDiv.append($('<div/>').text(edw(listCfg.noItemLabel)).addClass('shortListOfObjectsNoItems'));
4335        this.containerObj && this.containerObj.scrollTop(0);
4336        return;
4337      }
4338
4339      // Creo tutte le righe della tabella
4340      for (plantCounter = 0; plantCounter < nRow; plantCounter++) {
4341        if (listCfg.rowObj) { this.itemsObj.push(new listCfg.rowObj()); } else { this.itemsObj.push(new window[listCfg.objName]()); }
4342
4343        this.itemsObj[plantCounter].init({
4344          itemCfg: toShow[plantCounter],
4345          appendTo: this.$tableDiv,
4346          columnWidth: listCfg.columnWidth,
4347          columnLabels: listCfg.columnLabels,
4348          tabClass: plantCounter % 2 ? listCfg.listClass[0] : listCfg.listClass[1],
4349          fieldsId: listCfg.fieldsId,
4350          tableWidth: listCfg.tableWidth,
4351          onSliding: listCfg.onSliding,
4352          listPos: plantCounter,
4353          listObj: this
4354        });
4355      }
4356
4357      if (this.options.scrollDiv) {
4358        function onScroll() {
4359          if (plantCounter >= toShow.length) { return; }
4360          if (listCfg.rowObj) { self.itemsObj.push(new listCfg.rowObj()); } else { self.itemsObj.push(new window[listCfg.objName]()); }
4361          // self.itemsObj.push( new window[ listCfg.objName ]() );
4362          self.itemsObj[plantCounter].init({
4363            itemCfg: toShow[plantCounter],
4364            appendTo: self.$tableDiv,
4365            columnWidth: listCfg.columnWidth,
4366            columnLabels: listCfg.columnLabels,
4367            tabClass: plantCounter % 2 ? listCfg.listClass[0] : listCfg.listClass[1],
4368            fieldsId: listCfg.fieldsId,
4369            tableWidth: listCfg.tableWidth,
4370            onSliding: listCfg.onSliding,
4371            listPos: plantCounter,
4372            listObj: self
4373          });
4374          plantCounter++;
4375          listCfg.onDraw && listCfg.onDraw();
4376        }
4377
4378        self.options.scrollDiv.parent().on('scroll', function (e) {
4379          e.stopPropagation();
4380          e.preventDefault();
4381
4382          if (plantCounter >= toShow.length || scrolling) { return; }
4383
4384          scrolling = true;
4385          for (z = 0; z < 16; z++) { onScroll(); }
4386
4387          setTimeout(function () { scrolling = false; self.containerObj && self.containerObj.update(0); }, 25);
4388        });
4389      }
4390
4391      listCfg.onDraw && listCfg.onDraw();
4392      this.containerObj && this.containerObj.scrollTop(0);
4393    };
4394
4395    this.removeItem = function (id) {
4396      let thisId;
4397      for (let i = 0; i < this.itemsList.length; i++) {
4398        if (Array.isArray && Array.isArray(this.itemsList[i])) { thisId = this.itemsList[i][this.itemsList[i].length - 1]; } else { thisId = this.itemsList[i].interfaceTableId; }
4399
4400        if (thisId == id) {
4401          this.removedItems.push(this.itemsList[i]);
4402          this.itemsList.remove(i);
4403          return;
4404        }
4405      }
4406    };
4407
4408    this.selectAll = function () {
4409      if (!this.toShow && !this.toShow.length) { return; }
4410
4411      this.allStatus = !this.allStatus;
4412
4413      for (let i = 0; i < this.toShow.length; i++) {
4414        if (this.itemsObj[i]) { this.itemsObj[i].select && this.itemsObj[i].select(this.allStatus); } else { this.toShow[i].selected = this.allStatus; }
4415      }
4416    };
4417
4418    this.addItem = function (itemCfg, noRedraw) {
4419      if (HigJS.type.isArray(itemCfg)) {
4420        if (this.options.disableCloneList) {
4421          itemCfg = itemCfg;
4422        } else {
4423          itemCfg = HigJS.obj.clone(itemCfg);
4424        }
4425        itemCfg.push(this.getNewId());
4426        this.itemsList.push(itemCfg);
4427      } else {
4428        if (this.options.disableCloneList) {
4429          itemCfg.interfaceTableId = this.getNewId();
4430          this.itemsList.push(itemCfg);
4431        } else {
4432          this.itemsList.push(HigJS.obj.extendAdv({ interfaceTableId: this.getNewId() }, itemCfg));
4433        }
4434      }
4435      !noRedraw && this.drawTable(self.itemsList);
4436    };
4437
4438    this.replaceList = function (list, noRedraw) {
4439      if (Array.isArray && Array.isArray(list)) {
4440        this.itemsList = [];
4441        for (let i = 0; i < list.length; i++) {
4442          list[i].interfaceTableId = this.getNewId();
4443          this.itemsList.push(this.options.disableCloneList ? list[i] : HigJS.obj.clone(list[i]));
4444        }
4445      }
4446      !noRedraw && this.drawTable(self.itemsList);
4447    };
4448
4449    this.getNewId = function () {
4450      let id = HigJS.num.genNum({ max: 10000000 }); let i;
4451      for (i = 0; i < this.itemsList.length; i++) {
4452        if (this.itemsList[i].interfaceTableId == id) {
4453          i = 0;
4454          id = HigJS.num.genNum({ max: 10000000 });
4455        }
4456      }
4457      return id;
4458    };
4459
4460    this.getValues = function () {
4461      const res = HigJS.obj.clone(this.itemsList);
4462      // Rimuovo le variabili d'ambiente inserite dal sistema
4463      for (let i = 0; i < res.length; i++) {
4464        if (Array.isArray && Array.isArray(res[i])) { res[i] = HigJS.obj.clone(res[i]); res[i].pop(); } // rimuovo l'ultimo elemento che contiene interfaceTableId
4465        else { delete res[i].interfaceTableId; }
4466      }
4467      return res;
4468    };
4469
4470    this.openLastAdded = function () {
4471      this.itemsObj[this.itemsObj.length - 1].slideDown && this.itemsObj[this.itemsObj.length - 1].slideDown();
4472      this.containerObj && this.containerObj.scrollTop(this.options.scrollDiv.height());
4473      this.containerObj && this.containerObj.update();
4474    };
4475
4476    mainOpt && this.init(mainOpt);
4477    return this;
4478  };
4479
4480  HigJS.forms.simpleListTitleObj = function () {
4481    const self = this;
4482
4483    this.init = function (customOpt) {
4484      const defaultOpt = {
4485        itemCfg: { labelsAlign: 'center' },
4486        columnLabels: [],
4487        elValfunc: function (valOpt) { return valOpt.val; },
4488        draw: true
4489      };
4490      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt);
4491
4492      if (this.options.draw) { this.draw(this.itemsList); }
4493    };
4494
4495    this.draw = function () {
4496      const options = this.options; let j;
4497
4498      this.$div = $('<div/>').appendTo(this.options.appendTo);
4499      this.$tabDiv = $('<div/>').appendTo(this.$div).css({ display: 'inline-block', width: options.tableWidth });
4500
4501      const itemsTab = HigJS.DOM.create({ type: 'table', rows: 1, cells: options.columnWidth.length });
4502      this.$itemsTab = $(itemsTab).css({ margin: 'auto', 'text-align': 'left' })
4503        .attr({ cellpadding: 0, cellspacing: 0 })
4504        .appendTo(this.$tabDiv);
4505
4506      $(itemsTab.rows[0]).addClass(options.titleClass);
4507
4508      for (i = 0; i < options.columnLabels.length; i++) {
4509        $(itemsTab.rows[0].cells[i]).css({ width: options.columnWidth[i], 'text-align': options.itemCfg.labelsAlign }).text(options.columnLabels[i]);
4510
4511        for (j = 0; j < options.columnToOrder.length; j++) {
4512          if (options.fieldsId[i] == options.columnToOrder[j]) {
4513            $(itemsTab.rows[0].cells[i]).css({ cursor: 'pointer' })
4514              .on('click', (function (i) {
4515                return function () {
4516                  this.order = this.order ? !this.order : true;
4517                  HigJS.forms.sortDataByFields({
4518                    field: options.fieldsId[i],
4519                    data: self.options.listObj.toShow,
4520                    func: function (toShow) {
4521                      self.options.listObj.drawTable(toShow);
4522                    },
4523                    order: this.order,
4524                    elValfunc: options.elValfunc
4525                  });
4526                };
4527              }(i)));
4528            break;
4529          }
4530        }
4531      }
4532    };
4533
4534    this.remove = function () { return false; };
4535    this.select = function (flag) { return false; };
4536  };
4537
4538  /*
4539  * Ordina una matrice a seconda del campo "field" specificato e dal maggiore al minore o viceversa a seconda del campo order
4540  */
4541  HigJS.forms.sortDataByFields = function (opt) {
4542    let x, y;
4543
4544    if (!opt.data || !opt.data.length || !opt.data[0]/* [ opt.field ] */) {
4545      opt.func && opt.func(opt.data);
4546      return false;
4547    }
4548
4549    opt.data.sort(function (a, b) {
4550      opt.elValfunc ? x = opt.elValfunc({ val: a[opt.field], field: opt.field, obj: a }) : x = a[opt.field];
4551      opt.elValfunc ? y = opt.elValfunc({ val: b[opt.field], field: opt.field, obj: b }) : y = b[opt.field];
4552
4553      try {
4554        x = HigJS.num.isNum(x) ? parseFloat(x) : HigJS.str.toLowerCase(x);
4555        y = HigJS.num.isNum(y) ? parseFloat(y) : HigJS.str.toLowerCase(y);
4556      } catch (e) { }
4557
4558      return opt.order ? ((x < y) ? -1 : ((x > y) ? 1 : 0)) : ((x > y) ? -1 : ((x < y) ? 1 : 0));
4559    });
4560
4561    opt.func && opt.func(opt.data);
4562  };
4563
4564  HigJS.forms.filterData = function (opt) {
4565    const data = opt.data;
4566    let searchWord = opt.searchWord;
4567
4568    !this.timerObj && (this.timerObj = {});
4569    !opt.searchId && (opt.searchId = 'default');
4570
4571    clearTimeout(this.timerObj[opt.searchId]);
4572
4573    this.timerObj[opt.searchId] = setTimeout(function () {
4574      const toShowSearch = []; let wordFlag = false; let words; let hardSearch = false;
4575      const fields = opt.fields; let wordData; let i; let j; let z; let foundWords = {};
4576
4577      if (searchWord == '' || searchWord == ' ') {
4578        opt.func && opt.func(data);
4579        return;
4580      }
4581
4582      searchWord = HigJS.str.toLowerCase(searchWord);
4583
4584      if (searchWord.split('"').length == 3) {
4585        words = [HigJS.str.cleanString(searchWord).replace(/"/, '')];
4586        hardSearch = true;
4587      } else {
4588        words = HigJS.str.toLowerCase(searchWord).split(' ');
4589      }
4590
4591      for (j = 0; j < words.length; j++) {
4592        if (!words[j] || words[j] == '' || words[j] == ' ') {
4593          words.remove(j);
4594          j--;
4595        }
4596      }
4597
4598      for (i = 0; i < data.length; i++) {
4599        flag = false;
4600        if (searchWord && searchWord != '' && searchWord != ' ') {
4601          foundWords = {};
4602          // Cerco per ogni campo (colonna) se c'è la parola
4603          for (z = 0; z < fields.length; z++) {
4604            for (j = 0; j < words.length; j++) {
4605              wordData = opt.elValfunc
4606                ? opt.elValfunc({ val: data[i][fields[z]], field: fields[z], obj: data[i] }) // Funzione che permette di elaborare il dato prima di esere comparato
4607                : HigJS.str.toLowerCase(data[i][fields[z]]);
4608
4609              // Se trovo una parola setto a true
4610              if (hardSearch && words[j] == wordData) {
4611                foundWords[words[j]] = true;
4612              } else if (!hardSearch && HigJS.str.containString(wordData, words[j])) {
4613                foundWords[words[j]] = true;
4614              }
4615            }
4616          }
4617
4618          wordFlag = 0;
4619          for (j = 0; j < words.length; j++) { // Resetto l'oggetto che conteggia le parole trovate
4620            foundWords[words[j]] && (wordFlag++);
4621          }
4622          wordFlag = wordFlag == words.length;
4623        } else {
4624          wordFlag = true;
4625        }
4626
4627        wordFlag && (toShowSearch.push(data[i]));
4628      }
4629
4630      opt.func && opt.func(toShowSearch);
4631    }, 500);
4632  };
4633
4634  HigJS.forms.menuSel = function (mainOpt) {
4635    const self = this;
4636
4637    this.init = function (customOpt) {
4638      const defaultOpt = {
4639        itemCfg: {
4640          inpWdt: 100,
4641          // inpHgt: 20,
4642          txtWdt: 100,
4643          upperLbl: false,
4644          key: 'value',
4645          items: [],
4646          itemsId: [],
4647          id: HigJS.num.genNum(),
4648          upperLblFont: { 'font-size': 12 },
4649          enabled: true
4650        },
4651        draw: true
4652      };
4653
4654      // original code: had a bug, delete null properties for saveTo object.
4655      // this.options = HigJS.obj.extendAdv( defaultOpt, customOpt, 5);
4656      // this.options.saveTo = customOpt.saveTo;
4657
4658      // new code fix bug: null on saveTo is kept.
4659      const saveTo = customOpt.saveTo;
4660      customOpt.saveTo = HigJS.obj.clone(customOpt.saveTo);
4661      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
4662      this.options.saveTo = saveTo;
4663
4664      this.options.draw && this.draw();
4665      return this;
4666    };
4667
4668    this.draw = function () {
4669      const options = this.options; const itemCfg = this.options.itemCfg; const selectOptions = []; let i; let key; let $group;
4670
4671      if (this.$div) { this.$div.empty(); } // Se esiste già lo svuoto, così gestisco il redraw dell'oggetto! Se non esiste lo creo
4672      else {
4673        this.$div = $('<div/>').appendTo(options.appendTo)
4674          .addClass('inputText2');
4675      }
4676
4677      if (itemCfg.upperLbl) {
4678        this.$label = $('<label/>', { for: itemCfg.id }).appendTo($('<div/>').appendTo(this.$div).css({ 'text-align': 'left' }))
4679          .css(itemCfg.upperLblFont || {})
4680          .text(itemCfg.label);
4681      } else {
4682        this.$label = $('<div/>', { id: 'label' }).appendTo(this.$div)
4683          .text(itemCfg.label);
4684      }
4685
4686      if (itemCfg.txtWdt === 0) { this.$label.css({ display: 'none' }); }
4687
4688      this.$select = $('<select/>').appendTo(this.$div);
4689
4690      if (itemCfg.categories) {
4691        // Nel caso in cui gli elementi siano suddivisi per categoria
4692        for (key in itemCfg.items) {
4693          if (key === '_noCategory') { // Aggiungo elementi senza categoria
4694            for (i = 0; i < itemCfg.items[key].length; i++) {
4695              $('<option/>', {
4696                text: itemCfg.items[key][i],
4697                value: itemCfg.itemsId[key][i],
4698                selected: options.saveTo[itemCfg.key] == itemCfg.itemsId[key][i] ? 'selected' : false
4699              }).appendTo(this.$select);
4700            }
4701          } else { // Elementi con categoria
4702            $group = $('<optgroup/>', { label: key }).appendTo(this.$select);
4703            // Per ogni gruppo aggiungo  gli elementi
4704            for (i = 0; i < itemCfg.items[key].length; i++) {
4705              $('<option/>', {
4706                text: itemCfg.items[key][i],
4707                value: itemCfg.itemsId[key][i],
4708                selected: options.saveTo[itemCfg.key] == itemCfg.itemsId[key][i] ? 'selected' : false
4709              }).appendTo($group);
4710            }
4711          }
4712        }
4713      } else {
4714        // Select standard
4715        !itemCfg.items.length && itemCfg.items.push(edw('menuSelnoItems'));
4716        for (i = 0; i < itemCfg.items.length; i++) {
4717          selectOptions.push($('<option/>', {
4718            text: itemCfg.items[i],
4719            value: itemCfg.itemsId[i],
4720            selected: options.saveTo[itemCfg.key] == itemCfg.itemsId[i] ? 'selected' : false
4721          })[0]);
4722        }
4723
4724        for (i = 0; i < selectOptions.length; i++) {
4725          try { this.$select[0].add(selectOptions[i], this.$select[0].selectOptions.null); } // for IE earlier than version 8
4726          catch (e) { this.$select[0].add(selectOptions[i], null); }
4727        }
4728      }
4729
4730      this.$select.on('change', function () {
4731        self.precVal = options.saveTo[itemCfg.key]; // Salvo il valore precendente
4732        options.saveTo[itemCfg.key] = this.value;
4733        options.onChange && options.onChange(this.value, this.selectedIndex);
4734      });
4735
4736      if (itemCfg.enabled === false || itemCfg.readOnly === true) {
4737        this.setAbil(false);
4738      } else {
4739        this.setAbil(true);
4740      }
4741
4742      this.setSize({ txtWdt: itemCfg.txtWdt, inpWdt: itemCfg.inpWdt });
4743
4744      return this;
4745    };
4746
4747    this.getValue = function () {
4748      return this.options.saveTo[this.options.itemCfg.key] || this.options.itemCfg.itemsId[0];
4749    };
4750
4751    this.getSelectedLabel = function () {
4752      return this.$select.find('option:selected').text();
4753    };
4754
4755    this.setValue = function (value) {
4756      if (this.options.itemCfg.itemsId.indexOf(value) < 0) { console.log('menuSel: not setting invalid value ' + value); return; }
4757      this.$select.val(value).trigger('change');
4758    };
4759
4760    this.setSize = function (opt) {
4761      const itemCfg = this.options.itemCfg; let inpWdt = itemCfg.inpWdt; let txtWdt = itemCfg.txtWdt; let width;
4762
4763      // if( (opt.inpWdt && !opt.txtWdt) || (!opt.inpWdt && opt.txtWdt) ){
4764      //   opt.inpWdt = opt.inpWdt || itemCfg.inpWdt;
4765      //   opt.txtWdt = opt.txtWdt || itemCfg.txtWdt;
4766      // }
4767
4768      if (opt.txtWdt || opt.inpWdt) {
4769        inpWdt = parseInt(opt.inpWdt) || itemCfg.inpWdt;
4770        txtWdt = parseInt(opt.txtWdt) || itemCfg.txtWdt;
4771        width = itemCfg.upperLbl ? inpWdt : inpWdt + txtWdt;
4772      } else if (opt.width && itemCfg.upperLbl) {
4773        inpWdt = parseInt(opt.width);
4774        txtWdt = parseInt(opt.width);
4775        width = parseInt(opt.width);
4776      } else if (opt.width && !itemCfg.upperLbl) {
4777        inpWdt = parseInt(opt.width / 2);
4778        txtWdt = parseInt(opt.width / 2);
4779        width = parseInt(opt.width);
4780      }
4781
4782      this.$label.css({ width: txtWdt });
4783      this.$select.css({ width: inpWdt });
4784      this.$div.css({ width: width });
4785
4786      itemCfg.txtWdt = parseInt(txtWdt);
4787      itemCfg.inpWdt = parseInt(inpWdt);
4788      itemCfg.width = parseInt(width);
4789      return this;
4790    };
4791
4792    this.getSize = function (key) {
4793      const itemCfg = this.options.itemCfg;
4794      if (!key) {
4795        return {
4796          width: itemCfg.upperLbl ? parseInt(itemCfg.inpWdt) : parseInt(itemCfg.txtWdt) + parseInt(itemCfg.inpWdt),
4797          height: 'auto',
4798          txtWdt: parseInt(itemCfg.txtWdt),
4799          inpWdt: parseInt(itemCfg.inpWdt)
4800        };
4801      } else if (key === 'txt') {
4802        return { width: itemCfg.txtWdt, height: 'auto', txtWdt: itemCfg.txtWdt, inpWdt: itemCfg.inpWdt };
4803      } else if (key === 'inp') {
4804        return { width: itemCfg.inpWdt, height: 'auto', txtWdt: itemCfg.txtWdt, inpWdt: itemCfg.inpWdt };
4805      }
4806    };
4807
4808    this.setLabel = function (label) {
4809      this.$label.text(label);
4810      this.options.itemCfg.label = label;
4811    };
4812
4813    this.setStatus = function (flag) {
4814      flag ? self.$select.addClass('errorBox') : self.$select.removeClass('errorBox');
4815    };
4816
4817    this.setAbil = function (flag) {
4818      flag ? self.$select.removeAttr('disabled') : self.$select.attr('disabled', !flag);
4819      // Cambia il colore del select a bianco se abilitato. Non va bene in caso di modifiche al colore.
4820      // self.$select.css({ "background-color": flag ? "white" : "rgb(236, 236, 236)" });
4821    };
4822
4823    mainOpt && this.init(mainOpt);
4824    return this;
4825  };
4826
4827  HigJS.forms.checkBox = function (opt) {
4828    const self = this;
4829
4830    this.init = function (customOpt) {
4831      const defaultOpt = {
4832        itemCfg: {
4833          inpWdt: 30,
4834          inpHgt: 20,
4835          txtWdt: 100,
4836          readOnly: false,
4837          pos: 'right',
4838          txtAlign: 'right',
4839          id: HigJS.num.genNum()
4840        },
4841        onSave: function (val) { return val; },
4842        draw: true
4843      };
4844
4845      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
4846      this.options.saveTo = customOpt.saveTo || {};
4847      this.options.draw && this.draw();
4848      return this;
4849    };
4850
4851    this.draw = function () {
4852      const options = this.options; const itemCfg = this.options.itemCfg; let inpWdt; let value;
4853
4854      this.$div = $('<div/>').appendTo(options.appendTo)
4855        .addClass('checkBox2');
4856
4857      this.$label = $('<div/>', { id: 'label' }).text(itemCfg.label).on('click', function () { self.$ckBox.click(); });
4858
4859      if (itemCfg.txtWdt === 0) { this.$label.css({ display: 'none' }); }
4860
4861      value = this.checkValue(options.saveTo[itemCfg.key]);
4862
4863      this.$ckBox = $('<input/>', { type: 'checkbox', checked: value, id: itemCfg.id, name: itemCfg.id })
4864        .on('click', function (e) {
4865          if (itemCfg.readOnly) { return false; }
4866          options.saveTo[itemCfg.key] = ~~this.checked;
4867          options.onChange && options.onChange(this.checked, this);
4868        });
4869
4870      this.position(itemCfg.pos);
4871      this.setTxtAlign(itemCfg.txtAlign);
4872      this.setSize({ txtWdt: itemCfg.txtWdt, inpWdt: itemCfg.inpWdt });
4873
4874      return this;
4875    };
4876
4877    this.position = function (pos) {
4878      this.$label.detach();
4879      this.$ckBox.detach();
4880      pos = (pos && pos == 'right') ? 'right' : 'left';
4881      this.options.itemCfg.pos = pos;
4882      pos == 'right' && this.$div.append(this.$label).append(this.$ckBox);
4883      pos == 'left' && this.$div.append(this.$ckBox).append(this.$label);
4884    };
4885
4886    this.setTxtAlign = function (pos) {
4887      pos = (pos && pos == 'right') ? 'right' : 'left';
4888      this.options.itemCfg.txtAlign = pos;
4889      this.$label.css({ 'text-align': pos });
4890    };
4891
4892    this.setLabel = function (label) {
4893      this.$label.text(label);
4894      this.options.itemCfg.label = label;
4895    };
4896
4897    this.setSize = function (opt) {
4898      const itemCfg = this.options.itemCfg; let inpWdt = itemCfg.inpWdt; let txtWdt = itemCfg.txtWdt; let width;
4899
4900      if (opt.txtWdt || opt.inpWdt) {
4901        inpWdt = parseInt(opt.inpWdt) || itemCfg.inpWdt;
4902        txtWdt = parseInt(opt.txtWdt) || itemCfg.txtWdt;
4903        width = itemCfg.upperLbl ? inpWdt : inpWdt + txtWdt;
4904      } else if (opt.width && !itemCfg.upperLbl) {
4905        inpWdt = parseInt(opt.width / 2);
4906        txtWdt = parseInt(opt.width / 2);
4907        width = parseInt(opt.width);
4908      }
4909
4910      this.$label.css({ width: txtWdt });
4911      this.$div.css({ width: width });
4912
4913      itemCfg.txtWdt = parseInt(txtWdt);
4914      itemCfg.inpWdt = parseInt(inpWdt);
4915      itemCfg.width = parseInt(width);
4916      return this;
4917    };
4918
4919    this.getSize = function (key) {
4920      const itemCfg = this.options.itemCfg;
4921      if (!key) {
4922        return {
4923          width: itemCfg.upperLbl ? parseInt(itemCfg.inpWdt) : parseInt(itemCfg.txtWdt) + parseInt(itemCfg.inpWdt),
4924          height: 'auto',
4925          txtWdt: parseInt(itemCfg.txtWdt),
4926          inpWdt: parseInt(itemCfg.inpWdt)
4927        };
4928      } else if (key === 'txt') {
4929        return { width: itemCfg.txtWdt, height: 'auto', txtWdt: itemCfg.txtWdt, inpWdt: itemCfg.inpWdt };
4930      } else if (key === 'inp') {
4931        return { width: itemCfg.inpWdt, height: 'auto', txtWdt: itemCfg.txtWdt, inpWdt: itemCfg.inpWdt };
4932      }
4933    };
4934
4935    this.checkValue = function (value) {
4936      if (value === '0' || value === 'false') return false;
4937      return !!value;
4938    };
4939
4940    this.setValue = function (value) {
4941      const options = this.options; const itemCfg = this.options.itemCfg;
4942      value = this.checkValue(value);
4943      this.$ckBox[0].checked = value;
4944      options.saveTo[itemCfg.key] = ~~value;
4945      options.onChange && options.onChange(value);
4946      return this;
4947    };
4948
4949    this.updateValue = function (value) {
4950      this.$ckBox[0].checked = this.checkValue(value);
4951      return this;
4952    };
4953
4954    this.getValue = function () {
4955      return this.$ckBox[0].checked;
4956    };
4957
4958    opt && this.init(opt);
4959    return this;
4960  };
4961
4962  HigJS.forms.tabs = function (optMain) {
4963    const self = this;
4964
4965    this.init = function (customOpt) {
4966      const defaultOpt = {
4967        itemCfg: {
4968          tabs: [],
4969          height: 300,
4970          overflow: 'auto'
4971        },
4972        draw: true,
4973        css: {}
4974      };
4975
4976      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
4977      this.tabArray = [];
4978      this.tabIds = {};
4979
4980      this.options.draw && this.draw();
4981      return this;
4982    };
4983
4984    this.draw = function () {
4985      const options = this.options; const itemCfg = this.options.itemCfg; let i;
4986
4987      this.$div = $('<div/>', { id: 'tabs2MainDiv' }).appendTo(options.appendTo).css({ height: itemCfg.height, 'box-sizing': 'border-box', position: 'relative' });
4988      this.$tabsDiv = $('<div/>', { id: 'tabs2MenuContainer' }).appendTo(this.$div).addClass('tabs2MenuContainer');
4989
4990      for (i = 0; i < itemCfg.tabs.length; i++) {
4991        this.addTab(itemCfg.tabs[i]);
4992      }
4993
4994      this.$container = $('<div/>', { id: 'tab2Container' }).appendTo(this.$div).addClass('divData')
4995        .css({ 'box-sizing': 'border-box', height: 'calc( 100% - ' + this.$tabsDiv.height() + 'px )', overflow: itemCfg.overflow });
4996
4997      this.$container.css(this.options.css || {});
4998
4999      this.tabArray.length && this.tabArray[0].addClass('selCenterTabs');
5000
5001      setTimeout(function () { self.setSize({ height: itemCfg.height }); }, 200);
5002
5003      if (itemCfg.openTabByPos) { this.openTab({ pos: itemCfg.openTabByPos }); } else if (itemCfg.openTabById) { this.openTab({ id: itemCfg.openTabById }); } else { itemCfg.tabs.length && this.tabArray[0].trigger('click'); }
5004    };
5005
5006    this.addTab = function (tab) {
5007      let $subPageContainer;
5008
5009      !tab.id && (tab.id = this.getNewId());
5010
5011      const newTab = $('<div/>', { id: tab.id }).appendTo(this.$tabsDiv).addClass('centerTabs tabs2Tab')
5012        .text(tab.label)
5013        .on('click', function (e) {
5014          e.stopPropagation();
5015
5016          if (self.beforeChangeTab && !self.beforeChangeTab()) {
5017            return;
5018          }
5019          self.beforeChangeTab = null;
5020
5021          self.$container.empty();
5022          tab.drawFunc(self.$container);
5023
5024          self.deselectAllTabs();
5025          $(this).removeClass('centerTabs').addClass('selCenterTabs');
5026
5027          self.setSize({ height: self.options.itemCfg.height });
5028        })
5029        .on('mouseover', function () {
5030          $subPageContainer && $subPageContainer.show();
5031        })
5032        .on('mouseleave', function () {
5033          $subPageContainer && $subPageContainer.hide();
5034        });
5035
5036      if (tab.subPages && tab.subPages.length) {
5037        $subPageContainer = $('<div/>').appendTo(newTab)
5038          .addClass('tabs2SubPageContainer')
5039          .on('mouseleave', function () {
5040            $(this).hide();
5041          });
5042
5043        for (let i = 0; i < tab.subPages.length; i++) {
5044          this.addSubTab({ appendTo: $subPageContainer, page: tab.subPages[i] });
5045        }
5046      }
5047
5048      this.tabArray.push(newTab);
5049    };
5050
5051    this.deselectAllTabs = function () {
5052      for (let i = 0; i < this.tabArray.length; i++) {
5053        this.tabArray[i].removeClass('selCenterTabs').addClass('centerTabs');
5054      }
5055    };
5056
5057    this.setSize = function (opt) {
5058      if (opt.height && parseInt(opt.height)) {
5059        this.options.itemCfg.height = opt.height;
5060        this.$div.css({ height: opt.height });
5061        this.$container.css({ height: opt.height - this.$tabsDiv.height() });
5062      }
5063    };
5064
5065    this.getCurrentTab = function () {
5066      for (let i = 0; i < this.tabArray.length; i++) {
5067        if (this.tabArray[i].hasClass('selCenterTabs')) { return { pos: $(this.tabArray[i][0]).index(), id: this.options.itemCfg.tabs[i].id }; }
5068      }
5069      return { pos: 0, id: 0 };
5070    };
5071
5072    this.getCurrenTab = this.getCurrentTab; // Da mantenere per compatibilità
5073
5074    this.getNewId = function () {
5075      let newId = 100;
5076      while (this.tabIds[newId]) { newId++; }
5077
5078      this.tabIds[newId] = true;
5079      return newId;
5080    };
5081
5082    this.openTab = function (opt) {
5083      if (!this.tabArray.length) { return this; }
5084
5085      for (let i = 0; i < this.tabArray.length; i++) {
5086        if (typeof opt.id !== 'undefined' && this.options.itemCfg.tabs[i].id === opt.id) {
5087          this.tabArray[i].trigger('click');
5088          return;
5089        } else if (typeof opt.pos !== 'undefined' && $(this.tabArray[i][0]).index() === opt.pos) {
5090          this.tabArray[i].trigger('click');
5091          return;
5092        }
5093      }
5094      this.tabArray[0].trigger('click');
5095
5096      return this;
5097    };
5098
5099    this.addSubTab = function (opt) {
5100      let $subPageContainer;
5101
5102      !opt.page.id && (opt.page.id = this.getNewId());
5103
5104      var newTab = $('<div/>', { id: opt.page.id }).appendTo(opt.appendTo).addClass('centerTabs tab2SubTab')
5105        .text(opt.page.label)
5106        .on('click', function (e) {
5107          e.stopPropagation();
5108
5109          if (self.beforeChangeTab && !self.beforeChangeTab()) {
5110            return;
5111          }
5112          self.beforeChangeTab = null;
5113
5114          self.$container.empty();
5115          opt.page.drawFunc(self.$container);
5116
5117          self.deselectAllTabs();
5118          $(this).closest('.tabs2Tab').removeClass('centerTabs').addClass('selCenterTabs');
5119
5120          self.setSize({ height: self.options.itemCfg.height });
5121        })
5122        .on('mouseover', function () {
5123          $subPageContainer && $subPageContainer.show().css({ left: (newTab.width() + 18) + 'px' });
5124        })
5125        .on('mouseleave', function () {
5126          $subPageContainer && $subPageContainer.hide();
5127        });
5128
5129      if (opt.page.subPages && opt.page.subPages.length) {
5130        $subPageContainer = $('<div/>').addClass('tabs2Sub2PageContainer')
5131          .addClass('tabs2Sub2PageContainer')
5132          .appendTo(newTab)
5133          .on('mouseleave', function () {
5134            $subPageContainer && $subPageContainer.css({ display: 'none' });
5135          });
5136
5137        for (let i = 0; i < opt.page.subPages.length; i++) {
5138          this.addSubTab({ appendTo: $subPageContainer, page: opt.page.subPages[i] });
5139        }
5140      }
5141    };
5142
5143    this.hidePage = function (opt) {
5144      const tabs = this.options.itemCfg.tabs; let key; let i;
5145      for (key in opt) {
5146        for (i = 0; i < tabs.length; i++) {
5147          if (tabs[i][key] === opt[key]) {
5148            this.$div.find('#' + tabs[i].id).css({ display: 'none' });
5149            return this;
5150          }
5151
5152          if (tabs[i].subPages && tabs[i].subPages.length && hideSubPage(key, opt[key], tabs[i].subPages)) { return this; }
5153        }
5154      }
5155
5156      function hideSubPage(tabKey, tabVal, pages) {
5157        for (let j = 0; j < pages.length; j++) {
5158          if (pages[j][tabKey] === tabVal) {
5159            self.$div.find('#' + pages[j].id).css({ display: 'none' });
5160            return true;
5161          }
5162
5163          if (pages[j].subPages && pages[j].subPages.length && hideSubPage(key, opt[key], pages[j].subPages)) { return true; }
5164        }
5165        return false;
5166      }
5167    };
5168
5169    this.showPage = function (opt) {
5170      const tabs = this.options.itemCfg.tabs; let key; let i;
5171      for (key in opt) {
5172        for (i = 0; i < tabs.length; i++) {
5173          if (tabs[i][key] === opt[key]) {
5174            this.$div.find('#' + tabs[i].id).css({ display: 'inline-block' });
5175            return this;
5176          }
5177
5178          if (tabs[i].subPages && tabs[i].subPages.length && showSubPage(key, opt[key], tabs[i].subPages)) { return this; }
5179        }
5180      }
5181
5182      function showSubPage(tabKey, tabVal, pages) {
5183        for (let j = 0; j < pages.length; j++) {
5184          if (pages[j][tabKey] === tabVal) {
5185            self.$div.find('#' + pages[j].id).css({ display: 'inline-block' });
5186            return true;
5187          }
5188
5189          if (pages[j].subPages && pages[j].subPages.length && showSubPage(key, opt[key], pages[j].subPages)) { return true; }
5190        }
5191        return false;
5192      }
5193    };
5194
5195    optMain && this.init(optMain);
5196    return this;
5197  };
5198
5199  HigJS.forms.containerObj = function (opt) {
5200    this.container = $('<div/>')
5201      .addClass('container')
5202      .css({ height: opt.height, width: opt.width })
5203      .appendTo(opt.target);
5204
5205    this.div = $('<div/>')
5206      .appendTo(this.container)
5207      .css({ 'padding-bottom': opt.noBottomPadding ? 0 : 50 });
5208
5209    if (HigJS.browser.isMobile()) { opt.nativeScroll = true; }
5210
5211    if (HigJS.browser.isIe() || opt.nativeScroll) {
5212      this.container.css({ overflow: 'auto' }).on('scroll', function () {
5213        opt.onScrollTop && opt.onScrollTop();
5214        opt.onScrollLeft && opt.onScrollLeft();
5215      });
5216    } else {
5217      this.container.perfectScrollbar({
5218        minScrollbarLength: opt.minScrollbarLength,
5219        wheelSpeed: opt.wheelSpeed || 5,
5220        // barColor: opt.color || "black",
5221        wheelPropagation: opt.wheelPropagation,
5222        // barWidth: 10,
5223        onScrollLeft: opt.onScrollLeft,
5224        onScrollTop: opt.onScrollTop
5225      });
5226
5227      this.container.find('.ps-scrollbar-x').css({ 'background-color': opt.color || '#000000', height: opt.barThickness || 8 });
5228      this.container.find('.ps-scrollbar-y').css({ 'background-color': opt.color || '#000000', width: opt.barThickness || 8 });
5229
5230      this.container.find('.always-visible.ps-container > .ps-scrollbar-x-rail').css({ opacity: 0.6 });
5231      this.container.find('.always-visible.ps-container > .ps-scrollbar-y-rail').css({ opacity: 0.6 });
5232
5233      this.container.scrollTop(0);
5234    }
5235
5236    this.container.div = this.container;
5237
5238    this.resize = function (size) {
5239      this.container.css({ height: size.height, width: size.width });
5240      this.update();
5241    };
5242
5243    this.update = function () {
5244      if (!HigJS.browser.isIe() || opt.nativeScroll) { this.container.perfectScrollbar('update'); }
5245    };
5246
5247    this.scrollTop = function (val) {
5248      this.container.scrollTop(val);
5249      this.update();
5250    };
5251
5252    this.remove = function () {
5253      this.container.remove();
5254    };
5255  };
5256
5257  /**
5258   * Visualizza il layer del caricamento della pagina.
5259   * @extends GWC.HigJS.forms
5260  */
5261  HigJS.forms.startLoader = function (opt) {
5262    opt = HigJS.type.isObject(opt) ? opt : {};
5263    opt.imgPath = HigJS.type.isString(opt.imgPath) ? opt.imgPath : 'img/';
5264    opt.appendTo = opt.appendTo || $('body');
5265    opt.zIndex = HigJS.type.isNumber(opt.zIndex) ? opt.zIndex : 500;
5266    opt.fontawesome = !!opt.fontawesome;
5267
5268    function waitObj(opt) {
5269      const $waitDiv = $('<div/>', { class: 'HigJS-Loader' });
5270      this.div = $waitDiv[0];
5271      this.status = 'close';
5272
5273      this.startWait = function () {
5274        if (this.status === 'open') { return; }
5275
5276        this.status = 'open';
5277        $waitDiv.appendTo(opt.appendTo).css({
5278          position: 'fixed',
5279          top: 0,
5280          left: 0,
5281          bottom: 0,
5282          right: 0,
5283          margin: 'auto',
5284          'z-index': opt.zIndex
5285        });
5286
5287        if (opt.fontawesome) {
5288          $waitDiv.css({ width: '100%', height: '100%' }).append($(
5289            '<span class="icons fa-stack" style="vertical-align: top; font-size: 80px; position: absolute; top: 50%; left: 50%; transform: translate( -50%, -50% );">' +
5290            '<i style="color: var( --main-color-light );" class="far fa-circle fa-stack-1x"></i>' +
5291            '<i style="color:var( --main-color );" class="far fa-spinner-third fa-stack-1x fa-spin"></i>' +
5292            '</span>'
5293          )).on('mousewheel DOMMouseScroll click', function (e) { e.preventDefault(); e.stopPropagation(); });
5294        } else {
5295          $waitDiv.css({ background: "rgba(0,0,0,0.5) url('" + opt.imgPath + "/ajax-loader.gif') no-repeat center center" });
5296        }
5297
5298        // opt.appendTo.css({ overflow: "hidden" });
5299      };
5300
5301      this.stopWait = function () {
5302        if (this.status === 'close') { return; }
5303        $waitDiv.remove();
5304        this.status = 'close';
5305        // opt.appendTo.css({ overflow: "auto" });
5306      };
5307    }
5308
5309    // Il loader deve essere inizializzato tutte le volte per problemi di scope quando viene clonata la libreria HigJS da pagina a pagina
5310    if (HigJS.forms.loader) {
5311      try { HigJS.forms.loader.stopWait(); } catch (e) { }
5312    }
5313    HigJS.forms.loader = new waitObj(opt);
5314
5315    HigJS.forms.loader.startWait();
5316  };
5317
5318  /**
5319   *  Rimuove il layer del caricamento della pagina.
5320   *  @extends GWC.HigJS.forms
5321  */
5322  HigJS.forms.stopLoader = function () {
5323    HigJS.forms.loader && HigJS.forms.loader.stopWait();
5324  };
5325
5326  /**
5327   * Oggetto immagine
5328   *
5329   * @constructor
5330   * @version 1.0
5331   * @author  <a href="mailto:[email protected]">Fabio Conedera</a>
5332   * @param {Object}         opt             Oggetto jSon contenente la configurazione
5333   * @param {String}       opt.src         Posizione dell'immagine.
5334   * @param {String}       opt.srcAlt      Posizione dell'immagine che viene visualizzata al mouseover.
5335   * @param {Number}       opt.width       Larghezza.
5336   * @param {Number}       opt.height      Altezza.
5337   * @param {String}       opt.id          Id del tag <img>.
5338   * @param {String}       opt.title       Testo che appare al mouse over.
5339   * @param {Boolean}      opt.mouseOver   Se true appare la manina sopra l'immagine al mouseover. Default false
5340  */
5341
5342  HigJS.forms.image = function (optMain) {
5343    const self = this;
5344
5345    this.init = function (customOpt) {
5346      const defaultOpt = {
5347        itemCfg: {
5348          src: '',
5349          srcAlt: false,
5350          title: false,
5351          mouseOver: false
5352        },
5353        draw: true
5354      };
5355
5356      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
5357      this.options.draw && this.draw();
5358      return this;
5359    };
5360
5361    this.draw = function () {
5362      const options = this.options; const itemCfg = this.options.itemCfg;
5363
5364      this.$img = $('<img/>', { src: itemCfg.src, title: itemCfg.title, id: itemCfg.id })
5365        .css({ width: itemCfg.width, height: itemCfg.height })
5366        .appendTo(options.appendTo)
5367        .on('click', function () {
5368          options.onClick && options.onClick();
5369        });
5370
5371      if (itemCfg.mouseOver) {
5372        this.$img.mouseover(function () {
5373          if (itemCfg.srcAlt) $(this).attr({ src: oOpt.srcAlt });
5374        }).mouseout(function () {
5375          if (itemCfg.srcAlt) $(this).attr({ src: oOpt.src });
5376        }).css({
5377          cursor: 'pointer'
5378        });
5379      }
5380    };
5381
5382    optMain && this.init(optMain);
5383  };
5384
5385  HigJS.forms.overlayBox = function (optMain) {
5386    const self = this;
5387
5388    this.init = function (customOpt) {
5389      const defaultOpt = {
5390        itemCfg: {
5391          id: HigJS.num.genNum(),
5392          small: false
5393        },
5394        appendTo: $('body'),
5395        draw: true
5396      };
5397
5398      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
5399      this.options.draw && this.draw();
5400      return this;
5401    };
5402
5403    this.draw = function () {
5404      const options = this.options; const itemCfg = this.options.itemCfg;
5405
5406      this.$div = $('<div/>').appendTo(options.appendTo)
5407        .addClass('upperPageLayer')
5408        .css({ width: $(window).width(), height: $(window).height() });
5409
5410      $(window).on('resize.' + itemCfg.id, function () {
5411        self.$div.css({ width: $(window).width(), height: $(window).height() });
5412      });
5413
5414      this.$container = $('<div/>').appendTo(this.$div)
5415        .addClass(itemCfg.small ? 'optContainerSmall' : 'optContainer')
5416        .css({ 'text-align': 'center' });
5417
5418      if (!itemCfg.disableClose) {
5419        this.$closeDiv = $('<div/>').addClass('closeDiv closeDivHigJS')
5420          // .css({ right: 10, top: 7, "z-index": 1000})
5421          .appendTo(this.$container)
5422          .on('click', function (e) {
5423            e.stopPropagation();
5424            self.close();
5425          });
5426      }
5427    };
5428
5429    this.close = function () {
5430      const options = this.options; const itemCfg = this.options.itemCfg;
5431      $(window).off('resize.' + itemCfg.id);
5432      options.onClose && options.onClose();
5433      self.$div.remove();
5434    };
5435
5436    optMain && this.init(optMain);
5437  };
5438
5439  HigJS.forms.dateTimePicker = function (mainOpt) {
5440    const self = this;
5441
5442    this.init = function (customOpt) {
5443      const defaultOpt = {
5444        itemCfg: {
5445          date: true,
5446          time: true,
5447          inpWdt: 100,
5448          txtWdt: 100,
5449          readOnly: false,
5450          upperLbl: false,
5451          id: HigJS.num.genNum(),
5452          upperLblFont: { 'font-size': 12 },
5453          localTime: true,
5454          keepEmpty: false
5455        },
5456        draw: true
5457      };
5458
5459      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
5460
5461      this.options.saveTo = customOpt.saveTo;
5462      !this.options.itemCfg.keepEmpty && !this.options.saveTo[this.options.itemCfg.key] && (this.options.saveTo[this.options.itemCfg.key] = parseInt((new Date()).getTime() / 1000));
5463      if (this.options.itemCfg.keepEmpty && !this.options.saveTo[this.options.itemCfg.key]) this.options.saveTo[this.options.itemCfg.key] = null;
5464      this.options.draw && this.draw();
5465      return this;
5466    };
5467
5468    this.draw = function () {
5469      const options = this.options; const itemCfg = this.options.itemCfg; const date = HigJS.num.formatDate({ utc: options.saveTo[itemCfg.key], time: false, date: true });
5470
5471      const confObj = {
5472        date: date,
5473        time: (this.options.itemCfg.keepEmpty && !this.options.saveTo[this.options.itemCfg.key] ? 0 : options.saveTo[itemCfg.key] - HigJS.date.getIntervalFromStrDate(date, itemCfg.localTime)[0])
5474      };
5475
5476      !this.$div ? (this.$div = $('<div/>').appendTo(options.appendTo)) : this.$div.empty();
5477
5478      if (itemCfg.date) {
5479        this.datePicker = new HigJS.forms.calendar({
5480          itemCfg: { key: 'date', inpWdt: itemCfg.inpWdt, txtWdt: itemCfg.txtWdt, label: itemCfg.dateLabel || edw('selDate') },
5481          saveTo: confObj,
5482          appendTo: $('<div/>').appendTo(this.$div).addClass('optionField'),
5483          onChange: function (val) {
5484            options.saveTo[itemCfg.key] = HigJS.date.getIntervalFromStrDate(confObj.date)[0] + parseInt(confObj.time);
5485            options.onChange && options.onChange(options.saveTo[itemCfg.key]);
5486          }
5487        });
5488      }
5489
5490      if (itemCfg.time) {
5491        this.timePicker = new HigJS.forms.timeSelect({
5492          itemCfg: { key: 'time', inpWdt: itemCfg.inpWdt, txtWdt: itemCfg.txtWdt, label: itemCfg.timeLabel || edw('selTime') },
5493          saveTo: confObj,
5494          appendTo: $('<div/>').appendTo(this.$div).addClass('optionField'),
5495          onChange: function () {
5496            options.saveTo[itemCfg.key] = HigJS.date.getIntervalFromStrDate(confObj.date)[0] + parseInt(confObj.time);
5497            options.onChange && options.onChange(options.saveTo[itemCfg.key]);
5498          }
5499        });
5500      }
5501    };
5502
5503    mainOpt && this.init(mainOpt);
5504  };
5505
5506  HigJS.forms.timeSelect = function (mainOpt) {
5507    const self = this;
5508    this.init = function (customOpt) {
5509      const defaultOpt = {
5510        itemCfg: {
5511          inpWdt: 100,
5512          txtWdt: 100,
5513          readOnly: false,
5514          upperLbl: false,
5515          id: HigJS.num.genNum(),
5516          upperLblFont: { 'font-size': 12 }
5517        },
5518        draw: true
5519      };
5520
5521      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
5522
5523      this.options.saveTo = customOpt.saveTo;
5524      this.options.draw && this.draw();
5525      return this;
5526    };
5527
5528    this.draw = function () {
5529      const options = this.options; const itemCfg = this.options.itemCfg; const confObj = { hours: parseInt(options.saveTo[itemCfg.key] / 3600) * 3600, minutes: parseInt((options.saveTo[itemCfg.key] % 3600) / 60) };
5530      !this.$div ? (this.$div = $('<div/>', { class: 'hoursSelect' }).appendTo(options.appendTo)) : this.$div.empty();
5531      // this.$div = $("<div/>").appendTo( options.appendTo )
5532
5533      const startTimeLbl = []; const startTimeId = []; const hours = 0; const startTimeLblM = []; const startTimeIdM = [];
5534      !options.saveTo[itemCfg.key] && (options.saveTo[itemCfg.key] = 0);
5535
5536      for (var i = 0; i < 24; i++) {
5537        startTimeLbl.push(i < 10 ? '0' + i : i);
5538        startTimeId.push(i * 3600);
5539      }
5540
5541      this.selectHoursObj = new HigJS.forms.menuSel({
5542        itemCfg: {
5543          label: itemCfg.label, key: 'hours', items: startTimeLbl, itemsId: startTimeId, txtWdt: itemCfg.txtWdt, inpWdt: 60
5544        },
5545        saveTo: confObj,
5546        onChange: function () {
5547          options.saveTo[itemCfg.key] = (parseInt(confObj.hours)) + (parseInt(confObj.minutes) * 60);
5548          options.onChange && options.onChange(options.saveTo[itemCfg.key]);
5549        },
5550        appendTo: $('<div/>').appendTo(this.$div).css({ display: 'inline-block' })
5551      });
5552
5553      this.$div.append(' : ');
5554
5555      for (i = 0; i < 60; i++) {
5556        startTimeLblM.push(i < 10 ? '0' + i : i);
5557        startTimeIdM.push(i);
5558      }
5559
5560      this.selectSecsObj = new HigJS.forms.menuSel({
5561        itemCfg: {
5562          key: 'minutes', items: startTimeLblM, itemsId: startTimeIdM, txtWdt: 0, inpWdt: 60
5563        },
5564        saveTo: confObj,
5565        onChange: function () {
5566          options.saveTo[itemCfg.key] = (parseInt(confObj.hours)) + (parseInt(confObj.minutes) * 60);
5567          options.onChange && options.onChange(options.saveTo[itemCfg.key]);
5568        },
5569        appendTo: $('<div/>').appendTo(this.$div).css({ display: 'inline-block' })
5570      });
5571    };
5572
5573    mainOpt && this.init(mainOpt);
5574  };
5575
5576  HigJS.forms.calendar = function (mainOpt) {
5577    const self = this;
5578
5579    this.init = function (customOpt) {
5580      const defaultOpt = {
5581        itemCfg: {
5582          inpWdt: 100,
5583          txtWdt: 100,
5584          readOnly: false,
5585          upperLbl: false,
5586          id: HigJS.num.genNum(),
5587          upperLblFont: { 'font-size': 12 }
5588        },
5589        onSave: function (val) {
5590          // self.options.itemCfg.number && val && ( val = parseFloat(val) );
5591          return val;
5592        },
5593        onShow: function (val) { return val; },
5594        onEnter: false, // Funzione da eseguire alla pressione del tasto enter
5595        checkInput: function (val) { return true; },
5596        draw: true
5597      };
5598
5599      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
5600      this.options.saveTo = customOpt.saveTo;
5601      this.options.draw && this.draw();
5602      return this;
5603    };
5604
5605    this.draw = function () {
5606      const options = this.options; const itemCfg = this.options.itemCfg; let value;
5607
5608      this.inputObj = new HigJS.forms.inputText(this.options);
5609      this.inputObj.$div.css({ position: 'relative' });
5610
5611      this.inputObj.$input.click(function () {
5612        if (self.$calendarContainer.is(':hidden')) {
5613          self.$calendarContainer.show()
5614            .css({ position: 'absolute', top: 0, right: 0 });
5615
5616          const bcr = self.$calendarContainer[0].getBoundingClientRect();
5617          if (bcr.left < 0) {
5618            self.$calendarContainer.css({ position: 'absolute', top: 0, left: 0 });
5619          }
5620        } /*else {
5621          self.$calendarContainer.hide();
5622        }*/
5623      });
5624
5625      try {
5626        this.$calendarContainer = $('<div/>').css({ 'z-index': 10000 })
5627          .appendTo(this.inputObj.$div).datepicker({
5628            onSelect: function (date, inst) {
5629              self.inputObj.setValue(date);
5630              self.$calendarContainer.datepicker('setDate', date)
5631                .hide();
5632            }
5633          })
5634          .css({ position: 'absolute', top: 0, right: 0 })
5635          .hide()
5636          .datepicker('setDate', options.saveTo[itemCfg.key])
5637          .mouseleave(function () {
5638            self.$calendarContainer.hide();
5639          });
5640      } catch (e) {
5641
5642      }
5643      return this;
5644    };
5645
5646    this.getValue = function () {
5647      const value = this.$input[0].value;
5648      return value;
5649    };
5650
5651    this.getUTC = function () {
5652      return HigJS.date.getIntervalFromStrDate(this.inputObj.getValue())[0];
5653    };
5654
5655    this.setValue = function (value, opt) {
5656
5657    };
5658
5659    this.setSize = function () {
5660
5661    };
5662
5663    mainOpt && this.init(mainOpt);
5664  };
5665
5666  HigJS.forms.dropDownSelector = function (mainOpt) {
5667    this.init = function (customOpt) {
5668      this.options = customOpt;
5669      this.preliminary();
5670      this.setGlobalElements();
5671      this.setGlobalListeners();
5672      this.options.draw && this.draw();
5673    };
5674
5675    this.preliminary = function () {
5676      this.styleSheet = window.document.querySelector('head style[id=higDropDown]');
5677      if (!this.styleSheet) {
5678        this.styleSheet = window.document.createElement('style');
5679        this.styleSheet.setAttribute('id', 'higDropDown');
5680        this.styleSheet.textContent = '.dropdownContainer ul > li:hover {background-color: #EEF6FF;}.higInputWrapper {position: relative;padding: 5px;}.higInputWrapper::after {content: "";height: 1px;position: absolute;background: rgba(0, 0, 0, 0.2);bottom: 3px;left: 2px;right: 2px;}.higSelectorSimulator {position: relative; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;}.higSelectorSimulator::after {position: absolute;content: "▾"; /*alternative \u25bc*/right: 5px;transform: scale(1);}';
5681        window.document.head.appendChild(this.styleSheet);
5682      }
5683      this.DOM = {};
5684      this.css = {
5685        table: {
5686          display: 'table'
5687          // 'font-size': '12px'
5688        },
5689        row: {
5690          display: 'table-row'
5691        },
5692        cell: {
5693          display: 'table-cell',
5694          'vertical-align': 'middle'
5695        },
5696        select: {
5697          border: '1px solid black',
5698          outline: 0,
5699          width: this.options.inputWdt || 'auto',
5700          'background-color': 'white',
5701          padding: '2px 5px',
5702          'font-size': '13.33333px'
5703        },
5704        selectwithsearch: {
5705          border: '1px solid black',
5706          outline: 0,
5707          width: this.options.inputWdt || '100%',
5708          'background-color': 'white',
5709          padding: '3px 15px 3px 6px',
5710          display: 'inline-block',
5711          'font-size': '13.33333px'
5712        },
5713        selectWrapper: {
5714          position: 'relative',
5715          'min-width': '200px'
5716        },
5717        container: {
5718          display: 'inline-block',
5719          'vertical-align': 'middle',
5720          padding: '2px 7px'
5721        },
5722        option: {},
5723        options: {
5724          'font-weight': 'normal',
5725          display: 'block',
5726          'white-space': 'pre',
5727          'min-height': '1.2em',
5728          padding: '0px 2px 1px 5px',
5729          'font-size': '13.3px',
5730          cursor: 'pointer'
5731        },
5732        optionList: {
5733          width: 'calc( 100% - 1px )',
5734          overflow: 'auto',
5735          'max-height': '30vh',
5736          margin: 0,
5737          'list-style-type': 'none',
5738          padding: '2px 0'
5739        },
5740        dropdown: {
5741          position: 'absolute',
5742          left: 0,
5743          right: 0,
5744          'z-index': 10,
5745          border: '1px solid black',
5746          'border-top': 0,
5747          'background-color': '#ffffff'
5748        },
5749        search: {
5750          outline: 0,
5751          border: 0
5752        },
5753        searchWrapper: {},
5754        label: {
5755          'padding-right': this.options.topLabel ? '0' : '5px',
5756          width: this.options.textWdt || 'auto',
5757          'font-size': '13px'
5758        }
5759      };
5760      this.showable = [];
5761      this.correspondence = {};
5762      this.clearSearch(false);
5763
5764      if (this.options.css) {
5765        for (const elem in this.options.css) {
5766          this.css[elem] = this.options.css[elem];
5767        }
5768      }
5769      if (!this.options.items) this.options.items = [];
5770      if (!this.options.itemsId) this.options.itemsId = [];
5771      if (!this.options.initValue) this.options.initValue = undefined;
5772    };
5773
5774    this.setGlobalElements = function () {
5775      const dom = this.DOM;
5776      const css = this.css;
5777      dom.options = [];
5778      dom.$container = $('<div/>').css(css.container).addClass('dropdownContainer');
5779      dom.$table = $('<div/>').css(css.table).appendTo(dom.$container);
5780      if (this.options.topLabel) {
5781        dom.$topRow = $('<div/>').css(css.row).appendTo(dom.$table);
5782      }
5783      dom.$mainRow = $('<div/>').css(css.row).appendTo(dom.$table);
5784      dom.$label = $('<div/>').css(css.cell).text(this.options.label).css(css.label).appendTo(dom.$topRow || dom.$mainRow);
5785
5786      if (this.options.withSearch) {
5787        dom.$selectorWrapper = $('<div/>').css(css.cell).css(css.selectWrapper).appendTo(dom.$mainRow).append(
5788          dom.$selector = $('<div/>').css(css.selectwithsearch).addClass('higSelectorSimulator')
5789        );
5790
5791        dom.$dropdown = $('<div/>').css(css.dropdown).append(
5792          dom.$searchWrapper = $('<div/>').css(css.searchWrapper).addClass('higInputWrapper').append(
5793            dom.$search = $('<input/>', { type: 'text', style: 'width:100%', placeholder: (edw('search') + '...') }).css(css.search)
5794          ),
5795          dom.$optionList = $('<ul/>').css(css.optionList)
5796        );
5797
5798        this.dropdown = {
5799          visible: false,
5800          element: dom.$dropdown,
5801          appear: function (state) {
5802            if (!arguments.length) {
5803              this.appear(!this.visible);
5804            } else {
5805              if (state) {
5806                this.element.appendTo(dom.$selectorWrapper);
5807                this.visible = true;
5808              } else {
5809                this.element.detach();
5810                this.visible = false;
5811              }
5812            }
5813          }
5814        };
5815
5816        dom.$selector.on('click', (function (self) {
5817          return function (e) {
5818            self.dropdown.appear();
5819          };
5820        }(this)));
5821
5822        dom.$search.on('input', (function (self) {
5823          return function (e) {
5824            clearTimeout(this.searchTimeout);
5825            this.searchTimeout = setTimeout(function () {
5826              /* Standard Analisys of the search string */
5827              const string = e.target.value;
5828              let hardSearch = false;
5829              let tmp;
5830              let searchArray = [];
5831              if (typeof string !== 'string') return;
5832              if (!string.replace(/ +/g, '')) { // this pattern transform remove all white spaces so that also string like "       " are false.
5833                self.clearSearch();
5834                return;
5835              }
5836              tmp = string.split('"');
5837              if (tmp.length == 3) {
5838                searchArray.push(string.replace(/"/g, '')); // this pattern replaces " with empty strings (removes all the ").
5839                hardSearch = true;
5840              } else {
5841                tmp = string.toLowerCase();
5842                searchArray = tmp.replace(/ +/g, ' ').replace(/ $/, '').split(' '); // this pattern narrow down consecutive white spaces to a single one and trim the one in the end.
5843              }
5844              self.filterOptions({
5845                hard: hardSearch,
5846                sArray: searchArray
5847              });
5848            }, 250);
5849          };
5850        }(this)));
5851
5852        for (var i = 0; i < this.options.items.length; i++) {
5853          this.correspondence[this.options.itemsId[i]] = { idx: i, item: this.options.items[i] };
5854          dom.options[i] = $('<li/>', { value: this.options.itemsId[i] }).css(css.options)[this.options.itemsWithHtml ? 'html' : 'text'](this.options.items[i]).on('click', (function (self) {
5855            return function (e) {
5856              dom.$selector.attr('value', e.currentTarget.attributes.value.textContent);
5857              dom.$selector.attr('title', e.currentTarget.textContent);
5858              dom.$selector.selectorValue = e.currentTarget.attributes.value.textContent;
5859              dom.$selector[0].value = e.currentTarget.attributes.value.textContent;
5860              dom.$selector[self.options.itemsWithHtml ? 'html' : 'text'](e.currentTarget.textContent);
5861              dom.$selector.trigger('change');
5862              self.dropdown.appear();
5863              self.clearSearch();
5864            };
5865          }(this)));
5866        }
5867
5868        /* SET INITIAL VALUE */
5869
5870        const position = this.options.initValue ? this.options.itemsId.indexOf(this.options.initValue) : 0;
5871        dom.$selector.attr('value', this.options.itemsId[position]);
5872        dom.$selector.attr('title', this.options.items[position]);
5873        dom.$selector.selectorValue = this.options.itemsId[position];
5874        dom.$selector[0].value = this.options.itemsId[position];
5875        dom.$selector[this.options.itemsWithHtml ? 'html' : 'text'](this.options.items[position]);
5876      } else {
5877        dom.$selectorWrapper = $('<div/>').css(css.cell).appendTo(dom.$mainRow).append(
5878          dom.$selector = $('<select/>').css(css.select)
5879        );
5880        for (var i = 0; i < this.options.items.length; i++) {
5881          this.correspondence[this.options.itemsId[i]] = { idx: i, item: this.options.items[i] };
5882          dom.options[i] = $('<option/>', { value: this.options.itemsId[i], selected: (this.options.itemsId[i] == this.options.initValue) }).css(css.option).text(this.options.items[i]).appendTo(dom.$selector);
5883        }
5884      }
5885    };
5886
5887    this.setGlobalListeners = function () {
5888      this.DOM.$selector.on('change', (function (self) {
5889        return function (e) {
5890          self.options.onChange && self.options.onChange(e);
5891        };
5892      }(this)));
5893    };
5894
5895    this.draw = function (appendTo) {
5896      this.listOptions();
5897      this.DOM.$container.detach();
5898      this.DOM.$container.appendTo(appendTo || this.options.appendTo);
5899    };
5900
5901    this.clearSearch = function (redraw) {
5902      this.showable = this.options.itemsId.map(function (v, i) {
5903        return true;
5904      }, this);
5905      this.DOM.$search && this.DOM.$search.val('');
5906
5907      if (!arguments.length || redraw) {
5908        this.listOptions();
5909      }
5910    };
5911
5912    this.filterOptions = function (filterOpt) {
5913      this.showable = this.options.items.map(function (text, i) {
5914        text = '' + text;
5915        if (filterOpt.hard) {
5916          for (var j = 0; j < filterOpt.sArray.length; j++) {
5917            if (filterOpt.sArray[j] == text) return true;
5918          }
5919        } else {
5920          let flag = 0;
5921          for (var j = 0; j < filterOpt.sArray.length; j++) {
5922            if (text.toLowerCase().indexOf(filterOpt.sArray[j].toLowerCase()) > -1) flag++;
5923          }
5924          if (flag == filterOpt.sArray.length) return true;
5925        }
5926        return false;
5927      }, this);
5928      this.listOptions();
5929    };
5930
5931    this.listOptions = function () {
5932      const dom = this.DOM;
5933      if (this.options.withSearch) {
5934        dom.$optionList.find('>').detach();
5935      } /* else {
5936        dom.$selector.find('>').detach();
5937      } */
5938
5939      for (let i = 0; i < this.showable.length; i++) {
5940        if (this.showable[i]) {
5941          dom.options[i].appendTo(this.options.withSearch ? dom.$optionList : dom.$selector);
5942        }
5943      }
5944    };
5945
5946    this.setSelected = function (id, preventChange) {
5947      const c = this.correspondence[id];
5948      if (!(c.hasOwnProperty('idx') || c.hasOwnProperty('item'))) {
5949        console.info('Element not found!');
5950        return;
5951      }
5952      if (!preventChange) {
5953        this.DOM.options[c.idx].attr('selected', true);
5954        this.DOM.$selector.trigger('change');
5955      }
5956    };
5957
5958    if (this instanceof HigJS.forms.dropDownSelector) {
5959      mainOpt && this.init(mainOpt);
5960    } else {
5961      return new HigJS.forms.dropDownSelector(mainOpt);
5962    }
5963  };
5964}.call(this));
5965
5966
5967/* eslint-disable */
5968
5969(function () {
5970  HigJS.forms.grOptionsChooser = function (mainOpt) {
5971    const self = this;
5972
5973    this.init = function (customOpt) {
5974      const defaultOpt = {
5975        itemCfg: {
5976          upperLbl: true,
5977          label: '',
5978          upperLbl: false,
5979          abilAggr: false
5980        },
5981        plants: [],
5982        onChange: function () {},
5983        draw: true
5984      };
5985
5986      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
5987      this.options.saveTo = customOpt.saveTo || {};
5988      this.options.lastSelection = customOpt.lastSelection || {};
5989
5990      this.options.itemCfg.inpWdtHalf = (this.options.itemCfg.inpWdt / 2) - 3;
5991      this.options.itemCfg.txtWdtHalf = (this.options.itemCfg.txtWdt / 2) - 3;
5992      this.options.draw && this.draw();
5993    };
5994
5995    this.draw = function () {
5996      const options = this.options; const itemCfg = this.options.itemCfg; const grLabel = {}; const grId = {}; let i;
5997
5998      if (HigJS.cns.checkMCC('mccCorePl') && itemCfg.abilAggr) {
5999        if (options.saveTo.gwcSn || !options.saveTo.nodeVarId) {
6000          options.type = 'raw';
6001        } else {
6002          options.type = 'aggr';
6003        }
6004
6005        this.dataType = new HigJS.forms.menuSel({
6006          itemCfg: {
6007            label: edw('dataTypeSel'),
6008            key: 'type',
6009            items: ['raw', 'aggr'],
6010            itemsId: ['raw', 'aggr'],
6011            inpWdt: itemCfg.inpWdt,
6012            txtWdt: itemCfg.txtWdt,
6013            upperLbl: itemCfg.upperLbl
6014          },
6015          saveTo: options,
6016          appendTo: $('<div/>').appendTo(options.appendTo).addClass('optionField').css({ display: 'inline-block' }),
6017          onChange: function (val) {
6018            options.onChange && options.onChange(val);
6019            self.drawItemSelectors();
6020          }
6021        });
6022
6023        this.$aggrSelContainer = $('<div/>').appendTo(options.appendTo).addClass('optionField').css({ display: 'inline-block' });
6024      } else {
6025        options.type = 'raw';
6026      }
6027
6028      this.$grSelContainer = $('<div/>').appendTo(options.appendTo).addClass('optionField').css({ display: 'inline-block' });
6029
6030      options.plants.sort(function (a, b) {
6031        a = a ? HigJS.str.toLowerCase(a.nome) : '';
6032        b = b ? HigJS.str.toLowerCase(b.nome) : '';
6033        return ((a < b) ? -1 : ((a > b) ? 1 : 0));
6034      });
6035
6036      this.drawItemSelectors();
6037
6038      if (itemCfg.umKey) {
6039        typeof options.saveTo[itemCfg.umKey] === 'undefined' && (options.saveTo[itemCfg.umKey] = '');
6040        this.umObj = new HigJS.forms.inputText({
6041          itemCfg: { label: HigJS.diz.edw('unit'), key: itemCfg.umKey, inpWdt: itemCfg.inpWdtHalf, txtWdt: itemCfg.txtWdtHalf, upperLbl: itemCfg.upperLbl },
6042          saveTo: options.saveTo,
6043          appendTo: $('<div/>').appendTo(options.appendTo).addClass('optionField').css({ display: 'inline-block' }),
6044          onChange: options.onChange
6045        });
6046      }
6047
6048      if (itemCfg.nDecKey) {
6049        typeof options.saveTo[itemCfg.nDecKey] === 'undefined' && (options.saveTo[itemCfg.nDecKey] = 1);
6050        this.gainObj = new HigJS.forms.inputText({
6051          itemCfg: { label: HigJS.diz.edw('nDec'), key: itemCfg.nDecKey, inpWdt: itemCfg.inpWdtHalf, txtWdt: itemCfg.txtWdtHalf, upperLbl: itemCfg.upperLbl },
6052          saveTo: options.saveTo,
6053          appendTo: $('<div/>').appendTo(options.appendTo).addClass('optionField').css({ display: 'inline-block' }),
6054          onChange: options.onChange
6055        });
6056      }
6057
6058      if (itemCfg.offsetKey) {
6059        typeof options.saveTo[itemCfg.offsetKey] === 'undefined' && (options.saveTo[itemCfg.offsetKey] = 0);
6060        this.offsetObj = new HigJS.forms.inputText({
6061          itemCfg: { label: HigJS.diz.edw('offset'), key: itemCfg.offsetKey, inpWdt: itemCfg.inpWdtHalf, txtWdt: itemCfg.txtWdtHalf, upperLbl: itemCfg.upperLbl },
6062          saveTo: options.saveTo,
6063          appendTo: $('<div/>').appendTo(options.appendTo).addClass('optionField').css({ display: 'inline-block' }),
6064          onChange: options.onChange
6065        });
6066      }
6067
6068      if (itemCfg.gainKey) {
6069        typeof options.saveTo[itemCfg.gainKey] === 'undefined' && (options.saveTo[itemCfg.gainKey] = 1);
6070        this.gainObj = new HigJS.forms.inputText({
6071          itemCfg: { label: HigJS.diz.edw('gain'), key: itemCfg.gainKey, inpWdt: itemCfg.inpWdtHalf, txtWdt: itemCfg.txtWdtHalf, upperLbl: itemCfg.upperLbl },
6072          saveTo: options.saveTo,
6073          appendTo: $('<div/>').appendTo(options.appendTo).addClass('optionField').css({ display: 'inline-block' }),
6074          onChange: options.onChange
6075        });
6076      }
6077    };
6078
6079    this.drawItemSelectors = function () {
6080      const options = this.options; const itemCfg = this.options.itemCfg; let i;
6081
6082      if (options.type == 'aggr' && itemCfg.abilAggr) {
6083        this.$grSelContainer.hide();
6084
6085        this.$aggrSelContainer.show();
6086        if (this.aggrSel) {
6087          return;
6088        }
6089
6090        this.aggrSel = new HigJS.forms.aggrDataChooser({
6091          itemCfg: {
6092            key: 'key',
6093            inpWdt: itemCfg.inpWdt,
6094            txtWdt: itemCfg.txtWdt,
6095            label: itemCfg.label || HigJS.diz.edw('selectItem'),
6096            upperLbl: itemCfg.upperLbl,
6097            readOnly: itemCfg.readOnly
6098          },
6099          imgPath: '../img/',
6100          saveTo: { key: options.saveTo },
6101          plants: options.plants,
6102          nodeTypes: options.nodeTypes,
6103          varTypes: options.varTypes,
6104          nodeVarPeriods: options.nodeVarPeriods,
6105          appendTo: this.$aggrSelContainer,
6106          onChange: function (val) {
6107            const toDel = ['grandezzaId', 'grandezzeId', 'plantId', 'plantLbl', 'devId', 'lbl', 'devLbl', 'gwcLbl', 'dispositiviId', 'gwcSn', 'tipo', 'unit', 'grp'];
6108            for (var i = 0; i < toDel.length; i++) {
6109              delete options.saveTo[toDel[i]];
6110            }
6111            for (i in val) {
6112              options.saveTo[i] = val[i];
6113            }
6114
6115            options.onChange && options.onChange(HigJS.obj.clone(options.saveTo));
6116          }
6117        });
6118      } else {
6119        this.$aggrSelContainer && this.$aggrSelContainer.hide();
6120
6121        this.$grSelContainer.show();
6122        if (this.grSel) {
6123          return;
6124        }
6125
6126        if (itemCfg.plantId && !options.saveTo.plantId) { // Setto l'impianto di default
6127          options.saveTo.plantId = itemCfg.plantId;
6128          for (i = 0; i < options.plants.length; i++) {
6129            if (options.plants[i].impiantiId == itemCfg.plantId) {
6130              options.saveTo.plantLbl = options.plants[i].nome;
6131              break;
6132            }
6133          }
6134        }
6135
6136        this.grSel = new HigJS.forms.grChooserObj({
6137          itemCfg: {
6138            key: 'key',
6139            inpWdt: itemCfg.inpWdt,
6140            txtWdt: itemCfg.txtWdt,
6141            label: itemCfg.label || HigJS.diz.edw('selectItem'),
6142            upperLbl: itemCfg.upperLbl,
6143            noItems: itemCfg.noItems,
6144            noDevs: itemCfg.noDevs,
6145            deviceOnly: itemCfg.deviceOnly,
6146            pluginOnly: itemCfg.pluginOnly,
6147            disablePlantSel: itemCfg.disablePlantSel,
6148            readOnly: itemCfg.readOnly
6149          },
6150          imgPath: '../img/',
6151          lastSelection: options.lastSelection,
6152          saveTo: { key: options.saveTo },
6153          plants: options.plants,
6154          appendTo: this.$grSelContainer,
6155          onChange: function (val) {
6156            delete val.nodeId;
6157            delete val.nodeVarId;
6158            options.onChange && options.onChange(val);
6159          }
6160        });
6161      }
6162    };
6163
6164    mainOpt && this.init(mainOpt);
6165    return this;
6166  };
6167
6168  HigJS.forms.grChooserObj = function (optMain) {
6169    const self = this;
6170
6171    this.init = function (customOpt) {
6172      const defaultOpt = {
6173        itemCfg: {
6174          inpWdt: 100,
6175          inpHgt: 20,
6176          txtWdt: 100,
6177          txtHgt: 20,
6178          timeout: 1, // Permette di eseguire la funzione onChange solo ogni "timeout" millisecondi
6179          readOnly: false,
6180          valueId: false, // Id dizionario
6181          upperLbl: false,
6182          id: HigJS.num.genNum(),
6183          upperLblFont: { 'font-size': 12 }
6184        },
6185        imgPath: 'img/',
6186        inpWdt: 300,
6187        txtWdt: 300,
6188        plants: [],
6189        devices: [],
6190        onSave: function (val) { return val; },
6191        onShow: function (val) { return val; },
6192        checkInput: function () { return true; },
6193        draw: true
6194      };
6195
6196      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
6197      this.options.saveTo = customOpt.saveTo;
6198      this.options.lastSelection = customOpt.lastSelection;
6199
6200      this.options.itemCfg.devOnly && (this.options.itemCfg.noItems = true); // Retrocompatibilità
6201
6202      (!this.options.itemCfg.key || this.options.itemCfg.key == '') && (this.options.itemCfg.key = this.options.itemCfg.id);
6203      !this.options.saveTo[this.options.itemCfg.key] && (this.options.saveTo[this.options.itemCfg.key] = {});
6204
6205      this.plants = [];
6206      this.devices = [];
6207
6208      this.options.draw && this.draw();
6209
6210      return this;
6211    };
6212
6213    this.draw = function () {
6214      const options = this.options; const itemCfg = this.options.itemCfg; let plantNames = []; let plantIds = []; const gwcNames = []; const gwcIds = []; const devNames = []; const devIds = []; const grNames = []; const grandezzaIds = [];
6215
6216      this.$div = $('<div/>').appendTo(options.appendTo);
6217
6218      const strTable = HigJS.DOM.create({ type: 'table', rows: 1, cells: 2 }); let lbl;
6219
6220      this.selectedGr = new HigJS.forms.inputText({
6221        itemCfg: { label: itemCfg.label, key: 'lbl', inpWdt: itemCfg.inpWdt, txtWdt: itemCfg.txtWdt, readOnly: true, upperLbl: itemCfg.upperLbl },
6222        saveTo: { lbl: this.getResultStr() },
6223        onChange: function () { options.onChange && options.onChange(options.saveTo[itemCfg.key]); },
6224        appendTo: this.$div
6225      });
6226
6227      this.selectedGr.$input.on('mousedown', function () {
6228        if (options.lastSelection && (!options.saveTo[options.itemCfg.key].grandezzaId || options.saveTo[options.itemCfg.key].grandezzaId == 0)) {
6229          for (const key in options.lastSelection) {
6230            options.saveTo[options.itemCfg.key][key] = options.lastSelection[key];
6231          }
6232          options.saveTo[options.itemCfg.key].grandezzaId = 0;
6233          options.saveTo[options.itemCfg.key].grandezzeId = 0;
6234        }
6235
6236        // if( itemCfg.readOnly ) return;
6237
6238        const grbox = new HigJS.forms.overlayBox({
6239          itemCfg: { small: true },
6240          onClose: function () {
6241            if (self.options.saveTo[itemCfg.key].plantId == 0 || self.options.saveTo[itemCfg.key].dispositiviId == 0) { self.selectedGr.setValue('---'); }
6242            // else if( itemCfg.disablePlantSel )
6243            //   self.selectedGr.setValue( options.saveTo[ itemCfg.key ].gwcLbl + "-->" + options.saveTo[ itemCfg.key ].devLbl + "-->" + options.saveTo[ itemCfg.key ].lbl );
6244            // else
6245            //   self.selectedGr.setValue( options.saveTo[ itemCfg.key ].plantLbl + "-->" + options.saveTo[ itemCfg.key ].gwcLbl + "-->" + options.saveTo[ itemCfg.key ].devLbl + "-->" + options.saveTo[ itemCfg.key ].lbl );
6246            else { self.selectedGr.setValue(self.getResultStr()); }
6247          }
6248        });
6249
6250        self.$winDiv = $('<div/>').css({ 'background-color': 'white', color: 'black', height: '100%', 'text-align': 'center', 'padding-top': 5 });
6251        grbox.$container.append(self.$winDiv);
6252
6253        HigJS.array.sort(self.options.plants, 'nome');
6254
6255        plantNames = [HigJS.diz.edw('select') + '...'];
6256        plantIds = [0];
6257
6258        for (let i = 0; i < self.options.plants.length; i++) {
6259          plantNames.push(self.options.plants[i].nome);
6260          plantIds.push(self.options.plants[i].impiantiId);
6261        }
6262
6263        if (!itemCfg.disablePlantSel) {
6264          self.plantSelector = new HigJS.forms.menuSel({
6265            itemCfg: { label: HigJS.diz.edw('plantSelector') + ' :', key: 'plantId', inpWdt: options.inpWdt, txtWdt: options.txtWdt, items: plantNames, itemsId: plantIds, upperLbl: true, readOnly: itemCfg.readOnly },
6266            saveTo: options.saveTo[itemCfg.key],
6267            appendTo: self.$winDiv.empty(),
6268            onChange: function (val, index) {
6269              self.$gwcDiv.empty();
6270              self.$deviceDiv.empty();
6271              self.$grDiv.empty();
6272              options.saveTo[itemCfg.key].plantLbl = index == 0 ? '---' : plantNames[index];
6273              options.saveTo[itemCfg.key].devId = 0;
6274              options.saveTo[itemCfg.key].grandezzaId = 0;
6275              options.saveTo[itemCfg.key].grandezzeId = 0;
6276              options.saveTo[itemCfg.key].lbl = '';
6277              options.saveTo[itemCfg.key].devLbl = '';
6278              options.saveTo[itemCfg.key].gwcLbl = '';
6279              options.saveTo[itemCfg.key].dispositiviId = 0;
6280              options.saveTo[itemCfg.key].gwcSn = 0;
6281
6282              index == 0 ? self.okButton.$button.show() : self.okButton.$button.hide();
6283
6284              options.onChange && options.onChange(options.saveTo[itemCfg.key]);
6285
6286              if (options.saveTo[itemCfg.key].plantId == 0) { return; }
6287
6288              self.setGwcArray({ plantId: options.saveTo[itemCfg.key].plantId, onSuccess: function () { self.drawGwcSel(); } });
6289            }
6290          });
6291          self.plantSelector.$div.css({ margin: '2px auto' });
6292
6293          self.$gwcDiv = $('<div/>').appendTo(self.$winDiv);
6294          self.$deviceDiv = $('<div/>').appendTo(self.$winDiv);
6295          self.$grDiv = $('<div/>').appendTo(self.$winDiv);
6296
6297          // if( options.saveTo[ itemCfg.key ].dispositiviId )
6298          if (parseInt(options.saveTo[itemCfg.key].plantId)) { self.setGwcArray({ plantId: options.saveTo[itemCfg.key].plantId, onSuccess: function () { self.drawGwcSel(); } }); }
6299        } else {
6300          self.$gwcDiv = $('<div/>').appendTo(self.$winDiv);
6301          self.$deviceDiv = $('<div/>').appendTo(self.$winDiv);
6302          self.$grDiv = $('<div/>').appendTo(self.$winDiv);
6303          options.saveTo[itemCfg.key].plantId = options.saveTo[itemCfg.key].plantId || plantIds[1];
6304          self.setGwcArray({ plantId: options.saveTo[itemCfg.key].plantId, onSuccess: function () { self.drawGwcSel(); } });
6305        }
6306
6307        self.okButton = new HigJS.forms.button({
6308          itemCfg: { label: HigJS.diz.edw('ok') },
6309          onClick: function () {
6310            if (options.lastSelection && options.saveTo[options.itemCfg.key].grandezzaId && options.saveTo[options.itemCfg.key].grandezzaId != 0) {
6311              for (const key in options.saveTo[options.itemCfg.key]) {
6312                options.lastSelection[key] = options.saveTo[options.itemCfg.key][key];
6313              }
6314              options.lastSelection.grandezzaId = 0;
6315              options.lastSelection.grandezzeId = 0;
6316            }
6317            grbox.close();
6318          },
6319          appendTo: $('<div/>').appendTo(self.$winDiv).css({ display: 'inline-block', 'margin-top': '5px' })
6320        });
6321
6322        if ((itemCfg.noItems && !options.saveTo[itemCfg.key].devId) ||
6323          (!itemCfg.noItems && !options.saveTo[itemCfg.key].grandezzaId) ||
6324          (!itemCfg.noDevs && !options.saveTo[itemCfg.key].gwcSn)) { self.okButton.$button.hide(); }
6325      });
6326    };
6327
6328    // Carico elendo dispositivi per un determinato impianto
6329    this.setGwcArray = function (gwcOpt) {
6330      if (this.plants[gwcOpt.plantId]) {
6331        gwcOpt.onSuccess && gwcOpt.onSuccess();
6332        return;
6333      }
6334
6335      HigJS.forms.startLoader();
6336      HigJS.ajax.request({
6337        act: 'readDispositiviImpianto',
6338        ids: userConf.ids,
6339        data: { impiantiId: gwcOpt.plantId, fields: ['nome', 'serialNumber', 'dispositiviId'] },
6340        url: '/PHP/phpScript/user.php',
6341        onSuccess: function (msg) {
6342          if (!HigJS.ajax.checkResponse(msg).ok) {
6343            HigJS.debug.error(HigJS.ajax.checkResponse(msg).errMsg);
6344            HigJS.DOM.alert(HigJS.diz.edw('errorOnReadUsers'));
6345            return 0;
6346          }
6347          self.plants[gwcOpt.plantId] = msg.DATI[0].DATI;
6348          HigJS.array.sort(self.plants[gwcOpt.plantId], 'nome');
6349
6350          gwcOpt.onSuccess && gwcOpt.onSuccess();
6351          HigJS.forms.stopLoader();
6352        }
6353      });
6354    };
6355
6356    // Carico periferiche e grandezze di un dispositivo
6357    this.setDevArray = function (devOpt) {
6358      const itemCfg = this.options.itemCfg; const options = this.options;
6359
6360      if (!options.saveTo[itemCfg.key].dispositiviId) { return; }
6361      if (this.devices[devOpt.dispositiviId]) {
6362        devOpt.onSuccess && devOpt.onSuccess();
6363      } else {
6364        HigJS.forms.startLoader();
6365        HigJS.ajax.request({
6366          act: 'readDispositivoGrandezze',
6367          ids: userConf.ids,
6368          data: { dispositiviId: devOpt.dispositiviId },
6369          url: '/PHP/phpScript/user.php',
6370          onSuccess: function (msg) {
6371            if (!HigJS.ajax.checkResponse(msg).ok) {
6372              HigJS.debug.error(HigJS.ajax.checkResponse(msg).errMsg);
6373              HigJS.DOM.alert(HigJS.diz.edw('errorOnReadUsers'));
6374              return 0;
6375            }
6376
6377            const devices = msg.DATI[0].DATI;
6378            if (devices.length) {
6379              let x, y, i;
6380              devices.sort(function (a, b) {
6381                x = a.lblTab ? a.lblTab.toLowerCase() : '';
6382                y = b.lblTab ? b.lblTab.toLowerCase() : '';
6383                return ((x < y) ? -1 : ((x > y) ? 1 : 0));
6384              });
6385              for (i = 0; i < devices.length; i++) {
6386                if (!devices[i].Grandezze || !devices[i].Grandezze.length) { continue; }
6387                devices[i].Grandezze.sort(function (a, b) {
6388                  x = a.lbl ? a.lbl.toLowerCase() : '';
6389                  y = b.lbl ? b.lbl.toLowerCase() : '';
6390                  return ((x < y) ? -1 : ((x > y) ? 1 : 0));
6391                });
6392              }
6393            }
6394
6395            self.devices[devOpt.dispositiviId] = devices;
6396            devOpt.onSuccess && devOpt.onSuccess();
6397            HigJS.forms.stopLoader();
6398          }
6399        });
6400      }
6401    };
6402
6403    this.drawGwcSel = function () {
6404      const gwcNames = [HigJS.diz.edw('select') + '...']; const gwcIds = [0]; const itemCfg = this.options.itemCfg; const options = this.options;
6405
6406      for (let i = 0; i < this.plants[options.saveTo[itemCfg.key].plantId].length; i++) {
6407        gwcNames.push(this.plants[options.saveTo[itemCfg.key].plantId][i].nome);
6408        gwcIds.push(this.plants[options.saveTo[itemCfg.key].plantId][i].dispositiviId);
6409      }
6410
6411      this.gwcSelector = new HigJS.forms.menuSel({
6412        itemCfg: { label: HigJS.diz.edw('gwcSelector') + ' :', key: 'dispositiviId', inpWdt: options.inpWdt, txtWdt: options.txtWdt, items: gwcNames, itemsId: gwcIds, upperLbl: true, readOnly: itemCfg.readOnly },
6413        saveTo: options.saveTo[itemCfg.key],
6414        appendTo: this.$gwcDiv.empty(),
6415        onChange: function (val, index) {
6416          options.saveTo[itemCfg.key].devId = 0;
6417          options.saveTo[itemCfg.key].grandezzaId = 0;
6418          options.saveTo[itemCfg.key].grandezzeId = 0;
6419          options.saveTo[itemCfg.key].lbl = '';
6420          options.saveTo[itemCfg.key].devLbl = '';
6421          options.saveTo[itemCfg.key].gwcLbl = '';
6422          self.$deviceDiv.empty();
6423          self.$grDiv.empty();
6424
6425          self.okButton.$button.hide();
6426          options.onChange && options.onChange(options.saveTo[itemCfg.key]);
6427
6428          if (options.saveTo[itemCfg.key].dispositiviId == 0) { return; }
6429
6430          if (val) {
6431            options.saveTo[itemCfg.key].gwcSn = self.plants[options.saveTo[itemCfg.key].plantId][index - 1].serialNumber;
6432            options.saveTo[itemCfg.key].gwcLbl = gwcNames[index];
6433          }
6434
6435          self.setDevArray({ dispositiviId: options.saveTo[itemCfg.key].dispositiviId, onSuccess: function () { self.drawDevSel(); } });
6436        }
6437      });
6438      this.gwcSelector.$div.css({ margin: '2px auto' });
6439
6440      if (parseInt(options.saveTo[itemCfg.key].dispositiviId)) { self.setDevArray({ dispositiviId: options.saveTo[itemCfg.key].dispositiviId, onSuccess: function () { self.drawDevSel(); } }); }
6441    };
6442
6443    this.drawDevSel = function () {
6444      const devNames = [HigJS.diz.edw('select') + '...']; const devIds = [0]; const itemCfg = this.options.itemCfg; const options = this.options;
6445
6446      if (itemCfg.noDevs) {
6447        self.okButton.$button.show();
6448        return;
6449      }
6450
6451      for (let i = 0; i < this.devices[options.saveTo[itemCfg.key].dispositiviId].length; i++) {
6452        // Salto le periferiche se voglio solo i plugin
6453        if (itemCfg.pluginOnly && parseInt(this.devices[options.saveTo[itemCfg.key].dispositiviId][i].idPeriferica) > 1999999) { continue; }
6454        if (itemCfg.deviceOnly && parseInt(this.devices[options.saveTo[itemCfg.key].dispositiviId][i].idPeriferica) < 2000000) { continue; }
6455        devNames.push(this.devices[options.saveTo[itemCfg.key].dispositiviId][i].lblTab);
6456        devIds.push(this.devices[options.saveTo[itemCfg.key].dispositiviId][i].idPeriferica);
6457      }
6458
6459      this.devSelector = new HigJS.forms.menuSel({
6460        itemCfg: { label: HigJS.diz.edw(itemCfg.pluginOnly ? 'pluginSelector' : 'devSelector') + ' :', key: 'devId', inpWdt: options.inpWdt, txtWdt: options.txtWdt, items: devNames, itemsId: devIds, upperLbl: true, readOnly: itemCfg.readOnly },
6461        saveTo: options.saveTo[itemCfg.key],
6462        appendTo: this.$deviceDiv.empty(),
6463        onChange: function (val, index) {
6464          options.saveTo[itemCfg.key].devId = val;
6465          options.saveTo[itemCfg.key].devLbl = devNames[index];
6466          options.saveTo[itemCfg.key].grandezzaId = 0;
6467          options.saveTo[itemCfg.key].grandezzeId = 0;
6468          options.saveTo[itemCfg.key].lbl = '';
6469          self.okButton.$button.hide();
6470          self.drawGrSel();
6471          options.onChange && options.onChange(options.saveTo[itemCfg.key]);
6472        }
6473      });
6474      this.devSelector.$div.css({ margin: '2px auto' });
6475
6476      if (options.saveTo[itemCfg.key].devId) { self.drawGrSel(); }
6477    };
6478
6479    this.drawGrSel = function () {
6480      const grNames = [HigJS.diz.edw('select') + '...']; const grandezzaIds = [0]; const grandezzeIds = [0]; const grandezze = []; let i = 0; let j = 0; const itemCfg = this.options.itemCfg; const options = this.options;
6481
6482      if (itemCfg.noItems) {
6483        self.okButton.$button.show();
6484        return;
6485      }
6486
6487      for (i = 0; i < this.devices[options.saveTo[itemCfg.key].dispositiviId].length; i++) {
6488        if (options.saveTo[itemCfg.key].devId == this.devices[options.saveTo[itemCfg.key].dispositiviId][i].idPeriferica) {
6489          for (j = 0; j < this.devices[options.saveTo[itemCfg.key].dispositiviId][i].Grandezze.length; j++) {
6490            if (itemCfg.um) {
6491              for (z = 0; z < itemCfg.um.length; z++) {
6492                if (itemCfg.um[z].toLowerCase() == this.devices[options.saveTo[itemCfg.key].dispositiviId][i].Grandezze[j].unit.toLowerCase()) {
6493                  grNames.push(this.devices[options.saveTo[itemCfg.key].dispositiviId][i].Grandezze[j].lbl);
6494                  grandezzaIds.push(this.devices[options.saveTo[itemCfg.key].dispositiviId][i].Grandezze[j].grandezzaId
6494);
6495                  grandezze.push(this.devices[options.saveTo[itemCfg.key].dispositiviId][i].Grandezze[j]);
6496                  break;
6497                }
6498              }
6499            } else {
6500              grNames.push(this.devices[options.saveTo[itemCfg.key].dispositiviId][i].Grandezze[j].lbl);
6501              grandezzaIds.push(this.devices[options.saveTo[itemCfg.key].dispositiviId][i].Grandezze[j].grandezzaId);
6502              grandezze.push(this.devices[options.saveTo[itemCfg.key].dispositiviId][i].Grandezze[j]);
6503            }
6504          }
6505          break;
6506        }
6507      }
6508
6509      this.grSelector = new HigJS.forms.menuSel({
6510        itemCfg: { label: HigJS.diz.edw('grSelector') + ' :', key: 'grandezzaId', inpWdt: options.inpWdt, txtWdt: options.txtWdt, items: grNames, itemsId: grandezzaIds, upperLbl: true, readOnly: itemCfg.readOnly },
6511        saveTo: options.saveTo[itemCfg.key],
6512        appendTo: this.$grDiv.empty(),
6513        onChange: function (val, index) {
6514          options.saveTo[itemCfg.key] = $.extend(true, options.saveTo[itemCfg.key], grandezze[index - 1]);
6515          options.onChange && options.onChange(options.saveTo[itemCfg.key]);
6516          self.okButton.$button.show();
6517        }
6518      });
6519      this.grSelector.$div.css({ margin: '2px auto' });
6520    };
6521
6522    this.getResultStr = function () {
6523      const options = this.options; const itemCfg = this.options.itemCfg; let retString = '';
6524      !itemCfg.disablePlantSel && (retString += options.saveTo[itemCfg.key].gwcLbl + '-->');
6525      retString += options.saveTo[itemCfg.key].gwcLbl;
6526
6527      if (itemCfg.noDevs) { return retString; }
6528      retString += '-->' + options.saveTo[itemCfg.key].devLbl;
6529
6530      if (itemCfg.noItems) { return retString; }
6531      retString += '-->' + options.saveTo[itemCfg.key].lbl;
6532      return retString;
6533
6534      // if( itemCfg.disablePlantSel && options.saveTo[ itemCfg.key ].gwcLbl && !itemCfg.noItems )
6535      //   return options.saveTo[ itemCfg.key ].gwcLbl + "-->" + options.saveTo[ itemCfg.key ].devLbl + "-->" + options.saveTo[ itemCfg.key ].lbl;
6536      // else if( itemCfg.disablePlantSel && options.saveTo[ itemCfg.key ].gwcLbl && itemCfg.noItems)
6537      //   return options.saveTo[ itemCfg.key ].gwcLbl + "-->" + options.saveTo[ itemCfg.key ].devLbl;
6538      // else if( options.saveTo[ itemCfg.key ].gwcLbl && !itemCfg.noItems )
6539      //   return options.saveTo[ itemCfg.key ].plantLbl + "-->" + options.saveTo[ itemCfg.key ].gwcLbl + "-->" + options.saveTo[ itemCfg.key ].devLbl + "-->" + options.saveTo[ itemCfg.key ].lbl;
6540      // else if( options.saveTo[ itemCfg.key ].gwcLbl && itemCfg.noItems )
6541      //   return options.saveTo[ itemCfg.key ].plantLbl + "-->" + options.saveTo[ itemCfg.key ].gwcLbl + "-->" + options.saveTo[ itemCfg.key ].devLbl;
6542    };
6543
6544    this.getValue = function () {
6545      return this.options.saveTo[this.options.itemCfg.key];
6546    };
6547
6548    this.getSize = function (opt) {
6549      return this.selectedGr.getSize(opt);
6550    };
6551
6552    this.setLabel = function (label) {
6553      this.selectedGr.setLabel(label);
6554    };
6555
6556    this.setSize = function (opt) {
6557      return this.selectedGr.setSize(opt);
6558    };
6559
6560    optMain && this.init(optMain);
6561    return this;
6562  };
6563
6564  HigJS.forms.uploadFileForm = function (optMain) {
6565    const self = this;
6566
6567    this.init = function (customOpt) {
6568      const defaultOpt = {
6569        itemCfg: {
6570          inpWdt: 100,
6571          txtWdt: 100,
6572          upperLblFont: { 'font-size': 12 },
6573          upperLbl: false,
6574          buttonLbl: 'Submit',
6575          label: 'Load File',
6576          phpFile: '/PHP/phpScript/user.php',
6577          align: 'left',
6578          req: { act: 'act', ids: 'ids_none', data: {} },
6579          id: HigJS.num.genNum()
6580        },
6581        draw: true
6582      };
6583
6584      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
6585      this.options.draw && this.draw();
6586      return this;
6587    };
6588
6589    this.draw = function () {
6590      const options = this.options; const itemCfg = this.options.itemCfg; let data;
6591
6592      if (!this.$div) {
6593        this.$div = $('<div/>').appendTo(options.appendTo)
6594          .addClass('inputText2')
6595          .css({ 'text-align': 'left' });
6596      } else {
6597        this.$div.empty();
6598      }
6599
6600      if (itemCfg.upperLbl) {
6601        this.$label = $('<label/>', { for: itemCfg.id }).appendTo($('<div/>').appendTo(this.$div).css({ 'text-align': 'left' }))
6602          .css(itemCfg.upperLblFont)
6603          .text(itemCfg.label);
6604      } else {
6605        this.$label = $('<div/>', { id: 'label' }).appendTo(this.$div)
6606          .text(itemCfg.label);
6607      }
6608
6609      if (!$('iframe[name=fakeFrame]').length) {
6610        $('body').append('<IFRAME  style="display:none" name ="fakeFrame" src=""></IFRAME>');
6611      }
6612
6613      this.$form = $('<form/>', {
6614        action: itemCfg.phpFile,
6615        target: 'fakeFrame',
6616        enctype: 'multipart/form-data',
6617        method: 'post'
6618      }).appendTo(this.$div).hide();
6619
6620      this.drawFileInput();
6621
6622      const query = HigJS.obj.toString([{ act: itemCfg.req.act, idReq: itemCfg.req.idReq || itemCfg.req.act, ids: itemCfg.req.ids, DATI: itemCfg.req.data }]);
6623
6624      itemCfg.phpFile == '/node' && (itemCfg.nodeJs = true);
6625
6626      $('<input/>', { type: 'hidden', name: 'query', value: itemCfg.nodeJs ? HigJS.Tea.encrypt
6626('query=' + query, 'SR0cM+3pitFygtrA') : 'query=' + query }).appendTo(this.$form);
6627      this.submitButton = new HigJS.forms.button({
6628        itemCfg: { label: itemCfg.buttonLbl, inpWdt: itemCfg.inpWdt },
6629        onClick: function () {
6630          options.onClick && options.onClick();
6631          self.$fileInput.trigger('click');
6632        },
6633        appendTo: $('<div/>').appendTo(this.$div).css({ display: 'inline-block', 'margin-top': 5 })
6634      });
6635
6636      this.setSize({ txtWdt: itemCfg.txtWdt, inpWdt: itemCfg.inpWdt });
6637    };
6638
6639    this.drawFileInput = function () {
6640      this.$fileInput && this.$fileInput.remove();
6641      this.$fileInput = $('<input/>', { type: 'file', name: 'file', width: 0 })
6642        .appendTo(this.$form)
6643        .on('change', function (e) {
6644          e.preventDefault();
6645          self.options.onSubmit && self.options.onSubmit();
6646          self.$form.submit();
6647          self.drawFileInput();
6648        })
6649        .hide();
6650    };
6651
6652    this.setSize = function (opt) {
6653      const itemCfg = this.options.itemCfg; let inpWdt = itemCfg.inpWdt; let txtWdt = itemCfg.txtWdt; let width;
6654
6655      if (opt.txtWdt || opt.inpWdt) {
6656        inpWdt = parseInt(opt.inpWdt) || itemCfg.inpWdt;
6657        txtWdt = parseInt(opt.txtWdt) || itemCfg.txtWdt;
6658        width = itemCfg.upperLbl ? inpWdt : inpWdt + txtWdt;
6659      } else if (opt.width && itemCfg.upperLbl) {
6660        inpWdt = parseInt(opt.width);
6661        txtWdt = parseInt(opt.width);
6662        width = parseInt(opt.width);
6663      } else if (opt.width && !itemCfg.upperLbl) {
6664        inpWdt = parseInt(opt.width / 2);
6665        txtWdt = parseInt(opt.width / 2);
6666        width = parseInt(opt.width);
6667      }
6668
6669      this.$label.css({ width: txtWdt });
6670      this.submitButton.setSize({ width: inpWdt });
6671      this.$div.css({ width });
6672
6673      itemCfg.txtWdt = parseInt(txtWdt);
6674      itemCfg.inpWdt = parseInt(inpWdt);
6675      itemCfg.width = parseInt(width);
6676      return this;
6677    };
6678
6679    optMain && this.init(optMain);
6680  };
6681
6682  HigJS.forms.uploadFile = function (optMain) {
6683    const self = this;
6684
6685    this.init = function (customOpt) {
6686      const defaultOpt = {
6687        itemCfg: {
6688          inpWdt: 100,
6689          txtWdt: 100,
6690          upperLblFont: { 'font-size': 12 },
6691          upperLbl: false,
6692          buttonLbl: 'Submit',
6693          label: 'Load File',
6694          url: '/PHP/phpScript/user.php',
6695          align: 'left',
6696          req: { act: 'act', ids: 'ids_none', data: {} },
6697          id: HigJS.num.genNum()
6698        },
6699        draw: true
6700      };
6701
6702      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
6703      this.options.draw && this.draw();
6704      return this;
6705    };
6706
6707    this.draw = function () {
6708      const options = this.options; const itemCfg = this.options.itemCfg;
6709
6710      if (!this.$div) {
6711        this.$div = $('<div/>').appendTo(options.appendTo)
6712          .addClass('inputText2')
6713          .css({ 'text-align': 'left' });
6714      } else {
6715        this.$div.empty();
6716      }
6717
6718      if (itemCfg.upperLbl) {
6719        this.$label = $('<label/>', { for: itemCfg.id }).appendTo($('<div/>').appendTo(this.$div).css({ 'text-align': 'left' }))
6720          .css(itemCfg.upperLblFont)
6721          .text(itemCfg.label);
6722      } else {
6723        this.$label = $('<div/>', { id: 'label' }).appendTo(this.$div)
6724          .text(itemCfg.label);
6725      }
6726
6727      this.drawFileInput();
6728      itemCfg.url === '/node' && (itemCfg.nodeJs = true);
6729
6730      this.submitButton = new HigJS.forms.button({
6731        itemCfg: { label: itemCfg.buttonLbl, inpWdt: itemCfg.inpWdt },
6732        onClick: function () {
6733          options.onClick && options.onClick();
6734          self.$fileInput.trigger('click');
6735        },
6736        appendTo: $('<div/>').appendTo(this.$div).css({ display: 'inline-block', 'margin-top': 5 })
6737      });
6738
6739      this.setSize({ txtWdt: itemCfg.txtWdt, inpWdt: itemCfg.inpWdt });
6740    };
6741
6742    this.drawFileInput = function () {
6743      const itemCfg = this.options.itemCfg;
6744      const options = this.options;
6745
6746      const query = 'query=' + HigJS.obj.toString([{ act: itemCfg.req.act, idReq: itemCfg.req.idReq || itemCfg.req.act, ids: itemCfg.req.ids, DATI: itemCfg.req.data }]);
6747
6748      const formData = new FormData();
6749      formData.append('query', query);
6750
6751      this.$fileInput && this.$fileInput.remove();
6752      this.$fileInput = $('<input/>', { type: 'file', name: 'file', width: 0 })
6753        .appendTo(this.$div)
6754        .on('change', function (e) {
6755          e.preventDefault();
6756
6757          self.options.onSubmit && self.options.onSubmit();
6758          formData.append('file', this.files[0]);
6759
6760          fetch(itemCfg.phpFile, { method: 'POST', body: formData })
6761            .then(async (msg) => {
6762              options.onSuccess && options.onSuccess(await msg.json());
6763            });
6764
6765          self.drawFileInput();
6766        })
6767        .hide();
6768    };
6769
6770    this.setSize = function (opt) {
6771      const itemCfg = this.options.itemCfg; let inpWdt = itemCfg.inpWdt; let txtWdt = itemCfg.txtWdt; let width;
6772
6773      if (opt.txtWdt || opt.inpWdt) {
6774        inpWdt = parseInt(opt.inpWdt) || itemCfg.inpWdt;
6775        txtWdt = parseInt(opt.txtWdt) || itemCfg.txtWdt;
6776        width = itemCfg.upperLbl ? inpWdt : inpWdt + txtWdt;
6777      } else if (opt.width && itemCfg.upperLbl) {
6778        inpWdt = parseInt(opt.width);
6779        txtWdt = parseInt(opt.width);
6780        width = parseInt(opt.width);
6781      } else if (opt.width && !itemCfg.upperLbl) {
6782        inpWdt = parseInt(opt.width / 2);
6783        txtWdt = parseInt(opt.width / 2);
6784        width = parseInt(opt.width);
6785      }
6786
6787      this.$label.css({ width: txtWdt });
6788      this.submitButton.setSize({ width: inpWdt });
6789      this.$div.css({ width });
6790
6791      itemCfg.txtWdt = parseInt(txtWdt);
6792      itemCfg.inpWdt = parseInt(inpWdt);
6793      itemCfg.width = parseInt(width);
6794      return this;
6795    };
6796
6797    optMain && this.init(optMain);
6798  };
6799
6800  HigJS.forms.callManagerObj = function (optMain) {
6801    const self = this;
6802
6803    this.init = function (customOpt) {
6804      const defaultOpt = {
6805        interval: true,
6806        start: false,
6807        source: 'server'
6808      };
6809
6810      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
6811      this.objs = [];
6812      this.options.start && this.startDaemon();
6813      return this;
6814    };
6815
6816    this.add = function (opt) {
6817      this.objs.push({ obj: opt.obj, id: opt.id || HigJS.num.genNum({ max: 100000 }) });
6818      return this;
6819    };
6820
6821    this.remove = function (opt) {
6822      !opt.id && HigJS.debug.error('CallManager2: remove - no obj.id');
6823      for (let i = 0; i < this.objs.length; i++) {
6824        if (this.objs[i].id === opt.id) {
6825          this.objs.remove(i);
6826          return;
6827        }
6828      }
6829    };
6830
6831    this.createAjaxCalls = function () {
6832      let i, ajaxCalls, j;
6833      this.calls = {};
6834
6835      for (i = 0; i < this.objs.length; i++) {
6836        ajaxCalls = this.objs[i].obj.createAjaxCalls();
6837
6838        if (!ajaxCalls || !ajaxCalls.length) {
6839          continue;
6840        }
6841
6842        for (j = 0; j < ajaxCalls.length; j++) {
6843          !this.calls[ajaxCalls[j].cgi] && (this.calls[ajaxCalls[j].cgi] = []);
6844          this.calls[ajaxCalls[j].cgi].push({ call: ajaxCalls[j], _obj: this.objs[i].obj });
6845        }
6846      }
6847      return this;
6848    };
6849
6850    this.startDaemon = function () {
6851      if (this.calling) {
6852        clearTimeout(this.timer);
6853        this.timer = setTimeout(function () { self.startDaemon(); }, 1000);
6854        return;
6855      }
6856
6857      this.calling = true;
6858      this.sendCalls({
6859        onComplete: function () {
6860          clearTimeout(self.mainTimer);
6861          self.mainTimer = setTimeout(function () { self.startDaemon(); }, self.options.interval);
6862          self.calling = false;
6863        }
6864      });
6865    };
6866
6867    this.stopDaemon = function () {
6868      clearTimeout(this.mainTimer);
6869      clearTimeout(this.timer);
6870    };
6871
6872    this.sendCalls = function (opt) {
6873      const cgies = []; let cgi; let i = 0; let func; const options = this.options;
6874
6875      !opt && (opt = {});
6876
6877      this.createAjaxCalls();
6878
6879      for (cgi in this.calls) { cgies.push(cgi); }
6880
6881      func = function () {
6882        if (i < cgies.length) { self.makeCallsByCgi({ cgi: cgies[i], onComplete: func }); } else {
6883          opt.onComplete && opt.onComplete();
6884          options.onComplete && options.onComplete();
6885        }
6886        i++;
6887      };
6888
6889      func();
6890      return this;
6891    };
6892
6893    this.sendSingleCall = function (opt) {
6894      if (this.calling) {
6895        setTimeout(function () { self.sendSingleCall(opt); }, 1000);
6896        return;
6897      }
6898
6899      const cgies = []; let cgi; let i; let ajaxCalls; let j;
6900      this.calls = {};
6901
6902      this.calling = true;
6903      this.stopDaemon();
6904
6905      opt.id && (opt.ids = [opt.id]);
6906
6907      for (i = 0; i < this.objs.length; i++) {
6908        for (j = 0; j < opt.ids.length; j++) {
6909          if (this.objs[i].id != opt.ids[j]) { continue; }
6910
6911          ajaxCalls = this.objs[i].obj.createAjaxCalls();
6912          for (j = 0; j < ajaxCalls.length; j++) {
6913            !this.calls[ajaxCalls[j].cgi] && (this.calls[ajaxCalls[j].cgi] = []);
6914            this.calls[ajaxCalls[j].cgi].push({ call: ajaxCalls[j], _obj: this.objs[i].obj });
6915          }
6916
6917          break;
6918        }
6919      }
6920
6921      i = 0;
6922      for (cgi in this.calls) { cgies.push(cgi); }
6923
6924      func = function () {
6925        if (i < cgies.length) { self.makeCallsByCgi({ cgi: cgies[i], onComplete: func }); } else {
6926          self.calling = false;
6927          opt.onSuccess && opt.onSuccess();
6928          clearTimeout(self.mainTimer);
6929          self.mainTimer = setTimeout(function () { self.startDaemon(); }, self.options.interval);
6930        }
6931        i++;
6932      };
6933
6934      func();
6935
6936      return this;
6937    };
6938
6939    /** *************** ORIGINALE ***************************/
6940
6941    this.makeCallsByCgi_old = function (opt) {
6942      const reqs = []; let i; let j;
6943
6944      for (i = 0; i < this.calls[opt.cgi].length; i++) {
6945        this.calls[opt.cgi][i].call.onRequest && this.calls[opt.cgi][i].call.onRequest();
6946        reqs.push({ act: this.calls[opt.cgi][i].call.act, sn: this.calls[opt.cgi][i].call.sn, idReq: this.calls[opt.cgi][i].call.idReq, data: this.calls[opt.cgi][i].call.data });
6947      }
6948
6949      HigJS.ajax.request({
6950        reqs,
6951        ids: opt.ids || userConf.ids,
6952        onSuccess: function (msg) {
6953          if (!HigJS.ajax.checkResponse(msg).ok) { HigJS.debug.error(HigJS.ajax.checkResponse(msg).errMsg); }
6954
6955          for (i = 0; i < msg.DATI.length; i++) {
6956            for (j = 0; j < self.calls[opt.cgi].length; j++) {
6957              if (self.calls[opt.cgi][j].call.idReq == msg.DATI[i].idReq) {
6958                try {
6959                  self.calls[opt.cgi][j]._obj.updateFromAjax({ msg: msg.DATI[i], cgi: opt.cgi, act: self.calls[opt.cgi][j].call.act, idReq: msg.DATI[i].idReq });
6960                } catch (e) {}
6961                break;
6962              }
6963            }
6964          }
6965        },
6966        onError: function () {
6967          HigJS.debug.error('CallManager2: error on make calls');
6968          opt.onComplete();
6969        },
6970        onComplete: opt.onComplete,
6971        url: opt.cgi,
6972        nodeJs: opt.cgi.indexOf('/node') == 0
6973      });
6974      return this;
6975    };
6976
6977    /** *************** MODIFICATA ***************************/
6978    this.makeCallsByCgi = function (opt) {
6979      const reqs = {
6980        gwc: [],
6981        server: []
6982      }; let i; let j;
6983
6984      for (i = 0; i < this.calls[opt.cgi].length; i++) {
6985        this.calls[opt.cgi][i].call.onRequest && this.calls[opt.cgi][i].call.onRequest();
6986        if (!this.calls[opt.cgi][i].call.hasOwnProperty('source') || (this.calls[opt.cgi][i].call.source && this.calls[opt.cgi][i].call.source.toLowerCase() == 'server')) {
6987          reqs.server.push({ act: this.calls[opt.cgi][i].call.act, sn: this.calls[opt.cgi][i].call.sn, idReq: this.calls[opt.cgi][i].call.idReq, data: this.calls[opt.cgi][i].call.data });
6988        } else if (this.calls[opt.cgi][i].call.source && this.calls[opt.cgi][i].call.source.toLowerCase() == 'gwc') {
6989          reqs.gwc.push({ act: this.calls[opt.cgi][i].call.act, sn: this.calls[opt.cgi][i].call.sn, idReq: this.calls[opt.cgi][i].call.idReq, data: this.calls[opt.cgi][i].call.data });
6990        }
6991      }
6992      if (reqs.server.length) {
6993        HigJS.ajax.request({
6994          reqs: reqs.server,
6995          ids: opt.ids || userConf.ids,
6996          onSuccess: function (msg) {
6997            if (!HigJS.ajax.checkResponse(msg).ok) { HigJS.debug.error(HigJS.ajax.checkResponse(msg).errMsg); }
6998
6999            for (i = 0; i < msg.DATI.length; i++) {
7000              for (j = 0; j < self.calls[opt.cgi].length; j++) {
7001                if (self.calls[opt.cgi][j].call.idReq == msg.DATI[i].idReq) {
7002                  try {
7003                    self.calls[opt.cgi][j]._obj.updateFromAjax({ msg: msg.DATI[i], cgi: opt.cgi, act: self.calls[opt.cgi][j].call.act, idReq: msg.DATI[i].idReq });
7004                  } catch (e) {}
7005                  break;
7006                }
7007              }
7008            }
7009          },
7010          onError: function () {
7011            HigJS.debug.error('CallManager2: error on make calls');
7012            opt.onComplete();
7013          },
7014          onComplete: opt.onComplete,
7015          url: opt.cgi,
7016          nodeJs: !(['/node', '/pvManager'].indexOf(opt.cgi) < 0)
7017        });
7018      }
7019      if (reqs.gwc.length) {
7020        HigJS.ajax.gwcRequest({
7021          reqs: reqs.gwc,
7022          source: 'GWC',
7023          sn: reqs.gwc[0].sn || null,
7024          ids: opt.ids || userConf.ids,
7025          onSuccess: function (msg) {
7026            if (!HigJS.ajax.checkResponse(msg).ok) { HigJS.debug.error(HigJS.ajax.checkResponse(msg).errMsg); }
7027
7028            for (i = 0; i < msg.DATI.length; i++) {
7029              for (j = 0; j < self.calls[opt.cgi].length; j++) {
7030                if (self.calls[opt.cgi][j].call.idReq == msg.DATI[i].idReq) {
7031                  try {
7032                    self.calls[opt.cgi][j]._obj.updateFromAjax({ msg: msg.DATI[i], cgi: opt.cgi, act: self.calls[opt.cgi][j].call.act, idReq: msg.DATI[i].idReq });
7033                  } catch (e) {}
7034                  break;
7035                }
7036              }
7037            }
7038          },
7039          onError: function () {
7040            HigJS.debug.error('CallManager2: error on make calls');
7041            opt.onComplete();
7042          },
7043          onComplete: opt.onComplete,
7044          cgi: opt.cgi,
7045          phpFile: '/phpScript/deviceServerCgi.php',
7046          nodeJs: opt.cgi.indexOf('/node') == 0
7047        });
7048      }
7049      return this;
7050    };
7051
7052    this.removeAll = function () {
7053      this.calls = {};
7054      this.objs = [];
7055      this.stopDaemon();
7056      this.calling = false;
7057    };
7058
7059    optMain && this.init(optMain);
7060  };
7061
7062  HigJS.forms.openGWCWindow = function (opt) {
7063    const plantCfg = opt.plant;
7064    let url; const hwType = plantCfg.hwType || 'GWC_V2';
7065    const exdate = new Date();
7066    exdate.setDate(exdate.getDate() + 1);
7067    document.cookie = 'ids' + '=' + userConf.ids + ';expires=' + exdate.toUTCString() + ';path=/';
7068
7069    if (window.location.href.indexOf('demoscada') >= 0) {
7070      return;
7071    }
7072
7073    if (plantCfg && plantCfg.feeStatus == 'alert') {
7074      HigJS.DOM.alert(HigJS.diz.edw('payPlease'));
7075    } else if (plantCfg && plantCfg.feeStatus == 'block') {
7076      HigJS.DOM.alert(HigJS.diz.edw('payToControl'));
7077      if (userConf.userType != 'superadmin') {
7078        return;
7079      }
7080    }
7081
7082    if (hwType === 'virtual') {
7083      url = '/interfaces/core/dev/archData.html?plantId=' + plantCfg.impiantiId;
7084      url = window.open(url, plantCfg.serialNumber, 'location=0,menubar=0,toolbar=0,status=0,resizable=yes');
7085      url.focus();
7086    } else if (plantCfg.gwcVersion) {
7087      !plantCfg.gwcInterface && (plantCfg.gwcInterface = '/desk/deskTop.html');
7088
7089      const options = {
7090        sn: plantCfg.serialNumber,
7091        onServer: 1,
7092        phpV: '/GWC_V200',
7093        impiantiId: plantCfg.impiantiId
7094      };
7095
7096      url = `/interfacceDevice/pkgs/${hwType}/core/${plantCfg.gwcVersion + plantCfg.gwcInterface}?request=${JSON.stringify(options)}`;
7097      url = window.open(url, plantCfg.serialNumber, 'location=0,menubar=0,toolbar=0,status=0,resizable=yes');
7098      url.focus();
7099    } else if (plantCfg.versioneSW) {
7100      const vers = plantCfg.versioneSW.split('.');
7101      if (vers.length == 2) {
7102        if (parseInt(vers[1]) > 114) {
7103          url = '/interfacceGWC/HTML_V' + vers[1] + '/HTML/GWC/Home.html?request={"sn":"' + plantCfg.serialNumber + '","onServer":1,"phpV":"/GWC_V200"}';
7104        } else {
7105          url = '/interfacceGWC/HTML_V' + vers[1] + '/GWC/Home.html?request={"sn":"' + plantCfg.serialNumber + '","onServer":1,"phpV":"/GWC_V200"}';
7106        }
7107        url = window.open(url, 'mywindow', 'location=0,menubar=0,toolbar=0,status=0,resizable=yes');
7108        url.focus();
7109      } else { HigJS.DOM.alert(edw('openGwcWindowErr')); }
7110    } else { HigJS.DOM.alert(edw('openGwcWindowErr')); }
7111    return url;
7112  };
7113
7114  HigJS.num.checkValue = function (val, tipo) {
7115    if (typeof (val) === 'number') { val = val.toString(); }
7116
7117    if (tipo == 'Bool') {
7118      if (val == 2) val = '---';
7119      else if (val == 3) val = '---';
7120      else if (val.indexOf('#E2') >= 0) val = '---';
7121      else if (val.indexOf('#E3') >= 0) val = '---';
7122      else if (val.indexOf('#E5') >= 0) val = '---';
7123    } else if (tipo == 'Num') {
7124      if (val.indexOf('#E2') >= 0) val = '---';
7125      else if (val.indexOf('#E3') >= 0) val = '---';
7126      else if (val.indexOf('#E5') >= 0) val = '---';
7127      else if (!HigJS.type.isNumber(val)) val = '---';
7128    } else if (tipo == 'String') {
7129      if (val.indexOf('#E2') >= 0) val = '---';
7130      else if (val.indexOf('#E3') >= 0) val = '---';
7131      else if (val.indexOf('#E5') >= 0) val = '---';
7132    }
7133
7134    return val;
7135  };
7136
7137  HigJS.forms.aggrDataChooser = function (mainOpt) {
7138    const self = this;
7139
7140    this.init = function (customOpt) {
7141      const defaultOpt = {
7142        draw: true
7143      };
7144
7145      this.options = HigJS.obj.extendAdv(defaultOpt, customOpt, 5);
7146      this.options.saveTo = customOpt.saveTo;
7147      this.options.draw && this.draw();
7148      return this;
7149    };
7150
7151    this.draw = function () {
7152      const itemCfg = this.options.itemCfg; const options = this.options;
7153
7154      this.$div = $('<div/>').appendTo(options.appendTo);
7155
7156      this.selectedItem = new HigJS.forms.inputText({
7157        itemCfg: { label: itemCfg.label, key: 'lbl', inpWdt: itemCfg.inpWdt, txtWdt: itemCfg.txtWdt, readOnly: true, upperLbl: itemCfg.upperLbl },
7158        saveTo: { lbl: this.getResultStr() },
7159        appendTo: this.$div
7160      });
7161
7162      this.selectedItem.$input.on('mousedown', function () {
7163        self.openNodeVarSelector();
7164      });
7165    };
7166
7167    this.getResultStr = function () {
7168      const selected = this.options.saveTo[this.options.itemCfg.key];
7169      if (selected.plantId !== selected.nodeId) {
7170        return selected.plantLabel + ' -> ' + selected.nodeLabel + ' -> ' + edw(selected.label);
7171      } else if (selected.nodeId && selected.plantId == selected.nodeId) {
7172        return selected.nodeLabel + ' -> ' + edw(selected.label);
7173      } else if (selected.label) {
7174        return edw(this.options.saveTo[this.options.itemCfg.key].label);
7175      } else {
7176        return edw('noItems');
7177      }
7178    };
7179
7180    this.openNodeVarSelector = function () {
7181      const options = this.options; const nodes = []; const itemCfg = this.options.itemCfg;
7182
7183      const itemBox = new HigJS.forms.overlayBox({
7184        itemCfg: { small: true },
7185        onClose: function () {
7186
7187        }
7188      });
7189
7190      itemBox.$container.css({ 'min-width': 300, padding: 0 });
7191
7192      const $topBar = $('<div/>').appendTo(itemBox.$container)
7193        .css({ 'text-align': 'left' })
7194        .addClass('optBar');
7195
7196      new HigJS.forms.button({
7197        itemCfg: { label: edw('apply') },
7198        onClick: function () {
7199          const selected = self.treeViewer.getSelection(true);
7200          if (!selected || !selected.vars) {
7201            self.selected = null;
7202            return;
7203          }
7204
7205          for (const key in selected.vars) {
7206            self.selected = selected.vars[key];
7207            self.selected.plantId = selected.details[key][0].archFather.id;
7208            self.selected.plantLabel = selected.details[key][0].archFather.label;
7209            self.selected.nodeLabel = selected.details[key][0].owner.label;
7210            break;
7211          }
7212
7213          self.selected.nodeVarId = self.selected.id;
7214          self.selected.name = options.saveTo[itemCfg.key].name;
7215          delete self.selected.id;
7216
7217          options.saveTo[itemCfg.key] = self.selected;
7218          options.onChange && options.onChange(self.selected);
7219
7220          self.selectedItem.setValue(self.getResultStr());
7221          itemBox.close();
7222        },
7223        appendTo: $topBar
7224      });
7225
7226      new HigJS.forms.button({
7227        itemCfg: { label: edw('cancel') },
7228        onClick: function () {
7229          itemBox.close();
7230        },
7231        appendTo: $topBar
7232      });
7233
7234      const periodsLbl = []; const periodsId = [];
7235      for (var i = 0; i < options.nodeVarPeriods.length; i++) {
7236        periodsLbl.push(edw(options.nodeVarPeriods[i].label));
7237        periodsId.push(options.nodeVarPeriods[i].id);
7238      }
7239
7240      this.selPeriod = new HigJS.forms.menuSel({
7241        itemCfg: {
7242          label: '',
7243          key: 'type',
7244          items: periodsLbl,
7245          itemsId: periodsId,
7246          inpWdt: 150,
7247          txtWdt: 0,
7248          upperLbl: false
7249        },
7250        saveTo: options,
7251        appendTo: $('<div/>').appendTo($topBar).addClass('optionField').css({ display: 'inline-block', 'margin-right': 30 }),
7252        onChange: function (val) {
7253          self.treeViewer.setPeriod(val);
7254        }
7255      });
7256
7257      this.$treeContainer = $('<div/>').css({ height: $body.height() - 150, overflow: 'auto' })
7258        .appendTo(itemBox.$container);
7259
7260      for (var i = 0; i < options.plants.length; i++) {
7261        options.plants[i].nodeId && nodes.push(options.plants[i].nodeId);
7262      }
7263
7264      options.nodeTypes = HigJS.obj.clone(options.nodeTypes);
7265      options.nodeTypes._data = { label: edw('data') };
7266
7267      const VAR_TYPE_ID = 1;
7268      const KPI_TYPE_ID = 4;
7269      const periods = [
7270        1, // 15 minutes sampling
7271        2, // 1 hour sampling
7272        3, // 1 day sampling
7273        4  // 1 month sampling
7274      ];
7275
7276      this.treeViewer = new treeWalker({
7277        link: { nodes: options.nodeTypes, vars: options.varTypes },
7278        selectable: { children: false, types: [VAR_TYPE_ID, KPI_TYPE_ID] },
7279        startPeriod: 1,
7280        measureUnit: true,
7281        multiSelection: false,
7282        whatToRequest: { children: true, types: [VAR_TYPE_ID, KPI_TYPE_ID], periods },
7283        nodes,
7284        appendTo: this.$treeContainer
7285      });
7286    };
7287
7288    mainOpt && this.init(mainOpt);
7289  };
7290
7291  HigJS.ajax.logEvent = function (opt) {
7292    opt.data.idUser = userConf.userId;
7293    HigJS.ajax.request({
7294      url: '/PHP/phpScript/user.php',
7295      reqs: [{ act: 'logUserAct', data: opt.data }],
7296      ids: opt.ids || userConf.ids,
7297      onSuccess: function (msg) {
7298        if (!HigJS.ajax.checkResponse(msg).ok) {
7299          HigJS.debug.error(HigJS.ajax.checkResponse(msg).errMsg);
7300        }
7301        opt.onSuccess && opt.onSuccess(msg);
7302      }
7303    });
7304  };
7305}.call(this));
7306

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.