No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 

10712 líneas
361 KiB

  1. /*
  2. Method: jsonAppObj
  3. Description: Functionality for jsonAppObj.
  4. @param {any} options - Description for options
  5. @returns {any} - Result of the operation
  6. */
  7. var jsonAppObj = function (options) {
  8. var self = this;
  9. console.log();
  10. this.json = {
  11. setup: {},
  12. blocks: {},
  13. parts: {},
  14. functions: {},
  15. do: {},
  16. on: {},
  17. shortcuts: {},
  18. texts: {},
  19. data: {},
  20. var: {}
  21. };
  22. this.app = this.json;
  23. var alertObj = {};
  24. var alertValues = {};
  25. this.params = {};
  26. this.javascriptReservedWord = ['abstract', 'arguments', 'await', 'boolean', 'break', 'byte', 'case', 'catch', 'char', 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'double', 'else', 'enum', 'eval', 'export', 'extends', 'false', 'final', 'finally', 'float', 'for', 'function', 'goto', 'if', 'implements', 'import', 'in', 'instanceof', 'int', 'interface', 'let', 'long', 'native', 'new', 'null', 'package', 'private', 'protected', 'public', 'return', 'short', 'static', 'super', 'switch', 'synchronized', 'this', 'throw', 'throws', 'transient', 'true', 'try', 'typeof', 'var', 'void', 'volatile', 'while', 'with', 'yield', 'Array', 'Date', 'eval', 'function', 'hasOwnProperty', 'Infinity', 'isFinite', 'isNaN', 'isPrototypeOf', 'length', 'Math', 'NaN', 'name', 'Number', 'Object', 'prototype', 'String', 'toString', 'undefined', 'valueOf', 'getClass', 'java', 'JavaArray', 'javaClass', 'JavaObject', 'JavaPackage', 'alert', 'all', 'anchor', 'anchors', 'area', 'assign', 'blur', 'button', 'checkbox', 'clearInterval', 'clearTimeout', 'clientInformation', 'close', 'closed', 'confirm', 'constructor', 'crypto', 'decodeURI', 'decodeURIComponent', 'defaultStatus', 'document', 'element', 'elements', 'embed', 'embeds', 'encodeURI', 'encodeURIComponent', 'escape', 'event', 'fileUpload', 'focus', 'form', 'forms', 'frame', 'innerHeight', 'innerWidth', 'layer', 'layers', 'link', 'location', 'mimeTypes', 'navigate', 'navigator', 'frames', 'frameRate', 'hidden', 'history', 'image', 'images', 'offscreenBuffering', 'open', 'opener', 'option', 'outerHeight', 'outerWidth', 'packages', 'pageXOffset', 'pageYOffset', 'parent', 'parseFloat', 'parseInt', 'password', 'pkcs11', 'plugin', 'prompt', 'propertyIsEnum', 'radio', 'reset', 'screenX', 'screenY', 'scroll', 'secure', 'select', 'self', 'setInterval', 'setTimeout', 'status', 'submit', 'taint', 'text', 'textarea', 'top', 'unescape', 'untaint', 'window', 'onblur', 'onclick', 'onerror', 'onfocus', 'onkeydown', 'onkeypress', 'onkeyup', 'onmouseover', 'onload', 'onmouseup', 'onmousedown', 'onsubmit'];
  27. var nodes = {
  28. extend: ['setup', 'blocks', 'parts', 'css', 'actions', 'texts', 'data', 'functions'],
  29. params: ['style', 'on', 'matchMedia', 'action', 'code', 'roles', 'plugins', 'css'],
  30. exclude: ['setup', 'container', 'selector', 'info', 'note', 'comment', 'lang', 'tag', 'plugins', 'template']
  31. };
  32. const FORMAT_REGEX = {
  33. email: /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/,
  34. url: /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/,
  35. ip: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
  36. date: /^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$/,
  37. color: /^#(?:[0-9a-fA-F]{3}){1,2}$|#(?:[0-9a-fA-F]{3,4}){1,2}$/,
  38. };
  39. /*
  40. Method: jsonToSchema
  41. Description: Functionality for jsonToSchema.
  42. @param {any} json - Description for json
  43. @param {any} options = {} - Description for options = {}
  44. @returns {any} - Result of the operation
  45. */
  46. this.jsonToSchema = function (json, options = {}) {
  47. if (typeof json === 'function') {
  48. throw new TypeError('Can not convert a function');
  49. }
  50. if (json === undefined) {
  51. return {};
  52. }
  53. if (typeof json === 'string') {
  54. if (FORMAT_REGEX.url.test(json)) return { type: 'string', format: 'url' };
  55. else if (FORMAT_REGEX.email.test(json)) return { type: 'string', format: 'email' };
  56. else if (FORMAT_REGEX.ip.test(json)) return { type: 'string', format: 'ip' };
  57. else if (FORMAT_REGEX.date.test(json)) return { type: 'string', format: 'date' };
  58. else if (FORMAT_REGEX.color.test(json)) return { type: 'string', format: 'color' };
  59. else return { type: 'string' };
  60. }
  61. else if (typeof json === 'boolean') return { type: 'boolean' };
  62. else if (typeof json === 'number') {
  63. if (Number.isInteger(json)) {
  64. return { type: 'integer' };
  65. } else {
  66. return { type: 'number' };
  67. }
  68. }
  69. else if (Array.isArray(json)) {
  70. let schema = { type: 'array' };
  71. if (!json.length) {
  72. schema.items = {};
  73. return schema;
  74. }
  75. let schemas = json.map(self.jsonToSchema);
  76. if (schemas.every(s => self.isEqual(s, schemas[0]))) {
  77. schema.items = schemas[0];
  78. } else {
  79. schema.items = { oneOf: unique(schemas) };
  80. }
  81. return schema;
  82. }
  83. if (json === null) {
  84. return { type: 'null' };
  85. }
  86. let schema = { type: 'object' };
  87. if (!Object.keys(json).length) {
  88. return schema;
  89. }
  90. schema.properties = Object.keys(json).reduce((properties, key) => {
  91. properties[key] = self.jsonToSchema(json[key]);
  92. return properties;
  93. }, {});
  94. return schema;
  95. };
  96. /*
  97. Method: isEqual
  98. Description: Functionality for isEqual.
  99. @param {any} a - Description for a
  100. @param {any} b - Description for b
  101. @returns {any} - Result of the operation
  102. */
  103. this.isEqual = function (a, b) {
  104. return (JSON.stringify(a) == JSON.stringify(b));
  105. };
  106. this.dataStorage = {
  107. _storage: new WeakMap(),
  108. set: function (element, key, obj) {
  109. if (!this._storage.has(element)) {
  110. this._storage.set(element, new Map());
  111. }
  112. this._storage.get(element).set(key, obj);
  113. },
  114. get: function (element, key) {
  115. return this._storage.get(element).get(key);
  116. },
  117. has: function (element, key) {
  118. return this._storage.has(element) && this._storage.get(element).has(key);
  119. },
  120. remove: function (element, key) {
  121. var ret = this._storage.get(element).delete(key);
  122. if (!this._storage.get(element).size === 0) {
  123. this._storage.delete(element);
  124. }
  125. return ret;
  126. }
  127. };
  128. /*
  129. Method: extend
  130. Description: Functionality for extend.
  131. @param {any} out - Description for out
  132. @returns {any} - Result of the operation
  133. */
  134. this.extend = function (out) {
  135. if (typeof arguments[0] == 'boolean' && arguments[0] == true)
  136. return deepExtend(out);
  137. else {
  138. out = out || {};
  139. for (var i = 1; i < arguments.length; i++) {
  140. if (!arguments[i])
  141. continue;
  142. for (var key in arguments[i]) {
  143. if (arguments[i].hasOwnProperty(key))
  144. out[key] = arguments[i][key];
  145. }
  146. }
  147. return out;
  148. }
  149. };
  150. /*
  151. Method: deepExtend
  152. Description: Functionality for deepExtend.
  153. @param {any} out - Description for out
  154. @returns {any} - Result of the operation
  155. */
  156. var deepExtend = function (out) {
  157. out = out || {};
  158. for (var i = 1; i < arguments.length; i++) {
  159. var obj = arguments[i];
  160. if (!obj) continue;
  161. for (var key in obj) {
  162. if (obj.hasOwnProperty(key)) {
  163. if (typeof obj[key] === "object" && obj[key] !== null) {
  164. if (obj[key] instanceof Array) out[key] = obj[key].slice(0);
  165. else out[key] = deepExtend(out[key], obj[key]);
  166. } else out[key] = obj[key];
  167. }
  168. }
  169. }
  170. return out;
  171. };
  172. /*
  173. Method: var
  174. Description: Functionality for var.
  175. @param {any} params - Description for params
  176. @param {any} args - Description for args
  177. @returns {any} - Result of the operation
  178. */
  179. this.var = function (params, args) {
  180. if (Array.isArray(params)) {
  181. for (var index in params)
  182. self.var(params[index], args);
  183. } else {
  184. var name;
  185. var value;
  186. var varValue;
  187. if (params.path && !params.name)
  188. name = self.path(params.path, args, '.');
  189. if (typeof params == 'string') {
  190. name = self.replaceProperties(params, args);
  191. varValue = self.docElement('self.json.var.' + name);
  192. } else {
  193. var paramsReplaced = self.replaceProperties(params, args);
  194. name = paramsReplaced.name;
  195. value = paramsReplaced.value;
  196. var operator = paramsReplaced.operator;
  197. var type = paramsReplaced.type;
  198. if (name) {
  199. var pathString = 'self.json.var.' + name;
  200. var pathLast = pathString.substr(pathString.lastIndexOf(".") + 1);
  201. var pathBase = pathString.substr(0, pathString.lastIndexOf("."));
  202. var varObj = self.docElement(pathBase);
  203. if (value !== undefined) {
  204. value = self.actionResult(value, args);
  205. switch (type) {
  206. case 'string': value = String(value); break;
  207. case 'number': value = Number(value); break;
  208. case 'boolean': value = Boolean(value); break;
  209. case 'array': value = JSON.parse(value); break;
  210. case 'object': value = JSON.parse(value); break;
  211. }
  212. if (varObj && pathLast) {
  213. switch (operator) {
  214. case '+=': varObj[pathLast] += value; break;
  215. case '-=': varObj[pathLast] -= value; break;
  216. case '/=': varObj[pathLast] /= value; break;
  217. case '*=': varObj[pathLast] *= value; break;
  218. default: varObj[pathLast] = value; break;
  219. }
  220. varValue = varObj[pathLast];
  221. } else {
  222. self.docElement(pathString, value);
  223. }
  224. } else if (paramsReplaced.push) {
  225. if (varObj && pathLast && varObj[pathLast]) {
  226. varObj[pathLast] = varObj[pathLast].push(paramsReplaced.push);
  227. varValue = varObj[pathLast];
  228. }
  229. } else if (paramsReplaced.extend) {
  230. if (varObj && pathLast && varObj[pathLast]) {
  231. varObj[pathLast] = self.extend({}, varObj[pathLast], paramsReplaced.extend);
  232. varValue = varObj[pathLast];
  233. }
  234. } else {
  235. varValue = varObj[pathLast];
  236. }
  237. } else {
  238. self.log('var name undefined');
  239. self.log(params);
  240. varValue = undefined;
  241. }
  242. if (params.do && params.do.length > 0) {
  243. self.log('this.var params.do');
  244. self.log(params.do);
  245. self.do(params.do, undefined, args);
  246. }
  247. }
  248. return varValue;
  249. }
  250. };
  251. /*
  252. Method: find
  253. Description: Functionality for find.
  254. @param {any} params - Description for params
  255. @param {any} args - Description for args
  256. @returns {any} - Result of the operation
  257. */
  258. this.find = function (params, args) {
  259. if (params.in) {
  260. var list = self.replaceProperties(params.in, args);
  261. return list.filter(function (item) {
  262. if (params.value) {
  263. if (typeof params.value == 'string') {
  264. if (JSON.stringify(item).indexOf(params.value) >= 0)
  265. return item;
  266. } else {
  267. for (var key in params.value) {
  268. if (params.value[key] == item[key])
  269. return item;
  270. }
  271. }
  272. }
  273. });
  274. }
  275. };
  276. /*
  277. Method: array
  278. Description: Functionality for array.
  279. @param {any} params - Description for params
  280. @param {any} args - Description for args
  281. @returns {any} - Result of the operation
  282. */
  283. this.array = function (params, args) {
  284. if (args)
  285. params = self.replacePropertyWithPrefix(params, 'result', args);
  286. for (var par in params) {
  287. var paramReplaced = self.replaceProperties(params[par], args);
  288. params[par] = paramReplaced;
  289. }
  290. var value = self.element({ path: params.name }) || [];
  291. if (params.push) {
  292. if (Array.isArray(params.push))
  293. value.push(...params.push);
  294. else
  295. value.push(params.push);
  296. }
  297. if (params.unshift) value.unshift(...params.unshift);
  298. if (params.pop) return value.pop(params.pop);
  299. if (params.shift) return value.shift(params.shift);
  300. self.element({ path: params.name, value: value });
  301. };
  302. /*
  303. Method: replace
  304. Description: Functionality for replace.
  305. @param {any} params - Description for params
  306. @param {any} args - Description for args
  307. @returns {any} - Result of the operation
  308. */
  309. this.replace = function (params, args) {
  310. params = self.replacePropertyWithPrefix(params, 'result', args);
  311. var value = self.element({ path: params.path }) || [];
  312. var to = params.to || '';
  313. var type = typeof value;
  314. if (type !== "string") value = JSON.stringify(value);
  315. if (params.from) value = self.replaceAll(value, params.from, to);
  316. switch (type) {
  317. case "number":
  318. value = Number(value);
  319. break;
  320. case "boolean":
  321. value = Boolean(value);
  322. break;
  323. case "object":
  324. value = JSON.parse(value);
  325. break;
  326. }
  327. return self.element({ path: params.path, value: value });
  328. };
  329. /*
  330. Method: unshift
  331. Description: Functionality for unshift.
  332. @param {any} params - Description for params
  333. @param {any} args - Description for args
  334. @returns {any} - Result of the operation
  335. */
  336. this.unshift = function (params, args) {
  337. for (var param in params) {
  338. var path = self.replaceProperties(param, args);
  339. var value = self.replaceProperties(params[param], args);
  340. if (value) {
  341. var obj = self.element({ path: path }) || [];
  342. obj.unshift(value);
  343. self.element({ path: path, value: obj });
  344. }
  345. }
  346. };
  347. /*
  348. Method: set
  349. Description: Functionality for set.
  350. @param {any} params - Description for params
  351. @param {any} args - Description for args
  352. @returns {any} - Result of the operation
  353. */
  354. this.set = function (params, args) {
  355. if (Array.isArray(params)) {
  356. for (var obj of params)
  357. self.set(obj, args);
  358. } else {
  359. for (var param in params) {
  360. var value = params[param];
  361. if (value) value = self.replaceProperties(value, args, false);
  362. if (value && args) value = self.replacePropertyWithPrefix(value, 'result', args);
  363. self.element({ path: param, value: value });
  364. }
  365. }
  366. };
  367. /*
  368. Method: get
  369. Description: Functionality for get.
  370. @param {any} element - Description for element
  371. @returns {any} - Result of the operation
  372. */
  373. this.get = function (element) {
  374. if (element.startsWith('\''))
  375. return String(element.match(/\'([^\']*)\'/)[1]); // stringa racchiusa tra apici (serve?)
  376. else if (element.startsWith('Boolean'))
  377. return Boolean(element.match(/Boolean\(([^\)]*)\)/)[0]); // Boolean(x)
  378. else if (element.startsWith('Number'))
  379. return Number(element.match(/Number\(([^\)]*)\)/)[0]); // Number(x)
  380. else if (element.startsWith('String'))
  381. return String(element.match(/String\(([^\)]*)\)/)[0]); // String(x)
  382. else
  383. return (self.docElement(element)); // ora le tipizzazioni sono già in docElement grazie a eval
  384. };
  385. /*
  386. Method: getJSON
  387. Description: Functionality for getJSON.
  388. @param {any} url - Description for url
  389. @param {any} callback - Description for callback
  390. @returns {any} - Result of the operation
  391. */
  392. this.getJSON = function (url, callback) {
  393. var xhr = new XMLHttpRequest();
  394. xhr.open('GET', url, true);
  395. xhr.responseType = 'json';
  396. xhr.onload = function () {
  397. var status = xhr.status;
  398. if (status === 200) {
  399. callback(null, xhr.response);
  400. } else {
  401. callback(status, xhr.response);
  402. }
  403. };
  404. xhr.send();
  405. };
  406. /*---------------------
  407. var
  408. ---------------------*/
  409. var database, auth, storage;
  410. this.listeners = {};
  411. this.resizeActions = {};
  412. /* var iconsFile;
  413. this.device = false; // touch device
  414. this.touch = 'mousedown'; if (this.device) {this.touch = 'touchstart';}
  415. var animations = {};
  416. var tweenLoading;
  417. var tasksIntervals = {};
  418. var timedTasks = {'yearly':{},'monthly':{},'daily':{},'hourly':{}, '10mins':{}, '5mins':{}, '30mins':{}, '1min':{}, '30sec': {}, '10sec': {}, '1sec': {}}; */
  419. /* this.dateSelection; // = {day:0, month:0, year:0};
  420. this.timeSelection = {hour:0, min:0, sec:0, ampm:'AM', allday:true};
  421. this.timeSelectionCallback = null; */
  422. /*--------------------
  423. FIREBASE
  424. --------------------*/
  425. //var firebaseInitialized = false;
  426. /*
  427. Method: firebaseVerifyUser
  428. Description: Functionality for firebaseVerifyUser.
  429. @param {any} data - Description for data
  430. @returns {any} - Result of the operation
  431. */
  432. this.firebaseVerifyUser = function (data) {
  433. self.log('firebaseVerifyUser');
  434. //self.log(data);
  435. //self.log(data.code);
  436. if (self.params.oobCode) {
  437. var oobCode = self.params.oobCode;
  438. auth.applyActionCode(oobCode).then(function (resp) {
  439. // self.log('resp');
  440. // self.log(resp);
  441. self.alert({
  442. //toast: true,
  443. icon: "success",
  444. title: "titVerifyEmail",
  445. html: "msgVerifyEmail",
  446. confirmButtonText: "btnOk",
  447. //showCancelButton: false,
  448. confirm: function () {
  449. //self.reload();
  450. // self.do(data);
  451. window.location.href = "/app/index.html";
  452. }
  453. });
  454. }).catch(function (error) {
  455. self.log('error');
  456. self.alert({
  457. icon: "error",
  458. title: "titWarning",
  459. html: error.code + " - " + error.message,
  460. confirmButtonText: "btnOk",
  461. //showCancelButton: false,
  462. confirm: function () {
  463. // self.reload();
  464. // self.do(data);
  465. window.location.href = "/app/index.html";
  466. }
  467. });
  468. });
  469. // verifica su auth
  470. }
  471. //data.code / data.params.code
  472. //self.do(data);
  473. self.do(data);
  474. };
  475. /*
  476. /*
  477. Method: firebaseInit
  478. Description: Functionality for firebaseInit.
  479. @param {any} data - Description for data
  480. @returns {any} - Result of the operation
  481. */
  482. this.firebaseInit = function (data) {
  483. self.log("firebaseInit");
  484. if (json.setup && json.setup.firebase) {
  485. //var.databaseURL = json.setup.firebase.databaseURL;
  486. firebase.initializeApp(json.setup.firebase);
  487. database = firebase.database();
  488. auth = firebase.auth();
  489. // if (self.json.plugins['firebase-storage'].active) OR find in self.json.plugins name: 'firebase-storage'
  490. //storage = firebase.storage();
  491. auth.onAuthStateChanged(user => {
  492. self.json.var.user = user;
  493. if (!user) {
  494. // No user logged in
  495. self.log('onAuthStateChanged:GUEST\n');
  496. // non bisognerebbe chiedere sempre di fare login
  497. } else {
  498. // User logged in
  499. self.log('onAuthStateChanged:USER\n');
  500. self.log('name: '+self.user('displayName') + '\nemail: '+user.email + '\nuid: '+ user.uid);
  501. }
  502. //self.log('firebaseInitialized');
  503. //self.log(firebaseInitialized);
  504. if (!firebaseInitialized) {
  505. firebaseInitialized = true;
  506. self.do(data);
  507. }
  508. });
  509. } else {
  510. self.do(data);
  511. }
  512. } */
  513. /*
  514. Method: sendMail
  515. Description: Functionality for sendMail.
  516. @param {any} data - Description for data
  517. @returns {any} - Result of the operation
  518. */
  519. this.sendMail = function (data) {
  520. self.log('sendMail');
  521. var emailParams = {
  522. Host: "smtp.mailgun.com",
  523. Username: "vito@nuvolaria.com",
  524. Password: "bee02191be84c784a665fa98c61e03ce-915161b7-d32cb9d0",
  525. From: data.from,
  526. To: data.to,
  527. Subject: data.subject,
  528. Body: data.html
  529. };
  530. Email.send(emailParams).then(
  531. message => self.alert({
  532. icon: 'success',
  533. title: 'titEmailSuccess',
  534. confirmButtonText: 'btnClose'
  535. })
  536. );
  537. /*
  538. "from": "gianfrancoguglielmi@gmail.com",
  539. "to": "vito.minchilli@gmail.com",
  540. "subject": "Prova oggetto",
  541. "html": "Prova testo",
  542. "text": "Prova testo"
  543. */
  544. /*
  545. var SERVER_NODEJS_BASEURL='https:
  546. var params = {
  547. rom: data.from,
  548. to: data.to,
  549. subject: data.subject,
  550. html: data.html,
  551. text: data.text
  552. };
  553. $.ajax({
  554. type: "POST",
  555. 'beforeSend': function(xhr) {
  556. xhr.setRequestHeader('Accept', 'application/json');
  557. xhr.setRequestHeader('Content-Type', 'application/json');
  558. },
  559. data: JSON.stringify(params),
  560. url: SERVER_NODEJS_BASEURL + '/sendMail',
  561. success: function(data) {
  562. self.log('sendMail SUCCESS');
  563. self.log(data);
  564. self.do(data);
  565. },
  566. error: function(error) {
  567. self.log('sendMail ERROR');
  568. self.log(error);
  569. self.do(data);
  570. }
  571. });
  572. */
  573. };
  574. var x = [{ if: 3 }, function () { }, 3, []];
  575. /*
  576. Method: firebaseAddListener
  577. Description: Functionality for firebaseAddListener.
  578. @param {any} params - Description for params
  579. @returns {any} - Result of the operation
  580. */
  581. this.firebaseAddListener = function (params) {
  582. if (database) {
  583. if (params.action) {
  584. if (!self.listeners[params.path]) self.listeners[params.path] = [];
  585. self.listeners[params.path].push(params.action);
  586. }
  587. var dbRef = database.ref(params.path);
  588. dbRef.off();
  589. if (params.orderByChild) dbRef = dbRef.orderByChild(params.orderByChild);
  590. if (params.orderByKey) dbRef = dbRef.orderByKey(params.orderByKey);
  591. if (params.orderByValue) dbRef = dbRef.orderByValue(params.orderByValue);
  592. if (params.equalTo) dbRef = dbRef.equalTo(params.equalTo);
  593. if (params.startAt) dbRef = dbRef.startAt(params.startAt);
  594. if (params.startAfter) dbRef = dbRef.startAfter(params.startAfter);
  595. if (params.endAt) dbRef = dbRef.endAt(params.endAt);
  596. if (params.endBefore) dbRef = dbRef.endBefore(params.endBefore);
  597. if (params.limitToFirst) dbRef = dbRef.limitToFirst(params.limitToFirst);
  598. if (params.limitToLast) dbRef = dbRef.limitToLast(params.limitToLast);
  599. if (params.where) dbRef = dbRef.where(params.where[0], params.where[1], params.where[2]);
  600. var feedback = dbRef.on('value', firebaseEvent);
  601. } else {
  602. self.log('database undefined');
  603. }
  604. };
  605. /*
  606. Method: firebaseEvent
  607. Description: Functionality for firebaseEvent.
  608. @param {any} snapshot - Description for snapshot
  609. @returns {any} - Result of the operation
  610. */
  611. var firebaseEvent = function (snapshot) {
  612. console.log(snapshot.val());
  613. var ref = snapshot.ref;
  614. if (snapshot.val() !== undefined) {
  615. var dbVal = snapshot.val();
  616. var path = snapshot.ref.toString();
  617. var pathArr = path.split(/\.\w+\
  618. var dbPath = pathArr[1];
  619. self.log('firebaseEvent: ' + dbPath);
  620. if (dbVal)
  621. self.localDbUpdate(dbVal, dbPath);
  622. else {
  623. var dbObj = self.element({ path: 'self.json.var.db.' + self.replaceAll(dbPath, '/', '.') });
  624. if (dbObj)
  625. dbObj = null;
  626. }
  627. }
  628. };
  629. /*
  630. Method: localDbUpdate
  631. Description: Functionality for localDbUpdate.
  632. @param {any} newObj - Description for newObj
  633. @param {any} dbPath - Description for dbPath
  634. @returns {any} - Result of the operation
  635. */
  636. this.localDbUpdate = function (newObj, dbPath) {
  637. newObj = Object.fromEntries(Object.entries(newObj).reverse());
  638. self.element({ path: 'self.json.var.db.' + self.replaceAll(dbPath, '/', '.'), value: newObj });
  639. if (self.listeners[dbPath] !== undefined && self.listeners[dbPath] !== null && self.listeners[dbPath].length > 0) {
  640. newObj.path = dbPath;
  641. if (self.listeners[dbPath]) {
  642. self.methods.firebaseEvent.action(newObj);
  643. self.do(self.listeners[dbPath], undefined, newObj);
  644. }
  645. }
  646. };
  647. /*
  648. Method: firebaseRemoveListener
  649. Description: Functionality for firebaseRemoveListener.
  650. @param {any} params - Description for params
  651. @returns {any} - Result of the operation
  652. */
  653. this.firebaseRemoveListener = function (params) {
  654. self.log('firebaseRemoveListener');
  655. if (self.listeners[params.path]) {
  656. delete self.listeners[params.path];
  657. var dbRef = database.ref(params.path);
  658. dbRef.off();
  659. }
  660. };
  661. /*
  662. Method: firebaseRemove
  663. Description: Functionality for firebaseRemove.
  664. @param {any} path - Description for path
  665. @param {any} callback - Description for callback
  666. @returns {any} - Result of the operation
  667. */
  668. this.firebaseRemove = function (path, callback) {
  669. self.log('firebaseRemove');
  670. self.log(path);
  671. if (database) {
  672. var result, dbRef;
  673. if (path) {
  674. dbRef = database.ref().child(path);
  675. } else {
  676. dbRef = database.ref();
  677. }
  678. return dbRef.remove(function (error) {
  679. if (error == null) {
  680. self.log('set SUCCESS');
  681. result = { success: true };
  682. } else {
  683. self.log('set ERROR');
  684. result = { success: false, error: error };
  685. }
  686. if (callback) callback(result);
  687. });
  688. } else {
  689. self.log('database not initialized');
  690. }
  691. };
  692. /*
  693. Method: firebaseSet
  694. Description: Functionality for firebaseSet.
  695. @param {any} path - Description for path
  696. @param {any} value - Description for value
  697. @param {any} callback - Description for callback
  698. @returns {any} - Result of the operation
  699. */
  700. this.firebaseSet = function (path, value, callback) {
  701. if (database) {
  702. var result, dbRef;
  703. if (path) {
  704. dbRef = database.ref().child(path);
  705. } else {
  706. dbRef = database.ref();
  707. }
  708. return dbRef.set(value, function (error) {
  709. if (error == null) {
  710. self.log('set SUCCESS');
  711. result = { success: true };
  712. } else {
  713. self.log('set ERROR');
  714. result = { success: false, error: error };
  715. }
  716. if (callback) callback(result);
  717. });
  718. } else {
  719. self.log('database not initialized');
  720. }
  721. };
  722. /*
  723. Method: firebaseUpdate
  724. Description: Functionality for firebaseUpdate.
  725. @param {any} path - Description for path
  726. @param {any} value - Description for value
  727. @param {any} callback - Description for callback
  728. @returns {any} - Result of the operation
  729. */
  730. this.firebaseUpdate = function (path, value, callback) {
  731. self.log('firebaseUpdate');
  732. self.log('path');
  733. self.log(path);
  734. self.log('value');
  735. self.log(value);
  736. if (database) {
  737. var result, dbRef;
  738. if (path) {
  739. dbRef = database.ref().child(path);
  740. } else {
  741. dbRef = database.ref();
  742. }
  743. return dbRef.update(value, function (error) {
  744. if (error == null) {
  745. self.log('update SUCCESS');
  746. result = { success: true };
  747. } else {
  748. self.log('update ERROR');
  749. result = { success: false, error: error };
  750. }
  751. if (callback) callback(result);
  752. });
  753. } else {
  754. self.log('database not initialized');
  755. }
  756. };
  757. /*
  758. Method: firebasePush
  759. Description: Functionality for firebasePush.
  760. @param {any} path - Description for path
  761. @param {any} value - Description for value
  762. @param {any} callback - Description for callback
  763. @returns {any} - Result of the operation
  764. */
  765. this.firebasePush = function (path, value, callback) {
  766. self.log('firebasePush');
  767. self.log(path);
  768. if (database) {
  769. var result, dbRef;
  770. if (path) {
  771. dbRef = database.ref().child(path);
  772. } else {
  773. dbRef = database.ref();
  774. }
  775. return dbRef.push(value, function (error) {
  776. if (error == null) {
  777. self.log('push SUCCESS');
  778. result = { success: true };
  779. } else {
  780. self.log('push ERROR');
  781. result = { success: false, error: error };
  782. }
  783. if (callback) callback(result);
  784. });
  785. } else {
  786. self.log('database not initialized');
  787. }
  788. };
  789. /*
  790. Method: firebaseGetPart
  791. Description: Functionality for firebaseGetPart.
  792. @param {any} params - Description for params
  793. @returns {any} - Result of the operation
  794. */
  795. this.firebaseGetPart = function (params) {
  796. self.log('firebaseGetPart');
  797. let remotePath = self.replaceAll(params.localPath, '.', '/');
  798. self.log('localPath:' + params.localPath);
  799. if (self.partContainers[params.localPath]) {
  800. self.partContainers[params.localPath].push(params);
  801. } else {
  802. self.partContainers[params.localPath] = [];
  803. self.partContainers[params.localPath].push(params);
  804. dbRef = database.ref().child(remotePath);
  805. return dbRef.once('value').then(function (object) {
  806. if (object) {
  807. self.log('firebaseGetPart SUCCESS');
  808. self.log(object);
  809. if (object.val() !== undefined) {
  810. window.dbVal = object.val();
  811. var dbVal = object.val();
  812. self.log('dbVal');
  813. self.log(dbVal);
  814. if (dbVal !== null) {
  815. let fullPath = object.ref.toString();
  816. let pathArr = fullPath.split(/\.\w+\
  817. let dbPath = pathArr[1];
  818. let localPath = self.replaceAll(dbPath, '/', '.');
  819. self.log('dbPath: ' + dbPath);
  820. self.log('localPath: ' + localPath);
  821. self.element({ path: localPath, value: dbVal });
  822. for (partObj of self.partContainers[localPath]) {
  823. let part = self.replacePropertyWithPrefix(dbVal, 'setup', partObj.setup);
  824. part = self.replacePropertyWithPrefix(part, 'arg', partObj.arg);
  825. self.extendJsonFromElement(part);
  826. self.html(part, partObj.container);
  827. }
  828. }
  829. }
  830. } else {
  831. self.log('firebaseGetPart ERROR');
  832. result = { success: false, error: 8 };
  833. }
  834. });
  835. }
  836. };
  837. /*
  838. Method: firebaseIncrease
  839. Description: Functionality for firebaseIncrease.
  840. @param {any} params - Description for params
  841. @returns {any} - Result of the operation
  842. */
  843. this.firebaseIncrease = function (params) {
  844. console.log('firebaseIncrease');
  845. self.firebaseGet(params.path, function (result) {
  846. console.log(result);
  847. if (result.success) {
  848. if (result.data === null || result.data === undefined || typeof result.data == 'number') {
  849. var counter = Number(result.data) + 1;
  850. console.log('counter:' + counter);
  851. self.firebaseSet(params.path, counter, function (result) {
  852. if (result.success) {
  853. self.log('firebaseIncrease SUCCESS');
  854. if (params.on && params.on.success) self.do(params.on.success, undefined, result);
  855. } else {
  856. if (params.on && params.on.error) self.do(params.on.error, undefined, result);
  857. }
  858. });
  859. } else {
  860. if (params.on && params.on.error) self.do(params.on.error, undefined, result);
  861. }
  862. } else {
  863. if (params.on && params.on.error) self.do(params.on.error, undefined, result);
  864. }
  865. });
  866. };
  867. /*
  868. Method: firebaseGet
  869. Description: Functionality for firebaseGet.
  870. @param {any} path - Description for path
  871. @param {any} callback - Description for callback
  872. @returns {any} - Result of the operation
  873. */
  874. this.firebaseGet = function (path, callback) {
  875. self.log('firebaseGet:' + path);
  876. var result = { success: false, error: 7 };
  877. if (path) {
  878. dbRef = database.ref().child(path);
  879. } else {
  880. dbRef = database.ref();
  881. }
  882. return dbRef.once('value').then(function (object) {
  883. if (object) {
  884. self.log('get SUCCESS');
  885. result = { success: true, error: null, data: object.val() };
  886. if (object.val() !== undefined) {
  887. var dbVal = object.val();
  888. var path = object.ref.toString();
  889. if (!dbVal) dbVal = {};
  890. var pathArr = path.split(/\.\w+\
  891. var dbPath = pathArr[1];
  892. self.log('dbPath: ' + dbPath);
  893. self.localDbUpdate(dbVal, dbPath);
  894. }
  895. } else {
  896. self.log('get ERROR');
  897. result = { success: false, error: 8 };
  898. }
  899. callback(result);
  900. });
  901. };
  902. /*
  903. Method: stringToKey
  904. Description: Functionality for stringToKey.
  905. @param {any} str - Description for str
  906. @returns {any} - Result of the operation
  907. */
  908. this.stringToKey = function (str) {
  909. return str.replace(/\./g, '%2E');
  910. };
  911. /*
  912. Method: keyToString
  913. Description: Functionality for keyToString.
  914. @param {any} key - Description for key
  915. @returns {any} - Result of the operation
  916. */
  917. this.keyToString = function (key) {
  918. return key.replace(/%2E/g, '.');
  919. };
  920. this.firebaseKey =
  921. /*
  922. Method: getKey
  923. Description: Functionality for getKey.
  924. @param {any} path - Description for path
  925. @returns {any} - Result of the operation
  926. */
  927. this.getKey = function (path) {
  928. var dbRef = database.ref(path);
  929. return dbRef.child(path).push().getKey();
  930. };
  931. /*
  932. Method: exist
  933. Description: Functionality for exist.
  934. @param {any} selector - Description for selector
  935. @returns {any} - Result of the operation
  936. */
  937. this.exist = function (selector) {
  938. console.log('selector');
  939. console.log(selector);
  940. console.log(Boolean(self.query(selector)));
  941. return Boolean(self.query(selector));
  942. };
  943. /*
  944. Method: count
  945. Description: Functionality for count.
  946. @param {any} selector - Description for selector
  947. @returns {any} - Result of the operation
  948. */
  949. this.count = function (selector) {
  950. return self.queryAll(selector).length;
  951. };
  952. /*
  953. Method: log
  954. Description: Functionality for log.
  955. @param {any} id - Description for id
  956. @param {any} value - Description for value
  957. @returns {any} - Result of the operation
  958. */
  959. var log = function (id, value) {
  960. self.log(id);
  961. self.log(value);
  962. };
  963. /*
  964. Method: classSelector
  965. Description: Functionality for classSelector.
  966. @param {any} selClass - Description for selClass
  967. @returns {any} - Result of the operation
  968. */
  969. this.classSelector = function (selClass) {
  970. if (selClass.indexOf('.') == 0) { selClass = String(selClass).substr(1); }
  971. let classes = selClass.split(' ');
  972. selClass = classes[0];
  973. var regex = new RegExp('[\-][\[]');
  974. if (selClass && selClass.match(regex)) selClass = classes[1];
  975. if (selClass && selClass.match(regex)) selClass = classes[2];
  976. return selClass;
  977. };
  978. /*
  979. Method: selector
  980. Description: Functionality for selector.
  981. @param {any} params - Description for params
  982. @param {any} containerParams - Description for containerParams
  983. @param {any} selectAll - Description for selectAll
  984. @returns {any} - Result of the operation
  985. */
  986. this.selector = function (params, containerParams, selectAll) {
  987. var selector;
  988. if (params) {
  989. if (typeof params == 'string') {
  990. return params;
  991. } else if (Array.isArray(params)) {
  992. return params;
  993. } else {
  994. var selContainer;
  995. if (params.selector || params.container)
  996. selContainer = params.selector || params.container;
  997. else if (containerParams)
  998. selContainer = containerParams.selector || containerParams.container;
  999. var attr = (params.attr) ? params.attr : {};
  1000. var selId = (attr.id) ? attr.id : params.id;
  1001. var selClass = (attr.class) ? attr.class : params.class;
  1002. var selValue = (attr.value) ? attr.value : params.value;
  1003. var selDataValue = (attr['data-value']) ? attr['data-value'] : params['data-value'];
  1004. selValue = selDataValue || selValue;
  1005. if (selId) selId = self.replaceProperties(selId);
  1006. if (selValue) selValue = self.replaceProperties(selValue);
  1007. if (selClass) selClass = self.replaceProperties(selClass);
  1008. if (selClass)
  1009. selClass = self.classSelector(selClass);
  1010. if (selId) {
  1011. selector = '#' + selId;
  1012. } else if (selValue && selClass) {
  1013. selector = '.' + selClass + '[data-value="' + selValue + '"]';
  1014. } else if (selValue && params.tag) {
  1015. selector = params.tag + '[data-value="' + selValue + '"]';
  1016. } else if (selClass && selectAll) {
  1017. selector = '.' + selClass;
  1018. } else if (params.tag) {
  1019. selector = params.tag;
  1020. if (selContainer) {
  1021. selector = selContainer + ' > ' + params.tag;
  1022. if (!selectAll) {
  1023. selector += ':eq(' + self.count(selector) + ')';
  1024. }
  1025. } else {
  1026. if (!selectAll) {
  1027. selector += ':eq(' + self.count(selector) + ')';
  1028. }
  1029. }
  1030. } else {
  1031. selector = selContainer;
  1032. };
  1033. }
  1034. return selector;
  1035. }
  1036. };
  1037. /*
  1038. Method: stringify
  1039. Description: Functionality for stringify.
  1040. @param {any} obj - Description for obj
  1041. @returns {any} - Result of the operation
  1042. */
  1043. this.stringify = function (obj) {
  1044. if (typeof obj == 'object')
  1045. try {
  1046. return JSON.stringify(obj);
  1047. } catch (error) {
  1048. return obj;
  1049. }
  1050. else
  1051. return obj;
  1052. };
  1053. /*
  1054. Method: parse
  1055. Description: Functionality for parse.
  1056. @param {any} str - Description for str
  1057. @returns {any} - Result of the operation
  1058. */
  1059. this.parse = function (str) {
  1060. if (typeof str == 'string')
  1061. try {
  1062. return JSON.parse(str);
  1063. } catch (error) {
  1064. return str;
  1065. }
  1066. else
  1067. return str;
  1068. };
  1069. self.setupId = 0;
  1070. /*
  1071. Method: replacePropertyWithPrefix
  1072. Description: Functionality for replacePropertyWithPrefix.
  1073. @param {any} params - Description for params
  1074. @param {any} prefix - Description for prefix
  1075. @param {any} args - Description for args
  1076. @returns {any} - Result of the operation
  1077. */
  1078. this.replacePropertyWithPrefix = function (params, prefix, args) {
  1079. var paramsString;
  1080. if (typeof params == 'object')
  1081. paramsString = self.stringify(params);
  1082. else
  1083. paramsString = String(params);
  1084. if (paramsString && paramsString.indexOf('{' + prefix) >= 0) {
  1085. paramsString = paramsString.replace(new RegExp('"{' + prefix + '[:\\s]?([\\w\\d\\s\\.\\|]*)}"', 'g'), function (match, path) {
  1086. if (path) {
  1087. let value = self.replaceUndefined({ match: match, path: path, root: args, removeUndefined: true });
  1088. if (value === undefined) {
  1089. return '""';
  1090. } else if (typeof value == 'object')
  1091. return JSON.stringify(value);
  1092. else if (typeof value == 'string')
  1093. return '"' + value + '"';
  1094. else
  1095. return value;
  1096. } else {
  1097. if (typeof args == 'object')
  1098. return JSON.stringify(args);
  1099. else if (typeof args == 'string')
  1100. return '"' + args + '"';
  1101. else
  1102. return args;
  1103. }
  1104. });
  1105. paramsString = paramsString.replace(new RegExp('{' + prefix + '[:\\s]?([\\w\\d\\s\\.]*)}', 'g'), function (match, path) {
  1106. if (path) {
  1107. let value = self.replaceUndefined({ match: match, path: path, root: args, removeUndefined: true });
  1108. if (value === undefined)
  1109. return '';
  1110. else if (typeof value == 'object')
  1111. return JSON.stringify(value);
  1112. else
  1113. return value;
  1114. } else {
  1115. if (typeof args == 'object')
  1116. return JSON.stringify(args);
  1117. else
  1118. return args;
  1119. }
  1120. });
  1121. if (self.isJsonString(paramsString)) {
  1122. var paramsObj = self.parse(paramsString);
  1123. return paramsObj;
  1124. } else {
  1125. return paramsString;
  1126. }
  1127. } else {
  1128. return params;
  1129. }
  1130. };
  1131. /*
  1132. Method: replaceResult
  1133. Description: Functionality for replaceResult.
  1134. @param {any} params - Description for params
  1135. @param {any} args - Description for args
  1136. @returns {any} - Result of the operation
  1137. */
  1138. this.replaceResult = function (params, args) {
  1139. var paramOn, paramSuccess, paramError;
  1140. if (typeof params == 'object') {
  1141. var paramsObj = self.cloneObject(params);
  1142. if (paramsObj && paramsObj.on) {
  1143. paramOn = self.cloneObject(paramsObj.on);
  1144. delete paramsObj.on;
  1145. }
  1146. if (paramsObj && paramsObj.success) {
  1147. paramSuccess = self.cloneObject(paramsObj.success);
  1148. delete paramsObj.success;
  1149. }
  1150. params = self.stringify(params);
  1151. }
  1152. if (typeof args !== 'string') {
  1153. params = self.replaceAll(params, '"{result}"', JSON.stringify(args));
  1154. } else {
  1155. params = self.replaceAll(params, '{result}', args);
  1156. }
  1157. if (self.isJson(params)) {
  1158. var paramsObj = self.parse(params);
  1159. if (paramOn) paramsObj.on = paramOn;
  1160. if (paramSuccess) paramsObj.success = paramSuccess;
  1161. if (paramError) paramsObj.error = paramError;
  1162. return paramsObj;
  1163. } else {
  1164. return params;
  1165. }
  1166. };
  1167. /*
  1168. Method: langText
  1169. Description: Functionality for langText.
  1170. @param {any} textId - Description for textId
  1171. @returns {any} - Result of the operation
  1172. */
  1173. this.langText = function (textId) {
  1174. if (textId) {
  1175. var textValue = textId;
  1176. if (typeof textId == 'string') {
  1177. if (self.json.texts[textId]) {
  1178. textValue = self.json.texts[textId];
  1179. if (typeof textValue == 'object')
  1180. textValue = textValue[self.json.setup.language] || textValue['en'] || textValue[Object.keys[0]];
  1181. }
  1182. else
  1183. textValue = textId;
  1184. } else if (typeof textId == 'object') {
  1185. textValue = textId[self.json.setup.language] || textId['en'] || textId[Object.keys[0]];
  1186. }
  1187. return textValue;
  1188. } else {
  1189. return textId;
  1190. }
  1191. };
  1192. /*
  1193. Method: lang
  1194. Description: Functionality for lang.
  1195. @param {any} params - Description for params
  1196. @param {any} args - Description for args
  1197. @returns {any} - Result of the operation
  1198. */
  1199. this.lang = function (params, args) {
  1200. if (args) {
  1201. var value = self.replaceProperties(params, args);
  1202. self.json.setup.language = value;
  1203. self.log('lang');
  1204. self.log(value);
  1205. document.querySelectorAll('[data-text]').forEach(function (element, index) {
  1206. var dataParams = self.dataStorage.get(element, 'params');
  1207. var selector = self.dataStorage.get(element, 'selector');
  1208. self.html(dataParams, { selector: selector });
  1209. });
  1210. } else {
  1211. return self.json.setup.language;
  1212. }
  1213. };
  1214. /*
  1215. Method: isClipboardWritingAllowed
  1216. Description: Functionality for isClipboardWritingAllowed.
  1217. @param {any} - No parameters
  1218. @returns {any} - Result of the operation
  1219. */
  1220. var isClipboardWritingAllowed = function () {
  1221. return new Promise(function (resolve, reject) {
  1222. try {
  1223. navigator.permissions.query({ name: "clipboard-write" }).then(function (status) {
  1224. self.log(status);
  1225. resolve((status.state == "granted"));
  1226. });
  1227. } catch (error) {
  1228. reject(error);
  1229. }
  1230. });
  1231. };
  1232. /*
  1233. Method: codeSearch
  1234. Description: Functionality for codeSearch.
  1235. @param {any} params - Description for params
  1236. @returns {any} - Result of the operation
  1237. */
  1238. this.codeSearch = function (params) {
  1239. let selector = params.selector || params.container;
  1240. if (selector && params.word) {
  1241. var element = self.query(selector);
  1242. var editor = ace.edit(element);
  1243. var range = editor.find(params.word, {
  1244. wrap: true,
  1245. caseSensitive: true,
  1246. wholeWord: true,
  1247. regExp: false,
  1248. preventScroll: false
  1249. });
  1250. editor.session.selection.clearSelection();
  1251. editor.setOption("highlightActiveLine", true);
  1252. }
  1253. };
  1254. /*
  1255. Method: ace
  1256. Description: Functionality for ace.
  1257. @param {any} params - Description for params
  1258. @param {any} selectorParams - Description for selectorParams
  1259. @returns {any} - Result of the operation
  1260. */
  1261. this.ace = function (params, selectorParams) {
  1262. var selector = params.selector || params.container;
  1263. var container = selector || self.selector(selectorParams);
  1264. var value = params.value;
  1265. if (params.blocks && self.json.blocks)
  1266. if (self.json.blocks[params.blocks])
  1267. value = self.json.blocks[params.blocks];
  1268. else
  1269. self.log('"code" method can\'t find in "blocks" the element ' + params.blocks);
  1270. if (params.module) {
  1271. let moduleName = self.replaceProperties(params.module);
  1272. if (moduleName && self.modules[moduleName] !== undefined) {
  1273. value = self.modules[moduleName];
  1274. }
  1275. else
  1276. self.log('"code" method can\'t find the file ' + params.file);
  1277. }
  1278. if (params.var)
  1279. if (self.json.var)
  1280. value = self.var(params.var);
  1281. else
  1282. self.log('"code" method can\'t find the variable ' + params.blocks);
  1283. var element = self.query(container);
  1284. if (element) {
  1285. var editor = ace.edit(element);
  1286. if (!params.do || (params.do == 'set')) {
  1287. if (params.theme)
  1288. editor.setTheme(params.theme);
  1289. var editorMode = params.mode || "ace/mode/json";
  1290. editor.getSession().setMode(editorMode);
  1291. if (params.options)
  1292. editor.setOptions(params.options);
  1293. var editorStyle = self.extend({
  1294. }, params.style);
  1295. self.css({
  1296. style: editorStyle
  1297. }, {
  1298. selector: container
  1299. });
  1300. var codeString;
  1301. if (typeof value == 'string')
  1302. if (editorMode == "ace/mode/json")
  1303. codeString = JSON.stringify(JSON.parse(value), null, '\t');
  1304. else
  1305. codeString = value;
  1306. else {
  1307. if (editorMode == "ace/mode/json")
  1308. codeString = JSON.stringify(value, null, '\t');
  1309. else {
  1310. var functionObj = self.docElement(value.function);
  1311. var functionParams = value.params;
  1312. codeString = functionObj(functionParams);
  1313. }
  1314. }
  1315. if (codeString) {
  1316. var codeRows = codeString.split(/\r\n|\r|\n/).length;
  1317. element.style.height = Number(21 * codeRows) + 'px';
  1318. editor.setValue(codeString, -1);
  1319. self.uiUpdate();
  1320. }
  1321. if (params.on) {
  1322. var containerId = self.attribute(element, 'id');
  1323. self.codeChangeFunctions[containerId] = params.on;
  1324. if (params.on.change) {
  1325. editor.on('change', function (event, obj) {
  1326. if (self.isJson(obj.getValue())) {
  1327. var code = JSON.parse(obj.getValue());
  1328. var action = self.codeChangeFunctions[obj.container.id].change;
  1329. var methods = self.replaceResult(action, code);
  1330. self.do(methods);
  1331. } else {
  1332. }
  1333. });
  1334. }
  1335. }
  1336. } else if (params.do == 'get') {
  1337. return JSON.parse(editor.getValue());
  1338. } else if (params.do == 'update') {
  1339. self.uiUpdate();
  1340. } else if (params.do == 'search') {
  1341. if (params.word) {
  1342. var range = editor.find(params.word, {
  1343. wrap: true,
  1344. caseSensitive: true,
  1345. wholeWord: true,
  1346. regExp: false,
  1347. preventScroll: false
  1348. });
  1349. editor.session.selection.clearSelection();
  1350. editor.setOption("highlightActiveLine", true);
  1351. }
  1352. } else if (params.do == 'find') {
  1353. editor.execCommand('find');
  1354. } else if (params.do == 'copy') {
  1355. editor.selectAll();
  1356. let copyText = editor.getCopyText();
  1357. isClipboardWritingAllowed().then(function (allowed) {
  1358. if (allowed) {
  1359. navigator.clipboard.writeText(copyText).then(function () {
  1360. editor.getSession().selection.clearSelection();
  1361. });
  1362. }
  1363. }).catch(function (err) {
  1364. self.log("Cannot copy to clipboard", err);
  1365. });
  1366. } else {
  1367. self.log('"code" function requires value param');
  1368. }
  1369. } else {
  1370. self.log('"code" method can\'t select the container');
  1371. self.log('container');
  1372. self.log(container);
  1373. self.log('element');
  1374. self.log(element);
  1375. }
  1376. };
  1377. this.codeChangeFunctions = {};
  1378. this.editorChangeFunctions = {};
  1379. this.quillElements = {};
  1380. /*
  1381. Method: text
  1382. Description: Functionality for text.
  1383. @param {any} params - Description for params
  1384. @param {any} selectorParams - Description for selectorParams
  1385. @param {any} args - Description for args
  1386. @returns {any} - Result of the operation
  1387. */
  1388. this.text = function (params, selectorParams, args) {
  1389. var textKey;
  1390. var textCase;
  1391. var textArgs;
  1392. var textLang;
  1393. var langId;
  1394. var selector, element;
  1395. if (typeof params == 'object') {
  1396. if (selectorParams && selectorParams.isConnected) {
  1397. element = selectorParams;
  1398. selector = self.elementToSelector(element);
  1399. } else {
  1400. selector = self.selector(self.extend({}, params, selectorParams));
  1401. element = self.query(selector);
  1402. }
  1403. textCase = params.case;
  1404. textArgs = params.args;
  1405. if (typeof params == 'object') {
  1406. textKey = params.key || params.string || params;
  1407. } else {
  1408. textKey = params;
  1409. }
  1410. } else if (typeof params == 'string') {
  1411. textKey = params;
  1412. if (selectorParams) {
  1413. if (selectorParams.isConnected) {
  1414. element = selectorParams;
  1415. selector = self.dataStorage.get(element, 'selector');
  1416. } else {
  1417. selector = self.selector(selectorParams);
  1418. element = self.query(selector);
  1419. }
  1420. } else {
  1421. }
  1422. }
  1423. if (typeof textKey == 'string') {
  1424. textKey = self.replaceProperties(textKey, textArgs);
  1425. }
  1426. if (params && params.lang) {
  1427. textLang = self.langText(params.lang);
  1428. textLang = self.replaceProperties(textLang, textArgs);
  1429. if (textCase) textLang = self.textCase(textLang, textCase);
  1430. if (element) {
  1431. element.textContent = textLang;
  1432. self.attribute(element, 'data-text', true);
  1433. self.dataStorage.set(element, 'params', params);
  1434. }
  1435. } else {
  1436. if (textKey) {
  1437. if (textKey.lang)
  1438. textLang = self.langText(textKey.lang);
  1439. else
  1440. textLang = textKey;
  1441. textLang = self.replaceProperties(textLang, textArgs);
  1442. if (textCase) textLang = self.textCase(textLang, textCase);
  1443. if (element) {
  1444. if (self.json.texts[textKey]) {
  1445. self.attribute(element, 'data-text', true);
  1446. self.dataStorage.set(element, 'params', params);
  1447. }
  1448. if (params.style)
  1449. self.css({
  1450. style: params.style
  1451. }, {
  1452. selector: selector
  1453. });
  1454. element.textContent = textLang;
  1455. } else {
  1456. return textLang;
  1457. }
  1458. } else {
  1459. return params;
  1460. }
  1461. }
  1462. };
  1463. /*
  1464. Method: caseUp
  1465. Description: Functionality for caseUp.
  1466. @param {any} string - Description for string
  1467. @returns {any} - Result of the operation
  1468. */
  1469. var caseUp = function (string) {
  1470. return string.toUpperCase();
  1471. };
  1472. /*
  1473. Method: caseDown
  1474. Description: Functionality for caseDown.
  1475. @param {any} string - Description for string
  1476. @returns {any} - Result of the operation
  1477. */
  1478. var caseDown = function (string) {
  1479. return string.toLowerCase();
  1480. };
  1481. /*
  1482. Method: capitalize
  1483. Description: Functionality for capitalize.
  1484. @param {any} string - Description for string
  1485. @returns {any} - Result of the operation
  1486. */
  1487. var capitalize = function (string) {
  1488. return self.capitalize(string);
  1489. };
  1490. /*
  1491. Method: textCase
  1492. Description: Functionality for textCase.
  1493. @param {any} textParam - Description for textParam
  1494. @param {any} caseParam - Description for caseParam
  1495. @returns {any} - Result of the operation
  1496. */
  1497. this.textCase = function (textParam, caseParam) {
  1498. if (textParam) {
  1499. var text = textParam;
  1500. switch (caseParam) {
  1501. case 'up':
  1502. text = text.toUpperCase();
  1503. break;
  1504. case 'down':
  1505. text = text.toLowerCase();
  1506. break;
  1507. case 'capitalize':
  1508. text = self.capitalize(text);
  1509. break;
  1510. }
  1511. return text;
  1512. } else {
  1513. self.log('textParam undefined in textCase');
  1514. }
  1515. };
  1516. /*
  1517. Method: replaceUndefined
  1518. Description: Functionality for replaceUndefined.
  1519. @param {any} params - Description for params
  1520. @returns {any} - Result of the operation
  1521. */
  1522. this.replaceUndefined = function (params) {
  1523. let value, defaultValue;
  1524. if (typeof params.path !== undefined) {
  1525. if (params.path.indexOf('|') > 0)
  1526. [params.path, defaultValue] = params.path.split('|');
  1527. value = self.element({ path: params.path, root: params.root });
  1528. }
  1529. if (value == undefined || value == null) {
  1530. if (typeof defaultValue !== undefined)
  1531. value = defaultValue;
  1532. else {
  1533. if (params.removeUndefined) {
  1534. value = '';
  1535. } else {
  1536. value = params.match;
  1537. self.log(value + ' not found', 'yellow');
  1538. }
  1539. }
  1540. } else {
  1541. }
  1542. return value;
  1543. };
  1544. /*
  1545. Method: replaceProperties
  1546. Description: Functionality for replaceProperties.
  1547. @param {any} params - Description for params
  1548. @param {any} args - Description for args
  1549. @param {any} removeUndefined - Description for removeUndefined
  1550. @returns {any} - Result of the operation
  1551. */
  1552. this.replaceProperties = function (params, args, removeUndefined) {
  1553. var paramsString;
  1554. var paramOn, paramDo, paramSuccess, paramError, paramEvents, paramConfirm;
  1555. if (typeof params == 'string') {
  1556. paramsString = params;
  1557. } else {
  1558. var paramsObj = self.cloneObject(params);
  1559. if (paramsObj) {
  1560. if (paramsObj.on) { paramOn = paramsObj.on; delete paramsObj.on; }
  1561. if (paramsObj.success) { paramSuccess = paramsObj.success; delete paramsObj.success; }
  1562. if (paramsObj.error) { paramError = paramsObj.error; delete paramsObj.error; }
  1563. if (paramsObj.events) { paramEvents = paramsObj.events; delete paramsObj.events; }
  1564. if (paramsObj.confirm) { paramConfirm = paramsObj.confirm; delete paramsObj.confirm; }
  1565. if (paramsObj.do) { paramDo = paramsObj.do; delete paramsObj.do; }
  1566. }
  1567. paramsString = JSON.stringify(paramsObj);
  1568. }
  1569. if (paramsString && paramsString.indexOf('{') >= 0) {
  1570. paramsString = paramsString.replace(/\"\{([\w\s\.]+)\}\"/g, function (match, p1, offset, string) {
  1571. var value;
  1572. if (p1) {
  1573. //self.log('p1:' + p1);
  1574. //value = self.element({path: p1}); // || match;
  1575. value = self.replaceUndefined({ match: '{' + match + '}', path: p1, removeUndefined: removeUndefined });
  1576. if (value) {
  1577. if (value.isConnected) return self.elementToSelector(value); // DOM element to CSS selector
  1578. if (typeof value !== 'string')
  1579. return self.stringify(value); // object or array to string (TO DO: check numbers)
  1580. else {
  1581. //console.warn('we are here');
  1582. return '"' + value + '"';
  1583. }
  1584. }
  1585. else
  1586. return '""';
  1587. } else {
  1588. return '""';
  1589. }
  1590. });
  1591. paramsString = paramsString.replace(/\{(\w+\:)?([\w\s\->|\/=\.:#&;,\[\]\']+)\}/g, function (match, p1, p2, offset, string) {
  1592. /*
  1593. Firebase references may contain any unicode characters except:
  1594. . (period)
  1595. $ (dollar sign)
  1596. [ (left square bracket)
  1597. ] (right square bracket)
  1598. # (hash or pound sign)
  1599. / (forward slash)
  1600. */
  1601. /* self.log("paramstring");
  1602. self.log(match, p1, p2); */
  1603. // self.log(match, p1, p2);
  1604. var value;
  1605. if (p1) {
  1606. if (p1.endsWith(':')) {
  1607. p1 = p1.slice(0, -1); // remove the final ":"
  1608. // check if is a
  1609. /*
  1610. Method: name
  1611. Description: Functionality for name.
  1612. @param {any} in this.json.functions - Description for in this.json.functions
  1613. @returns {any} - Result of the operation
  1614. */
  1615. function name (in this.json.functions)
  1616. if (self.functions[p1]) {
  1617. //value = self.functions[p1](JSON.parse(p2));
  1618. let funcArgs = p2.split('|');
  1619. /* console.warn('p2');
  1620. console.warn(p2);
  1621. console.warn('funcArgs');
  1622. console.warn(funcArgs); */
  1623. // if Number(funcArgs[i]) == funcArgs[i] -> funcArgs[i] = Number(funcArgs[i]);
  1624. value = self.function({ name: p1, arguments: [funcArgs] });
  1625. } else {
  1626. switch (p1) {
  1627. /* case 'hasClass':
  1628. var element = document.querySelector(p2);
  1629. if (p3)
  1630. value = self.hasClass(el,p3);
  1631. else
  1632. value = false; el:selector.class (esiste l'elemento selector.class o l'elemento selector ha la classe class)
  1633. break; */
  1634. // 'isVisible', 'isHidden', 'isDisplay', 'inViewport', 'outViewport', 'notClass', 'hasClass'
  1635. // hasClass da aggiungere come funzione css
  1636. // html markups
  1637. // 'b:string' 'i:string' 'u:string' 'a:STRING|URL'
  1638. /* case 'i': case 'b': case 'u': case 'strong': case 'em': case 'mark': case 'del': case 'ins': case 'sub': case 'sup':
  1639. value = '<'+p1+'>'+p2+'</'+p1+'>';
  1640. break;
  1641. case 'a':
  1642. // example: "{a:text|href:....|target:_blank}"
  1643. let props = p2.split('|'); // or indexOf(':') prima occorrenza
  1644. let string = props.shift();
  1645. var propsString = '';
  1646. for (var prop of props) {
  1647. //let propArr = prop.split(':'), propName = propArr[0], propValue = propArr[1];
  1648. propsString += ' ' + prop;
  1649. }
  1650. if (propsString == '') propsString = ' href="'+string+'"';
  1651. value = '<a'+propsString+'>'+string+'</a>';
  1652. // https://stackoverflow.com/questions/1547899/which-characters-make-a-url-invalid
  1653. // https://www.w3schools.com/tags/tag_a.asp
  1654. break;
  1655. */
  1656. // DOM properties
  1657. case 'visible':
  1658. var element = document.querySelector(p2); // self.query(p2);
  1659. value = (element && self.isVisible(element));
  1660. //value = ($(p2).is(':visible'));
  1661. break;
  1662. case 'number':
  1663. value = Number(p2);
  1664. break;
  1665. case 'string':
  1666. value = String(p2);
  1667. break;
  1668. case 'js': // deprecated (too much special characters like {})
  1669. try {
  1670. value = eval(p2);
  1671. } catch (error) {
  1672. value = '';
  1673. self.log('javascript error on ' + p2);
  1674. self.log(error);
  1675. }
  1676. break;
  1677. /* case 'item':
  1678. if (fieldsObj) {
  1679. //self.log('fieldsObj['+p2+']:'+fieldsObj[p2]);
  1680. value = fieldsObj[p2] || ''; //|| p2+'=NULL';
  1681. } else {
  1682. //self.log('p2:'+p2);
  1683. //self.log('fieldsObj == undefined');
  1684. value = '{'+p1+':'+p2+'}';
  1685. }
  1686. break; */
  1687. /* case 'item':
  1688. case 'items':
  1689. value = self.docElement('self.json.items.'+p2);
  1690. break; */
  1691. /* case 'frame':
  1692. var element = self.query(p2);
  1693. element.contentWindow
  1694. break; */
  1695. /* case 'field':
  1696. if (fieldsObj) {
  1697. //self.log('fieldsObj['+p2+']:'+fieldsObj[p2]);
  1698. value = fieldsObj[p2] || ''; // || p2+'=NULL';
  1699. } else {
  1700. //self.log('p2:'+p2);
  1701. //self.log('fieldsObj == undefined');
  1702. value = '';
  1703. }
  1704. break; */
  1705. /* case 'setup':
  1706. value = self.docElement('self.json.setup.'+p2) || match;
  1707. break; */
  1708. /*
  1709. case 'setup':
  1710. if (args) {
  1711. self.partSetup = args;
  1712. value = self.docElement('self.partSetup.'+p2);
  1713. delete self)Setup;
  1714. } else {
  1715. value = '';
  1716. }
  1717. break; */
  1718. case 'wp':
  1719. case 'wordpress':
  1720. // TO DO: should get/set data with jsonic.get/setWordpressData
  1721. // setWordpressData can be done automatically in the init
  1722. value = self.docElement('self.json.setup.wordpress.' + p2) ?? match;
  1723. //alert(value);
  1724. //if (value.indexOf('"') >= 0)
  1725. // value = self.replaceAll(value, '"', '\\"');
  1726. // the first should replace only " and not \" but it doesn't works
  1727. break;
  1728. case 'plugins':
  1729. value = self.json.resources.pluginsFunctions[p2];
  1730. if (value && !Array.isArray(value)) value = [value];
  1731. else value = [];
  1732. break;
  1733. case 'database':
  1734. case 'db':
  1735. value = self.docElement('self.json.var.db.' + self.replaceProperties(p2, args));
  1736. break;
  1737. case 'media':
  1738. if (self.json.setup && self.json.data.media)
  1739. value = self.docElement('self.json.data.media.' + p2) || match;
  1740. else
  1741. value = match;
  1742. break;
  1743. case 'color':
  1744. if (self.json.data && self.json.data.colors)
  1745. value = self.docElement('self.json.data.colors.' + p2) || match;
  1746. else
  1747. value = match;
  1748. break;
  1749. case 'class':
  1750. if (self.json.data && self.json.data.class)
  1751. value = self.docElement('self.json.data.class.' + p2) || match;
  1752. else
  1753. value = match;
  1754. break;
  1755. case 'text':
  1756. value = self.langText(p2);
  1757. break;
  1758. case 'param':
  1759. value = self.params[p2] || '';
  1760. break;
  1761. case 'height':
  1762. var element = document.querySelector(p2);
  1763. if (element)
  1764. value = element.offsetHeight + 'px';
  1765. else
  1766. value = '0px';
  1767. break;
  1768. case 'offsetWidth':
  1769. var element = document.querySelector(p2);
  1770. if (element)
  1771. value = element.offsetWidth;
  1772. else
  1773. value = '0';
  1774. break;
  1775. case 'width':
  1776. var element = document.querySelector(p2);
  1777. if (element)
  1778. value = element.offsetWidth + 'px';
  1779. else
  1780. value = '0px';
  1781. break;
  1782. case 'local':
  1783. value = self.methods.local.get(p2);
  1784. break;
  1785. case 'ace':
  1786. var element = document.querySelector(p2);
  1787. if (element) {
  1788. var editor = ace.edit(element);
  1789. value = JSON.parse(editor.getValue());
  1790. }
  1791. break;
  1792. case 'shuffle':
  1793. value = self.element({ path: p2 });
  1794. value = self.methods.shuffle(value);
  1795. break;
  1796. case 'select':
  1797. case 'input':
  1798. case 'value':
  1799. var element = document.querySelector(p2);
  1800. value = (element) ? String(element.value || '') : '';
  1801. break;
  1802. case 'user':
  1803. if (p2 == 'in') {
  1804. value = self.userIn();
  1805. } else if (p2 == 'out')
  1806. value = self.userOut();
  1807. else
  1808. value = self.user(p2) || match;
  1809. break;
  1810. case 'length':
  1811. var varObj = self.element({ path: p2 });
  1812. if (varObj)
  1813. if (typeof varObj == 'object')
  1814. value = Object.keys(varObj).length;
  1815. else
  1816. value = varObj.length;
  1817. else
  1818. self.log('' + p2 + ' is undefined');
  1819. break;
  1820. case 'Date':
  1821. case 'time':
  1822. if (p2 == 'timeZone') value = new Intl.DateTimeFormat().resolvedOptions().timeZone;
  1823. else if (p2 == 'weekday') value = self.weekday();
  1824. else if (p2 == 'stamp') value = self.getTimestamp();
  1825. else if (p2 == 'timestamp') value = self.getTimestamp();
  1826. else if (p2 == 'getTimestamp') value = self.getTimestamp();
  1827. else if (p2 == 'getDay') value = new Date().getDay();
  1828. else if (p2 == 'getDate') value = new Date().getDate();
  1829. else if (p2 == 'getMonth') value = new Date().getMonth();
  1830. else if (p2 == 'getFullYear') value = new Date().getFullYear();
  1831. else if (p2 == 'getTime') value = new Date().getTime();
  1832. else if (p2 == 'getSeconds') value = new Date().getSeconds();
  1833. else if (p2 == 'getMinutes') value = new Date().getMinutes();
  1834. else if (p2 == 'getHours') value = new Date().getHours();
  1835. else value = p2 + '=NULL';
  1836. break;
  1837. case 'now':
  1838. break;
  1839. case 'month':
  1840. var month = (p2 == 'today' || p2 == undefined) ? new Date().getMonth() : Number(p2);
  1841. value = self.month(month);
  1842. break;
  1843. case 'weekday':
  1844. var day = (p2 == 'today' || p2 == undefined) ? new Date().getDay() : Number(p2);
  1845. value = self.calendar({ index: Number(day), unit: 'weekday', format: 'long' });
  1846. break;
  1847. case 'weekdayNarrow':
  1848. var day = (p2 == 'today' || p2 == undefined) ? new Date().getDay() : Number(p2);
  1849. value = self.calendar({ index: Number(day), unit: 'weekday', format: 'narrow' });
  1850. break;
  1851. case 'weekdayShort':
  1852. var day = (p2 == 'today' || p2 == undefined) ? new Date().getDay() : Number(p2);
  1853. value = self.calendar({ index: Number(day), unit: 'weekday', format: 'short' });
  1854. break;
  1855. case 'moment':
  1856. var timeFormat = (p2) ? p2 : '';
  1857. value = moment().format(timeFormat);
  1858. break;
  1859. case 'dayjs':
  1860. var timeFormat = (p2) ? p2 : '';
  1861. value = dayjs().format(timeFormat);
  1862. break;
  1863. case 'Math':
  1864. value = self.Math(p2);
  1865. break;
  1866. case 'action':
  1867. case 'do':
  1868. self.log('do');
  1869. self.log('p2');
  1870. self.log(p2);
  1871. value = self.do(p2);
  1872. break;
  1873. case 'method':
  1874. var method = self.element({ path: p2, root: self.methods });
  1875. if (method) {
  1876. value = method(args);
  1877. } else {
  1878. value = match;
  1879. }
  1880. break;
  1881. case 'function':
  1882. var func = self.element({ path: p2, root: self.functions });
  1883. if (func) {
  1884. value = func(args);
  1885. } else {
  1886. value = match;
  1887. }
  1888. break;
  1889. case 'on':
  1890. if (args) {
  1891. self.onResult = args;
  1892. value = self.docElement('self.onResult.' + p2);
  1893. delete self.onResult;
  1894. } else {
  1895. value = match;
  1896. }
  1897. break;
  1898. case 'ajax':
  1899. if (args) {
  1900. self.ajaxResult = args;
  1901. value = self.docElement('self.ajaxResult.' + p2);
  1902. delete self.ajaxResult;
  1903. } else {
  1904. value = match;
  1905. }
  1906. break;
  1907. case 'if':
  1908. p2 = self.replaceProperties(p2);
  1909. var ifArr = p2.split('|');
  1910. if (self.js(ifArr[0])) value = true;
  1911. if (ifArr.length > 1 && value) value = ifArr[1];
  1912. if (ifArr.length > 2 && !value) value = ifArr[2];
  1913. break;
  1914. case 'random':
  1915. value = String(Math.floor(Number(p2) * Math.random()));
  1916. break;
  1917. case 'getKey':
  1918. case 'firebaseKey':
  1919. value = self.firebaseKey(p2);
  1920. break;
  1921. case 'window':
  1922. value = self.docElement(p2) || match;
  1923. break;
  1924. default:
  1925. break;
  1926. }
  1927. }
  1928. }
  1929. } else if (p2) {
  1930. let keyPrefix = p2.split(' ')[0];
  1931. if (self.functions[keyPrefix]) {
  1932. value = self.function({ name: keyPrefix });
  1933. value = self.element({ path: p2, root: value });
  1934. console.log(keyPrefix);
  1935. console.log(value);
  1936. }
  1937. else
  1938. value = self.replaceUndefined({ match: match, path: p2, removeUndefined: removeUndefined });
  1939. }
  1940. if (value && value.isConnected) value = self.elementToSelector(value);
  1941. if (!value) {
  1942. if (removeUndefined)
  1943. value = '';
  1944. else {
  1945. if (typeof value == undefined)
  1946. self.log(match + ' is undefined', 'yellow');
  1947. }
  1948. }
  1949. if (typeof value !== 'string') value = self.stringify(value);
  1950. return value;
  1951. });
  1952. if (paramsString.startsWith('{js:') && paramsString.endsWith('}'))
  1953. paramsString = self.js(paramsString.substr(4, paramsString.length - 1 - 4));
  1954. if (self.isJsonString(paramsString)) {
  1955. var paramsObj = self.parse(paramsString);
  1956. if (paramOn) paramsObj.on = paramOn;
  1957. if (paramDo) paramsObj.do = paramDo;
  1958. if (paramConfirm) paramsObj.confirm = paramConfirm;
  1959. if (paramSuccess) paramsObj.success = paramSuccess;
  1960. if (paramError) paramsObj.success = paramError;
  1961. if (paramEvents) paramsObj.events = paramEvents;
  1962. return paramsObj;
  1963. } else {
  1964. return paramsString;
  1965. }
  1966. } else {
  1967. if (paramOn) params.on = paramOn;
  1968. if (paramDo) params.do = paramDo;
  1969. if (paramConfirm) params.confirm = paramConfirm;
  1970. if (paramSuccess) params.success = paramSuccess;
  1971. if (paramError) params.error = paramError;
  1972. if (paramEvents) params.events = paramEvents;
  1973. return params;
  1974. }
  1975. };
  1976. /*
  1977. Method: isJsonString
  1978. Description: Functionality for isJsonString.
  1979. @param {any} str - Description for str
  1980. @returns {any} - Result of the operation
  1981. */
  1982. this.isJsonString = function (str) {
  1983. try {
  1984. JSON.parse(str);
  1985. } catch (e) {
  1986. return false;
  1987. }
  1988. return true;
  1989. };
  1990. /*
  1991. Method: isJson
  1992. Description: Functionality for isJson.
  1993. @param {any} item - Description for item
  1994. @returns {any} - Result of the operation
  1995. */
  1996. this.isJson = function (item) {
  1997. item = typeof item !== "string" ? JSON.stringify(item) : item;
  1998. try {
  1999. item = JSON.parse(item);
  2000. } catch (e) {
  2001. return false;
  2002. }
  2003. if (typeof item === "object" && item !== null) {
  2004. return true;
  2005. }
  2006. return false;
  2007. };
  2008. /*
  2009. Method: replaceStringInObject
  2010. Description: Functionality for replaceStringInObject.
  2011. @param {any} obj - Description for obj
  2012. @param {any} stringToReplace - Description for stringToReplace
  2013. @param {any} value - Description for value
  2014. @returns {any} - Result of the operation
  2015. */
  2016. this.replaceStringInObject = function (obj, stringToReplace, value) {
  2017. var paramsString, valueString;
  2018. if (typeof obj == 'string') paramsString = obj; else paramsString = JSON.stringify(obj);
  2019. if (typeof value == 'string') valueString = value; else valueString = JSON.stringify(value);
  2020. paramsString = self.replaceAll(paramsString, stringToReplace, valueString);
  2021. if (self.isJson(paramsString))
  2022. return self.parse(paramsString);
  2023. else
  2024. return paramsString;
  2025. };
  2026. /*
  2027. Method: replaceItems
  2028. Description: Functionality for replaceItems.
  2029. @param {any} params - Description for params
  2030. @param {any} item - Description for item
  2031. @param {any} name - Description for name
  2032. @returns {any} - Result of the operation
  2033. */
  2034. this.replaceItems = function (params, item, name) {
  2035. var paramsString;
  2036. var specialPattern;
  2037. var itemName = name || 'item';
  2038. if (typeof params == 'string') paramsString = params; else paramsString = JSON.stringify(params);
  2039. if (typeof item == 'object' || Array.isArray(item)) {
  2040. paramsString = self.replaceAll(paramsString, '"{' + itemName + '}"', JSON.stringify(item));
  2041. for (let key in item) {
  2042. if (typeof item[key] == 'object')
  2043. paramsString = self.replaceAll(paramsString, '"{' + itemName + ':' + key + '}"', JSON.stringify(item[key]));
  2044. else
  2045. paramsString = self.replaceAll(paramsString, '{' + itemName + ':' + key + '}', item[key]);
  2046. }
  2047. } else {
  2048. paramsString = self.replaceAll(paramsString, '{' + itemName + '}', String(item));
  2049. }
  2050. paramsString = paramsString.replace(/(\"\s*)\{item\:(\w+)\}(\s*\")/g, function (match, p1, p2, p3, offset, string) {
  2051. var value;
  2052. if (item)
  2053. value = item[p2] || '';
  2054. else
  2055. value = '';
  2056. if (typeof value == 'object')
  2057. value = self.stringify(value);
  2058. else if (Array.isArray(value))
  2059. value = value;
  2060. else
  2061. value = p1 + value + p3; // p1 and p3 are the " matched by (\"\s*) and (\s*\")
  2062. return value;
  2063. });
  2064. /*
  2065. specialPattern = new RegExp('\{'+itemName+'\:([^\}]*)\}', 'g');
  2066. paramsString = paramsString.replace(specialPattern, function(match, p2, offset, string) {
  2067. //paramsString = paramsString.replace(/\{item\:([^\}]*)\}/g, function(match, p2, offset, string) {
  2068. var value;
  2069. if (item)
  2070. value = item[p2] || '';
  2071. else
  2072. value = '';
  2073. if (typeof value == 'object')
  2074. value = self.stringify(value);
  2075. return value;
  2076. }); */
  2077. if (self.isJson(paramsString))
  2078. return self.parse(paramsString);
  2079. else
  2080. return paramsString;
  2081. //if (typeof params == 'object') return self.parse(paramsString); else return paramsString;
  2082. };
  2083. /*
  2084. /*
  2085. Method: replaceItems
  2086. Description: Functionality for replaceItems.
  2087. @param {any} objWithNames - Description for objWithNames
  2088. @param {any} name - Description for name
  2089. @returns {any} - Result of the operation
  2090. */
  2091. this.replaceItems = function (objWithNames, name) {
  2092. //self.log('replaceItems');
  2093. var paramString = self.stringify(objWithNames);
  2094. //self.log(paramString);
  2095. if (!name) name = '';
  2096. paramString = self.replaceAll(paramString, '{item}', name);
  2097. //self.log(paramString);
  2098. //paramString = self.replaceTags({text:paramString});
  2099. //self.log(paramString);
  2100. //paramString = self.replaceProperties(paramString);
  2101. //self.log(paramString);
  2102. if (typeof objWithNames == 'object') return self.parse(paramString); else return paramString;
  2103. } */
  2104. /*
  2105. Method: color
  2106. Description: Functionality for color.
  2107. @param {any} params - Description for params
  2108. @param {any} args - Description for args
  2109. @returns {any} - Result of the operation
  2110. */
  2111. this.color = function (params, args) {
  2112. var paramsReplaced = self.replaceProperties(params, args);
  2113. //if (self.json.styles.colors)
  2114. // return self.json.styles.colors[paramsReplaced];
  2115. if (self.json.data && self.json.data.colors)
  2116. return self.json.data.colors[paramsReplaced];
  2117. };
  2118. // ----------------------------
  2119. // ELEMENT METHODS
  2120. // ----------------------------
  2121. /*
  2122. Method: empty
  2123. Description: Functionality for empty.
  2124. @param {any} params - Description for params
  2125. @returns {any} - Result of the operation
  2126. */
  2127. this.empty = function (params) {
  2128. /* self.log('empty');
  2129. self.log(params); */
  2130. var el = self.query(params);
  2131. if (el) {
  2132. while (el.firstChild)
  2133. el.removeChild(el.firstChild);
  2134. } else {
  2135. self.log('"empty" is unable to select element');
  2136. self.log(params);
  2137. }
  2138. };
  2139. /*
  2140. Method: isArray
  2141. Description: Functionality for isArray.
  2142. @param {any} value - Description for value
  2143. @returns {any} - Result of the operation
  2144. */
  2145. this.isArray = function (value) {
  2146. return Array.isArray(self.js(value));
  2147. };
  2148. /*
  2149. Method: isVisible
  2150. Description: Functionality for isVisible.
  2151. @param {any} el - Description for el
  2152. @returns {any} - Result of the operation
  2153. */
  2154. this.isVisible = function (el) {
  2155. return (el.style.display !== 'none' && !self.hasClass(el, 'd-none'));
  2156. };
  2157. /*
  2158. Method: isHidden
  2159. Description: Functionality for isHidden.
  2160. @param {any} el - Description for el
  2161. @returns {any} - Result of the operation
  2162. */
  2163. this.isHidden = function (el) {
  2164. return (el.offsetParent === null);
  2165. };
  2166. /*
  2167. Method: isDisplay
  2168. Description: Functionality for isDisplay.
  2169. @param {any} el - Description for el
  2170. @param {any} displayValue - Description for displayValue
  2171. @returns {any} - Result of the operation
  2172. */
  2173. this.isDisplay = function (el, displayValue) {
  2174. //var style = window.getComputedStyle(el);
  2175. /* self.log('isDisplay');
  2176. self.log('el.style');
  2177. self.log(el.style);
  2178. self.log('displayValue');
  2179. self.log(displayValue); */
  2180. return (el.style.display === displayValue);
  2181. };
  2182. /*
  2183. Method: inViewport
  2184. Description: Functionality for inViewport.
  2185. @param {any} el - Description for el
  2186. @returns {any} - Result of the operation
  2187. */
  2188. this.inViewport = function (el) {
  2189. const rect = el.getBoundingClientRect();
  2190. return (
  2191. rect.top >= 0 &&
  2192. rect.left >= 0 &&
  2193. rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
  2194. rect.right <= (window.innerWidth || document.documentElement.clientWidth)
  2195. );
  2196. };
  2197. /*
  2198. Method: outViewport
  2199. Description: Functionality for outViewport.
  2200. @param {any} el - Description for el
  2201. @returns {any} - Result of the operation
  2202. */
  2203. this.outViewport = function (el) {
  2204. return !self.outViewport(el);
  2205. };
  2206. /*
  2207. Method: notClass
  2208. Description: Functionality for notClass.
  2209. @param {any} el - Description for el
  2210. @param {any} className - Description for className
  2211. @returns {any} - Result of the operation
  2212. */
  2213. this.notClass = function (el, className) {
  2214. return !self.hasClass(el, className);
  2215. };
  2216. /*
  2217. Method: hasClass
  2218. Description: Functionality for hasClass.
  2219. @param {any} el - Description for el
  2220. @param {any} className - Description for className
  2221. @returns {any} - Result of the operation
  2222. */
  2223. this.hasClass = function (el, className) {
  2224. if (el.classList)
  2225. return el.classList.contains(className);
  2226. else
  2227. return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'));
  2228. };
  2229. /*
  2230. Method: addClass
  2231. Description: Functionality for addClass.
  2232. @param {any} el - Description for el
  2233. @param {any} className - Description for className
  2234. @returns {any} - Result of the operation
  2235. */
  2236. this.addClass = function (el, className) {
  2237. if (el.classList)
  2238. el.classList.add(className);
  2239. else if (!self.hasClass(el, className)) el.className += " " + className;
  2240. };
  2241. /*
  2242. Method: removeClass
  2243. Description: Functionality for removeClass.
  2244. @param {any} el - Description for el
  2245. @param {any} className - Description for className
  2246. @returns {any} - Result of the operation
  2247. */
  2248. this.removeClass = function (el, className) {
  2249. if (el.classList)
  2250. el.classList.remove(className);
  2251. else if (self.hasClass(el, className)) {
  2252. var reg = new RegExp('(\\s|^)' + className + '(\\s|$)');
  2253. el.className = el.className.replace(reg, ' ');
  2254. }
  2255. };
  2256. /*
  2257. Method: toggleClass
  2258. Description: Functionality for toggleClass.
  2259. @param {any} el - Description for el
  2260. @param {any} className - Description for className
  2261. @returns {any} - Result of the operation
  2262. */
  2263. this.toggleClass = function (el, className) {
  2264. if (self.hasClass(el, className))
  2265. self.removeClass(el, className);
  2266. else
  2267. self.addClass(el, className);
  2268. };
  2269. this.choose =
  2270. /*
  2271. Method: select
  2272. Description: Functionality for select.
  2273. @param {any} params - Description for params
  2274. @param {any} selectorParams - Description for selectorParams
  2275. @param {any} args - Description for args
  2276. @returns {any} - Result of the operation
  2277. */
  2278. this.select = function (params, selectorParams, args) {
  2279. // "choose OR options / "select" is deprecated because select is an html tag
  2280. if (Array.isArray(params)) {
  2281. for (var obj of params)
  2282. self.choose(obj, args);
  2283. } else {
  2284. var selId, selClass, selValue;
  2285. selValue = params['data-value'];
  2286. if (params.id) selId = self.replaceProperties(params.id, args);
  2287. if (params.class) selClass = self.replaceProperties(params.class, args);
  2288. if (selValue) selValue = self.replaceProperties(selValue, args);
  2289. if (params.selection) {
  2290. var selectionClass = params.selection;
  2291. var selector = self.selector({ class: selClass });
  2292. var elements = document.querySelectorAll('.' + selClass);
  2293. elements.forEach(function (element, index) {
  2294. self.removeClass(element, selectionClass);
  2295. });
  2296. if (selId || selValue) {
  2297. var selector = self.selector({ id: selId, class: selClass, 'data-value': selValue });
  2298. var elements = document.querySelectorAll(selector);
  2299. elements.forEach(function (element, index) {
  2300. self.addClass(element, selectionClass);
  2301. });
  2302. }
  2303. } else {
  2304. self.hide({
  2305. "selector": {
  2306. "class": selClass
  2307. }
  2308. });
  2309. self.show({
  2310. "selector": {
  2311. "id": selId,
  2312. "class": selClass,
  2313. "data-value": selValue
  2314. }
  2315. });
  2316. }
  2317. self.uiUpdate();
  2318. }
  2319. };
  2320. /*
  2321. Method: toggle
  2322. Description: Functionality for toggle.
  2323. @param {any} params - Description for params
  2324. @param {any} selectorParams - Description for selectorParams
  2325. @param {any} args - Description for args
  2326. @returns {any} - Result of the operation
  2327. */
  2328. this.toggle = function (params, selectorParams, args) {
  2329. self.log('toggle');
  2330. self.log(params);
  2331. if (Array.isArray(params)) {
  2332. for (var index in params)
  2333. self.toggle(params[index], selectorParams, args);
  2334. } else {
  2335. var selector;
  2336. if (typeof params == 'string')
  2337. selector = params;
  2338. else
  2339. selector = self.selector(params.selector || params.container, undefined, true) || self.selector(selectorParams, undefined, true);
  2340. var element = self.query(selector);
  2341. if (self.isVisible(element))
  2342. self.out(params, selectorParams, args);
  2343. else
  2344. self.in(params, selectorParams, args);
  2345. }
  2346. };
  2347. /*
  2348. Method: in
  2349. Description: Functionality for in.
  2350. @param {any} params - Description for params
  2351. @param {any} selectorParams - Description for selectorParams
  2352. @param {any} args - Description for args
  2353. @returns {any} - Result of the operation
  2354. */
  2355. this.in = function (params, selectorParams, args) {
  2356. if (Array.isArray(params)) {
  2357. for (var index in params)
  2358. self.in(params[index], selectorParams, args);
  2359. } else {
  2360. var selector;
  2361. if (typeof params == 'string')
  2362. selector = params;
  2363. else
  2364. selector = self.selector(params.selector || params.container, undefined, true) || self.selector(selectorParams, undefined, true);
  2365. var transition = params.transition || 'fadeIn';
  2366. var duration = params.duration || '500ms';
  2367. var start = [{
  2368. "show": {
  2369. "selector": selector,
  2370. }
  2371. }];
  2372. var end = [
  2373. {
  2374. "do": self.resizeEvent
  2375. }
  2376. ];
  2377. if (params.on && params.on.start)
  2378. start.push(params.on.start);
  2379. if (params.on && params.on.end)
  2380. end.push(params.on.end);
  2381. var animation = {
  2382. "animate": {
  2383. "selector": selector,
  2384. "transition": transition,
  2385. "duration": duration,
  2386. "on": {
  2387. "start": start,
  2388. "end": end
  2389. }
  2390. }
  2391. };
  2392. self.do(animation, undefined, args);
  2393. }
  2394. };
  2395. /*
  2396. Method: out
  2397. Description: Functionality for out.
  2398. @param {any} params - Description for params
  2399. @param {any} selectorParams - Description for selectorParams
  2400. @param {any} args - Description for args
  2401. @returns {any} - Result of the operation
  2402. */
  2403. this.out = function (params, selectorParams, args) {
  2404. if (Array.isArray(params)) {
  2405. for (var index in params)
  2406. self.out(params[index], selectorParams);
  2407. } else {
  2408. var selector;
  2409. if (typeof params == 'string')
  2410. selector = params;
  2411. else
  2412. selector = self.selector(params.selector || params.container, undefined, true) || self.selector(selectorParams, undefined, true);
  2413. var transition = params.transition || 'fadeOut';
  2414. var duration = params.duration || '500ms';
  2415. var start = [];
  2416. var end = [
  2417. {
  2418. "hide": {
  2419. "selector": selector,
  2420. }
  2421. },
  2422. {
  2423. "do": self.resizeEvent
  2424. }
  2425. ];
  2426. if (params.on && params.on.start)
  2427. start.push(params.on.start);
  2428. if (params.on && params.on.end)
  2429. end.push(params.on.end);
  2430. var animation = {
  2431. "animate": {
  2432. "selector": selector,
  2433. "transition": transition,
  2434. "duration": duration,
  2435. "on": {
  2436. "start": start,
  2437. "end": end
  2438. }
  2439. }
  2440. };
  2441. self.do(animation, undefined, args);
  2442. }
  2443. };
  2444. /*
  2445. Method: show
  2446. Description: Functionality for show.
  2447. @param {any} params - Description for params
  2448. @param {any} selectorParams - Description for selectorParams
  2449. @param {any} args - Description for args
  2450. @returns {any} - Result of the operation
  2451. */
  2452. this.show = function (params, selectorParams, args) {
  2453. if (Array.isArray(params)) {
  2454. for (var index in params)
  2455. self.show(params[index], selectorParams);
  2456. } else {
  2457. var selector;
  2458. if (typeof params == 'string')
  2459. selector = params;
  2460. else
  2461. selector = self.selector(params.selector || params.container, undefined, true) || self.selector(selectorParams, undefined, true);
  2462. var elements = self.queryAll(selector);
  2463. elements.forEach(function (element, index) {
  2464. self.removeClass(element, 'hidden');
  2465. self.removeClass(element, 'opacity-0');
  2466. self.removeClass(element, 'invisible');
  2467. self.removeClass(element, 'd-none');
  2468. element.style.visibility = 'visible';
  2469. });
  2470. }
  2471. };
  2472. /*
  2473. Method: hide
  2474. Description: Functionality for hide.
  2475. @param {any} params - Description for params
  2476. @param {any} selectorParams - Description for selectorParams
  2477. @param {any} args - Description for args
  2478. @returns {any} - Result of the operation
  2479. */
  2480. this.hide = function (params, selectorParams, args) {
  2481. if (Array.isArray(params)) {
  2482. for (var index in params)
  2483. self.hide(params[index], selectorParams);
  2484. } else {
  2485. var selector;
  2486. if (typeof params == 'string')
  2487. selector = params;
  2488. else
  2489. selector = self.selector(params.selector || params.container, undefined, true) || self.selector(selectorParams, undefined, true);
  2490. var elements = self.queryAll(selector);
  2491. elements.forEach(function (element, index) {
  2492. self.addClass(element, 'hidden');
  2493. });
  2494. }
  2495. };
  2496. /*
  2497. Method: matchMedia
  2498. Description: Functionality for matchMedia.
  2499. @param {any} mediaAction - Description for mediaAction
  2500. @param {any} mediaEvent - Description for mediaEvent
  2501. @returns {any} - Result of the operation
  2502. */
  2503. this.matchMedia = function (mediaAction, mediaEvent) {
  2504. const mediaQuery = window.matchMedia(mediaEvent);
  2505. mediaQuery.addListener(function (e) {
  2506. if (e.matches) {
  2507. self.do(mediaAction);
  2508. }
  2509. });
  2510. };
  2511. /*
  2512. Method: addFirebaseTag
  2513. Description: Functionality for addFirebaseTag.
  2514. @param {any} params - Description for params
  2515. @returns {any} - Result of the operation
  2516. */
  2517. this.addFirebaseTag = function (params) {
  2518. var dataObj = params.database;
  2519. if (dataObj) {
  2520. dataObj = self.replaceProperties(dataObj);
  2521. var path, success;
  2522. if (typeof dataObj == 'string') {
  2523. path = dataObj;
  2524. } else {
  2525. path = dataObj.path;
  2526. success = dataObj.success;
  2527. }
  2528. if (path) {
  2529. var selector = self.selector(params, undefined, false);
  2530. var elements = self.queryAll(selector);
  2531. if (elements)
  2532. elements.forEach(function (element, index) {
  2533. var listenerObj = {
  2534. path: path
  2535. };
  2536. var elementsDataPath = document.querySelectorAll('[data-firebase="' + path + '"]');
  2537. if (elementsDataPath.length == 0) {
  2538. listenerObj.action = [
  2539. ];
  2540. if (dataObj.success)
  2541. listenerObj.action.push(dataObj.success);
  2542. }
  2543. if (element) {
  2544. element.setAttribute('data-firebase', path);
  2545. self.dataStorage.set(element, 'data-template', params);
  2546. } else {
  2547. self.log('!element selector:' + selector + ' / firebase path:' + path);
  2548. self.log('params');
  2549. self.log(params);
  2550. }
  2551. if (dataObj.orderByChild !== undefined) listenerObj.orderByChild = dataObj.orderByChild;
  2552. if (dataObj.equalTo !== undefined) listenerObj.equalTo = dataObj.equalTo;
  2553. self.firebaseAddListener(listenerObj);
  2554. });
  2555. } else {
  2556. self.log('data object requires path parameter');
  2557. self.log(params);
  2558. }
  2559. }
  2560. };
  2561. /*
  2562. Method: dbObject
  2563. Description: Functionality for dbObject.
  2564. @param {any} path - Description for path
  2565. @returns {any} - Result of the operation
  2566. */
  2567. this.dbObject = function (path) {
  2568. var pathString = 'self.json.var.db.' + self.replaceAll(path, '/', '.');
  2569. return self.docElement(pathString);
  2570. };
  2571. /*
  2572. Method: only
  2573. Description: Functionality for only.
  2574. @param {any} permissions - Description for permissions
  2575. @param {any} user - Description for user
  2576. @returns {any} - Result of the operation
  2577. */
  2578. this.only = function (permissions, user) {
  2579. if (user) {
  2580. return (user == self.user('uid'));
  2581. } else {
  2582. var permission = (permissions) ? String(permissions).split(',') : false;
  2583. return (!permission || (permissions.indexOf(self.userRole()) >= 0));
  2584. }
  2585. };
  2586. /*
  2587. Method: extendJsonFromElement
  2588. Description: Functionality for extendJsonFromElement.
  2589. @param {any} p - Description for p
  2590. @returns {any} - Result of the operation
  2591. */
  2592. this.extendJsonFromElement = function (p) {
  2593. var params = self.cloneObject(p);
  2594. if (params.resources) self.extendJson(self.json, { "resources": params.resources });
  2595. if (params.plugins) self.extendJson(self.json, { "plugins": params.plugins });
  2596. if (params.parts) self.extendJson(self.json, { "parts": params.parts });
  2597. if (params.blocks) self.extendJson(self.json, { "blocks": params.parts });
  2598. if (params.shortcuts) self.extendJson(self.json, { "shortcuts": params.shortcuts });
  2599. if (params.css) self.extendJson(self.json, { "css": params.css });
  2600. if (params.setup) self.extendJson(self.json, { "setup": params.setup });
  2601. if (params.data) self.extendJson(self.json, { "data": params.data });
  2602. if (params.var) self.extendJson(self.json, { "var": params.var });
  2603. if (params.texts) self.extendJson(self.json, { "texts": params.texts });
  2604. };
  2605. /*
  2606. Method: query
  2607. Description: Functionality for query.
  2608. @param {any} selector - Description for selector
  2609. @param {any} element - Description for element
  2610. @returns {any} - Result of the operation
  2611. */
  2612. this.query = function (selector, element) {
  2613. if (selector) {
  2614. if (typeof selector == 'object')
  2615. selector = self.selector(selector, undefined, true);
  2616. var routes = selector.split(/[ >]+/);
  2617. if (!element) element = document;
  2618. for (var index in routes) {
  2619. if (element && element[0]) element = element[0];
  2620. if (element && element.isConnected) {
  2621. var route = routes[index];
  2622. var routeParts = route.match(/(.*):eq\((\d*)\)/);
  2623. if (routeParts) {
  2624. var routeElement = String(routeParts[1]);
  2625. var routeIndex = Number(routeParts[2]);
  2626. if (routeElement.startsWith('.'))
  2627. routeElement = '.' + self.classSelector(routeElement);
  2628. element = element.querySelectorAll(routeElement)[routeIndex];
  2629. } else {
  2630. if (route.startsWith('.'))
  2631. route = '.' + self.classSelector(route);
  2632. element = element.querySelectorAll(route)[0];
  2633. }
  2634. } else {
  2635. element = undefined;
  2636. }
  2637. }
  2638. if (!element)
  2639. self.log('can\'t find the element "' + selector + '" ("query" function)');
  2640. return element;
  2641. } else {
  2642. }
  2643. };
  2644. /*
  2645. Method: queryAll
  2646. Description: Functionality for queryAll.
  2647. @param {any} selector - Description for selector
  2648. @param {any} element - Description for element
  2649. @returns {any} - Result of the operation
  2650. */
  2651. this.queryAll = function (selector, element) {
  2652. if (selector) {
  2653. if (Array.isArray(selector)) {
  2654. let elements = self.queryAll(selector[0]);
  2655. selector.shift();
  2656. for (let str of selector) {
  2657. elements = Array.prototype.slice.call(elements).concat(Array.prototype.slice.call(self.queryAll(str)));
  2658. }
  2659. return elements;
  2660. } else {
  2661. var routes = selector.split(/[ >]+/);
  2662. if (!element) element = document;
  2663. for (var index in routes) {
  2664. if (element && element[0]) element = element[0];
  2665. if (element && element.isConnected) {
  2666. var route = routes[index];
  2667. var routeParts = route.match(/([^:]*):eq\((\d*)\)/);
  2668. if (routeParts) {
  2669. var routeElement = String(routeParts[1]);
  2670. var routeIndex = Number(routeParts[2]);
  2671. if (routeElement.startsWith('.'))
  2672. routeElement = '.' + self.classSelector(routeElement);
  2673. element = element.querySelectorAll(routeElement)[routeIndex];
  2674. if (index == (routes.length - 1) && element) {
  2675. element = [element];
  2676. }
  2677. } else {
  2678. if (route.startsWith('.'))
  2679. routeElement = '.' + self.classSelector(route);
  2680. element = element.querySelectorAll(route);
  2681. }
  2682. } else {
  2683. element = [];
  2684. }
  2685. }
  2686. if (!element)
  2687. self.log('No element selected by ' + selector);
  2688. return element;
  2689. }
  2690. } else {
  2691. console.log('%cDOM queryAll requires selector argument', 'color: orange');
  2692. }
  2693. };
  2694. /*
  2695. Method: jitcss
  2696. Description: Functionality for jitcss.
  2697. @param {any} classes - Description for classes
  2698. @returns {any} - Result of the operation
  2699. */
  2700. this.jitcss = function (classes) {
  2701. if (classes.indexOf('-[') > -1) {
  2702. let classesArr = classes.split(' ');
  2703. self.log('jitcss');
  2704. for (cl of classesArr) {
  2705. self.log(cl);
  2706. let par = [...cl.matchAll(new RegExp('([^-]+)[\-][\[](.+)\]', 'g'))];
  2707. self.log('jitcss');
  2708. self.log(par);
  2709. }
  2710. }
  2711. };
  2712. /*
  2713. Method: compileClasses
  2714. Description: Functionality for compileClasses.
  2715. @param {any} string - Description for string
  2716. @returns {any} - Result of the operation
  2717. */
  2718. this.compileClasses = function (string) {
  2719. var classesString = string;
  2720. if (self.json.shortcuts && self.json.shortcuts.class) {
  2721. for (shortcut in self.json.shortcuts.class) {
  2722. if (string.indexOf(shortcut) > -1) {
  2723. classesString = self.replaceAll(string, shortcut, self.json.shortcuts.class[shortcut]);
  2724. }
  2725. }
  2726. }
  2727. if (string.indexOf('(') >= 0) {
  2728. classesString = '';
  2729. let classesArr = string.split(' ');
  2730. for (cl of classesArr) {
  2731. if (cl.indexOf('(') >= 0 && cl.endsWith(')')) {
  2732. let classArr = cl.split('(');
  2733. classArr[1] = classArr[1].slice(0, -1);
  2734. if (Boolean(self.js(classArr[1]))) {
  2735. if (classesString !== '') classesString += ' ';
  2736. classesString += classArr[0];
  2737. }
  2738. } else {
  2739. if (classesString !== '') classesString += ' ';
  2740. classesString += cl;
  2741. }
  2742. }
  2743. if (string == classesString) {
  2744. self.log('wrong dynamic class syntax');
  2745. self.log(string);
  2746. }
  2747. }
  2748. return classesString;
  2749. };
  2750. /*
  2751. Method: createElement
  2752. Description: Functionality for createElement.
  2753. @param {any} params - Description for params
  2754. @param {any} selectorParams - Description for selectorParams
  2755. @returns {any} - Result of the operation
  2756. */
  2757. this.createElement = function (params, selectorParams) {
  2758. let selector = params.selector || params.container;
  2759. var container = selector || self.selector(selectorParams);
  2760. var containerElement = self.query(container);
  2761. var newSelector = self.selector(params, selectorParams);
  2762. var newElements = [];
  2763. if (containerElement) {
  2764. if (!params) params = {};
  2765. var element = document.createElement(params.tag);
  2766. containerElement.appendChild(element);
  2767. if (params.attr) {
  2768. if (params.attr.class) {
  2769. params.attr.class = self.compileClasses(params.attr.class);
  2770. }
  2771. }
  2772. self.dataStorage.set(element, 'code', params);
  2773. self.dataStorage.set(element, 'key', params.key);
  2774. newElements.push(element);
  2775. if (params.attr) self.setAttributes(newElements, params.attr);
  2776. if (params.style) self.css(params, newSelector);
  2777. }
  2778. return newElements;
  2779. };
  2780. this.do = this.action =
  2781. /*
  2782. Method: execute
  2783. Description: Functionality for execute.
  2784. @param {any} params - Description for params
  2785. @param {any} selectorParams - Description for selectorParams
  2786. @param {any} args - Description for args
  2787. @returns {any} - Result of the operation
  2788. */
  2789. this.execute = function (params, selectorParams, args) {
  2790. if (params !== undefined && params !== null) {
  2791. if (typeof params == 'string')
  2792. params = self.replaceProperties(params, args);
  2793. let pluginsRequired = self.pluginsRequired(params);
  2794. if (pluginsRequired.length > 0)
  2795. self.pluginsLoader(pluginsRequired, self.do, [params, selectorParams, args]);
  2796. else {
  2797. if (Array.isArray(params))
  2798. for (var obj of params)
  2799. self.do(obj, selectorParams, args);
  2800. else if (typeof params == 'object') {
  2801. if (params.if == undefined || self.if(params.if)) {
  2802. if (self.only(params.roles, params.user)) {
  2803. if (params.tag) {
  2804. var selector = self.selector(params, selectorParams);
  2805. self.extendJsonFromElement(params);
  2806. var newElements = self.createElement(params, selectorParams);
  2807. if (params.matchMedia) {
  2808. for (var mediaEvent in params.matchMedia) {
  2809. self.matchMedia(params.matchMedia[mediaEvent], mediaEvent);
  2810. }
  2811. }
  2812. if (params.html) {
  2813. self.html(params.html, selector, args);
  2814. } else {
  2815. for (var par in params)
  2816. if ((nodes.exclude.indexOf(par) < 0) && (nodes.params.indexOf(par) < 0))
  2817. self.nested({ key: par, obj: params[par], selector: { selector: selector }, args: args });
  2818. }
  2819. self.on(params.on, { selector: selector });
  2820. } else {
  2821. var selector = self.selector(params, selectorParams);
  2822. for (var par in params)
  2823. if ((nodes.exclude.indexOf(par) < 0) && (nodes.params.indexOf(par) < 0))
  2824. self.nested({ key: par, obj: params[par], selector: selector, args: args });
  2825. if (params.on)
  2826. self.on(params.on, { selector: selector });
  2827. }
  2828. }
  2829. }
  2830. } else if (typeof params == 'function')
  2831. return params(selectorParams);
  2832. else
  2833. self.log('can\'t execute: ' + params);
  2834. }
  2835. }
  2836. };
  2837. /*
  2838. Method: callback
  2839. Description: Functionality for callback.
  2840. @param {any} params - Description for params
  2841. @returns {any} - Result of the operation
  2842. */
  2843. this.callback = function (params) {
  2844. if (params) {
  2845. var path = params.to;
  2846. if (params.var) path = 'var ' + params.var;
  2847. let selector;
  2848. let element = params.element;
  2849. if (element && element.isConnected) params.value = self.elementToSelector(element);
  2850. if (path) {
  2851. var context = self.context(path);
  2852. self.element({ path: path, value: params.value, root: context });
  2853. }
  2854. if (params.do)
  2855. self.do(params.do, selector);
  2856. }
  2857. };
  2858. /*
  2859. Method: nested
  2860. Description: Functionality for nested.
  2861. @param {any} params - Description for params
  2862. @returns {any} - Result of the operation
  2863. */
  2864. this.nested = function (params) {
  2865. let pluginsRequired = self.pluginsRequired(params.key);
  2866. if (pluginsRequired.length > 0) {
  2867. self.pluginsLoader(pluginsRequired, self.nested, [params]);
  2868. } else {
  2869. if (params.key.startsWith('set ')) {
  2870. self.setData({ key: params.key.substr(4), value: params.obj });
  2871. } else if (params.key.startsWith('var ') || params.key.startsWith('data ') || params.key.startsWith('set ')) {
  2872. console.log('%cdeprecated key: "' + params.key + '". Use "set key": "value"}', 'color:orange');
  2873. self.setData({ key: params.key, value: params.obj });
  2874. } else {
  2875. var method = self.element({ path: params.key, root: self.methods });
  2876. if (method) {
  2877. self.log('METHOD: ' + params.key, 'grey');
  2878. var methodArgs = params.obj;
  2879. method(methodArgs, params.selector, params.args);
  2880. } else {
  2881. let nested;
  2882. let part;
  2883. var jsonicPart = false;
  2884. if (self.json.parts) {
  2885. part = self.element({ path: self.replaceAll(params.key, ':', '.'), root: self.json.parts });
  2886. }
  2887. if (part) {
  2888. self.log('PART: ' + params.key, 'grey');
  2889. var partObj = params.obj;
  2890. partObj = self.replaceProperties(partObj);
  2891. partObj.selector = partObj.selector || params.selector;
  2892. if (partObj.setup) partObj = partObj.setup;
  2893. nested = self.replacePropertyWithPrefix(part, 'setup', partObj);
  2894. nested = self.replacePropertyWithPrefix(nested, 'arguments', partObj);
  2895. self.extendJsonFromElement(nested);
  2896. self.do(nested, params.selector, partObj);
  2897. } else {
  2898. if (self.json && self.json.functions && params.key && self.json.functions[params.key]) {
  2899. self.log('FUNCTION: ' + params.key, 'grey');
  2900. let args = self.replaceProperties(params.obj, undefined, true);
  2901. if (!args || !Array.isArray(args)) args = [args];
  2902. if (self.json.functions[params.key].requires) {
  2903. let pluginsRequired = [];
  2904. for (let plugin of self.json.functions[params.key].requires) {
  2905. if (!self.pluginsLoaded[plugin])
  2906. pluginsRequired.push({ "name": plugin, version: "" });
  2907. }
  2908. if (pluginsRequired.length > 0)
  2909. self.pluginsLoader(pluginsRequired, self.function, [{ name: params.key, arguments: args }]);
  2910. else {
  2911. self.log('Plugins already loaded: ' + params.key, 'grey');
  2912. self.function({ name: params.key, arguments: args });
  2913. }
  2914. } else {
  2915. self.log('Function without plugin required: ' + params.key, 'grey');
  2916. self.function({ name: params.key, arguments: args });
  2917. }
  2918. } else {
  2919. var windowFunction = self.element({ path: params.key, root: window });
  2920. if (typeof windowFunction === 'function') {
  2921. self.log('WINDOW function: ' + params.key, 'grey');
  2922. windowFunction(self.replaceProperties(params.obj, undefined, true));
  2923. } else if (windowFunction !== undefined) {
  2924. self.log('window.' + params.key + ' is not a function', 'red');
  2925. } else {
  2926. if (params.selector) {
  2927. self.log('TAG: ' + params.key, 'grey');
  2928. let pluginsRequired = self.pluginsRequiredByTag(params.obj, params.key);
  2929. if (pluginsRequired.length > 0) {
  2930. let htmlTagParams = [params.obj, params.selector, params.key];
  2931. self.pluginsLoader(pluginsRequired, self.htmlTag, htmlTagParams);
  2932. } else {
  2933. self.htmlTag(params.obj, params.selector, params.key);
  2934. }
  2935. } else {
  2936. self.log(params.key + ' not found', 'red');
  2937. }
  2938. }
  2939. }
  2940. }
  2941. }
  2942. }
  2943. }
  2944. };
  2945. /*
  2946. Method: setData
  2947. Description: Functionality for setData.
  2948. @param {any} params - Description for params
  2949. @returns {any} - Result of the operation
  2950. */
  2951. this.setData = function (params) {
  2952. let setObj = {};
  2953. setObj[params.key] = params.value;
  2954. self.set(setObj);
  2955. };
  2956. this.partContainers = {};
  2957. /*
  2958. Method: pluginsRequiredByTag
  2959. Description: Functionality for pluginsRequiredByTag.
  2960. @param {any} params - Description for params
  2961. @param {any} tagKey - Description for tagKey
  2962. @returns {any} - Result of the operation
  2963. */
  2964. this.pluginsRequiredByTag = function (params, tagKey) {
  2965. if (self.json.resources) {
  2966. const pluginsTags = self.json.resources.pluginsTags;
  2967. const pluginsAttr = self.json.resources.pluginsAttr;
  2968. var pluginsRequired = [];
  2969. if (pluginsTags[tagKey] && !self.pluginsLoaded[pluginsTags[tagKey].name])
  2970. pluginsRequired.push(pluginsTags[tagKey]);
  2971. if (typeof params == 'string') {
  2972. } else if (typeof params == 'object') {
  2973. var objArray;
  2974. if (Array.isArray(params)) objArray = params; else objArray = [params];
  2975. for (var obj of objArray) {
  2976. if (obj.attr) {
  2977. var attr = 'data-icon';
  2978. if (obj.attr[attr]) {
  2979. if (pluginsAttr[attr] && !self.pluginsLoaded[pluginsAttr[attr].name])
  2980. pluginsRequired.push(pluginsAttr[attr]);
  2981. }
  2982. }
  2983. }
  2984. }
  2985. return pluginsRequired;
  2986. } else {
  2987. return false;
  2988. }
  2989. };
  2990. /*
  2991. Method: calendar
  2992. Description: Functionality for calendar.
  2993. @param {any} params - Description for params
  2994. @param {any} args - Description for args
  2995. @returns {any} - Result of the operation
  2996. */
  2997. this.calendar = function (params, args) {
  2998. const localeName = (self.json.setup.language !== 'en') ? self.json.setup.language : 'en-US';
  2999. let calendarArr, todayIndex;
  3000. if (params.unit) {
  3001. switch (params.unit) {
  3002. case 'month':
  3003. const monthFormat = params.format || 'long';
  3004. var format = new Intl.DateTimeFormat(localeName, { month: monthFormat }).format;
  3005. calendarArr = [...Array(12).keys()].map((m) => format(new Date(Date.UTC(2021, m))));
  3006. todayIndex = new Date().getMonth();
  3007. break;
  3008. case 'weekday':
  3009. const weekdayFormat = params.format || 'long';
  3010. var format = new Intl.DateTimeFormat(localeName, { weekday: weekdayFormat }).format;
  3011. calendarArr = [...Array(7).keys()].map((day) => format(new Date(Date.UTC(2021, 5, day))));
  3012. todayIndex = self.weekday();
  3013. break;
  3014. default:
  3015. self.log('"calendar" function can\'t recognize "unit" parameter');
  3016. self.log(params.unit);
  3017. break;
  3018. }
  3019. if (calendarArr) {
  3020. if (params.index !== undefined) {
  3021. params.index = self.js(params.index);
  3022. let index = Number(self.replaceProperties(params.index, args));
  3023. return calendarArr[index];
  3024. } else {
  3025. return calendarArr[todayIndex];
  3026. }
  3027. } else {
  3028. self.log('"calendar" function can\'t recognize "unit" or "format" parameters');
  3029. }
  3030. } else {
  3031. self.log('"calendar" function requires "unit" parameter');
  3032. }
  3033. };
  3034. /*
  3035. Method: month
  3036. Description: Functionality for month.
  3037. @param {any} params - Description for params
  3038. @param {any} monthFormat = 'long' - Description for monthFormat = 'long'
  3039. @returns {any} - Result of the operation
  3040. */
  3041. this.month = function (params, monthFormat = 'long') {
  3042. const localeName = (self.json.setup.language !== 'en') ? self.json.setup.language : 'en-GB';
  3043. const format = new Intl.DateTimeFormat(localeName, { month: monthFormat }).format;
  3044. const weekdayArr = [...Array(12).keys()].map((m) => format(new Date(Date.UTC(2021, m))));
  3045. if (params !== undefined) {
  3046. var index = Number(self.replaceProperties(params));
  3047. return weekdayArr[index];
  3048. }
  3049. else
  3050. return weekdayArr;
  3051. };
  3052. /*
  3053. Method: weekday
  3054. Description: Functionality for weekday.
  3055. @param {any} params - Description for params
  3056. @param {any} weekdayFormat - Description for weekdayFormat
  3057. @returns {any} - Result of the operation
  3058. */
  3059. this.weekday = function (params, weekdayFormat) {
  3060. const localeName = (self.json.setup.language !== 'en') ? self.json.setup.language : 'en-GB';
  3061. const format = new Intl.DateTimeFormat(localeName, { weekday: weekdayFormat }).format;
  3062. const weekdayArr = [...Array(7).keys()].map((day) => format(new Date(Date.UTC(2021, 5, day))));
  3063. var result;
  3064. if (params !== undefined) {
  3065. var index = Number(self.replaceProperties(params));
  3066. result = weekdayArr[index];
  3067. }
  3068. else
  3069. result = weekdayArr;
  3070. return result;
  3071. };
  3072. /*
  3073. Method: method
  3074. Description: Functionality for method.
  3075. @param {any} params - Description for params
  3076. @param {any} args - Description for args
  3077. @returns {any} - Result of the operation
  3078. */
  3079. this.method = function (params, args) {
  3080. var value;
  3081. if (typeof params == 'string') {
  3082. return self.docElement(params);
  3083. } else {
  3084. if ((params.if == undefined) || self.if(params.if, undefined, args)) {
  3085. if (self.notEmptyObject(params)) {
  3086. var actionKey = Object.keys(params)[0];
  3087. var actionFunction = self.docElement(actionKey);
  3088. var actionValue = params[actionKey];
  3089. if (!Array.isArray(actionValue))
  3090. actionValue = [actionValue];
  3091. if (actionFunction) {
  3092. if (typeof actionFunction == 'function')
  3093. return actionFunction(...actionValue);
  3094. else
  3095. return actionFunction;
  3096. } else {
  3097. self.log('unknown function');
  3098. self.log(params);
  3099. return params;
  3100. }
  3101. } else {
  3102. return undefined;
  3103. }
  3104. }
  3105. }
  3106. };
  3107. /*
  3108. Method: Number
  3109. Description: Functionality for Number.
  3110. @param {any} params - Description for params
  3111. @param {any} args - Description for args
  3112. @returns {any} - Result of the operation
  3113. */
  3114. this.Number = function (params, args) {
  3115. self.log('Number');
  3116. return self.method({ "Number": params }, args);
  3117. };
  3118. /*
  3119. Method: String
  3120. Description: Functionality for String.
  3121. @param {any} params - Description for params
  3122. @param {any} args - Description for args
  3123. @returns {any} - Result of the operation
  3124. */
  3125. this.String = function (params, args) {
  3126. self.log('String');
  3127. return self.method({ "String": params }, args);
  3128. };
  3129. /*
  3130. Method: Math
  3131. Description: Functionality for Math.
  3132. @param {any} params - Description for params
  3133. @param {any} args - Description for args
  3134. @returns {any} - Result of the operation
  3135. */
  3136. this.Math = function (params, args) {
  3137. return self.method(params, args, 'Math');
  3138. };
  3139. /*
  3140. Method: dayjs
  3141. Description: Functionality for dayjs.
  3142. @param {any} params - Description for params
  3143. @param {any} args - Description for args
  3144. @returns {any} - Result of the operation
  3145. */
  3146. this.dayjs = function (params, args) {
  3147. return self.method(params, args, 'dayjs');
  3148. };
  3149. /*
  3150. Method: moment
  3151. Description: Functionality for moment.
  3152. @param {any} params - Description for params
  3153. @param {any} args - Description for args
  3154. @returns {any} - Result of the operation
  3155. */
  3156. this.moment = function (params, args) {
  3157. return self.method(params, args, 'moment');
  3158. };
  3159. /*
  3160. Method: dynamicCss
  3161. Description: Functionality for dynamicCss.
  3162. @param {any} selector - Description for selector
  3163. @param {any} property - Description for property
  3164. @param {any} value - Description for value
  3165. @returns {any} - Result of the operation
  3166. */
  3167. this.dynamicCss = function (selector, property, value) {
  3168. if (value.indexOf('{') >= 0) {
  3169. var resizeData = self.dataStorage.get(element, "resize");
  3170. if (!resizeData) resizeData = {};
  3171. resizeData[property] = value;
  3172. var resizeData = self.dataStorage.set(element, "resize", resizeData);
  3173. if (!self.resizeActions[selector]) self.resizeActions[selector] = {};
  3174. self.resizeActions[selector][property] = value;
  3175. var result = self.replaceProperties(value) || '';
  3176. } else {
  3177. var style = {};
  3178. style[property] = value;
  3179. self.css({
  3180. style: style
  3181. });
  3182. }
  3183. };
  3184. /*
  3185. Method: li
  3186. Description: Functionality for li.
  3187. @param {any} params - Description for params
  3188. @param {any} selectorParams - Description for selectorParams
  3189. @returns {any} - Result of the operation
  3190. */
  3191. this.li = function (params, selectorParams) {
  3192. if (Array.isArray(params)) {
  3193. for (var index in params)
  3194. self.li(params[index], selectorParams);
  3195. } else {
  3196. if (params.items) {
  3197. var itemsArray = (typeof params.items == 'string') ? self.json.items[params.items] : params.items;
  3198. delete params.items;
  3199. for (var index in itemsArray) {
  3200. if (self.only(itemsArray[index].roles))
  3201. self.li(self.replaceItems(params, itemsArray[index]), selectorParams);
  3202. }
  3203. } else {
  3204. if (typeof params == 'string') { params = { html: params }; };
  3205. params.tag = 'li';
  3206. self.do(params, selectorParams);
  3207. }
  3208. }
  3209. };
  3210. /*
  3211. Method: remove
  3212. Description: Functionality for remove.
  3213. @param {any} params - Description for params
  3214. @param {any} selectorParams - Description for selectorParams
  3215. @param {any} args - Description for args
  3216. @returns {any} - Result of the operation
  3217. */
  3218. this.remove = function (params, selectorParams, args) {
  3219. var selector = self.selector(params.selector || self.selector(selectorParams));
  3220. if (selector) {
  3221. var elements = self.queryAll(selector);
  3222. if (elements) {
  3223. elements.forEach(function (element, index) {
  3224. element.remove();
  3225. });
  3226. }
  3227. }
  3228. };
  3229. /*
  3230. Method: dispatchEvent
  3231. Description: Functionality for dispatchEvent.
  3232. @param {any} params - Description for params
  3233. @param {any} selectorParams - Description for selectorParams
  3234. @param {any} args - Description for args
  3235. @returns {any} - Result of the operation
  3236. */
  3237. this.dispatchEvent = function (params, selectorParams, args) {
  3238. var selector = self.selector(params.selector || self.selector(selectorParams));
  3239. if (selector) {
  3240. var elements = self.queryAll(selector);
  3241. if (elements) {
  3242. elements.forEach(function (element, index) {
  3243. element.dispatchEvent(new Event(params.name));
  3244. });
  3245. }
  3246. }
  3247. };
  3248. /*
  3249. Method: html
  3250. Description: Functionality for html.
  3251. @param {any} params - Description for params
  3252. @param {any} selectorParams - Description for selectorParams
  3253. @param {any} args - Description for args
  3254. @returns {any} - Result of the operation
  3255. */
  3256. this.html = function (params, selectorParams, args) {
  3257. if (params) {
  3258. if (Array.isArray(params)) {
  3259. for (var obj of params)
  3260. self.html(obj, selectorParams, args);
  3261. } else {
  3262. var container = self.selector(params.selector || params.container) || self.selector(selectorParams);
  3263. if (container) {
  3264. var element = self.query(container);
  3265. if (element) {
  3266. if (typeof params == 'string') {
  3267. var paramsCompiled = self.replaceProperties(params, args);
  3268. if (paramsCompiled) {
  3269. if (typeof paramsCompiled == 'object') {
  3270. self.do(paramsCompiled, { selector: container }, args);
  3271. } else if (typeof paramsCompiled == 'string') {
  3272. element.innerHTML += paramsCompiled;
  3273. }
  3274. }
  3275. } else {
  3276. if (params.empty || params.do == 'empty') {
  3277. element.innerHTML = '';
  3278. delete params.empty;
  3279. }
  3280. if (params.tag) {
  3281. self.do(params, container, args);
  3282. }
  3283. else if (params.html) {
  3284. var htmlCompiled = self.replaceProperties(params.html, args);
  3285. self.html(htmlCompiled, { selector: container });
  3286. } else if (params.lang) {
  3287. var textLang = params.lang[self.json.setup.language] || params.lang['en'] || params.lang[Object.keys[0]];
  3288. if (Array.isArray(textLang)) {
  3289. var paragraphs = [];
  3290. for (var paragraph of textLang)
  3291. paragraphs.push({ p: paragraph });
  3292. self.html(paragraphs, selectorParams, args);
  3293. }
  3294. else
  3295. element.innerHTML = self.replaceProperties(textLang, args);
  3296. if (element) {
  3297. self.attribute(element, 'data-text', true);
  3298. self.dataStorage.set(element, 'params', params);
  3299. }
  3300. } else if (params.text) {
  3301. element.textContent = self.replaceProperties(params.text, args);
  3302. } else if (params.append) {
  3303. element.innerHTML += self.replaceProperties(params.append, args);
  3304. } else if (params.prepend) {
  3305. element.innerHTML = self.replaceProperties(params.prepend, args) + element.innerHTML;
  3306. } else if (params.blocks) {
  3307. self.blocks(params.blocks, { selector: container }, args);
  3308. } else {
  3309. let nestedParams = self.cloneObject(params);
  3310. if (nestedParams.style) delete nestedParams.style;
  3311. if (nestedParams.attr) delete nestedParams.attr;
  3312. console.warn('UNKNOWN TAG');
  3313. console.warn(params);
  3314. self.do(nestedParams, { selector: container }, args);
  3315. if (element.isConnected) {
  3316. if (params.attr) self.setAttributes(element, params.attr, args);
  3317. if (params.style) self.css(params, selectorParams, args);
  3318. }
  3319. }
  3320. }
  3321. } else {
  3322. }
  3323. } else {
  3324. self.log('"html" object requires selector property', 'red');
  3325. self.log(params);
  3326. }
  3327. }
  3328. } else {
  3329. self.log('"html" object without params');
  3330. }
  3331. };
  3332. /*
  3333. Method: setAttributes
  3334. Description: Functionality for setAttributes.
  3335. @param {any} elements - Description for elements
  3336. @param {any} attrs - Description for attrs
  3337. @param {any} args - Description for args
  3338. @returns {any} - Result of the operation
  3339. */
  3340. this.setAttributes = function (elements, attrs, args) {
  3341. for (var attribute in attrs)
  3342. if (attrs[attribute])
  3343. self.attribute(elements, attribute, self.replaceResult(attrs[attribute], args));
  3344. else
  3345. self.attribute(elements, attribute, "");
  3346. };
  3347. /*
  3348. Method: attribute
  3349. Description: Functionality for attribute.
  3350. @param {any} elements - Description for elements
  3351. @param {any} attrId - Description for attrId
  3352. @param {any} attrValue - Description for attrValue
  3353. @returns {any} - Result of the operation
  3354. */
  3355. this.attribute = function (elements, attrId, attrValue) {
  3356. if (typeof attrValue !== undefined) {
  3357. if (!Array.isArray(elements)) elements = [elements];
  3358. elements.forEach(function (element, index) {
  3359. if (typeof attrValue == 'boolean' && attrValue) {
  3360. element.setAttribute(attrId, "");
  3361. } else {
  3362. element.setAttribute(attrId, self.replaceProperties(attrValue));
  3363. }
  3364. });
  3365. } else {
  3366. if (!Array.isArray(elements))
  3367. return elements.getAttribute(attrId);
  3368. else
  3369. return elements[0].getAttribute(attrId);
  3370. }
  3371. };
  3372. /*
  3373. Method: attr
  3374. Description: Functionality for attr.
  3375. @param {any} params - Description for params
  3376. @param {any} selectorParams - Description for selectorParams
  3377. @param {any} args - Description for args
  3378. @returns {any} - Result of the operation
  3379. */
  3380. this.attr = function (params, selectorParams, args) {
  3381. self.css(self.replaceProperties(params), selectorParams, args);
  3382. };
  3383. /*
  3384. Method: styleElement
  3385. Description: Functionality for styleElement.
  3386. @param {any} params - Description for params
  3387. @param {any} element - Description for element
  3388. @param {any} args - Description for args
  3389. @returns {any} - Result of the operation
  3390. */
  3391. this.styleElement = function (params, element, args) {
  3392. for (var styleName in params) {
  3393. if (styleName.startsWith('--'))
  3394. element.style.setProperty(styleName, self.replaceProperties(params[styleName], args));
  3395. else
  3396. element.style[styleName] = self.replaceProperties(params[styleName], args);
  3397. }
  3398. };
  3399. /*
  3400. Method: css
  3401. Description: Functionality for css.
  3402. @param {any} params - Description for params
  3403. @param {any} selectorParams - Description for selectorParams
  3404. @param {any} args - Description for args
  3405. @returns {any} - Result of the operation
  3406. */
  3407. this.css = function (params, selectorParams, args) {
  3408. if (Array.isArray(params)) {
  3409. for (var obj of params)
  3410. self.css(obj, selectorParams, args);
  3411. } else {
  3412. var selector = self.selector(params.selector || params.container, undefined, true) || self.selector(selectorParams, undefined, true);
  3413. var elements = self.queryAll(selector);
  3414. if (elements) {
  3415. elements.forEach(function (element, index) {
  3416. if (element) {
  3417. if (typeof params.style == 'object') {
  3418. self.styleElement(params.style, element, args);
  3419. }
  3420. if (params.addClass)
  3421. self.addClass(element, params.addClass);
  3422. if (params.removeClass)
  3423. self.removeClass(element, params.removeClass);
  3424. if (params.toggleClass)
  3425. self.toggleClass(element, params.toggleClass);
  3426. } else {
  3427. self.log('the function "css" can\'t find the selector ' + selector);
  3428. self.log(params);
  3429. self.log(selectorParams);
  3430. }
  3431. });
  3432. } else {
  3433. self.log('"css" function is unable to select: ' + selector);
  3434. self.log('params');
  3435. self.log(params);
  3436. self.log('selectorParams');
  3437. self.log(selectorParams);
  3438. }
  3439. }
  3440. };
  3441. /*
  3442. Method: numberToHour
  3443. Description: Functionality for numberToHour.
  3444. @param {any} data - Description for data
  3445. @returns {any} - Result of the operation
  3446. */
  3447. this.numberToHour = function (data) {
  3448. var fraction = data.value / data.max;
  3449. var dayMin = Math.round(24 * 60 * fraction);
  3450. var hour = parseInt(dayMin / 60);
  3451. var min = dayMin - hour * 60;
  3452. var hourString = String(hour < 10 ? '0' : '') + String(hour);
  3453. var minString = String(min < 10 ? '0' : '') + String(min);
  3454. return hourString + ':' + minString;
  3455. };
  3456. /*
  3457. Method: hourToNumber
  3458. Description: Functionality for hourToNumber.
  3459. @param {any} data - Description for data
  3460. @returns {any} - Result of the operation
  3461. */
  3462. this.hourToNumber = function (data) {
  3463. var timeArr = data.value.split(':');
  3464. var dayMin = (60 * Number(timeArr[0])) + Number(timeArr[1]);
  3465. var fraction = dayMin / (24 * 60);
  3466. return Math.round(fraction * data.max);
  3467. };
  3468. /*
  3469. Method: pannellum
  3470. Description: Functionality for pannellum.
  3471. @param {any} params - Description for params
  3472. @param {any} selectorParams - Description for selectorParams
  3473. @param {any} args - Description for args
  3474. @returns {any} - Result of the operation
  3475. */
  3476. this.pannellum = function (params, selectorParams, args) {
  3477. self.log('pannellum');
  3478. var container = params.selector || params.container;
  3479. var selector = self.selector(container) || self.selector(selectorParams);
  3480. var element = self.query(selector);
  3481. pannellum.viewer(element, params);
  3482. };
  3483. /*
  3484. Method: qrcode
  3485. Description: Functionality for qrcode.
  3486. @param {any} params - Description for params
  3487. @param {any} selectorParams - Description for selectorParams
  3488. @param {any} args - Description for args
  3489. @returns {any} - Result of the operation
  3490. */
  3491. this.qrcode = function (params, selectorParams, args) {
  3492. self.log('qrcode');
  3493. var container = params.selector || params.container;
  3494. var selector = self.selector(container) || self.selector(selectorParams);
  3495. var element = self.query(selector);
  3496. self.log(selector);
  3497. self.log('element');
  3498. self.log(element);
  3499. var QRCodeOptions = {
  3500. text: self.replaceProperties(params.text, args) || 'jsonic.io',
  3501. width: params.size || 128,
  3502. height: params.size || 128,
  3503. useSVG: true,
  3504. colorDark: params.colorDark || '#000000',
  3505. colorLight: params.colorLight || '#ffffff',
  3506. correctLevel: QRCode.CorrectLevel.H
  3507. };
  3508. self.log('QRCodeOptions');
  3509. self.log(QRCodeOptions);
  3510. element.textContent = '';
  3511. var qrcode = new QRCode(element, QRCodeOptions);
  3512. self.log('qrcode');
  3513. self.log(qrcode);
  3514. return qrcode;
  3515. };
  3516. /*
  3517. Method: weekdaysShort
  3518. Description: Functionality for weekdaysShort.
  3519. @param {any} length - Description for length
  3520. @param {any} caseFunction - Description for caseFunction
  3521. @returns {any} - Result of the operation
  3522. */
  3523. this.weekdaysShort = function (length, caseFunction) {
  3524. if (!caseFunction) caseFunction = caseUp;
  3525. var language = 'en';
  3526. var fixoLang = fixo.getFixoLanguage();
  3527. var userLang = fixo.getUserLanguage();
  3528. if (fixo.device) language = fixoLang; else language = userLang;
  3529. var weekDays = self.cloneObject(moment.localeData(language).weekdays());
  3530. weekDays[7] = weekDays[0];
  3531. weekDays.shift();
  3532. for (var i = 0; i < 7; i++) {
  3533. if (length) weekDays[i] = weekDays[i].substr(0, length);
  3534. if (caseFunction) weekDays[i] = caseFunction(weekDays[i]);
  3535. }
  3536. return weekDays;
  3537. };
  3538. /*
  3539. Method: weekDaysToString
  3540. Description: Functionality for weekDaysToString.
  3541. @param {any} days - Description for days
  3542. @returns {any} - Result of the operation
  3543. */
  3544. this.weekDaysToString = function (days) {
  3545. var text = '';
  3546. for (var i in days) {
  3547. if (days[i]) {
  3548. if (text !== '') text += '/';
  3549. text += self.weekdaysShort(3, capitalize)[i];
  3550. }
  3551. }
  3552. return text;
  3553. };
  3554. var sortField;
  3555. /*
  3556. Method: dynamicSort
  3557. Description: Functionality for dynamicSort.
  3558. @param {any} data - Description for data
  3559. @returns {any} - Result of the operation
  3560. */
  3561. var dynamicSort = function (data) {
  3562. var sortOrder = 1;
  3563. if (data.reverse) { sortOrder = -1; }
  3564. sortField = data.field;
  3565. return function (a, b) {
  3566. var result = (a[sortField] < b[sortField]) ? -1 : (a[sortField] > b[sortField]) ? 1 : 0;
  3567. return result * sortOrder;
  3568. };
  3569. };
  3570. /*
  3571. Method: sort
  3572. Description: Functionality for sort.
  3573. @param {any} data - Description for data
  3574. @returns {any} - Result of the operation
  3575. */
  3576. this.sort = function (data) {
  3577. if (data.object !== undefined) {
  3578. if (Array.isArray(data.object)) {
  3579. return data.object.sort(dynamicSort({
  3580. field: data.field,
  3581. reverse: data.reverse
  3582. }));
  3583. } else {
  3584. var arr = self.objectToArray({
  3585. object: data.object,
  3586. add: data.add,
  3587. });
  3588. return arr.sort(dynamicSort({
  3589. field: data.field,
  3590. reverse: data.reverse
  3591. }));
  3592. }
  3593. } else {
  3594. self.log('sort of undefined');
  3595. return [];
  3596. }
  3597. };
  3598. /*
  3599. Method: objectToArray
  3600. Description: Functionality for objectToArray.
  3601. @param {any} data - Description for data
  3602. @returns {any} - Result of the operation
  3603. */
  3604. this.objectToArray = function (data) {
  3605. var arr = [];
  3606. var obj = data.object;
  3607. if (obj !== undefined) {
  3608. for (var key in obj) {
  3609. obj[key].id = key;
  3610. if (data.add) obj[key] = Object.assign(obj[key], data.add);
  3611. arr.push(obj[key]);
  3612. }
  3613. }
  3614. return arr;
  3615. };
  3616. /*
  3617. Method: equal
  3618. Description: Functionality for equal.
  3619. @param {any} obj1 - Description for obj1
  3620. @param {any} obj2 - Description for obj2
  3621. @returns {any} - Result of the operation
  3622. */
  3623. this.equal = function (obj1, obj2) {
  3624. if (obj1 && obj2) {
  3625. return (JSON.stringify(obj1).replace('"', '') == JSON.stringify(obj2).replace('"', ''));
  3626. } else {
  3627. return (obj1 == obj2);
  3628. }
  3629. };
  3630. /*
  3631. Method: escapeRegExp
  3632. Description: Functionality for escapeRegExp.
  3633. @param {any} str - Description for str
  3634. @returns {any} - Result of the operation
  3635. */
  3636. var escapeRegExp = function (str) {
  3637. return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
  3638. };
  3639. /*
  3640. Method: replaceAll
  3641. Description: Functionality for replaceAll.
  3642. @param {any} str - Description for str
  3643. @param {any} find - Description for find
  3644. @param {any} replace - Description for replace
  3645. @returns {any} - Result of the operation
  3646. */
  3647. this.replaceAll = function (str, find, replace) {
  3648. if (str !== undefined) {
  3649. let result;
  3650. if (typeof str == 'string') result = str; else result = JSON.stringify(str);
  3651. if (str) {
  3652. if (find) {
  3653. result = String(str).replace(new RegExp(escapeRegExp(find), 'g'), replace);
  3654. if (typeof str == 'object' && result) return JSON.parse(result);
  3655. else
  3656. return result;
  3657. } else {
  3658. return str;
  3659. }
  3660. }
  3661. } else {
  3662. return str;
  3663. }
  3664. };
  3665. /*
  3666. Method: capitalize
  3667. Description: Functionality for capitalize.
  3668. @param {any} str - Description for str
  3669. @returns {any} - Result of the operation
  3670. */
  3671. this.capitalize = function (str) {
  3672. return str.replace(/\b\w/g, l => l.toUpperCase());
  3673. };
  3674. /*
  3675. Method: getPageName
  3676. Description: Functionality for getPageName.
  3677. @param {any} url - Description for url
  3678. @returns {any} - Result of the operation
  3679. */
  3680. this.getPageName = function (url) {
  3681. var index = url.lastIndexOf("/") + 1;
  3682. var filenameWithExtension = url.substr(index);
  3683. var filename = filenameWithExtension.split(".")[0];
  3684. return filename;
  3685. };
  3686. /*
  3687. Method: goToMainUrl
  3688. Description: Functionality for goToMainUrl.
  3689. @param {any} - No parameters
  3690. @returns {any} - Result of the operation
  3691. */
  3692. this.goToMainUrl = function () {
  3693. window.location = self.mainUrl;
  3694. };
  3695. /*
  3696. Method: getParameterByName
  3697. Description: Functionality for getParameterByName.
  3698. @param {any} name - Description for name
  3699. @param {any} url - Description for url
  3700. @returns {any} - Result of the operation
  3701. */
  3702. this.getParameterByName = function (name, url) {
  3703. if (!url) url = window.location.href;
  3704. name = name.replace(/[\[\]]/g, "\\$&");
  3705. var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), results = regex.exec(url);
  3706. if (!results) return null;
  3707. if (!results[2]) return '';
  3708. return decodeURIComponent(results[2].replace(/\+/g, " "));
  3709. };
  3710. /*
  3711. Method: paramsToObject
  3712. Description: Functionality for paramsToObject.
  3713. @param {any} params - Description for params
  3714. @returns {any} - Result of the operation
  3715. */
  3716. var paramsToObject = function (params) {
  3717. params = params.split('#')[0];
  3718. return JSON.parse('{"' + params.replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') + '"}');
  3719. };
  3720. /*
  3721. Method: objectToParams
  3722. Description: Functionality for objectToParams.
  3723. @param {any} object - Description for object
  3724. @returns {any} - Result of the operation
  3725. */
  3726. var objectToParams = function (object) {
  3727. var str = '';
  3728. for (var key in object) str += '&' + key + '=' + object[key];
  3729. if (str) str = str.substr(1);
  3730. return encodeURI(str);
  3731. };
  3732. /*
  3733. Method: getParams
  3734. Description: Functionality for getParams.
  3735. @param {any} - No parameters
  3736. @returns {any} - Result of the operation
  3737. */
  3738. this.getParams = function () {
  3739. var params = {};
  3740. var url = window.location.href.split('#')[0];
  3741. if (url.indexOf('?') > -1) {
  3742. var urlParams = decodeURI(url.split('?')[1]);
  3743. self.log(urlParams);
  3744. if (urlParams) {
  3745. var k = self.getParameterByName('k', url);
  3746. //self.log(k);
  3747. if (k) {
  3748. params = self.atob(k);
  3749. } else {
  3750. params = paramsToObject(urlParams);
  3751. }
  3752. }
  3753. }
  3754. return params;
  3755. };
  3756. /*
  3757. Method: atob
  3758. Description: Functionality for atob.
  3759. @param {any} k - Description for k
  3760. @returns {any} - Result of the operation
  3761. */
  3762. this.atob = function (k) {
  3763. self.log('atob');
  3764. var params = paramsToObject(atob(k)); // base64 -> query -> object
  3765. // decompress params
  3766. if (params.h) // hotel
  3767. params.h = String(parseInt(String(params.h), 36)); // base36
  3768. if (params.c) // customer
  3769. params.c = String(parseInt(String(params.c), 36)); // base36
  3770. if (params.n) { // phone
  3771. params.n = String(parseInt(String(params.n), 36)); // base36
  3772. params.n = '+' + params.n;
  3773. }
  3774. //if (params.s) params.s = var.services.id[params.s];
  3775. self.log(params);
  3776. return params;
  3777. };
  3778. /*
  3779. Method: btoa
  3780. Description: Functionality for btoa.
  3781. @param {any} params - Description for params
  3782. @returns {any} - Result of the operation
  3783. */
  3784. this.btoa = function (params) {
  3785. self.log('btoa');
  3786. //if (params.s) params.s = var.services.id.indexOf(params.s);
  3787. if (params.h) // hotel
  3788. params.h = Number(params.h).toString(36); // base36
  3789. if (params.c) // customer
  3790. params.c = Number(params.c).toString(36); // base36
  3791. if (params.n) { // phone
  3792. if (params.n.startsWith('+')) params.n = params.n.substr(1);
  3793. params.n = params.n.replace(/ /g, '');
  3794. params.n = params.n.replace(/-/g, '');
  3795. params.n = Number(params.n).toString(36); // base36
  3796. }
  3797. self.log(params);
  3798. return btoa(objectToParams(params)); // query -> base64
  3799. };
  3800. /*
  3801. /*
  3802. Method: encodeNum
  3803. Description: Functionality for encodeNum.
  3804. @param {any} num - Description for num
  3805. @returns {any} - Result of the operation
  3806. */
  3807. var encodeNum = function(num) { // 0..1296 es:customer
  3808. var hex = c.toString(36);
  3809. return c.toString(36);
  3810. }
  3811. /*
  3812. Method: decodeNum
  3813. Description: Functionality for decodeNum.
  3814. @param {any} str - Description for str
  3815. @returns {any} - Result of the operation
  3816. */
  3817. var decodeNum = function(str) {
  3818. return str.parseInt(36); // .length == 1 ? "0" + hex : hex
  3819. }
  3820. */
  3821. /*
  3822. Method: colorToRgba
  3823. Description: Functionality for colorToRgba.
  3824. @param {any} hex - Description for hex
  3825. @param {any} opacity - Description for opacity
  3826. @returns {any} - Result of the operation
  3827. */
  3828. this.colorToRgba = function (hex, opacity) {
  3829. if (hex == 'white') { hex = '#fff'; }
  3830. if (hex == 'black') { hex = '#000'; }
  3831. var c;
  3832. if (/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) {
  3833. c = hex.substring(1).split('');
  3834. if (c.length == 3) {
  3835. c = [c[0], c[0], c[1], c[1], c[2], c[2]];
  3836. }
  3837. c = '0x' + c.join('');
  3838. return 'rgba(' + [(c >> 16) & 255, (c >> 8) & 255, c & 255].join(',') + ',' + opacity + ')';
  3839. } else {
  3840. self.log('Bad Hex:' + hex);
  3841. }
  3842. };
  3843. /*
  3844. Method: hueToRGB
  3845. Description: Functionality for hueToRGB.
  3846. @param {any} m1 - Description for m1
  3847. @param {any} m2 - Description for m2
  3848. @param {any} h - Description for h
  3849. @returns {any} - Result of the operation
  3850. */
  3851. var hueToRGB = function (m1, m2, h) {
  3852. h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h);
  3853. if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
  3854. if (h * 2 < 1) return m2;
  3855. if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6;
  3856. return m1;
  3857. };
  3858. /*
  3859. Method: HSLToRGB
  3860. Description: Functionality for HSLToRGB.
  3861. @param {any} hsl - Description for hsl
  3862. @returns {any} - Result of the operation
  3863. */
  3864. var HSLToRGB = function (hsl) {
  3865. var m1, m2, r, g, b;
  3866. var h = hsl[0], s = hsl[1], l = hsl[2];
  3867. m2 = (l <= 0.5) ? l * (s + 1) : l + s - l * s;
  3868. m1 = l * 2 - m2;
  3869. return [hueToRGB(m1, m2, h + 0.33333),
  3870. hueToRGB(m1, m2, h),
  3871. hueToRGB(m1, m2, h - 0.33333)];
  3872. };
  3873. /*
  3874. Method: packRGB
  3875. Description: Functionality for packRGB.
  3876. @param {any} rgb - Description for rgb
  3877. @returns {any} - Result of the operation
  3878. */
  3879. var packRGB = function (rgb) {
  3880. var r = Math.round(rgb[0] * 255);
  3881. var g = Math.round(rgb[1] * 255);
  3882. var b = Math.round(rgb[2] * 255);
  3883. // '#' +
  3884. return (r < 16 ? '0' : '') + r.toString(16) +
  3885. (g < 16 ? '0' : '') + g.toString(16) +
  3886. (b < 16 ? '0' : '') + b.toString(16);
  3887. };
  3888. /*
  3889. Method: degToRGB
  3890. Description: Functionality for degToRGB.
  3891. @param {any} deg - Description for deg
  3892. @returns {any} - Result of the operation
  3893. */
  3894. this.degToRGB = function (deg) {
  3895. return packRGB(HSLToRGB([deg / 360, 1, 0.5]));
  3896. };
  3897. /*
  3898. Method: stripHtml
  3899. Description: Functionality for stripHtml.
  3900. @param {any} html - Description for html
  3901. @returns {any} - Result of the operation
  3902. */
  3903. this.stripHtml = function (html) {
  3904. var tmp = document.createElement("DIV");
  3905. tmp.innerHTML = html;
  3906. return tmp.textContent || tmp.innerText || "";
  3907. };
  3908. //--------------------------
  3909. // TASK MANAGER
  3910. //--------------------------
  3911. /*
  3912. Method: log
  3913. Description: Functionality for log.
  3914. @param {any} value - Description for value
  3915. @param {any} color - Description for color
  3916. @returns {any} - Result of the operation
  3917. */
  3918. this.log = function (value, color) {
  3919. if (self.json.setup && self.json.setup.log) { // log enabled
  3920. if (typeof value === 'string')
  3921. console.log('%c' + value, 'color:' + color);
  3922. else
  3923. console.log(value);
  3924. }
  3925. };
  3926. /*
  3927. Method: varlog
  3928. Description: Functionality for varlog.
  3929. @param {any} str - Description for str
  3930. @returns {any} - Result of the operation
  3931. */
  3932. var varlog = function (str) {
  3933. self.log(str);
  3934. self.log(window[str]); // 'var' -> var
  3935. };
  3936. /*
  3937. Method: logJson
  3938. Description: Functionality for logJson.
  3939. @param {any} jsonPar - Description for jsonPar
  3940. @returns {any} - Result of the operation
  3941. */
  3942. this.logJson = function (jsonPar) { self.log(JSON.stringify(jsonPar)); };
  3943. /*
  3944. Method: getTimestamp
  3945. Description: Functionality for getTimestamp.
  3946. @param {any} - No parameters
  3947. @returns {any} - Result of the operation
  3948. */
  3949. this.getTimestamp = function () {
  3950. // we need also an API to get the time
  3951. // like .getTime()?
  3952. return Math.floor(Date.now());
  3953. };
  3954. /*
  3955. Method: cloneObject
  3956. Description: Functionality for cloneObject.
  3957. @param {any} obj - Description for obj
  3958. @returns {any} - Result of the operation
  3959. */
  3960. this.cloneObject = function (obj) {
  3961. var newObj = JSON.stringify(obj);
  3962. return self.parse(newObj);
  3963. };
  3964. /*------------------------
  3965. TEXT
  3966. ------------------------*/
  3967. /*
  3968. /*
  3969. Method: caseUp
  3970. Description: Functionality for caseUp.
  3971. @param {any} string - Description for string
  3972. @returns {any} - Result of the operation
  3973. */
  3974. var caseUp = function (string) {
  3975. if (!string) string = '';
  3976. return string.toUpperCase();
  3977. }
  3978. /*
  3979. Method: caseDown
  3980. Description: Functionality for caseDown.
  3981. @param {any} string - Description for string
  3982. @returns {any} - Result of the operation
  3983. */
  3984. var caseDown = function (string) {
  3985. if (!string) string = '';
  3986. return string.toLowerCase();
  3987. }
  3988. /*
  3989. Method: capitalize
  3990. Description: Functionality for capitalize.
  3991. @param {any} string - Description for string
  3992. @returns {any} - Result of the operation
  3993. */
  3994. var capitalize = function(string) {
  3995. if (!string) string = '';
  3996. return self.capitalize(string);
  3997. }
  3998. /*
  3999. Method: text
  4000. Description: Functionality for text.
  4001. @param {any} key - Description for key
  4002. @param {any} caseFunction - Description for caseFunction
  4003. @returns {any} - Result of the operation
  4004. */
  4005. var text = function (key, caseFunction) {
  4006. var t = self.json.text[key] || '';
  4007. if (caseFunction) return caseFunction(t); else return t;
  4008. } */
  4009. /*
  4010. Method: setElement
  4011. Description: Functionality for setElement.
  4012. @param {any} elementString - Description for elementString
  4013. @param {any} elementValue - Description for elementValue
  4014. @returns {any} - Result of the operation
  4015. */
  4016. this.setElement = function (elementString, elementValue) {
  4017. var context = window;
  4018. var namespaces = elementString.split(".");
  4019. var func = namespaces.pop();
  4020. if (namespaces[0] == 'frame') {
  4021. namespaces.shift();
  4022. var frameName = namespaces.shift();
  4023. if (frameName && document.getElementById(frameName) !== null)
  4024. context = document.getElementById(frameName).contentWindow;
  4025. } else if (namespaces[0] == 'admin') { // fixo
  4026. namespaces.shift();
  4027. context = fixoAdmin;
  4028. }
  4029. for (var i = 0; i < namespaces.length; i++) {
  4030. if (context[namespaces[i]]) { // var
  4031. context = context[namespaces[i]];
  4032. } else {
  4033. if (elementValue) // scrittura
  4034. context[namespaces[i]] = {}; // crea contesto inesistente
  4035. }
  4036. }
  4037. context[func] = elementValue;
  4038. };
  4039. /*
  4040. Method: context
  4041. Description: Functionality for context.
  4042. @param {any} path - Description for path
  4043. @returns {any} - Result of the operation
  4044. */
  4045. this.context = function (path) {
  4046. const re = /^(setup|var|data|texts|parts)[\.\s]/; // reserved namespaces
  4047. if (re.test(path)) {
  4048. /* self.log('MATCHED setup|var|data|parts');
  4049. console.log(params); */
  4050. return self.json;
  4051. } else {
  4052. return window;
  4053. }
  4054. };
  4055. /*
  4056. Method: element
  4057. Description: Functionality for element.
  4058. @param {any} params - Description for params
  4059. @returns {any} - Result of the operation
  4060. */
  4061. this.element = function (params) {
  4062. // {root, path, value}
  4063. // in respect to docElement, it includes replaceProperties for path and value
  4064. // but only if value is a string. TO DO: check it
  4065. let context;
  4066. let path = self.replaceProperties(params.path, params.args);
  4067. let value = (params.value && typeof params.value == 'string') ? self.replaceProperties(params.value, params.args) : params.value;
  4068. // NOTE: log error if the params.root is equal to the first element of the path? (window.window works)
  4069. if (!params.root) {
  4070. context = self.context(path);
  4071. } else {
  4072. context = params.root;
  4073. }
  4074. return self.docElement(path, value, context, params.delete);
  4075. //self.log(value);
  4076. /* if (value && typeof value == 'string') {
  4077. if (value.startsWith('js:')) value = self.js(value.substr(3));
  4078. else if (value.startsWith('+=')) value = self.element({path: path}) + self.js(value.substr(2));
  4079. else if (value.startsWith('-=')) value = self.element({path: path}) - self.js(value.substr(2));
  4080. else if (value.startsWith('/=')) value = self.element({path: path}) / self.js(value.substr(2));
  4081. else if (value.startsWith('*=')) value = self.element({path: path}) / self.js(value.substr(2))
  4082. } */
  4083. // self.log(value);
  4084. /* if (value.startsWith('number:')) value = Number(self.js(value.substr(6)));
  4085. alert('dopo number:'+value);
  4086. if (value.startsWith('boolean:')) value = Boolean(self.js(value.substr(7)));
  4087. if (value.startsWith('string:')) value = String(self.js(value.substr(6)));
  4088. if (value.startsWith('+:')) value = self.element({path: path}) + self.js(value.substr(2));
  4089. if (value.startsWith('-:')) value = self.element({path: path}) - self.js(value.substr(2));
  4090. if (value.startsWith('/:')) value = self.element({path: path}) / self.js(value.substr(2));
  4091. if (value.startsWith('*:')) value = self.element({path: path}) / self.js(value.substr(2)); */
  4092. /* // verificare...
  4093. if (value.startsWith('push:')) {var obj = self.docElement(path, undefined, root); return obj.push(value.substr(3));}
  4094. if (value.startsWith('unshift:')) {var obj = self.docElement(path, undefined, root); return obj.unshift(value.substr(3));}
  4095. if (value.startsWith('pop:')) {var obj = self.docElement(path, undefined, root); return obj.pop(value.substr(3));}
  4096. if (value.startsWith('shift:')) {var obj = self.docElement(path, undefined, root); return obj.shift(value.substr(3));} */
  4097. };
  4098. /*
  4099. Method: docElement
  4100. Description: Functionality for docElement.
  4101. @param {any} elementString - Description for elementString
  4102. @param {any} elementValue - Description for elementValue
  4103. @param {any} context - Description for context
  4104. @param {any} elementDelete - Description for elementDelete
  4105. @returns {any} - Result of the operation
  4106. */
  4107. this.docElement = function (elementString, elementValue, context, elementDelete) {
  4108. if (!context) context = window; // TO DO: remove
  4109. var namespaces = elementString.split(/[.\s]+/); // path nodes separed by dot or spaces
  4110. /* console.log('<-------');
  4111. console.log('context');
  4112. console.log(context);
  4113. console.log('path');
  4114. console.log(elementString);
  4115. console.log('value');
  4116. console.log(elementValue);
  4117. console.log('------>');
  4118. */
  4119. var lastElement = namespaces.pop();
  4120. /* if (namespaces[0] == 'self') {
  4121. namespaces.shift();
  4122. context = self;
  4123. } else if (namespaces[0] == 'frame') {
  4124. namespaces.shift();
  4125. var frameName = namespaces.shift();
  4126. if (frameName && document.getElementById(frameName) !== null)
  4127. context = document.getElementById(frameName).contentWindow;
  4128. } */
  4129. /* console.log('namespaces');
  4130. console.log(namespaces); */
  4131. for (var i = 0; i < namespaces.length; i++) {
  4132. if (context[namespaces[i]]) { // var
  4133. context = context[namespaces[i]];
  4134. } else {
  4135. if (elementValue !== undefined && elementValue !== null) { // wants to assign a value
  4136. context[namespaces[i]] = {}; // it create the context context[namespaces[i]] if it doesn't exist
  4137. context = context[namespaces[i]];
  4138. /* self.log('crea context inesistente');
  4139. self.log('namespaces[i]: '+namespaces[i]); */
  4140. /* self.log('elementValue');
  4141. self.log(elementValue);
  4142. self.log('context[namespaces[i]]');
  4143. self.log(context[namespaces[i]]); */
  4144. } else {
  4145. /* self.log(elementString + ' undefined');
  4146. self.log('lastElement:' + lastElement);
  4147. self.log(elementValue); */
  4148. }
  4149. //break; // perché? rendeva impossibile creare un listener su un nodo secondario (solo su app e non su app/dev)
  4150. }
  4151. }
  4152. if (elementValue !== undefined) { // write
  4153. //self.log(lastElement+'='+elementValue);
  4154. if (typeof elementValue == 'string') elementValue = self.js(elementValue); // 1.0.3
  4155. context[lastElement] = elementValue;
  4156. // elementValue can be a js function
  4157. /* self.log('context');
  4158. self.log(context);
  4159. self.log('context[lastElement]');
  4160. self.log(context[lastElement]);
  4161. self.log('====='); */
  4162. }
  4163. if (elementDelete) delete context[lastElement];
  4164. /* self.log('context');
  4165. self.log(context); */
  4166. /* console.log('namespaces');
  4167. console.log(namespaces);
  4168. self.log('lastElement');
  4169. self.log(lastElement);
  4170. self.log('context[lastElement]');
  4171. self.log(context[lastElement]); */
  4172. if (context[lastElement] && context[lastElement].isConnected)
  4173. return self.elementToSelector(context[lastElement]);
  4174. else
  4175. return context[lastElement];
  4176. };
  4177. /*
  4178. /*
  4179. Method: openCloseDropdown
  4180. Description: Functionality for openCloseDropdown.
  4181. @param {any} key - Description for key
  4182. @returns {any} - Result of the operation
  4183. */
  4184. this.openCloseDropdown = function(key) {
  4185. self.log('openCloseDropdown');
  4186. self.log("key");
  4187. self.log(key);
  4188. //$('.dropdown-menu').css('display','none');
  4189. var selector = self.selector({
  4190. "id": "dropdown" +key,
  4191. "class": 'points',
  4192. "value": key,
  4193. });
  4194. self.log("selector");
  4195. self.log(selector);
  4196. if ($(selector + ' > .dropdown-menu').css('display') == 'none') {
  4197. $(selector + ' > .dropdown-menu').css('display', 'block');
  4198. } else {
  4199. $(selector + ' > .dropdown-menu').css('display', 'none');
  4200. }
  4201. } */
  4202. /*
  4203. Method: timeToMs
  4204. Description: Functionality for timeToMs.
  4205. @param {any} string - Description for string
  4206. @returns {any} - Result of the operation
  4207. */
  4208. this.timeToMs = function (string) {
  4209. // bug
  4210. var timeArray = string.match(/(\d+)(\w+)/); // es: 1s / 100ms
  4211. if (timeArray) {
  4212. var value = Number(timeArray[0]);
  4213. var unit = timeArray[1];
  4214. var unitInMs = {
  4215. ms: 1,
  4216. s: 1000,
  4217. m: 1000 * 60,
  4218. h: 1000 * 60 * 60,
  4219. d: 1000 * 60 * 60 * 24,
  4220. milliseconds: 1,
  4221. seconds: 1000,
  4222. minutes: 1000 * 60,
  4223. hours: 1000 * 60 * 60,
  4224. days: 1000 * 60 * 60 * 24
  4225. };
  4226. if (value)
  4227. if (unitInMs[unit])
  4228. return value * unitInMs[unit];
  4229. else
  4230. self.log('wrong unit in the time string [value][unit]: ' + string);
  4231. else
  4232. self.log('wrong value in the time string [value][unit]: ' + string);
  4233. }
  4234. else
  4235. return Number(string);
  4236. };
  4237. this.intervals = {};
  4238. /*
  4239. Method: timer
  4240. Description: Functionality for timer.
  4241. @param {any} params - Description for params
  4242. @param {any} args - Description for args
  4243. @returns {any} - Result of the operation
  4244. */
  4245. this.timer = function (params, args) {
  4246. // can go in "browser.json / functions (JS Browser BOM)
  4247. let name = self.replaceProperties(params.name);
  4248. if (!name)
  4249. name = self.getTimestamp() + Math.random(1000);
  4250. if (params.play !== undefined && params.play == 0) {
  4251. if (self.intervals[name]) {
  4252. self.clearInterval({
  4253. name: name
  4254. }, args);
  4255. }
  4256. if (self.timeouts[name]) {
  4257. self.clearTimeout({
  4258. name: name
  4259. }, args);
  4260. }
  4261. }
  4262. else if (params.every !== undefined) {
  4263. let every = self.replaceProperties(params.every);
  4264. if (every) {
  4265. self.setInterval({
  4266. name: name,
  4267. duration: every,
  4268. do: params.do
  4269. }, args);
  4270. }
  4271. }
  4272. else if (params.after !== undefined) {
  4273. let after = self.replaceProperties(params.after);
  4274. if (after) {
  4275. self.setTimeout({
  4276. name: name,
  4277. duration: after,
  4278. do: params.do
  4279. }, args);
  4280. } else {
  4281. self.do(params.do, null, args);
  4282. }
  4283. }
  4284. };
  4285. /*
  4286. Method: setInterval
  4287. Description: Functionality for setInterval.
  4288. @param {any} params - Description for params
  4289. @param {any} args - Description for args
  4290. @returns {any} - Result of the operation
  4291. */
  4292. this.setInterval = function (params, args) {
  4293. if (params.name && params.duration) {
  4294. if (self.intervals[params.name])
  4295. clearInterval(self.intervals[params.name]);
  4296. self.do(params.do);
  4297. self.intervals[params.name] = setInterval(function () {
  4298. self.do(params.do);
  4299. return params.name;
  4300. }, Number(params.duration));
  4301. }
  4302. else
  4303. self.log('"setInterval" function requires "name" and "duration" parameters');
  4304. };
  4305. /*
  4306. Method: clearInterval
  4307. Description: Functionality for clearInterval.
  4308. @param {any} params - Description for params
  4309. @param {any} args - Description for args
  4310. @returns {any} - Result of the operation
  4311. */
  4312. this.clearInterval = function (params, args) {
  4313. if (self.intervals[params.name]) {
  4314. clearInterval(self.intervals[params.name]);
  4315. delete self.intervals[params.name];
  4316. }
  4317. };
  4318. this.timeouts = {};
  4319. /*
  4320. Method: setTimeout
  4321. Description: Functionality for setTimeout.
  4322. @param {any} params - Description for params
  4323. @param {any} args - Description for args
  4324. @returns {any} - Result of the operation
  4325. */
  4326. this.setTimeout = function (params, args) {
  4327. if (params.name && params.duration) {
  4328. if (self.timeouts[params.name])
  4329. clearInterval(self.timeouts[params.name]);
  4330. self.timeouts[params.name] = setTimeout(function () {
  4331. self.do(params.do);
  4332. return params.name;
  4333. }, Number(params.duration));
  4334. }
  4335. else
  4336. self.log('"setTimeout" function requires "name" and "duration" parameters');
  4337. };
  4338. /*
  4339. Method: clearTimeout
  4340. Description: Functionality for clearTimeout.
  4341. @param {any} params - Description for params
  4342. @param {any} args - Description for args
  4343. @returns {any} - Result of the operation
  4344. */
  4345. this.clearTimeout = function (params, args) {
  4346. if (self.timeouts[params.name]) {
  4347. clearTimeout(self.timeouts[params.name]);
  4348. delete self.timeouts[params.name];
  4349. }
  4350. };
  4351. /*
  4352. Method: on
  4353. Description: Functionality for on.
  4354. @param {any} params - Description for params
  4355. @param {any} selectorParams - Description for selectorParams
  4356. @returns {any} - Result of the operation
  4357. */
  4358. this.on = function (params, selectorParams) {
  4359. var container = (selectorParams) ? self.selector(selectorParams) : params.selector;
  4360. var element;
  4361. if (container) {
  4362. element = self.query(container);
  4363. if (element)
  4364. self.dataStorage.set(element, "onData", { on: params, selector: container });
  4365. else {
  4366. self.log('can\'t find the element "' + container + '" ("on" function)');
  4367. self.log('params');
  4368. self.log(params);
  4369. self.log('selectorParams');
  4370. self.log(selectorParams);
  4371. }
  4372. }
  4373. for (var eventId in params) {
  4374. if (eventId == 'init') {
  4375. self.do(params.init, selectorParams);
  4376. } else if (eventId == 'hashchange') {
  4377. self.onHashChange.push(params.hashchange);
  4378. window.addEventListener('hashchange', function () {
  4379. self.json.setup.page.hash = window.location.hash.substr(1);
  4380. self.do(self.onHashChange);
  4381. self.uiUpdate();
  4382. });
  4383. } else if (eventId == 'scroll') {
  4384. self.onScroll.push(params.scroll);
  4385. window.addEventListener('scroll', function () {
  4386. self.do(self.onScroll);
  4387. });
  4388. } else if (eventId == 'resize') {
  4389. self.onResize.push(params.resize);
  4390. window.addEventListener('resize', function () {
  4391. self.do(self.onResize);
  4392. });
  4393. } else if (eventId == 'in') {
  4394. if (container) {
  4395. const observer = new IntersectionObserver((entries, observer) => {
  4396. entries.forEach(function (entry) {
  4397. if (entry.intersectionRatio == 1) {
  4398. var el = entry.target;
  4399. if (el.getAttribute('in') !== 'true') {
  4400. el.setAttribute('in', 'true');
  4401. self.onEvent(entry.target, { type: 'in' });
  4402. }
  4403. }
  4404. });
  4405. }, {
  4406. rootMargin: '0px',
  4407. threshold: [0, 1]
  4408. });
  4409. observer.observe(self.query(container));
  4410. }
  4411. } else if (eventId == 'inViewport') {
  4412. if (container) {
  4413. const observer = new IntersectionObserver((entries, observer) => {
  4414. entries.forEach(function (entry) {
  4415. if (entry.intersectionRatio > 0) {
  4416. self.onEvent(entry.target, { type: 'inViewport' });
  4417. }
  4418. });
  4419. }, {
  4420. rootMargin: '0px',
  4421. threshold: [0, 1]
  4422. });
  4423. observer.observe(self.query(container));
  4424. }
  4425. } else if (eventId == 'outViewport') {
  4426. const observer = new IntersectionObserver((entries, observer) => {
  4427. entries.forEach(function (entry) {
  4428. if (entry.intersectionRatio == 0) {
  4429. self.onEvent(entry.target, { type: 'outViewport' });
  4430. }
  4431. });
  4432. }, {
  4433. rootMargin: '0px',
  4434. threshold: [0, 1]
  4435. });
  4436. const element = self.query(container);
  4437. observer.observe(element);
  4438. } else if (eventId !== 'selector') {
  4439. if (element) {
  4440. element.addEventListener(eventId, function (event) {
  4441. element.setAttribute('listener', 'true');
  4442. self.onEvent(this, event);
  4443. });
  4444. if (eventId == 'mousedown' || eventId == 'mouseup' || eventId == 'click')
  4445. element.style.cursor = 'pointer';
  4446. }
  4447. }
  4448. }
  4449. };
  4450. /*
  4451. Method: money
  4452. Description: Functionality for money.
  4453. @param {any} value - Description for value
  4454. @returns {any} - Result of the operation
  4455. */
  4456. this.money = function (value) {
  4457. var rounded = Math.round(Number(value) * 100) / 100;
  4458. var string = String(rounded);
  4459. if (rounded == Math.floor(rounded))
  4460. string += ',00';
  4461. string = String(string).replace('.', ',');
  4462. return string;
  4463. };
  4464. /*
  4465. Method: offcanvas
  4466. Description: Functionality for offcanvas.
  4467. @param {any} params - Description for params
  4468. @returns {any} - Result of the operation
  4469. */
  4470. this.offcanvas = function (params) {
  4471. self.log('offcanvas');
  4472. self.log('params');
  4473. self.log(params);
  4474. var container = params.selector || params.container;
  4475. var selector = self.selector(container);
  4476. var element = self.query(selector);
  4477. self.log('offcanvas');
  4478. self.log(params);
  4479. self.log('selector');
  4480. self.log(selector);
  4481. self.log('element');
  4482. self.log(element);
  4483. if (element) {
  4484. if (params.do == 'hide') {
  4485. self.css({
  4486. removeClass: 'show'
  4487. }, params);
  4488. } else {
  4489. new bootstrap.Offcanvas(element).show();
  4490. }
  4491. } else {
  4492. self.log('"offcanvas" method can\'t find the selected element');
  4493. }
  4494. };
  4495. /*
  4496. Method: elementToSelector
  4497. Description: Functionality for elementToSelector.
  4498. @param {any} element - Description for element
  4499. @returns {any} - Result of the operation
  4500. */
  4501. this.elementToSelector = function (element) {
  4502. if (element.id) {
  4503. return '#' + element.id;
  4504. }
  4505. if (element.dataset?.value) {
  4506. const sameDataValue = document.querySelectorAll(`[data-value="${element.dataset.value}"]`);
  4507. if (sameDataValue.length === 1) {
  4508. return `[data-value="${element.dataset.value}"]`;
  4509. }
  4510. }
  4511. if (element.classList && element.classList.length > 0) {
  4512. for (const className of element.classList) {
  4513. if (className) {
  4514. const sameClass = document.querySelectorAll('.' + className);
  4515. if (sameClass.length === 1) {
  4516. return '.' + className;
  4517. }
  4518. }
  4519. }
  4520. }
  4521. const tagName = element.tagName.toLowerCase();
  4522. const sameTag = document.querySelectorAll(tagName);
  4523. if (sameTag.length === 1) {
  4524. return tagName;
  4525. }
  4526. let path = [];
  4527. while (element.parentNode) {
  4528. let selector = element.tagName.toLowerCase();
  4529. const index = Array.from(element.parentNode.children).indexOf(element) + 1;
  4530. selector += `:nth-child(${index})`;
  4531. path.unshift(selector);
  4532. element = element.parentNode;
  4533. }
  4534. return path.join(' > ');
  4535. };
  4536. /*
  4537. Method: onEvent
  4538. Description: Functionality for onEvent.
  4539. @param {any} element - Description for element
  4540. @param {any} event - Description for event
  4541. @returns {any} - Result of the operation
  4542. */
  4543. this.onEvent = function (element, event) {
  4544. var item = self.dataStorage.get(element, 'onData');
  4545. var code = self.dataStorage.get(element, 'code') || '';
  4546. var value = element.getAttribute('data-value');
  4547. var selector = self.elementToSelector(element);
  4548. var eventType = (event.type && item.on) ? item.on[event.type] : undefined;
  4549. var action, specialKey;
  4550. if (item.on) {
  4551. if (event.button == '2' && event.type == 'mousedown') {
  4552. if (item.on['contextmenu'])
  4553. action = item.on['contextmenu'];
  4554. } else if (event.type && item.on[event.type]) {
  4555. var eventAction = item.on[event.type];
  4556. if (eventAction) {
  4557. if (eventAction.shiftKey && event.shiftKey) {
  4558. specialKey = 'shiftKey';
  4559. action = eventAction.shiftKey;
  4560. } else if (eventAction.altKey && event.altKey) {
  4561. specialKey = 'altKey';
  4562. action = eventAction.altKey;
  4563. } else if (eventAction.cmdKey && event.cmdKey) {
  4564. specialKey = 'cmdKey';
  4565. action = eventAction.cmdKey;
  4566. } else if (!eventAction.shiftKey && !eventAction.altKey && !eventAction.cmdKey) {
  4567. action = item.on[event.type];
  4568. }
  4569. }
  4570. }
  4571. }
  4572. if (action) {
  4573. if (event.target) {
  4574. var actionString;
  4575. var targetId = event.target.id;
  4576. var targetClass = event.target.className;
  4577. var targetValue = event.target.dataset.value;
  4578. var targetSelector = event.target.dataset.selector;
  4579. targetSelector = self.replaceAll(targetSelector, '"', '\'');
  4580. action = self.stringify(action);
  4581. if (typeof targetId !== 'string') targetId = '';
  4582. if (typeof targetClass !== 'string') targetClass = '';
  4583. actionString = self.replaceAll(action, '{on:target.id}', targetId);
  4584. actionString = self.replaceAll(actionString, '{on:altKey}', event.altKey);
  4585. actionString = self.replaceAll(actionString, '{on:target.className}', targetClass);
  4586. actionString = self.replaceAll(actionString, '{on:target.data-value}', targetValue);
  4587. actionString = self.replaceAll(actionString, '{on:target.dataset.value}', targetValue);
  4588. actionString = self.replaceAll(actionString, '{on:target.dataset.selector}', targetSelector);
  4589. actionString = self.replaceAll(actionString, '{on:which}', event.which);
  4590. actionString = self.replaceAll(actionString, '{on:clientY}', event.clientY);
  4591. actionString = self.replaceAll(actionString, '{on:clientX}', event.clientX);
  4592. actionString = self.replaceAll(actionString, '{on:value}', targetValue);
  4593. actionString = self.replaceAll(actionString, '{on:dragging}', (event.which > 0));
  4594. if (this.isJson(actionString))
  4595. action = self.parse(actionString);
  4596. else
  4597. action = actionString;
  4598. }
  4599. var args = item.args;
  4600. let specialKeyLog = (specialKey) ? ' + ' + specialKey : '';
  4601. self.do(action, { selector: selector }, args);
  4602. }
  4603. };
  4604. this.pluginsFunctionAvailable = [];
  4605. self.pluginsLoader = function (packs, callback, params) {
  4606. var filesToLoad = [];
  4607. for (pack of packs) {
  4608. if (self.pluginsLoaded[pack.name] == undefined) {
  4609. self.log('require plugin ' + pack.name, 'grey');
  4610. var plugin = self.findPlugin(pack.name);
  4611. let version;
  4612. var pluginsFiles;
  4613. if (plugin) {
  4614. pluginsFiles = plugin.files || plugin;
  4615. version = plugin.version;
  4616. } else {
  4617. pluginsFiles = self.json.resources.pluginsFiles[pack.name];
  4618. version = pack.version;
  4619. }
  4620. self.pluginsLoaded[pack.name] = version;
  4621. if (!Array.isArray(pluginsFiles))
  4622. pluginsFiles = [pluginsFiles];
  4623. for (item of pluginsFiles) {
  4624. var url = self.replaceAll(item.url, '{version}', version);
  4625. if (!self.findUrl(filesToLoad, url))
  4626. filesToLoad.push({ name: item.name, url: url, type: item.type });
  4627. }
  4628. }
  4629. }
  4630. if (filesToLoad.length > 0) {
  4631. let promises = [];
  4632. filesToLoad.forEach(function (item) {
  4633. promises.push(loadPlugin({ name: item.name, url: item.url, type: item.type, rel: item.rel, as: item.as, content: item.content }));
  4634. });
  4635. Promise.all(promises).then(function (files) {
  4636. callback(...params);
  4637. }).catch(function (script) {
  4638. self.log('failed to load error');
  4639. self.log(item);
  4640. self.log(script);
  4641. });
  4642. }
  4643. };
  4644. /*
  4645. Method: pluginsRequired
  4646. Description: Functionality for pluginsRequired.
  4647. @param {any} params - Description for params
  4648. @returns {any} - Result of the operation
  4649. */
  4650. this.pluginsRequired = function (params) {
  4651. if (self.json.resources) {
  4652. const pluginsFunctions = self.json.resources.pluginsFunctions;
  4653. var pluginsRequired = [];
  4654. if (typeof params == 'string') {
  4655. if (pluginsFunctions[params]) {
  4656. if (!self.pluginsLoaded[pluginsFunctions[params].name])
  4657. pluginsRequired.push(pluginsFunctions[params]);
  4658. }
  4659. } else if (typeof params == 'object') {
  4660. var objArray;
  4661. if (Array.isArray(params)) objArray = params; else objArray = [params];
  4662. for (var obj of objArray) {
  4663. for (var key in obj) {
  4664. var mainFunction = (key.indexOf('.') >= 0) ? key.substr(0, key.indexOf('.')) : key;
  4665. if (pluginsFunctions[mainFunction]) {
  4666. if (!self.pluginsLoaded[pluginsFunctions[mainFunction].name])
  4667. pluginsRequired.push(pluginsFunctions[mainFunction]);
  4668. }
  4669. }
  4670. }
  4671. }
  4672. return pluginsRequired;
  4673. } else {
  4674. return [];
  4675. }
  4676. };
  4677. /*
  4678. Method: functionName
  4679. Description: Functionality for functionName.
  4680. @param {any} obj - Description for obj
  4681. @returns {any} - Result of the operation
  4682. */
  4683. this.functionName = function (obj) {
  4684. if (obj == 'object') {
  4685. const name = Object.keys(obj)[0];
  4686. const pluginFunctions = ['database', 'ace', 'moment', 'dayjs'];
  4687. if (pluginFunctions.indexOf(name) >= 0)
  4688. return name;
  4689. }
  4690. };
  4691. /*
  4692. Method: for
  4693. Description: Functionality for for.
  4694. @param {any} params - Description for params
  4695. @param {any} selectorParams - Description for selectorParams
  4696. @param {any} args - Description for args
  4697. @returns {any} - Result of the operation
  4698. */
  4699. this.for = function (params, selectorParams, args) {
  4700. let container = self.selector(params.selector || params.container) || self.selector(selectorParams);
  4701. let itemsName = params.id || params.name;
  4702. if (params.of) {
  4703. var itemsArray = self.replaceProperties(params.of, args);
  4704. if (itemsArray) {
  4705. if (params.html) {
  4706. if (!params.do) params.do = [];
  4707. else if (!Array.isArray(params.do)) params.do = [params.do];
  4708. params.do.push({ html: params.html });
  4709. }
  4710. if (typeof itemsArray == 'object') {
  4711. let indexNum = 0;
  4712. for (var index in itemsArray) {
  4713. var item = itemsArray[index];
  4714. if (typeof item == 'object') {
  4715. item.key = index;
  4716. item.index = index;
  4717. }
  4718. if (typeof item.output == 'object') {
  4719. for (let key in item.output) {
  4720. var output = item.output[key];
  4721. if (typeof output == 'string') {
  4722. output = self.js(output, args);
  4723. } else if (typeof output == 'object') {
  4724. output = self.replaceProperties(output, args);
  4725. }
  4726. item = self.replaceItems(item, output, key);
  4727. }
  4728. }
  4729. if (params.do.length > 0) {
  4730. let objWithIndex = self.cloneObject(params.do);
  4731. if (params.var) {
  4732. self.element({ path: params.var, value: item, root: self.json.var });
  4733. objWithIndex = self.replacePropertyWithPrefix(objWithIndex, 'index:' + params.var, index);
  4734. }
  4735. if (itemsName) {
  4736. objWithIndex = self.replacePropertyWithPrefix(objWithIndex, 'index:' + itemsName, index);
  4737. objWithIndex = self.replacePropertyWithPrefix(objWithIndex, itemsName, item);
  4738. }
  4739. if (params.delay) {
  4740. params.delay = self.replaceProperties(params.delay);
  4741. let forId = params.var || itemsName;
  4742. self.timer({
  4743. name: 't' + forId + index,
  4744. after: indexNum * params.delay,
  4745. do: objWithIndex
  4746. });
  4747. } else {
  4748. self.do(objWithIndex, { selector: container });
  4749. }
  4750. }
  4751. indexNum += 1;
  4752. }
  4753. }
  4754. }
  4755. } else if (params.from !== undefined && params.to !== undefined) {
  4756. var step = self.js(self.replaceProperties(params.step)) || 1;
  4757. var from = self.js(self.replaceProperties(params.from)) || 0;
  4758. var to = self.js(self.replaceProperties(params.to));
  4759. if (to !== undefined) {
  4760. for (var index = Number(from); index <= Number(to); index += Number(step)) {
  4761. if (params.var)
  4762. self.element({ path: params.var, value: index, root: self.json.var });
  4763. var item = self.replaceItems(params, String(index), itemsName);
  4764. if (item.output && typeof item.output == 'object') {
  4765. for (let key in item.output) {
  4766. var output = item.output[key];
  4767. if (typeof output == 'string') {
  4768. output = self.js(output, args);
  4769. } else if (typeof output == 'object') {
  4770. output = self.replaceProperties(output, args);
  4771. }
  4772. item = self.replaceItems(item, output, key);
  4773. }
  4774. }
  4775. if (item.do) {
  4776. params.do = self.replacePropertyWithPrefix(item.do, 'index:' + itemsName, index);
  4777. self.do(item.do, selectorParams, args);
  4778. }
  4779. if (item.html) {
  4780. params.html = self.replacePropertyWithPrefix(item.html, 'index:' + itemsName, index);
  4781. self.html(item.html, selectorParams);
  4782. }
  4783. }
  4784. }
  4785. } else {
  4786. self.log('"for" element requires "value" or "from" and "to" parameters');
  4787. self.log(params);
  4788. }
  4789. };
  4790. /*
  4791. Method: htmlTag
  4792. Description: Functionality for htmlTag.
  4793. @param {any} params - Description for params
  4794. @param {any} selectorParams - Description for selectorParams
  4795. @param {any} tagParam - Description for tagParam
  4796. @param {any} mainParam - Description for mainParam
  4797. @returns {any} - Result of the operation
  4798. */
  4799. this.htmlTag = function (params, selectorParams, tagParam, mainParam) {
  4800. if (Array.isArray(params)) {
  4801. for (var index in params)
  4802. self.htmlTag(params[index], selectorParams, tagParam, mainParam);
  4803. } else {
  4804. let htmlTagSplitter = tagParam.indexOf(' ');
  4805. if (htmlTagSplitter > 0) {
  4806. let tagClass = tagParam.substr(htmlTagSplitter + 1);
  4807. tagParam = tagParam.slice(0, htmlTagSplitter);
  4808. if (tagClass) {
  4809. if (typeof params !== 'object') params = { 'text': String(params) };
  4810. if (!params.attr) params.attr = {};
  4811. let tagArr = tagClass.split(' ');
  4812. var attrClass = '';
  4813. for (let tagProp of tagArr) {
  4814. let tagAttr = new RegExp("([_a-zA-Z]+[_a-zA-Z0-9-]*)=(.+)");
  4815. if (tagAttr.test(tagProp)) {
  4816. let tagPropArr = tagProp.split('=');
  4817. params.attr[tagPropArr[0]] = tagPropArr[1];
  4818. } else {
  4819. attrClass += ' ' + tagProp;
  4820. }
  4821. }
  4822. if (params.attr.class)
  4823. params.attr.class = params.attr.class + attrClass;
  4824. else {
  4825. params.attr.class = attrClass;
  4826. }
  4827. }
  4828. }
  4829. let htmlTagObj = self.createTagParams(params, tagParam, mainParam);
  4830. self.do(htmlTagObj, selectorParams);
  4831. if (params.database) self.addFirebaseTag(self.extend({}, params, selectorParams));
  4832. }
  4833. };
  4834. /*
  4835. Method: createTagParams
  4836. Description: Functionality for createTagParams.
  4837. @param {any} params - Description for params
  4838. @param {any} tagParam - Description for tagParam
  4839. @param {any} mainParam - Description for mainParam
  4840. @returns {any} - Result of the operation
  4841. */
  4842. this.createTagParams = function (params, tagParam, mainParam) {
  4843. if (!mainParam) {
  4844. switch (tagParam) {
  4845. case 'header':
  4846. case 'main':
  4847. case 'footer':
  4848. case 'div':
  4849. case 'p':
  4850. mainParam = 'html';
  4851. break;
  4852. case 'img':
  4853. mainParam = 'src';
  4854. break;
  4855. default:
  4856. mainParam = 'text';
  4857. break;
  4858. }
  4859. }
  4860. var paramsObj = {};
  4861. if (typeof params == 'string') paramsObj[mainParam] = params; else paramsObj = params;
  4862. paramsObj.tag = tagParam;
  4863. return paramsObj;
  4864. };
  4865. this.onResize = [];
  4866. this.onHashChange = [];
  4867. this.onScroll = [];
  4868. /*
  4869. Method: notEmptyObject
  4870. Description: Functionality for notEmptyObject.
  4871. @param {any} obj - Description for obj
  4872. @returns {any} - Result of the operation
  4873. */
  4874. this.notEmptyObject = function (obj) {
  4875. return (obj
  4876. && Object.keys(obj).length > 0);
  4877. };
  4878. /*
  4879. Method: run
  4880. Description: Functionality for run.
  4881. @param {any} params - Description for params
  4882. @param {any} selectorParams - Description for selectorParams
  4883. @param {any} args - Description for args
  4884. @returns {any} - Result of the operation
  4885. */
  4886. this.run = function (params, selectorParams, args) {
  4887. if (Array.isArray(params)) {
  4888. for (var index in params)
  4889. self.run(params[index], selectorParams, args);
  4890. } else {
  4891. var codeToRun;
  4892. if (typeof params == 'object')
  4893. codeToRun = self.cloneObject(params);
  4894. else if (typeof params == 'string')
  4895. codeToRun = self.replaceProperties(params);
  4896. else if (typeof params == 'function')
  4897. return params(args);
  4898. else
  4899. return params;
  4900. if (typeof codeToRun == 'object') {
  4901. var selector = codeToRun.selector || codeToRun.container;
  4902. if (!selector) selector = selectorParams;
  4903. if (typeof selector == 'string') selector = { selector: selector };
  4904. var actions = {};
  4905. for (key in codeToRun) {
  4906. if (nodes.extend.indexOf(key) >= 0) {
  4907. var obj = {};
  4908. obj[key] = codeToRun[key];
  4909. self.extendJson(self.json, obj);
  4910. } else if (['setup', 'container', 'selector', 'resources', 'on', 'do'].indexOf(key) < 0)
  4911. actions[key] = codeToRun[key];
  4912. }
  4913. if (codeToRun.on) { self.on(codeToRun.on, selector); }
  4914. if (codeToRun.do) { self.do(codeToRun.do, selector, args); }
  4915. if (self.notEmptyObject(actions)) {
  4916. return self.do(actions, selector, args);
  4917. }
  4918. }
  4919. }
  4920. };
  4921. /*
  4922. Method: inputValue
  4923. Description: Functionality for inputValue.
  4924. @param {any} params - Description for params
  4925. @returns {any} - Result of the operation
  4926. */
  4927. this.inputValue = function (params) {
  4928. var selector = self.selector(params.selector || params.container);
  4929. var element = document.querySelector(selector);
  4930. return element.value;
  4931. };
  4932. this.part =
  4933. /*
  4934. Method: block
  4935. Description: Functionality for block.
  4936. @param {any} params - Description for params
  4937. @param {any} selectorParams - Description for selectorParams
  4938. @param {any} args - Description for args
  4939. @returns {any} - Result of the operation
  4940. */
  4941. this.block = function (params, selectorParams, args) {
  4942. let nested;
  4943. let part;
  4944. let partArguments;
  4945. if (typeof params.do == 'string' && self.json.parts) {
  4946. self.log('PART: ' + params.do, 'brown');
  4947. params.do = self.replaceProperties(params.do);
  4948. if (typeof params.do == 'object')
  4949. part = params.do;
  4950. else
  4951. part = self.element({ path: self.replaceAll(params.do, ':', '.'), root: self.json.parts });
  4952. } else if (typeof params.do == 'object')
  4953. part = params.do;
  4954. if (part) {
  4955. if (params.arguments)
  4956. partArguments = self.replaceProperties(params.arguments);
  4957. if (typeof params.arguments == 'object') {
  4958. partArguments = (params.arguments.setup) ? params.arguments.setup : params.arguments;
  4959. partArguments.selector = partArguments.selector || params.selector;
  4960. }
  4961. nested = self.replacePropertyWithPrefix(part, 'setup', partArguments);
  4962. nested = self.replacePropertyWithPrefix(nested, 'arguments', partArguments);
  4963. self.extendJsonFromElement(nested);
  4964. self.do(nested, params.selector, partArguments);
  4965. }
  4966. };
  4967. /*
  4968. Method: blocks
  4969. Description: Functionality for blocks.
  4970. @param {any} params - Description for params
  4971. @param {any} selectorParams - Description for selectorParams
  4972. @param {any} args - Description for args
  4973. @returns {any} - Result of the operation
  4974. */
  4975. this.blocks = function (params, selectorParams, args) {
  4976. if (Array.isArray(params)) {
  4977. for (var index in params)
  4978. self.blocks(params[index], selectorParams, args);
  4979. } else {
  4980. if (typeof params == 'string') {
  4981. var blockName = self.replaceProperties(params, args);
  4982. var libraryObj = self.element({ path: 'self.json.blocks.' + blockName });
  4983. if (libraryObj)
  4984. self.run(libraryObj, selectorParams, args);
  4985. else
  4986. self.log('library component not found: ' + params);
  4987. } else {
  4988. self.run(params, selectorParams, args);
  4989. }
  4990. }
  4991. };
  4992. /*
  4993. Method: uiUpdate
  4994. Description: Functionality for uiUpdate.
  4995. @param {any} option - Description for option
  4996. @returns {any} - Result of the operation
  4997. */
  4998. this.uiUpdate = function (option) {
  4999. window.dispatchEvent(new Event('resize'));
  5000. };
  5001. /*
  5002. Method: resizeEvent
  5003. Description: Functionality for resizeEvent.
  5004. @param {any} event - Description for event
  5005. @returns {any} - Result of the operation
  5006. */
  5007. this.resizeEvent = function (event) {
  5008. for (var selector in self.resizeActions) {
  5009. var element = self.query(selector);
  5010. for (var property in self.resizeActions[selector]) {
  5011. if (property == 'action') {
  5012. self.do(self.resizeActions[element].action, { selector: selector });
  5013. } else {
  5014. var value = self.resizeActions[selector][property];
  5015. var result = self.replaceProperties(value) || '';
  5016. element.style[property] = result;
  5017. }
  5018. }
  5019. }
  5020. };
  5021. /*
  5022. Method: pageFullScreen
  5023. Description: Functionality for pageFullScreen.
  5024. @param {any} onOff - Description for onOff
  5025. @returns {any} - Result of the operation
  5026. */
  5027. this.pageFullScreen = function (onOff) {
  5028. self.log('pageFullScreen');
  5029. if (onOff)
  5030. self.addClass(document.querySelector('body'), 'fullscreen');
  5031. else
  5032. self.removeClass(document.querySelector('body'), 'fullscreen');
  5033. };
  5034. /*
  5035. Method: link
  5036. Description: Functionality for link.
  5037. @param {any} link - Description for link
  5038. @param {any} args - Description for args
  5039. @returns {any} - Result of the operation
  5040. */
  5041. this.link = function (link, args) {
  5042. link = self.replaceProperties(link, args);
  5043. window.location.href = link;
  5044. };
  5045. /*
  5046. Method: reload
  5047. Description: Functionality for reload.
  5048. @param {any} - No parameters
  5049. @returns {any} - Result of the operation
  5050. */
  5051. this.reload = function () {
  5052. location.reload();
  5053. };
  5054. /*
  5055. Method: gotoHomePage
  5056. Description: Functionality for gotoHomePage.
  5057. @param {any} - No parameters
  5058. @returns {any} - Result of the operation
  5059. */
  5060. this.gotoHomePage = function () {
  5061. self.gotoPage(self.homePage());
  5062. };
  5063. /*
  5064. Method: homePage
  5065. Description: Functionality for homePage.
  5066. @param {any} - No parameters
  5067. @returns {any} - Result of the operation
  5068. */
  5069. this.homePage = function () {
  5070. if (self.json.pages) {
  5071. if (Object.keys(self.json.pages).length > 0) {
  5072. if (self.json.pages.home)
  5073. return 'home';
  5074. else
  5075. return Object.keys(self.json.pages)[0];
  5076. } else {
  5077. self.log('No pages in "pages" node');
  5078. }
  5079. } else {
  5080. self.log('Can\'t find the "pages" node');
  5081. }
  5082. };
  5083. /*
  5084. Method: updateCodeEditors
  5085. Description: Functionality for updateCodeEditors.
  5086. @param {any} - No parameters
  5087. @returns {any} - Result of the operation
  5088. */
  5089. this.updateCodeEditors = function () {
  5090. var elements = document.querySelectorAll('.ace_editor');
  5091. if (elements) {
  5092. elements.forEach(function (element, index) {
  5093. var editor = ace.edit(element);
  5094. editor.renderer.updateFull(true);
  5095. });
  5096. }
  5097. };
  5098. /*
  5099. Method: gotoPage
  5100. Description: Functionality for gotoPage.
  5101. @param {any} pageId - Description for pageId
  5102. @param {any} fromHash - Description for fromHash
  5103. @returns {any} - Result of the operation
  5104. */
  5105. this.gotoPage = function (pageId, fromHash) {
  5106. self.log('page');
  5107. self.log('pageId');
  5108. self.log(pageId);
  5109. self.log('fromHash');
  5110. self.log(fromHash);
  5111. if (pageId) {
  5112. if (self.json.pages) {
  5113. if (self.json.pages[pageId]) {
  5114. var page = self.json.pages[pageId];
  5115. if (pageId !== self.json.setup.page.id || fromHash !== self.json.setup.page.hash) {
  5116. if (fromHash) {
  5117. self.json.setup.page.hash = fromHash;
  5118. } else {
  5119. delete self.json.setup.page.hash;
  5120. }
  5121. var fullScreen = self.json.pages[pageId].fullscreen || false;
  5122. var pageRoles = (page.roles) ? String(page.roles).split(',') : undefined;
  5123. if (self.params.d || !page.roles || pageRoles.indexOf(self.userRole()) >= 0) {
  5124. if (pageId !== self.json.setup.page.id) {
  5125. self.json.setup.page.id = pageId;
  5126. self.json.setup.page.title = page.title;
  5127. self.json.setup.page.roles = page.roles;
  5128. self.hide({
  5129. "class": "page"
  5130. });
  5131. self.in({
  5132. "class": "page",
  5133. "data-value": pageId,
  5134. "transition": "fadeIn"
  5135. });
  5136. self.uiUpdate();
  5137. }
  5138. if (page.update) {
  5139. self.do(page.update);
  5140. }
  5141. if (page.init) self.do(page.init);
  5142. self.log(page);
  5143. if (page.on)
  5144. self.on(page.on, { selector: '.page[data-value=' + pageId + ']' });
  5145. } else {
  5146. if (self.userRole() == 'guest') {
  5147. } else {
  5148. self.alert('Non hai i privilegi per accedere a questa pagina');
  5149. }
  5150. }
  5151. } else {
  5152. }
  5153. } else {
  5154. self.log('Can\'t find the page "' + pageId + '"');
  5155. }
  5156. } else {
  5157. self.log('Can\'t find the main node "pages"');
  5158. }
  5159. } else {
  5160. return self.json.setup.page;
  5161. }
  5162. };
  5163. var alertInterval;
  5164. /*
  5165. Method: getTime
  5166. Description: Functionality for getTime.
  5167. @param {any} ms - Description for ms
  5168. @returns {any} - Result of the operation
  5169. */
  5170. this.getTime = function (ms) {
  5171. var sec = parseInt(ms / 1000);
  5172. var min = parseInt(sec / 60);
  5173. sec = sec - min * 60;
  5174. if (min < 10) min = '0' + min;
  5175. if (sec < 10) sec = '0' + sec;
  5176. return min + ':' + sec;
  5177. };
  5178. /*
  5179. Method: sortablejs
  5180. Description: Functionality for sortablejs.
  5181. @param {any} params - Description for params
  5182. @param {any} selectorParams - Description for selectorParams
  5183. @param {any} args - Description for args
  5184. @returns {any} - Result of the operation
  5185. */
  5186. this.sortablejs = function (params, selectorParams, args) {
  5187. let container = self.selector(params.selector || params.container, undefined, true) || self.selector(selectorParams, undefined, true);
  5188. let query = self.query(container);
  5189. self.log('container');
  5190. self.log(container);
  5191. self.log('query');
  5192. self.log(query);
  5193. var sortable = Sortable.create(query);
  5194. };
  5195. /*
  5196. Method: alert
  5197. Description: Functionality for alert.
  5198. @param {any} params - Description for params
  5199. @param {any} args - Description for args
  5200. @returns {any} - Result of the operation
  5201. */
  5202. this.alert = function (params, args) {
  5203. var paramsReplaced = self.cloneObject(params);
  5204. if (paramsReplaced) {
  5205. if (paramsReplaced.do && paramsReplaced.do !== 'fire') {
  5206. return Swal[paramsReplaced.do](params);
  5207. } else {
  5208. if (typeof paramsReplaced == 'string') paramsReplaced = self.text({ string: paramsReplaced, args: args });
  5209. if (typeof paramsReplaced == 'number') paramsReplaced = String(paramsReplaced);
  5210. if (paramsReplaced.title !== undefined) paramsReplaced.title = self.text({ string: paramsReplaced.title, args: args });
  5211. if (paramsReplaced.html && typeof paramsReplaced.html == 'string') paramsReplaced.html = self.replaceProperties(paramsReplaced.html, args);
  5212. if (paramsReplaced.text !== undefined) paramsReplaced.text = self.text({ string: paramsReplaced.text, args: args });
  5213. if (paramsReplaced.inputValue) paramsReplaced.inputValue = self.text({ string: paramsReplaced.inputValue, args: args });
  5214. if (paramsReplaced.cancelButtonText) paramsReplaced.cancelButtonText = self.text({ string: paramsReplaced.cancelButtonText, args: args });
  5215. if (paramsReplaced.confirmButtonText) paramsReplaced.confirmButtonText = self.text({ string: paramsReplaced.confirmButtonText, args: args });
  5216. if (paramsReplaced.denyButtonText) paramsReplaced.denyButtonText = self.text({ string: paramsReplaced.denyButtonText, args: args });
  5217. if (paramsReplaced.inputPlaceholder) paramsReplaced.inputPlaceholder = self.text({ string: paramsReplaced.inputPlaceholder, args: args });
  5218. if (paramsReplaced.validationMessage) paramsReplaced.validationMessage = self.text({ string: paramsReplaced.validationMessage, args: args });
  5219. if (paramsReplaced.footer) {
  5220. paramsReplaced.footer = self.text({ string: paramsReplaced.footer, args: args });
  5221. }
  5222. if (paramsReplaced.upload) {
  5223. paramsReplaced.html = '<form class="box" method="post" action="" enctype="multipart/form-data"><div class="drop-zone"><div class="drop-zone-caption">' + self.text('dragAndDropFiles') + '</div><span class="btn btn-primary btn-file" style="position: relative"><span>' + self.text('chooseFiles') + '</span><input type="file" accept=".ply, .obj, .stl" class="drop-zone-file" name="files[]"></span></div></form> ';
  5224. }
  5225. alertObj.confirm = paramsReplaced.confirm;
  5226. alertObj.cancel = paramsReplaced.cancel;
  5227. alertObj.deny = paramsReplaced.deny;
  5228. alertObj.on = paramsReplaced.on;
  5229. alertObj.id = paramsReplaced.id;
  5230. delete paramsReplaced.on;
  5231. var alertHtml = paramsReplaced.html || paramsReplaced.blocks;
  5232. if (alertHtml)
  5233. paramsReplaced.html = " ";
  5234. var swalParams = self.replaceProperties(paramsReplaced, args);
  5235. if (paramsReplaced.animate) {
  5236. var animationIn = paramsReplaced.animate.in || paramsReplaced.animate;
  5237. var animationOut = paramsReplaced.animate.out || paramsReplaced.animate;
  5238. if (paramsReplaced.animate.in)
  5239. animationIn = paramsReplaced.animate.in.transition || paramsReplaced.animate.in;
  5240. if (paramsReplaced.animate.out)
  5241. animationOut = paramsReplaced.animate.out.transition || paramsReplaced.animate.out;
  5242. swalParams.showClass = {
  5243. popup: 'animate__animated animate__faster animate__animated animate__' + animationIn
  5244. };
  5245. swalParams.hideClass = {
  5246. popup: 'animate__animated animate__faster animate__animated animate__' + animationOut
  5247. };
  5248. }
  5249. var customIcon;
  5250. if (swalParams.icon) {
  5251. if (typeof swalParams.icon !== 'string') {
  5252. customIcon = self.cloneObject(swalParams.icon);
  5253. delete swalParams.icon;
  5254. }
  5255. }
  5256. delete swalParams.blocks;
  5257. delete swalParams.onUpload;
  5258. delete swalParams.upload;
  5259. if (swalParams.confirm) delete swalParams.confirm;
  5260. if (swalParams.cancel) delete swalParams.cancel;
  5261. if (swalParams.timerProgressBar) {
  5262. swalParams.onBeforeOpen = function () {
  5263. alertInterval = setInterval(() => {
  5264. const content = Swal.getContent();
  5265. if (content) {
  5266. const b = content.querySelector('b');
  5267. if (b) {
  5268. b.textContent = self.getTime(Swal.getTimerLeft());
  5269. }
  5270. }
  5271. }, 100);
  5272. };
  5273. swalParams.onClose = function () {
  5274. clearInterval(alertInterval);
  5275. };
  5276. }
  5277. Swal.fire(swalParams).then((result) => {
  5278. var alertResult = result.value;
  5279. if (alertObj.on) {
  5280. if (alertObj.on.value && result.value) {
  5281. if (alertObj.id) alertValues[alertObj.id] = result.value;
  5282. alertValues.value = result.value;
  5283. setTimeout(function () {
  5284. alertObj.on.value = self.replacePropertyWithPrefix(alertObj.on.value, 'alert', alertValues);
  5285. self.do(alertObj.on.value, undefined, result.value);
  5286. }, 500);
  5287. }
  5288. if (alertObj.on.isConfirmed && result.isConfirmed) {
  5289. if (alertObj.id) alertValues[alertObj.id] = result.isConfirmed;
  5290. alertObj.on.isConfirmed = self.replacePropertyWithPrefix(alertObj.on.isConfirmed, 'alert', alertValues);
  5291. alertObj.on.isConfirmed = self.replacePropertyWithPrefix(alertObj.on.isConfirmed, 'alert', result);
  5292. self.do(alertObj.on.isConfirmed, undefined, result.value);
  5293. }
  5294. if (alertObj.on.isDenied && result.isDenied) {
  5295. alertObj.on.isDenied = self.replacePropertyWithPrefix(alertObj.on.isDenied, 'alert', result);
  5296. self.do(alertObj.on.isDenied, undefined, result.value);
  5297. }
  5298. if (alertObj.on.isDismissed && result.isDismissed) {
  5299. alertObj.on.isDismissed = self.replacePropertyWithPrefix(alertObj.on.isDismissed, 'alert', result);
  5300. self.do(alertObj.on.isDismissed, undefined, result.dismiss);
  5301. }
  5302. console.log('alertValues');
  5303. console.log(alertValues);
  5304. } else {
  5305. }
  5306. });
  5307. if (alertHtml)
  5308. self.do(alertHtml, { selector: '#swal2-html-container' });
  5309. if (customIcon) {
  5310. self.do(customIcon, { selector: '.swal2-icon' });
  5311. self.css({
  5312. selector: '.swal2-icon',
  5313. style: {
  5314. 'border': '0px solid transparent'
  5315. }
  5316. });
  5317. self.show({
  5318. selector: '.swal2-icon'
  5319. });
  5320. }
  5321. if (swalParams.on && swalParams.on.init)
  5322. self.do(swalParams.on.init);
  5323. }
  5324. }
  5325. };
  5326. /*
  5327. Method: findKey
  5328. Description: Functionality for findKey.
  5329. @param {any} obj - Description for obj
  5330. @param {any} key - Description for key
  5331. @returns {any} - Result of the operation
  5332. */
  5333. this.findKey = function (obj, key) {
  5334. return obj.filter(function (item) {
  5335. return Boolean(item[key]);
  5336. });
  5337. };
  5338. /*
  5339. Method: formatBytes
  5340. Description: Functionality for formatBytes.
  5341. @param {any} bytes - Description for bytes
  5342. @param {any} decimals - Description for decimals
  5343. @returns {any} - Result of the operation
  5344. */
  5345. var formatBytes = function (bytes, decimals) {
  5346. if (bytes == 0) return '0 Byte';
  5347. var k = 1000;
  5348. var dm = decimals + 1 || 3;
  5349. var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
  5350. var i = Math.floor(Math.log(bytes) / Math.log(k));
  5351. return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
  5352. };
  5353. /*
  5354. Method: userRole
  5355. Description: Functionality for userRole.
  5356. @param {any} - No parameters
  5357. @returns {any} - Result of the operation
  5358. */
  5359. this.userRole = function () {
  5360. switch (Boolean(self.user('uid'))) {
  5361. case true:
  5362. return 'user';
  5363. break;
  5364. case false:
  5365. return 'guest';
  5366. break;
  5367. }
  5368. };
  5369. /*
  5370. Method: userIn
  5371. Description: Functionality for userIn.
  5372. @param {any} - No parameters
  5373. @returns {any} - Result of the operation
  5374. */
  5375. this.userIn = function () {
  5376. return Boolean(self.user('uid'));
  5377. };
  5378. /*
  5379. Method: userOut
  5380. Description: Functionality for userOut.
  5381. @param {any} - No parameters
  5382. @returns {any} - Result of the operation
  5383. */
  5384. this.userOut = function () {
  5385. return (!self.user('uid'));
  5386. };
  5387. /*
  5388. Method: user
  5389. Description: Functionality for user.
  5390. @param {any} param - Description for param
  5391. @returns {any} - Result of the operation
  5392. */
  5393. this.user = function (param) {
  5394. if (auth && auth.currentUser)
  5395. if (param == 'firstName')
  5396. return self.firstName(auth.currentUser['displayName']);
  5397. else if (auth.currentUser[param])
  5398. return auth.currentUser[param];
  5399. else if (!param)
  5400. return auth.currentUser;
  5401. else
  5402. return undefined;
  5403. else
  5404. return undefined;
  5405. };
  5406. /*
  5407. Method: firstName
  5408. Description: Functionality for firstName.
  5409. @param {any} nameParam - Description for nameParam
  5410. @returns {any} - Result of the operation
  5411. */
  5412. this.firstName = function (nameParam) {
  5413. var firstNameStr = (nameParam) ? nameParam.split(' ')[0] : '';
  5414. return firstNameStr;
  5415. };
  5416. /*
  5417. Method: userUid
  5418. Description: Functionality for userUid.
  5419. @param {any} - No parameters
  5420. @returns {any} - Result of the operation
  5421. */
  5422. this.userUid = function () {
  5423. if (auth) return auth.currentUser.uid;
  5424. else return undefined;
  5425. };
  5426. /*
  5427. Method: userVerified
  5428. Description: Functionality for userVerified.
  5429. @param {any} - No parameters
  5430. @returns {any} - Result of the operation
  5431. */
  5432. this.userVerified = function () {
  5433. if (auth) return auth.currentUser.emailVerified;
  5434. else return undefined;
  5435. };
  5436. /*
  5437. Method: thunkableMessage
  5438. Description: Functionality for thunkableMessage.
  5439. @param {any} message - Description for message
  5440. @param {any} callback - Description for callback
  5441. @returns {any} - Result of the operation
  5442. */
  5443. this.thunkableMessage = function (message, callback) {
  5444. if (callback) callback(message);
  5445. };
  5446. this.onMessage = {
  5447. alert: "test"
  5448. };
  5449. /*
  5450. Method: processMessage
  5451. Description: Functionality for processMessage.
  5452. @param {any} message - Description for message
  5453. @returns {any} - Result of the operation
  5454. */
  5455. this.processMessage = function (message) {
  5456. self.alert('processMessage');
  5457. self.do(self.onMessage, message);
  5458. };
  5459. /*
  5460. Method: thunkable
  5461. Description: Functionality for thunkable.
  5462. @param {any} params - Description for params
  5463. @param {any} args - Description for args
  5464. @returns {any} - Result of the operation
  5465. */
  5466. this.thunkable = function (params, args) {
  5467. if (params.postMessage) {
  5468. var message = self.replaceProperties(params.postMessage, args);
  5469. if (message) {
  5470. try {
  5471. ThunkableWebviewerExtension.postMessage(message);
  5472. } catch (error) {
  5473. }
  5474. }
  5475. else
  5476. self.log('in function "thunkable" "postMessage" parameter is wrong');
  5477. }
  5478. if (params.receiveMessage) {
  5479. self.onMessage = params.receiveMessage;
  5480. try {
  5481. ThunkableWebviewerExtension.receiveMessage(self.processMessage);
  5482. } catch (error) {
  5483. }
  5484. }
  5485. };
  5486. /*
  5487. Method: extendFunctions
  5488. Description: Functionality for extendFunctions.
  5489. @param {any} functions - Description for functions
  5490. @returns {any} - Result of the operation
  5491. */
  5492. this.extendFunctions = function (functions) {
  5493. for (var name in functions) {
  5494. if (functions[name].js) {
  5495. try {
  5496. self.functions[name] = new Function(functions[name].js);
  5497. } catch (error) {
  5498. console.log('ERROR creating function %c' + name, 'color:orange;');
  5499. self.log(functions[name].js);
  5500. self.log(error.message);
  5501. }
  5502. } else {
  5503. self.log(name + ' function requires js property');
  5504. }
  5505. }
  5506. };
  5507. /*
  5508. Method: function
  5509. Description: Functionality for function.
  5510. @param {any} obj - Description for obj
  5511. @param {any} args - Description for args
  5512. @returns {any} - Result of the operation
  5513. */
  5514. this.function = function (obj, args) {
  5515. if (obj.name && obj.js) {
  5516. self.functions[obj.name] = new Function(obj.js);
  5517. } else if (obj.name && !obj.js) {
  5518. if (self.functions[obj.name]) {
  5519. if (!obj.arguments || !Array.isArray(obj.arguments)) obj.arguments = [obj.arguments];
  5520. try {
  5521. return self.functions[obj.name](...obj.arguments);
  5522. } catch (error) {
  5523. console.log('ERROR in function %c' + obj.name, 'color:orange;');
  5524. console.log('obj');
  5525. console.log(obj);
  5526. console.log('function');
  5527. console.log(self.json.functions[obj.name]);
  5528. console.log(error.message);
  5529. }
  5530. } else {
  5531. console.log('ERROR function undefined %c' + obj.name, 'color:orange;');
  5532. }
  5533. } else if (obj.js) {
  5534. if (obj.arguments && Array.isArray(obj.arguments)) {
  5535. return new Function(obj.js).call(null, obj.arguments);
  5536. } else {
  5537. return new Function(obj.js).call(null, obj.arguments);
  5538. }
  5539. }
  5540. };
  5541. this.eval =
  5542. /*
  5543. Method: js
  5544. Description: Functionality for js.
  5545. @param {any} code - Description for code
  5546. @param {any} args - Description for args
  5547. @returns {any} - Result of the operation
  5548. */
  5549. this.js = function (code, args) {
  5550. code = self.replaceProperties(code, args);
  5551. try {
  5552. return eval(code);
  5553. } catch (error) {
  5554. return code;
  5555. }
  5556. };
  5557. /*
  5558. Method: if
  5559. Description: Functionality for if.
  5560. @param {any} params - Description for params
  5561. @param {any} selectorParams - Description for selectorParams
  5562. @param {any} args - Description for args
  5563. @returns {any} - Result of the operation
  5564. */
  5565. this.if = function (params, selectorParams, args) {
  5566. if (typeof params == 'object') {
  5567. var conditionString = 'if';
  5568. var condition;
  5569. if (params.is !== undefined) {
  5570. if (typeof params.is == 'string') {
  5571. let isReplaced = self.replaceProperties(params.is, args, true);
  5572. self.log(isReplaced, 'grey');
  5573. try {
  5574. condition = Boolean(eval(isReplaced));
  5575. self.log(isReplaced + ' is ' + condition, 'grey');
  5576. } catch (error) {
  5577. self.log(isReplaced, 'red');
  5578. self.log('"if" condition wrong', 'red');
  5579. self.log(error, 'red');
  5580. }
  5581. conditionString += ' is ' + params.is;
  5582. } else if (Array.isArray(params.is)) {
  5583. let i = 0;
  5584. params.is[i];
  5585. switch (params.is[i + 1]) {
  5586. case '=': condition = Boolean(eval(params.is[i] + '===' + params.is[i + 2])); break;
  5587. }
  5588. }
  5589. } else if (params.not !== undefined) {
  5590. condition = (!Boolean(eval(self.replaceProperties(params.not, args, true))));
  5591. if (typeof params.not == 'string') conditionString += ' not ' + params.not;
  5592. } else if (params.regexp) {
  5593. const regex = new RegExp(params.regexp);
  5594. condition = Boolean(regex.test(params.string));
  5595. } else if (params.isArray) {
  5596. condition = self.isArray(params.isArray);
  5597. conditionString += 'isArray ' + params.isArray;
  5598. } else if (params.exist) {
  5599. let elementExist = self.element({ path: params.exist });
  5600. condition = (elementExist);
  5601. self.log('"if" exist ' + params.exist, 'grey');
  5602. } else if (params.value && params.in) {
  5603. condition = self.valueInJson(self.replaceProperties(params.in, args, true), self.replaceProperties(params.value));
  5604. self.log('"if" value ' + self.replaceProperties(params.value) + ' in array is ' + condition, 'grey');
  5605. } else if (params.key && params.in) {
  5606. condition = self.keyInJson(self.replaceProperties(params.in, args, true), self.replaceProperties(params.key));
  5607. self.log('"if" key ' + self.replaceProperties(params.key) + ' in object is ' + condition, 'grey');
  5608. } else {
  5609. let selector = self.selector(params.selector || params.container, undefined) || self.selector(selectorParams, undefined);
  5610. if (selector) {
  5611. if (params.exist) {
  5612. condition = Boolean(self.exist(selector));
  5613. conditionString += ' ' + selector + ' exist ' + params.exist;
  5614. }
  5615. if (params.hasClass) {
  5616. var element = self.query(selector);
  5617. condition = Boolean(self.hasClass(element, params.hasClass));
  5618. conditionString += ' ' + selector + ' hasClass ' + params.hasClass;
  5619. }
  5620. if (params.isVisible) {
  5621. var element = self.query(selector);
  5622. condition = Boolean(self.isVisible(element, params.isVisible));
  5623. conditionString += ' ' + selector + ' isVisible';
  5624. }
  5625. if (params.isHidden) {
  5626. var element = self.query(selector);
  5627. condition = Boolean(self.isHidden(element, params.isHidden));
  5628. conditionString += ' ' + selector + ' isHidden';
  5629. }
  5630. if (params.inViewport) {
  5631. var element = self.query(selector);
  5632. condition = Boolean(self.inViewport(element, params.inViewport));
  5633. conditionString += ' ' + selector + ' inViewport';
  5634. }
  5635. if (params.outViewport) {
  5636. var element = self.query(selector);
  5637. condition = Boolean(self.outViewport(element, params.outViewport));
  5638. conditionString += ' ' + selector + ' outViewport';
  5639. }
  5640. if (params.isDisplay) {
  5641. var element = self.query(selector);
  5642. condition = Boolean(self.isDisplay(element, params.isDisplay));
  5643. conditionString += ' ' + selector + ' isDisplay ' + params.isDisplay;
  5644. }
  5645. } else {
  5646. self.log('the "if" function requires "is" or "not" parameter');
  5647. }
  5648. }
  5649. if (condition)
  5650. if (params.then) {
  5651. if (typeof params.then == 'object') {
  5652. return self.do(params.then);
  5653. } if (typeof params.then == 'string') {
  5654. return self.replaceProperties(params.then);
  5655. } else {
  5656. return params.then;
  5657. }
  5658. }
  5659. else
  5660. self.log('the "if" function requires "then" parameter');
  5661. else if (params.else) {
  5662. if (typeof params.else == 'object') {
  5663. return self.do(params.else);
  5664. } if (typeof params.else == 'string') {
  5665. return self.replaceProperties(params.else);
  5666. } else {
  5667. return params.else;
  5668. }
  5669. }
  5670. } else {
  5671. return Boolean(self.js(params, args));
  5672. }
  5673. };
  5674. /*
  5675. Method: switch
  5676. Description: Functionality for switch.
  5677. @param {any} params - Description for params
  5678. @param {any} args - Description for args
  5679. @returns {any} - Result of the operation
  5680. */
  5681. this.switch = function (params, args) {
  5682. var value;
  5683. var answer;
  5684. if (params.expression)
  5685. value = String(self.js(params.expression, args));
  5686. else
  5687. self.log('"switch" function requires "expression" parameter');
  5688. if (params.cases) {
  5689. if (value !== undefined && params.cases[value]) {
  5690. if (typeof params.cases[value] == 'object')
  5691. answer = self.do(params.cases[value], undefined, args);
  5692. else
  5693. answer = params.cases[value];
  5694. } else if (params.cases['default']) {
  5695. self.log('default');
  5696. self.log(params.cases['default']);
  5697. if (typeof params.cases['default'] == 'object')
  5698. answer = self.do(params.cases['default'], undefined, args);
  5699. else
  5700. answer = params.cases['default'];
  5701. }
  5702. } else {
  5703. self.log('"switch" function requires "cases" parameter');
  5704. self.log('answer');
  5705. self.log(answer);
  5706. }
  5707. return answer;
  5708. };
  5709. /*
  5710. Method: delay
  5711. Description: Functionality for delay.
  5712. @param {any} params - Description for params
  5713. @param {any} selector - Description for selector
  5714. @param {any} args - Description for args
  5715. @returns {any} - Result of the operation
  5716. */
  5717. this.delay = function (params, selector, args) {
  5718. self.log('delay');
  5719. self.log('selector');
  5720. self.log(selector);
  5721. var duration = params.duration || 1000;
  5722. duration = Number(self.replaceProperties(duration, args));
  5723. self.log(duration);
  5724. if (params.do) {
  5725. setTimeout(function () {
  5726. self.do(params.do, selector, args);
  5727. }, duration);
  5728. }
  5729. };
  5730. /*
  5731. Method: firebasePasswordReset
  5732. Description: Functionality for firebasePasswordReset.
  5733. @param {any} paramEmail - Description for paramEmail
  5734. @param {any} paramSuccess - Description for paramSuccess
  5735. @param {any} paramError - Description for paramError
  5736. @returns {any} - Result of the operation
  5737. */
  5738. this.firebasePasswordReset = function (paramEmail, paramSuccess, paramError) {
  5739. firebase.auth().useDeviceLanguage();
  5740. auth.sendPasswordResetEmail(paramEmail).then(function () {
  5741. if (paramSuccess) self.do(paramSuccess);
  5742. }).catch(function (error) {
  5743. if (paramError) self.do(paramError, undefined, error.message);
  5744. });
  5745. };
  5746. /*
  5747. Method: firebaseUpdateProfile
  5748. Description: Functionality for firebaseUpdateProfile.
  5749. @param {any} params - Description for params
  5750. @param {any} paramSuccess - Description for paramSuccess
  5751. @param {any} paramError - Description for paramError
  5752. @returns {any} - Result of the operation
  5753. */
  5754. this.firebaseUpdateProfile = function (params, paramSuccess, paramError) {
  5755. self.log('firebaseUpdateProfile');
  5756. self.log(params);
  5757. auth.currentUser.updateProfile(params).then(function () {
  5758. self.log('User Profile Updated Successfully');
  5759. if (paramSuccess) self.do(paramSuccess);
  5760. }).catch(function (error) {
  5761. if (paramError) self.do(paramError, undefined, error.message);
  5762. });
  5763. };
  5764. /*
  5765. Method: firebaseRegister
  5766. Description: Functionality for firebaseRegister.
  5767. @param {any} params - Description for params
  5768. @param {any} success - Description for success
  5769. @param {any} error - Description for error
  5770. @returns {any} - Result of the operation
  5771. */
  5772. this.firebaseRegister = function (params, success, error) {
  5773. if (params.email && params.password) {
  5774. auth.createUserWithEmailAndPassword(params.email, params.password).then(cred => {
  5775. self.log(cred.user);
  5776. var user = firebase.auth().currentUser;
  5777. if (params.success) self.do(params.success);
  5778. }).catch(error => {
  5779. if (params.error) self.do(params.error, undefined, error.message);
  5780. });
  5781. }
  5782. };
  5783. /*
  5784. Method: firebaseLogin
  5785. Description: Functionality for firebaseLogin.
  5786. @param {any} params - Description for params
  5787. @returns {any} - Result of the operation
  5788. */
  5789. this.firebaseLogin = function (params) {
  5790. self.log('firebaseLogin');
  5791. self.log(params);
  5792. if (auth) {
  5793. auth.signInWithEmailAndPassword(String(params.email), String(params.password)).then(cred => {
  5794. var user = firebase.auth().currentUser;
  5795. if (user.emailVerified) {
  5796. if (params.success) self.do(self.replaceResult(params, undefined, cred));
  5797. } else {
  5798. self.sendEmailVerification(params);
  5799. }
  5800. }).catch(error => {
  5801. self.log('error.code');
  5802. self.log(error.code);
  5803. if (params.error) self.do(self.replaceResult(params, undefined, error.message));
  5804. });
  5805. } else {
  5806. }
  5807. };
  5808. /*
  5809. Method: firebaseLogout
  5810. Description: Functionality for firebaseLogout.
  5811. @param {any} params - Description for params
  5812. @returns {any} - Result of the operation
  5813. */
  5814. this.firebaseLogout = function (params) {
  5815. self.log('firebaseLogout');
  5816. firebase.auth().signOut().then(function () {
  5817. self.log('firebaseLogout SUCCESS');
  5818. self.log(params.success);
  5819. if (params.success) {
  5820. localStorage.clear();
  5821. self.do(params.success);
  5822. }
  5823. }).catch(function (error) {
  5824. self.log('firebaseLogout ERROR');
  5825. self.log(error);
  5826. if (params.error) self.do(params.error);
  5827. });
  5828. };
  5829. /*
  5830. Method: sendEmailVerification
  5831. Description: Functionality for sendEmailVerification.
  5832. @param {any} params - Description for params
  5833. @returns {any} - Result of the operation
  5834. */
  5835. this.sendEmailVerification = function (params) {
  5836. self.log('sendEmailVerification');
  5837. var user = firebase.auth().currentUser;
  5838. firebase.auth().languageCode = 'it';
  5839. var successAction = params.success || self.reload;
  5840. user.sendEmailVerification().then(function () {
  5841. firebase.auth().signOut();
  5842. self.alert({
  5843. icon: "success",
  5844. title: "verifyingemail",
  5845. html: "msgverifyingemail",
  5846. showConfirmButton: false,
  5847. confirm: successAction
  5848. });
  5849. });
  5850. };
  5851. /*
  5852. Method: path
  5853. Description: Functionality for path.
  5854. @param {any} pathParams - Description for pathParams
  5855. @param {any} args - Description for args
  5856. @param {any} separatorParam - Description for separatorParam
  5857. @returns {any} - Result of the operation
  5858. */
  5859. this.path = function (pathParams, args, separatorParam) {
  5860. var pathString = '';
  5861. var separator = separatorParam || '/';
  5862. if (typeof pathParams == 'string') {
  5863. pathString = self.replaceProperties(pathParams, args);
  5864. } else {
  5865. for (var index in pathParams) {
  5866. pathObj = pathParams[index];
  5867. if (pathString !== '') pathString += separator;
  5868. if (pathObj.string)
  5869. pathString += String(pathObj.string);
  5870. else if (pathObj.number)
  5871. pathString += Number(pathObj.number);
  5872. else if (pathObj.function)
  5873. pathString += self.doFunctionByName(pathObj.function, window, '');
  5874. }
  5875. }
  5876. return pathString;
  5877. };
  5878. /*
  5879. Method: executeFunctionByName
  5880. Description: Functionality for executeFunctionByName.
  5881. @param {any} functionName - Description for functionName
  5882. @param {any} context - Description for context
  5883. @returns {any} - Result of the operation
  5884. */
  5885. this.executeFunctionByName = function (functionName, context ) {
  5886. if (functionName) {
  5887. var args = [].slice.call(arguments).splice(2);
  5888. var namespaces = functionName.split(".");
  5889. var func = namespaces.pop();
  5890. for (var i = 0; i < namespaces.length; i++) {
  5891. context = context[namespaces[i]];
  5892. }
  5893. if (context[func] !== undefined) {
  5894. return context[func].apply(context, args);
  5895. } else {
  5896. }
  5897. } else {
  5898. self.log('executeFunctionByName');
  5899. self.log('functionName undefined');
  5900. }
  5901. };
  5902. this.functions = {};
  5903. this.methods = {
  5904. run: function (params, container, args) { self.run(params, container, args); },
  5905. delay: function (params, container, args) { self.delay(params, container, args); },
  5906. ajax: function (params, container, args) { self.ajax(params, container, args); },
  5907. do: function (params, container, args) { self.do(params, container, args); },
  5908. module: function (params, container, args) { self.module(params, args); },
  5909. js: function (params, container, args) { self.js(params, args); },
  5910. function: function (params, container, args) { self.function(params, args); },
  5911. dispatchEvent: function (params, container, args) { self.dispatchEvent(params, args); },
  5912. lang: function (params, container, args) { self.lang(params, args); },
  5913. find: function (params, container, args) { self.find(params, args); },
  5914. page: function (params, container, args) { self.page(params, args); },
  5915. for: function (params, container, args) { self.for(params, container, args); },
  5916. if: function (params, container, args) { self.if(params, container, args); },
  5917. switch: function (params, container, args) { self.switch(params, args); },
  5918. set: function (params, container, args) { self.set(params, args); },
  5919. data: {
  5920. set: function (params, args) {
  5921. for (var param in params) {
  5922. var value = params[param];
  5923. if (value) value = self.replaceProperties(value, args);
  5924. if (value && args) value = self.replacePropertyWithPrefix(value, 'result', args);
  5925. self.element({ path: param, value: value });
  5926. }
  5927. },
  5928. get: function (params) {
  5929. return self.element(params);
  5930. },
  5931. delete: function (params, args) {
  5932. var path = self.replaceProperties(params, args);
  5933. alert(path);
  5934. self.objToDelete = self.element({ path: path });
  5935. delete self.objToDelete;
  5936. },
  5937. add: function (params, args) {
  5938. for (var param in params) {
  5939. var path = self.replaceProperties(param, args);
  5940. var value = self.replaceProperties(params[param], args);
  5941. if (value) {
  5942. var obj = self.element({ path: path }) || '';
  5943. obj += String(value);
  5944. self.element({ path: path, value: obj });
  5945. }
  5946. }
  5947. },
  5948. sum: function (params, args) {
  5949. console.log('%cdeprecated key "sum". Use set{x: "{x}+1"}', 'color:orange');
  5950. console.log(params);
  5951. console.log(args);
  5952. for (var param in params) {
  5953. var path = self.replaceProperties(param, args);
  5954. var value = self.replaceProperties(params[param], args);
  5955. if (value) {
  5956. var obj = self.element({ path: path }) || 0;
  5957. obj += Number(value);
  5958. self.element({ path: path, value: obj });
  5959. }
  5960. }
  5961. },
  5962. sub: function (params, args) {
  5963. console.log('%cdeprecated key "sub". Use set{x: "{x}+1"}', 'color:orange');
  5964. console.log(params);
  5965. console.log(args);
  5966. for (var param in params) {
  5967. var path = self.replaceProperties(param, args);
  5968. var value = self.replaceProperties(params[param], args);
  5969. if (value) {
  5970. var obj = self.element({ path: path }) || 0;
  5971. obj -= Number(value);
  5972. self.element({ path: path, value: obj });
  5973. }
  5974. }
  5975. },
  5976. push: function (params, args) {
  5977. for (var param in params) {
  5978. var path = self.replaceProperties(param, args);
  5979. var value = self.replaceProperties(params[param], args);
  5980. if (value) {
  5981. var obj = self.element({ path: path }) || [];
  5982. obj.push(value);
  5983. self.element({ path: path, value: obj });
  5984. }
  5985. }
  5986. }
  5987. },
  5988. text: function (params, container, args) { self.text(params, container, args); },
  5989. html: function (params, container, args) { self.html(params, container, args); },
  5990. attr: function (params, container, args) { self.attr(params, container, args); },
  5991. empty: function (params, container, args) { self.empty(params, args); },
  5992. delete: function (params, args) {
  5993. var path = self.replaceProperties(params, args);
  5994. var obj = self.element({ path: path });
  5995. self.log(JSON.stringify(obj));
  5996. self.element({ path: path, delete: true });
  5997. self.log(obj);
  5998. },
  5999. add: function (params, container, args) {
  6000. for (var param in params) {
  6001. var path = self.replaceProperties(param, args);
  6002. var value = self.replaceProperties(params[param], args);
  6003. if (value) {
  6004. var obj = self.element({ path: path }) || '';
  6005. obj += String(value);
  6006. self.element({ path: path, value: obj });
  6007. }
  6008. }
  6009. },
  6010. sum: function (params, container, args) {
  6011. for (var param in params) {
  6012. var path = self.replaceProperties(param, args);
  6013. var value = self.replaceProperties(params[param], args);
  6014. if (value) {
  6015. var obj = self.element({ path: path }) || 0;
  6016. obj += Number(value);
  6017. self.element({ path: path, value: obj });
  6018. }
  6019. }
  6020. },
  6021. sub: function (params, container, args) {
  6022. for (var param in params) {
  6023. var path = self.replaceProperties(param, args);
  6024. var value = self.replaceProperties(params[param], args);
  6025. if (value) {
  6026. var obj = self.element({ path: path }) || 0;
  6027. obj -= Number(value);
  6028. self.element({ path: path, value: obj });
  6029. }
  6030. }
  6031. },
  6032. push: function (params, container, args) {
  6033. for (var param in params) {
  6034. var path = self.replaceProperties(param, args);
  6035. var value = self.replaceProperties(params[param], args);
  6036. if (value) {
  6037. var obj = self.element({ path: path }) || [];
  6038. obj.push(value);
  6039. self.element({ path: path, value: obj });
  6040. self.log('push obj');
  6041. self.log(obj);
  6042. }
  6043. }
  6044. },
  6045. calendar: function (params, container, args) { self.calendar(params, args); },
  6046. array: function (params, container, args) { self.array(params, args); },
  6047. replace: function (params, container, args) { self.replace(params, args); },
  6048. shuffle: function (array) {
  6049. let currentIndex = array.length, randomIndex;
  6050. while (currentIndex != 0) {
  6051. randomIndex = Math.floor(Math.random() * currentIndex);
  6052. currentIndex--;
  6053. [array[currentIndex], array[randomIndex]] = [
  6054. array[randomIndex], array[currentIndex]
  6055. ];
  6056. }
  6057. return array;
  6058. },
  6059. alert: function (params, container, args) { self.alert(params, args); },
  6060. offcanvas: function (params, container, args) { self.offcanvas(params, args); },
  6061. out: function (params, container, args) { self.out(params, container, args); },
  6062. qrcode: function (params, container, args) { self.qrcode(params, container, args); },
  6063. hide: function (params, container, args) { self.hide(params, container, args); },
  6064. show: function (params, container, args) { self.show(params, container, args); },
  6065. toggle: function (params, container, args) { self.toggle(params, container, args); },
  6066. sortablejs: function (params, container, args) { self.sortablejs(params, args); },
  6067. lottie: function (params, container, args) { self.lottie(params, container, args); },
  6068. chart: function (params, container, args) {
  6069. var selector = self.selector(container);
  6070. var element = self.query(selector);
  6071. element.innerHTML = '<canvas width="100%" height="100%"></canvas>';
  6072. const ctx = element.querySelector('canvas');
  6073. const myChart = new Chart(ctx, self.replaceProperties(params));
  6074. },
  6075. animate: function (params, container, args) { self.animate(params, container, args); },
  6076. uiUpdate: function (params, container, args) { self.uiUpdate(params, args); },
  6077. swiper: {
  6078. data: {},
  6079. init: function (params, selector, args) {
  6080. setTimeout(function () {
  6081. console.log('swiper inited');
  6082. console.log(selector || params.selector);
  6083. console.log(params.options);
  6084. var swiperConfig = params.options;
  6085. self.methods.swiper.data[params.name] = new Swiper(self.selector(selector || params.selector), swiperConfig);
  6086. console.log(self.methods.swiper.data[params.name]);
  6087. }, 1000);
  6088. }
  6089. },
  6090. link: function (params, container, args) { self.link(params, args); },
  6091. scroll: function (params, container, args) { self.scroll(params, args); },
  6092. reload: function (params, container, args) { self.reload(params, args); },
  6093. timer: function (params, container, args) { self.timer(params, args); },
  6094. setInterval: function (params, container, args) { self.setInterval(params, args); },
  6095. clearInterval: function (params, container, args) { self.clearInterval(params, args); },
  6096. setTimeout: function (params, container, args) { self.setTimeout(params, args); },
  6097. clearTimeout: function (params, container, args) { self.clearTimeout(params, args); },
  6098. local: {
  6099. set: function (params) {
  6100. for (var param in params) {
  6101. var value = params[param];
  6102. if (value) value = self.replaceProperties(value);
  6103. if (typeof value == 'object') value = JSON.stringify(value);
  6104. localStorage.setItem(param, value);
  6105. }
  6106. },
  6107. get: function (key) {
  6108. var localValue = localStorage.getItem(key);
  6109. if (localValue && self.isJsonString(localValue))
  6110. localValue = JSON.parse(localValue);
  6111. return localValue;
  6112. },
  6113. remove: function (key) {
  6114. localStorage.removeItem(key);
  6115. },
  6116. clear: function () {
  6117. localStorage.clear();
  6118. }
  6119. },
  6120. storage: {
  6121. _storage: new WeakMap(),
  6122. set: function (element, key, obj) {
  6123. if (!self.methods.storage._storage.has(element)) {
  6124. self.methods.storage._storage.set(element, new Map());
  6125. }
  6126. self.methods.storage._storage.get(element).set(key, obj);
  6127. },
  6128. get: function (element, key) {
  6129. return self.methods.storage._storage.get(element).get(key);
  6130. },
  6131. has: function (element, key) {
  6132. return self.methods.storage._storage.has(element) && self.methods.storage._storage.get(element).has(key);
  6133. },
  6134. remove: function (element, key) {
  6135. var ret = self.methods.storage._storage.get(element).delete(key);
  6136. if (!self.methods.storage._storage.get(element).size === 0) {
  6137. self.methods.storage._storage.delete(element);
  6138. }
  6139. return ret;
  6140. }
  6141. },
  6142. choose: function (params, container, args) { self.choose(params, container, args); },
  6143. remove: function (params, container, args) { self.remove(params, container, args); },
  6144. part: function (params, container, args) { self.part(params, container, args); },
  6145. blocks: function (params, container, args) { self.part(params, container, args); },
  6146. block: function (params, container, args) { self.part(params, container, args); },
  6147. ace: function (params, container, args) { self.ace(params, container, args); },
  6148. code: function (params, container, args) { self.code(params, container, args); },
  6149. database: function (params, container, args) { self.database(params, args); },
  6150. firebase: function (params, container, args) { self.firebase(params, args); },
  6151. firebaseEvent: {
  6152. action: function (newObj) {
  6153. var path = newObj.path;
  6154. delete newObj.path;
  6155. document.querySelectorAll('[data-firebase="' + path + '"]').forEach(function (element, index) {
  6156. var pathString = 'self.json.var.db.' + self.replaceAll(element.getAttribute('data-firebase'), '/', '.');
  6157. var dbObj = self.docElement(pathString);
  6158. var firebaseValue = newObj[element.getAttribute('data-value')];
  6159. var template = self.dataStorage.get(element, 'data-template');
  6160. if (element.tagName == 'UL') {
  6161. var liTemplate = template.li || template.template;
  6162. element.innerHTML = '';
  6163. var items = newObj;
  6164. for (itemKey in items) {
  6165. var item = items[itemKey];
  6166. item.key = itemKey;
  6167. var dbParams = self.replaceItems(liTemplate, item, 'item') || '';
  6168. var container = element.getAttribute('data-selector');
  6169. self.li(dbParams, { selector: container });
  6170. }
  6171. } else if (element.tagName == 'SPAN' || element.tagName == 'P') {
  6172. element.textContent = firebaseValue;
  6173. } else if (element.tagName == 'SVG') {
  6174. } else {
  6175. if (template.blocks || template.html) {
  6176. var blocksTemplate = template.html || template.blocks;
  6177. element.innerHTML = '';
  6178. var items = newObj;
  6179. self.log('newObj');
  6180. self.log(newObj);
  6181. for (itemKey in items) {
  6182. var item = items[itemKey];
  6183. item.key = itemKey;
  6184. var dbParams = self.replaceProperties(blocksTemplate, undefined, item) || '';
  6185. self.html(dbParams, { selector: container });
  6186. }
  6187. }
  6188. if (template.init) self.do(template.init);
  6189. }
  6190. });
  6191. }
  6192. },
  6193. auth: {
  6194. init: function (params, container, args) {
  6195. self.log("auth init");
  6196. auth = firebase.auth();
  6197. auth.onAuthStateChanged(user => {
  6198. self.json.var.user = user;
  6199. if (!user) {
  6200. self.log('authStateChanged: GUEST\n');
  6201. } else {
  6202. self.log('authStateChanged: USER\n');
  6203. self.log('name: ' + self.user('displayName') + '\nemail: ' + user.email + '\nuid:' + user.uid);
  6204. }
  6205. self.do(params.onAuthStateChanged);
  6206. });
  6207. },
  6208. sendEmailVerification: function (params, container, args) {
  6209. self.sendEmailVerification(params);
  6210. },
  6211. login: function (params, container, args) {
  6212. self.log('params.auth');
  6213. self.log(params.auth);
  6214. self.log(args);
  6215. var fba = self.replaceProperties(params.auth, args);
  6216. self.log('fba');
  6217. self.log(fba);
  6218. var fbAuth = self.cloneObject(fba);
  6219. self.log('fbAuth');
  6220. self.log(fbAuth);
  6221. if (params.success) fbAuth.success = params.success;
  6222. if (params.error) fbAuth.error = params.error;
  6223. self.firebaseLogin(fbAuth, params.success, params.error);
  6224. },
  6225. register: function (params, container, args) {
  6226. var fbAuth = self.replaceProperties(params.auth, args);
  6227. fbAuth.success = params.success;
  6228. fbAuth.error = params.error;
  6229. self.firebaseRegister(fbAuth, params.success, params.error);
  6230. },
  6231. updateProfile: function (params, container, args) {
  6232. params.profile = self.replaceProperties(params.profile, args);
  6233. self.firebaseUpdateProfile(params.profile, params.success, params.error);
  6234. },
  6235. passwordReset: function (params, container, args) {
  6236. params.email = self.replaceProperties(params.email, args);
  6237. self.firebasePasswordReset(params.email, params.success, params.error);
  6238. },
  6239. logout: function (params, container, args) {
  6240. self.firebaseLogout(params);
  6241. }
  6242. },
  6243. thunkable: function (params, container, args) { self.thunkable(params, args); },
  6244. modelViewer: {
  6245. events: {},
  6246. on: function (params) {
  6247. let container = self.selector(params.selector || params.container);
  6248. let element = self.query(container);
  6249. self.log('modelViewer on');
  6250. self.log('container');
  6251. self.log(container);
  6252. self.log('element');
  6253. self.log(element);
  6254. if (element) {
  6255. self.methods.modelViewer.events[container] = {};
  6256. var event = 'load';
  6257. if (params[event]) {
  6258. self.methods.modelViewer.events[container][event] = params[event];
  6259. self.log('modelViewer element');
  6260. self.log(element);
  6261. element.addEventListener(event, (e) => {
  6262. self.log('modelViewer event');
  6263. self.log(e);
  6264. let container = e.path[0].getAttribute('data-selector');
  6265. self.log(container);
  6266. self.do(self.methods.modelViewer.events[container][e.type]);
  6267. });
  6268. }
  6269. }
  6270. },
  6271. set: function (params) {
  6272. let element = self.query(self.selector(params.selector || params.container));
  6273. if (element) {
  6274. if (params.color) {
  6275. let color = params.color.split(',').map(numberString => parseFloat(numberString));
  6276. self.log('Changing color to: ', color);
  6277. const [material] = element.model.materials;
  6278. material.pbrMetallicRoughness.setBaseColorFactor(color);
  6279. }
  6280. if (params.exposure) element.exposure = params.exposure;
  6281. if (params.shadow) element.shadowIntensity = params.shadow;
  6282. if (params.orientation) element.orientation = params.orientation;
  6283. }
  6284. }
  6285. }
  6286. };
  6287. /*
  6288. Method: googleSignInPopup
  6289. Description: Functionality for googleSignInPopup.
  6290. @param {any} - No parameters
  6291. @returns {any} - Result of the operation
  6292. */
  6293. this.googleSignInPopup = function () {
  6294. self.log('googleSignInPopup');
  6295. var provider = new firebase.auth.GoogleAuthProvider();
  6296. firebase.auth().useDeviceLanguage();
  6297. firebase.auth()
  6298. .signInWithPopup(provider)
  6299. .then((result) => {
  6300. var credential = result.credential;
  6301. var token = credential.accessToken;
  6302. var user = result.user;
  6303. window.location.reload();
  6304. }).catch((error) => {
  6305. var errorCode = error.code;
  6306. var errorMessage = error.message;
  6307. var email = error.email;
  6308. var credential = error.credential;
  6309. });
  6310. };
  6311. /*
  6312. Method: console
  6313. Description: Functionality for console.
  6314. @param {any} params - Description for params
  6315. @param {any} args - Description for args
  6316. @returns {any} - Result of the operation
  6317. */
  6318. this.console = function (params, args) {
  6319. if (typeof params.log == 'string' && params.color) {
  6320. var color = params.color || 'white';
  6321. console.log('%c' + self.replaceProperties(params.log), 'color:' + color);
  6322. } else {
  6323. console.log(self.replaceProperties(params.log || params));
  6324. }
  6325. };
  6326. /*
  6327. Method: module
  6328. Description: Functionality for module.
  6329. @param {any} params - Description for params
  6330. @param {any} args - Description for args
  6331. @returns {any} - Result of the operation
  6332. */
  6333. this.module = function (params, args) {
  6334. if (typeof params == 'string') {
  6335. var nameReplaced = self.replaceProperties(params, args);
  6336. return self.element({ root: self.modules, path: nameReplaced });
  6337. } else {
  6338. if (params.name) {
  6339. if (params.value) {
  6340. var name = self.replaceProperties(params.name, args);
  6341. var value = self.replaceProperties(value, args);
  6342. self.log('module');
  6343. self.log(name);
  6344. self.log('value');
  6345. self.log(value);
  6346. self.log(value.app.html.div.div[0].text.lang.en);
  6347. self.modules[name] = value;
  6348. } else if (params.url) {
  6349. self.addModule(params);
  6350. }
  6351. }
  6352. }
  6353. };
  6354. /*
  6355. Method: db
  6356. Description: Functionality for db.
  6357. @param {any} params - Description for params
  6358. @param {any} args - Description for args
  6359. @returns {any} - Result of the operation
  6360. */
  6361. this.db = function (params, args) {
  6362. self.log('db');
  6363. if (typeof params == 'string') {
  6364. var paramsReplaced = self.replaceProperties(params, args);
  6365. self.log('paramsReplaced');
  6366. self.log(paramsReplaced);
  6367. self.log(self.var('db.' + paramsReplaced, args));
  6368. return self.var('db.' + paramsReplaced, args);
  6369. }
  6370. };
  6371. /*
  6372. Method: firebase
  6373. Description: Functionality for firebase.
  6374. @param {any} params - Description for params
  6375. @param {any} args - Description for args
  6376. @returns {any} - Result of the operation
  6377. */
  6378. this.firebase = function (params, args) {
  6379. if (params.initializeApp) {
  6380. var firebaseConfig = self.replaceProperties(params.initializeApp);
  6381. firebase.initializeApp(firebaseConfig);
  6382. } else {
  6383. self.database(params, args);
  6384. }
  6385. };
  6386. /*
  6387. Method: database
  6388. Description: Functionality for database.
  6389. @param {any} params - Description for params
  6390. @param {any} args - Description for args
  6391. @returns {any} - Result of the operation
  6392. */
  6393. this.database = function (params, args) {
  6394. if (params.do == 'init') {
  6395. database = firebase.database();
  6396. self.log('database');
  6397. self.log(database);
  6398. } else {
  6399. if (database) {
  6400. if (typeof params == 'string') {
  6401. return self.db(params, args);
  6402. } else {
  6403. if (params) {
  6404. if (params.path) {
  6405. params.path = self.path(params.path, args);
  6406. }
  6407. if (params.value) {
  6408. params.value = self.replaceProperties(params.value, args);
  6409. self.log("params.value post replace");
  6410. self.log(params.value);
  6411. }
  6412. if (params.do == 'init') {
  6413. } else if (params.do == 'increase') {
  6414. self.firebaseIncrease(params);
  6415. } else if (params.do == 'get') {
  6416. self.firebaseGet(params.path, function (result) {
  6417. if (result.success) {
  6418. if (result.data) {
  6419. self.log('firebase get SUCCESS');
  6420. self.log(params.success);
  6421. if (params.on && params.on.success) self.do(params.on.success, undefined, result);
  6422. } else {
  6423. self.log('firebase get no result.data ERROR');
  6424. if (params.on && params.on.error) self.do(params.on.error);
  6425. }
  6426. } else {
  6427. self.log('firebase get ERROR');
  6428. if (params.on && params.on.error) self.do(params.on.error, undefined, result);
  6429. }
  6430. });
  6431. } else if (params.do == 'new' && params.value) {
  6432. var newKey = self.getKey(params.path);
  6433. self.firebaseSet(params.path + '/' + newKey, params.value, function (result) {
  6434. if (result.success) {
  6435. self.log('firebase set SUCCESS');
  6436. if (params.on && params.on.success) self.do(params.on.success, undefined, result);
  6437. } else {
  6438. self.log('firebase set ERROR');
  6439. if (params.on && params.on.error) self.do(params.on.error, undefined, result);
  6440. }
  6441. });
  6442. } else if (params.do == 'remove' && params.path) {
  6443. self.firebaseRemove(params.path, function (result) {
  6444. if (result.success) {
  6445. self.log('firebase set SUCCESS');
  6446. if (params.on && params.on.success) self.do(params.on.success, undefined, result);
  6447. } else {
  6448. self.log('firebase set ERROR');
  6449. if (params.on && params.on.error) self.do(params.on.error, undefined, result);
  6450. }
  6451. });
  6452. } else if (params.do == 'addListener') {
  6453. self.firebaseAddListener(params);
  6454. } else if (params.do == 'removeListener') {
  6455. self.firebaseRemoveListener(params);
  6456. } else if (params.do == 'update') {
  6457. if (params.value) {
  6458. self.firebaseUpdate(params.path, params.value, function (result) {
  6459. if (result.success) {
  6460. self.log('firebase update SUCCESS');
  6461. if (params.on && params.on.success) self.do(params.on.success, undefined, result);
  6462. } else {
  6463. self.log('firebase update ERROR');
  6464. if (params.on && params.on.error) self.do(params.on.error, undefined, result);
  6465. }
  6466. });
  6467. } else {
  6468. self.log('data update requires value param');
  6469. }
  6470. } else if (params.do == 'push') {
  6471. if (params.value) {
  6472. self.firebasePush(params.path, params.value, function (result) {
  6473. if (result.success) {
  6474. self.log('firebase push SUCCESS');
  6475. if (params.on && params.on.success) self.do(params.on.success, undefined, result);
  6476. } else {
  6477. self.log('firebase push ERROR');
  6478. if (params.on && params.on.error) self.do(params.on.error, undefined, result);
  6479. }
  6480. });
  6481. } else {
  6482. self.log('data push requires value param');
  6483. }
  6484. } else {
  6485. if (params.value) {
  6486. self.firebaseSet(params.path, params.value, function (result) {
  6487. if (result.success) {
  6488. self.log('firebase set SUCCESS');
  6489. if (params.on && params.on.success) self.do(params.on.success, undefined, result);
  6490. } else {
  6491. self.log('firebase set ERROR');
  6492. if (params.on && params.on.error) self.do(params.on.error, undefined, result);
  6493. }
  6494. });
  6495. }
  6496. }
  6497. }
  6498. }
  6499. } else {
  6500. self.log('"database" function needs to be initialised');
  6501. }
  6502. }
  6503. };
  6504. /*
  6505. Method: ajax
  6506. Description: Functionality for ajax.
  6507. @param {any} params - Description for params
  6508. @param {any} selectorParams - Description for selectorParams
  6509. @param {any} args - Description for args
  6510. @returns {any} - Result of the operation
  6511. */
  6512. this.ajax = function (params, selectorParams, args) {
  6513. if (params.url) {
  6514. var url = self.replaceProperties(params.url, args);
  6515. var data;
  6516. if (params.data)
  6517. data = JSON.stringify(self.replaceProperties(params.data, args));
  6518. var type = params.type || 'POST';
  6519. var request = new XMLHttpRequest();
  6520. request.open(type, url, true);
  6521. request.onload = function () {
  6522. self.log('onload');
  6523. self.log(this);
  6524. if (this.status >= 200 && this.status < 400) {
  6525. var result = {};
  6526. var response = this.response;
  6527. response = response.replace(/(\\\")/g, '&quot;');
  6528. try {
  6529. response = decodeURI(response);
  6530. } catch (error) {
  6531. /* console.log('response');
  6532. console.log(response); */
  6533. console.log('decodeURI error');
  6534. console.log(error);
  6535. }
  6536. result.response = self.parse(response);
  6537. result.status = this.status;
  6538. result.header = this.getAllResponseHeaders().split('\r\n').reduce((resultHeader, current) => {
  6539. let [name, value] = current.split(': ');
  6540. resultHeader[name] = value;
  6541. return resultHeader;
  6542. }, {});
  6543. //} catch (e) {
  6544. //}
  6545. self.log('result');
  6546. self.log(result);
  6547. if (params.success)
  6548. self.do(params.success, undefined, result);
  6549. //self.do(params.success, result);
  6550. //self.do(self.replaceProperty(params.success, 'result', result), result);
  6551. } else {
  6552. // We reached our target server, but it returned an error
  6553. if (params.error)
  6554. self.do(params.error, undefined, 'Server error');
  6555. //self.do(params.error, 'Server error');
  6556. }
  6557. };
  6558. request.onerror = function (error) {
  6559. // There was a connection error of some sort
  6560. self.log('error');
  6561. self.log(error);
  6562. self.log('this');
  6563. self.log(this);
  6564. if (params.error)
  6565. self.do(params.error, undefined, 'Server unavailable');
  6566. //self.do(params.error, 'Server unavailable');
  6567. };
  6568. //request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
  6569. if (data)
  6570. request.send(data);
  6571. else
  6572. request.send();
  6573. } else {
  6574. self.log('ajax method requires url parameter');
  6575. }
  6576. /* $.ajax({
  6577. url: paramsReplaced.url,
  6578. type: params.type || 'post',
  6579. //dataType: 'json', // questo dovrebbe evitare JSON.parse
  6580. //dataType: 'text', // verificare se necessario
  6581. data: paramsReplaced.data || {},
  6582. success: function (result) {
  6583. self.log('ajax');
  6584. self.log('result');
  6585. self.log(result);
  6586. self.do(params.success, result);
  6587. //self.do(data); // in .params dovrebbe andare il resto
  6588. },
  6589. error: function (error) {
  6590. var errorText = error.responseText || error;
  6591. self.do(params.error, errorText);
  6592. //self.do(data); // in .params dovrebbe andare il resto
  6593. }
  6594. }); */
  6595. };
  6596. /* View in fullscreen */
  6597. /*
  6598. Method: openFullscreen
  6599. Description: Functionality for openFullscreen.
  6600. @param {any} id - Description for id
  6601. @returns {any} - Result of the operation
  6602. */
  6603. this.openFullscreen = function (id) {
  6604. var element = document.getElementById(id);
  6605. if (screenfull.isEnabled) {
  6606. screenfull.request(element);
  6607. }
  6608. };
  6609. /*
  6610. /*
  6611. Method: addListener
  6612. Description: Functionality for addListener.
  6613. @param {any} params - Description for params
  6614. @returns {any} - Result of the operation
  6615. */
  6616. this.addListener = function(params) {
  6617. var selector = self.selector(params);
  6618. if (selector)
  6619. $(selector).on(params.event, self.do(params.action));
  6620. //event.stopPropagation();
  6621. } */
  6622. /* Close fullscreen */
  6623. /*
  6624. Method: closeFullscreen
  6625. Description: Functionality for closeFullscreen.
  6626. @param {any} - No parameters
  6627. @returns {any} - Result of the operation
  6628. */
  6629. this.closeFullscreen = function () {
  6630. //document.exitFullscreen();
  6631. screenfull.off('change'); // callback
  6632. };
  6633. /*
  6634. /*
  6635. Method: list
  6636. Description: Functionality for list.
  6637. @param {any} params - Description for params
  6638. @param {any} selectorParams - Description for selectorParams
  6639. @returns {any} - Result of the operation
  6640. */
  6641. this.list = function (params, selectorParams) {
  6642. var container = (selectorParams) ? self.selector(selectorParams) : params.container;
  6643. var selector = self.selector(self.extend({}, params, selectorParams));
  6644. if (selector) {
  6645. if (params.list) params.items = params.list; // retro-compatibilità
  6646. if (params.listAction) $(selector).data('listAction', params.listAction);
  6647. if (params.listClass) $(selector).data('listClass', params.listClass); // ul
  6648. if (params.items) {
  6649. $(selector).empty();
  6650. var index = 0;
  6651. //params.items = self.replaceTags({text:params.items, args:selectorParams});
  6652. //params.items = self.replaceResult(params.items, selectorParams);
  6653. params.items = self.replaceProperties(params.items, selectorParams);
  6654. for (var itemKey in params.items) {
  6655. // da rimuovere id="item'+itemKey+'" href=""
  6656. //self.log('PARAMETRI');
  6657. //self.log(itemKey);
  6658. //self.log(params.items);
  6659. $(selector).append('<li data-index="'+itemKey+'" class="list-group-item"></li>');
  6660. var item = params.items[itemKey];
  6661. //var itemSelector = selector + ' li:eq(' + index + ')';
  6662. var itemSelector = selector + ' li:eq(' + itemKey + ')';
  6663. // Item action
  6664. var itemAction;
  6665. if (item.action)
  6666. itemAction = item.action;
  6667. else if (params.action)
  6668. itemAction = params.action;
  6669. else if ($(selector).data('listAction'))
  6670. itemAction = $(selector).data('listAction');
  6671. item.action = itemAction;
  6672. if (item.action) {
  6673. $(itemSelector).addClass('list-group-item-action');
  6674. $(itemSelector).css('cursor', 'pointer');
  6675. }
  6676. if (item.color) $(itemSelector).css('color', item.color);
  6677. if (item.background) $(itemSelector).css('background', item.background);
  6678. //$(itemSelector).append('<div></div>');
  6679. var itemFields = params.items[itemKey].fields || params.items[itemKey]; // retro-compatibilità
  6680. //self.log('itemFields');
  6681. //self.log(itemFields);
  6682. for (var itemField in itemFields) {
  6683. var field = itemFields[itemField];
  6684. //self.log(field);
  6685. if (itemField == 'icons') {
  6686. self.icons(field, {container: itemSelector});
  6687. } else if ((itemField != 'params') && (itemField != 'action')) { // retro-compatibilità
  6688. $(itemSelector).append('<span data-field="'+itemField+'">'+self.text(itemFields[itemField])+'</span>');
  6689. }
  6690. }
  6691. // action
  6692. if (item.action) {
  6693. $(itemSelector).data('onData', item);
  6694. $(itemSelector).on(self.touch, function (event) {
  6695. event.stopPropagation();
  6696. self.onEvent(this, event);
  6697. });
  6698. }
  6699. // events
  6700. if (item.on) self.on(item.on, {container: selector});
  6701. index++;
  6702. }
  6703. } else if (params.append) {
  6704. // aggiunge una riga alla fine (calcolare path)
  6705. } else if (params.prepend) {
  6706. // aggiunge una riga all'inizio (calcolare path)
  6707. // sballa tutti i dati presenti in var.functions
  6708. // sarebbe meglio mem in data value tutto il json
  6709. // azione
  6710. }
  6711. // List classes
  6712. //if (params.id) $(selector).attr('id', params.id);
  6713. var listClass = $(selector).data('listClass');
  6714. if (listClass) {
  6715. var ulClass = listClass.ul || '';
  6716. var liClass = listClass.li || '';
  6717. $(selector).addClass(ulClass);
  6718. $(selector + ' > li').addClass(liClass);
  6719. var index = 0;
  6720. for (var field in listClass.fields) {
  6721. var fieldClass = listClass.fields[field] || '';
  6722. $(selector + ' > li > span[data-field='+field+']').addClass(fieldClass);
  6723. index++;
  6724. }
  6725. }
  6726. }
  6727. } */
  6728. /*
  6729. Method: scroll
  6730. Description: Functionality for scroll.
  6731. @param {any} params - Description for params
  6732. @returns {any} - Result of the operation
  6733. */
  6734. this.scroll = function (params) {
  6735. // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
  6736. // {id, class, value}
  6737. var selector = self.selector(params.selector || params.container);
  6738. var block = document.querySelector(selector);
  6739. //var offset = elem.dataset.offset ? parseInt(elem.dataset.offset) : 0;
  6740. if (block) {
  6741. var bodyOffset = document.body.getBoundingClientRect().top;
  6742. window.scrollTo({
  6743. top: block.getBoundingClientRect().top - bodyOffset, // + offset,
  6744. behavior: 'smooth'
  6745. });
  6746. } else {
  6747. self.log('scroll to unknown element: ' + selector);
  6748. }
  6749. };
  6750. /*
  6751. /*
  6752. Method: scroll
  6753. Description: Functionality for scroll.
  6754. @param {any} params - Description for params
  6755. @returns {any} - Result of the operation
  6756. */
  6757. this.scroll = function (params) {
  6758. // var selector = self.selector(params);
  6759. //var obj = $(selector).get(0);
  6760. var selector = "g."+params.class+".myLabelStyle."+params.value;
  6761. //var parent = $(selector).parent().get(0);
  6762. //document.querySelector(selector).scrollIntoView();
  6763. //self.resizeEvent(); // bug workaround
  6764. //$(selector).parent().scrollTop($(selector).position().top);
  6765. $(selector).parent().animate({
  6766. //scrollTop: $(selector).position().top
  6767. //scrollTop: $(selector).position().top,
  6768. transform: 'translate(0,-'+$(selector).position().top+'), scale(1)'
  6769. });
  6770. }
  6771. */
  6772. //------------------------
  6773. /*
  6774. /*
  6775. Method: do
  6776. Description: Functionality for do.
  6777. @param {any} data - Description for data
  6778. @param {any} args - Description for args
  6779. @returns {any} - Result of the operation
  6780. */
  6781. this.do = function (data, args) {
  6782. if (data) {
  6783. if (typeof data == 'string' && self.json.actions[data]) {
  6784. self.do(self.json.actions[data], args);
  6785. } else {
  6786. if (!data.index) data.index = 0;
  6787. if (!data.tasks) {
  6788. if (Array.isArray(data)) {
  6789. if (data.index < data.length) {
  6790. self.do(data[data.index]);
  6791. data.index = data.index +1;
  6792. self.do(data);
  6793. } else {
  6794. delete data.index;
  6795. }
  6796. } else {
  6797. self.do(data);
  6798. }
  6799. //} else if (data.tasks.length > 0) {
  6800. } else {
  6801. if (data.index < data.tasks.length) {
  6802. var currentTask = data.tasks[data.index];
  6803. //var currentTask = data.tasks.shift();
  6804. if (currentTask.params == undefined) {currentTask.params = {}}
  6805. if (data.params == undefined) {data.params = {}}
  6806. if (currentTask.if == undefined) {currentTask.if = true}
  6807. var taskParams = currentTask.params; // parametri specifici del task
  6808. taskParams.params = data.params;
  6809. taskParams.index = data.index+1;
  6810. //for (var param in data.params) {taskParams[param] = data.params[param]; } // merge
  6811. taskParams.tasks = data.tasks;
  6812. var taskIf = (typeof currentTask.if == "function") ? currentTask.if() : currentTask.if;
  6813. if (taskIf) {
  6814. if (currentTask.delay !== undefined) {
  6815. setTimeout(function () {
  6816. self.do(currentTask.task, taskParams);
  6817. }, currentTask.delay);
  6818. } else if (currentTask.interval !== undefined) {
  6819. self.createTaskInterval(currentTask);
  6820. } else {
  6821. self.do(currentTask.task,taskParams);
  6822. }
  6823. } else {
  6824. self.do(taskParams);
  6825. }
  6826. }
  6827. }
  6828. }
  6829. }
  6830. } */
  6831. /*
  6832. /*
  6833. Method: playTaskInterval
  6834. Description: Functionality for playTaskInterval.
  6835. @param {any} taskFunction - Description for taskFunction
  6836. @returns {any} - Result of the operation
  6837. */
  6838. this.playTaskInterval = function (taskFunction) {
  6839. self.log('playTaskInterval');
  6840. var taskName = taskFunction.name;
  6841. if (tasksIntervals[taskName]) {
  6842. clearInterval(tasksIntervals[taskName].id);
  6843. tasksIntervals[taskName].id = setInterval(function () {
  6844. tasksIntervals[taskName].task(tasksIntervals[taskName].params);
  6845. }, tasksIntervals[taskName].interval);
  6846. } else {
  6847. self.log('taskName: '+taskName);
  6848. }
  6849. }
  6850. /*
  6851. Method: stopTaskInterval
  6852. Description: Functionality for stopTaskInterval.
  6853. @param {any} taskFunction - Description for taskFunction
  6854. @returns {any} - Result of the operation
  6855. */
  6856. this.stopTaskInterval = function (taskFunction) {
  6857. self.log('stopTaskInterval');
  6858. var taskName = taskFunction.name;
  6859. if (tasksIntervals[taskFunction.name]) {
  6860. clearInterval(tasksIntervals[taskFunction.name].id);
  6861. } else {
  6862. self.log('taskName: '+taskName);
  6863. }
  6864. }
  6865. /*
  6866. Method: createTaskInterval
  6867. Description: Functionality for createTaskInterval.
  6868. @param {any} myTask - Description for myTask
  6869. @returns {any} - Result of the operation
  6870. */
  6871. this.createTaskInterval = function (myTask) {
  6872. tasksIntervals[myTask.task.name] = {};
  6873. tasksIntervals[myTask.task.name].task = myTask.task;
  6874. tasksIntervals[myTask.task.name].params = myTask.params;
  6875. tasksIntervals[myTask.task.name].interval = myTask.interval;
  6876. self.playTaskInterval(myTask.task.name);
  6877. }
  6878. /*
  6879. Method: addTimedTask
  6880. Description: Functionality for addTimedTask.
  6881. @param {any} data - Description for data
  6882. @returns {any} - Result of the operation
  6883. */
  6884. this.addTimedTask = function (data) {
  6885. self.log('addTimedTask');
  6886. if (data.frequence && data.task) {
  6887. if (!data.active) {data.active = true;}
  6888. if (!timedTasks[data.frequence]) {timedTasks[data.frequence] = {}}
  6889. timedTasks[data.frequence][data.task] = {active:data.active, params:{}};
  6890. if (data.params) {
  6891. timedTasks[data.frequence][id].params = data.params;
  6892. }
  6893. }
  6894. }
  6895. /*
  6896. Method: removeTimedTask
  6897. Description: Functionality for removeTimedTask.
  6898. @param {any} data - Description for data
  6899. @returns {any} - Result of the operation
  6900. */
  6901. this.removeTimedTask = function (data) {
  6902. self.log('removeTimedTask');
  6903. if (data.frequence && data.task) {
  6904. delete timedTasks[data.frequence][data.task];
  6905. }
  6906. }
  6907. /*
  6908. Method: doTimedTask
  6909. Description: Functionality for doTimedTask.
  6910. @param {any} data - Description for data
  6911. @returns {any} - Result of the operation
  6912. */
  6913. this.doTimedTask = function (data) {
  6914. self.log('doTimedTask');
  6915. self.log(data);
  6916. for (var task in timedTasks[data.frequence]) {
  6917. var taskObj = timedTasks[data.frequence][task];
  6918. if (taskObj.active) {
  6919. self.do(task, taskObj.params);
  6920. }
  6921. }
  6922. } */
  6923. //------------------------
  6924. // CSS METHODS
  6925. //------------------------
  6926. /* // SELETTORI
  6927. var previewPanel = '.appPanel[data-value="pnlPreview"]';
  6928. var toolsPanel = '.appPanel[data-value="pnlTools"]';
  6929. var stagePanel = '.framePanel[data-value="pnlStage"]';
  6930. var devicePanel = '.framePanel[data-value="pnlDevice"]';
  6931. /*
  6932. Method: closePanel
  6933. Description: Functionality for closePanel.
  6934. @param {any} value - Description for value
  6935. @returns {any} - Result of the operation
  6936. */
  6937. this.closePanel = function(value) {
  6938. self.log(value);
  6939. switch (value) {
  6940. case 'closePanelTools':
  6941. $(toolsPanel).fadeOut();
  6942. $(previewPanel).fadeIn();
  6943. case 'closePanelFrame':
  6944. $(devicePanel).fadeOut();
  6945. $(stagePanel).fadeIn();
  6946. }
  6947. }
  6948. */
  6949. //------------------------
  6950. // CSS METHODS
  6951. //------------------------
  6952. /*
  6953. /*
  6954. Method: cssProp
  6955. Description: Functionality for cssProp.
  6956. @param {any} propPar - Description for propPar
  6957. @returns {any} - Result of the operation
  6958. */
  6959. this.cssProp = function (propPar) {
  6960. var cssObj = {transform: ''};
  6961. if ((propPar.x) && (propPar.y)) {cssObj.transform += ' translate('+propPar.x+'px,'+propPar.y+'px)'; }
  6962. if (propPar.rotateY) {cssObj.transform += ' rotateY('+propPar.rotateY+'deg)'; }
  6963. if (propPar.rotateX) {cssObj.transform += ' rotateX('+propPar.rotateX+'deg)'; }
  6964. if (propPar.scale) {cssObj.transform += ' scale('+propPar.scale+','+propPar.scale+')'; }
  6965. if (propPar.deg) {cssObj.transform += ' rotate('+propPar.deg+'deg)'; }
  6966. if (propPar.opacity) {cssObj.opacity = propPar.opacity;}
  6967. return cssObj;
  6968. } */
  6969. /*
  6970. /*
  6971. Method: getCSS
  6972. Description: Functionality for getCSS.
  6973. @param {any} data - Description for data
  6974. @returns {any} - Result of the operation
  6975. */
  6976. this.getCSS = function (data) {
  6977. var $inspector = $("<div>").css('display', 'none').addClass(data.class);
  6978. $("body").append($inspector); // add to DOM, in order to read the CSS property
  6979. try {
  6980. var props = [];
  6981. for (i=0; i<data.properties.length; i++) {props.push($inspector.css(data.properties[i]))}
  6982. return props;
  6983. } finally {
  6984. $inspector.remove(); // and remove from DOM
  6985. }
  6986. }
  6987. /*
  6988. Method: getTransform
  6989. Description: Functionality for getTransform.
  6990. @param {any} object - Description for object
  6991. @returns {any} - Result of the operation
  6992. */
  6993. this.getTransform = function (object) {
  6994. var transformArray = $(object).css('transform').match(/(-?[0-9\.]+)/g);
  6995. var objTransform = {x:0,y:0};
  6996. objTransform.x = transformArray[4];
  6997. objTransform.y = transformArray[5];
  6998. return objTransform;
  6999. } */
  7000. /*
  7001. Method: getClickPosition
  7002. Description: Functionality for getClickPosition.
  7003. @param {any} e - Description for e
  7004. @returns {any} - Result of the operation
  7005. */
  7006. var getClickPosition = function (e) {
  7007. var parentPosition = getPosition(e.currentTarget);
  7008. var xPosition = e.clientX - parentPosition.x;
  7009. var yPosition = e.clientY - parentPosition.y;
  7010. };
  7011. /*
  7012. Method: getPosition
  7013. Description: Functionality for getPosition.
  7014. @param {any} element - Description for element
  7015. @returns {any} - Result of the operation
  7016. */
  7017. function getPosition(element) {
  7018. var xPosition = 0;
  7019. var yPosition = 0;
  7020. while (element) {
  7021. xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft);
  7022. yPosition += (element.offsetTop - element.scrollTop + element.clientTop);
  7023. element = element.offsetParent;
  7024. }
  7025. return { x: xPosition, y: yPosition };
  7026. }
  7027. /*
  7028. /*
  7029. Method: cssTransform
  7030. Description: Functionality for cssTransform.
  7031. @param {any} namePar - Description for namePar
  7032. @param {any} fromPar - Description for fromPar
  7033. @param {any} toPar - Description for toPar
  7034. @returns {any} - Result of the operation
  7035. */
  7036. var cssTransform = function (namePar, fromPar, toPar) {
  7037. var sdDefineFrom = {transform: ''};
  7038. var sdDefineTo = {transform: ''};
  7039. if ((fromPar.x) && (fromPar.y)) {sdDefineFrom.transform += ' translate('+fromPar.x+'px,'+fromPar.y+'px)'; }
  7040. if ((toPar.x) && (toPar.y)) {sdDefineTo.transform += ' translate('+toPar.x+'px,'+toPar.y+'px)'; }
  7041. if (fromPar.scale) {sdDefineFrom.transform += ' scale('+fromPar.scale+','+fromPar.scale+')'; }
  7042. if (toPar.scale) {sdDefineTo.transform += ' scale('+toPar.scale+','+toPar.scale+')'; }
  7043. if (fromPar.deg !== undefined) {sdDefineFrom.transform += ' rotate('+fromPar.deg+'deg)'; }
  7044. if (toPar.deg !== undefined) {sdDefineTo.transform += ' rotate('+toPar.deg+'deg)';}
  7045. if (fromPar.opacity) {sdDefineFrom.transform += ' opacity'; sdDefineFrom.opacity = String(fromPar.opacity); }
  7046. if (toPar.opacity) {sdDefineTo.transform += ' opacity'; sdDefineTo.opacity = String(toPar.opacity); }
  7047. $.keyframe.define({name: namePar, from: sdDefineFrom, to: sdDefineTo});
  7048. }
  7049. /*
  7050. Method: defineTransform
  7051. Description: Functionality for defineTransform.
  7052. @param {any} data - Description for data
  7053. @returns {any} - Result of the operation
  7054. */
  7055. this.defineTransform = function (data) {
  7056. cssTransform(data.name, data.from, data.to);
  7057. cssTransform(data.name+'Reverse', data.to, data.from);
  7058. animations[data.name] = {name: data.name, duration:data.duration, timingFunction: data.ease, fillMode:'both'};
  7059. } */
  7060. /*
  7061. /*
  7062. Method: defineAnimations
  7063. Description: Functionality for defineAnimations.
  7064. @param {any} data - Description for data
  7065. @returns {any} - Result of the operation
  7066. */
  7067. this.defineAnimations = function (data) {
  7068. self.log('defineAnimations');
  7069. for (var name in self.json.styles.animations) {
  7070. self.json.styles.animations[name].name = name;
  7071. self.defineTransform(self.json.styles.animations[name]);
  7072. }
  7073. self.do(data);
  7074. }
  7075. */
  7076. /*
  7077. /*
  7078. Method: styleToAnimation
  7079. Description: Functionality for styleToAnimation.
  7080. @param {any} obj - Description for obj
  7081. @param {any} style - Description for style
  7082. @returns {any} - Result of the operation
  7083. */
  7084. this.styleToAnimation = function (obj, style) {
  7085. // inutilizzata
  7086. $(obj).addClass('resetAnimation'); // Disable transitions
  7087. $(obj).css(style);
  7088. $(obj).eq(0).offsetHeight; // Trigger a reflow, flushing the CSS changes
  7089. $(obj).removeClass('resetAnimation'); // Re-enable transitions
  7090. // https://stackoverflow.com/questions/11131875/what-is-the-cleanest-way-to-disable-css-transition-effects-temporarily
  7091. } */
  7092. //------------------------
  7093. // DIPENDENZE TWEENMAX
  7094. //------------------------
  7095. /*
  7096. /*
  7097. Method: getImage
  7098. Description: Functionality for getImage.
  7099. @param {any} data - Description for data
  7100. @returns {any} - Result of the operation
  7101. */
  7102. this.getImage = function (data) {
  7103. // corrisponde al metodo fixo.loadImage
  7104. // ma senza la dipendenza con fixo.iconUrl
  7105. // che aggiunge il dominio ai nomi di file senza url
  7106. // se si vuole utilizzare al posto di fixo.loadImage
  7107. // data.url = fixo.iconUrl(data.url); va fatta in fixo.js
  7108. // fixo.loadImage è usato sicuramente in hom.js / spo.js
  7109. // e in fixo.items.js
  7110. if (data.style)
  7111. $(data.object).css(data.style);
  7112. //if (data.animation == undefined) {TweenMax.to(data.object,0,{opacity:0,display:'block'});}
  7113. if (data.animation !== undefined)
  7114. $(data.object).css({opacity:0, display:'none'});
  7115. if (TweenMax) TweenMax.set(data.object,{backgroundImage:'url('+data.url+')'});
  7116. $(data.object).waitForImages({
  7117. each: function(loaded, count, success) {if(!success) {log('error loadImage id:'+this.id);}},
  7118. eachError: function() {
  7119. // http://stackoverflow.com/questions/6137934/how-should-i-handle-a-missing-image-in-my-plugin
  7120. self.log('error:'+urlPar);
  7121. },
  7122. finished: function () {
  7123. if (data.animation !== undefined) {
  7124. self.animation({object:data.object, animation:data.animation});
  7125. } else {
  7126. if (TweenMax) TweenMax.to(data.object,1,{autoAlpha:1,display:'block',float:'left'});
  7127. else $(data.object).css({display: 'block', opacity: '1'});
  7128. }
  7129. if (data.move != undefined) {
  7130. self.move({object:data.object, move:data.move, target:data.target});
  7131. }
  7132. if (data.action) {self.setAction({object:data.object, action:data.action});} // obsolete
  7133. if (data.on) {self.on(data.on, {container: data.object});}
  7134. if (data.onComplete) {self.do(data.onComplete)};
  7135. },
  7136. waitForAll: true
  7137. });
  7138. //$(objPar).waitForImages.progress(function(loaded, count, success) {alert(loaded + ' of ' + count + ' images has ' + (success ? 'loaded' : 'failed to load') + '.');});
  7139. } */
  7140. /*
  7141. /*
  7142. Method: setAction
  7143. Description: Functionality for setAction.
  7144. @param {any} data - Description for data
  7145. @returns {any} - Result of the operation
  7146. */
  7147. this.setAction = function (data) {
  7148. $(data.object).off().on(self.touch, function () {
  7149. var.touchTime = self.getTimestamp();
  7150. self.do(data.action, data.value);
  7151. });
  7152. } */
  7153. /*
  7154. Method: animate
  7155. Description: Functionality for animate.
  7156. @param {any} params - Description for params
  7157. @param {any} selectorParams - Description for selectorParams
  7158. @param {any} args - Description for args
  7159. @returns {any} - Result of the operation
  7160. */
  7161. this.animate = function (params, selectorParams, args) {
  7162. // We create a Promise and return it
  7163. new Promise((resolve, reject) => {
  7164. /* self.log('animate');
  7165. self.log('params');
  7166. self.log(params);
  7167. self.log('selectorParams');
  7168. self.log(selectorParams); */
  7169. /* selectorParams.container = (params.container) ? params.container : selectorParams.container;
  7170. selectorParams.id = (params.id) ? params.id : selectorParams.id ;
  7171. selectorParams.class = (params.class) ? params.class : selectorParams.class;
  7172. selectorParams.value = (params.value) ? params.value : selectorParams.value; */
  7173. const prefix = 'animate__';
  7174. //var selector = self.selector(self.extend({}, params, selectorParams), undefined, true); // selectAll
  7175. let selector = self.selector(params.selector || params.container, undefined, true) || self.selector(selectorParams, undefined, true);
  7176. //var selector = self.selector(params.selector || params.container, selectorParams, true); // selectAll
  7177. /* self.log('animate');
  7178. self.log('selector');
  7179. self.log(selector); */
  7180. var transition = params.transition || params;
  7181. transition = self.replaceProperties(transition, args);
  7182. const duration = params.duration || '0.5s';
  7183. const animationName = `${prefix}${transition}`;
  7184. if (!selector) {
  7185. self.log('animate function without selector');
  7186. self.log(params);
  7187. self.log(selectorParams);
  7188. } else {
  7189. var elements = self.queryAll(selector);
  7190. /* console.log('elements');
  7191. console.log(elements); */
  7192. //var elements = document.querySelectorAll(selector);
  7193. if (elements)
  7194. elements.forEach(function (element, index) {
  7195. if (element) {
  7196. //element.classList.add(`${prefix}animated`, animationName);
  7197. //console.log(element.classList);
  7198. element.classList.add('animate__animated', animationName);
  7199. element.style.setProperty('--animate-duration', duration);
  7200. } else {
  7201. console.log('element');
  7202. console.log(element);
  7203. }
  7204. });
  7205. if (params.on && params.on.start)
  7206. self.do(params.on.start, { selector: selector });
  7207. //self.do(params.on.start, undefined, {selector: selector});
  7208. if (params.style) self.css(params, selectorParams); // TO DO: deprecated / to be removed
  7209. //if (params.infinite)
  7210. // node.style.setProperty('--animate-infinite', 'infinite');
  7211. // When the animation ends, we clean the classes and resolve the Promise
  7212. /*
  7213. Method: handleAnimationEnd
  7214. Description: Functionality for handleAnimationEnd.
  7215. @param {any} event - Description for event
  7216. @returns {any} - Result of the operation
  7217. */
  7218. function handleAnimationEnd(event) {
  7219. if (params.on && params.on.end) {
  7220. self.do(params.on.end, { selector: selector });
  7221. //self.do(params.on.end, undefined, {selector: selector});
  7222. /* self.log('handleAnimationEnd');
  7223. self.log('params.on.end');
  7224. self.log(params.on.end); */
  7225. }
  7226. event.stopPropagation();
  7227. if (elements)
  7228. elements.forEach(function (element, index) {
  7229. if (element)
  7230. element.classList.remove('animate__animated', animationName);
  7231. });
  7232. resolve('Animation ended');
  7233. }
  7234. if (elements)
  7235. elements.forEach(function (element, index) {
  7236. if (element)
  7237. element.addEventListener('animationend', handleAnimationEnd, { once: true });
  7238. });
  7239. }
  7240. });
  7241. };
  7242. /*
  7243. /*
  7244. Method: animation
  7245. Description: Functionality for animation.
  7246. @param {any} data - Description for data
  7247. @returns {any} - Result of the operation
  7248. */
  7249. this.animation = function (data) { // deprecated
  7250. if (data.animation != undefined) {
  7251. if (data.animation == 'show') {
  7252. $(data.object).css({'display':'block', opacity:1});
  7253. } else if (data.animation == 'hide') {
  7254. $(data.object).css({'display':'none'});
  7255. } else {
  7256. //if (data.autoDisplay == undefined) {data.autoDisplay = true};
  7257. //var animationObject = self.cloneObject(animations[data.animation]);
  7258. var animationObject = jQuery.extend({}, animations[data.animation]);
  7259. //if (data.autoDisplay)
  7260. // if (data.animation == 'fadeIn') $(data.object).css({'display':'block'});
  7261. if (data.reverse) {animationObject.name += 'Reverse'}
  7262. if (data.duration !== undefined) {animationObject.duration = data.duration}
  7263. animationObject.complete = function () {
  7264. if (data.autoDisplay) {
  7265. if ((data.animation == 'fadeOut') || (data.animation == 'hide')) {
  7266. $('data.object').css({'display':'none'});
  7267. }
  7268. }
  7269. if (data.onComplete !== undefined) {
  7270. self.do(data.onComplete);
  7271. }
  7272. }
  7273. self.log('animationObject.name');
  7274. self.log(animationObject.name);
  7275. self.log('animationObject');
  7276. self.log(animationObject);
  7277. // playKeyframe va aggiornato con
  7278. // animate({from, to, ease, type, stiffness, dumping, mass, velocity, duration})
  7279. // https://popmotion.io/#quick-start-animation-animate-keyframes-options
  7280. //var obj = popmotion.styler($(data.object));
  7281. //popmotion.animate(animationObject).start(obj.set); // $(data.object).css
  7282. $(data.object).playKeyframe(animationObject);
  7283. }
  7284. } else {
  7285. $(data.object).resetKeyframe();
  7286. $(data.object).css({'opacity':1,'display':'block'});
  7287. self.log('ANIMATION UNDEFINED');
  7288. self.log(data);
  7289. }
  7290. }
  7291. /*
  7292. Method: move
  7293. Description: Functionality for move.
  7294. @param {any} data - Description for data
  7295. @returns {any} - Result of the operation
  7296. */
  7297. this.move = function (data) { // deprecated
  7298. var targetPos = {x:0,y:0};
  7299. if (data.target != 'center') { targetPos = {x:384,y:384}; }
  7300. else if (data.target !== undefined) {targetPos = self.getTransform(data.target);}
  7301. else {self.log(data);}
  7302. if (data.move == 'toTarget') {
  7303. TweenMax.to(data.object, self.TweenMaxDuration(data.duration), { x: targetPos.x, y: targetPos.y});
  7304. } else if (data.move == 'fromTarget') {
  7305. TweenMax.from(this, self.TweenMaxDuration(data.duration), { x: targetPos.x, y: targetPos.y});
  7306. }
  7307. if (data.animation !== undefined) {
  7308. self.animation({object:data.object, animation:data.animation});
  7309. }
  7310. }
  7311. /*
  7312. Method: TweenMaxDuration
  7313. Description: Functionality for TweenMaxDuration.
  7314. @param {any} duration - Description for duration
  7315. @returns {any} - Result of the operation
  7316. */
  7317. this.TweenMaxDuration = function (duration) {
  7318. if (duration != undefined) {return Number(duration)/1000} else {return 0.667;}
  7319. }
  7320. */
  7321. // CSS CLASSES
  7322. /*
  7323. Method: addClassRule
  7324. Description: Functionality for addClassRule.
  7325. @param {any} ruleName - Description for ruleName
  7326. @param {any} ruleParams - Description for ruleParams
  7327. @returns {any} - Result of the operation
  7328. */
  7329. this.addClassRule = function (ruleName, ruleParams) {
  7330. //self.log('addClassRule');
  7331. var ruleProperties = '{';
  7332. for (var property in ruleParams) {
  7333. if (typeof ruleParams[property] == 'object') {
  7334. self.addClassRule(ruleName + ' ' + property, ruleParams[property]);
  7335. } else {
  7336. ruleProperties += property + ':' + ruleParams[property] + ';';
  7337. }
  7338. }
  7339. ruleProperties += '}';
  7340. self.styleObj.sheet.insertRule(ruleName + ' ' + ruleProperties);
  7341. };
  7342. /*
  7343. Method: addApplyRule
  7344. Description: Functionality for addApplyRule.
  7345. @param {any} ruleName - Description for ruleName
  7346. @param {any} ruleParams - Description for ruleParams
  7347. @returns {any} - Result of the operation
  7348. */
  7349. this.addApplyRule = function (ruleName, ruleParams) {
  7350. // Use @apply to inline any existing utility classes into your own custom CSS
  7351. // https://tailwindcss.com/docs/functions-and-directives#apply
  7352. self.styleObj.sheet.insertRule(ruleName + ' {@apply ' + ruleParams + '}');
  7353. };
  7354. /*
  7355. Method: findPlugin
  7356. Description: Functionality for findPlugin.
  7357. @param {any} name - Description for name
  7358. @returns {any} - Result of the operation
  7359. */
  7360. this.findPlugin = function (name) {
  7361. if (self.json.plugins) {
  7362. for (var plugin of self.json.plugins) {
  7363. if (plugin.name == name) return plugin;
  7364. }
  7365. } else {
  7366. return false;
  7367. }
  7368. };
  7369. /*
  7370. Method: defineCss
  7371. Description: Functionality for defineCss.
  7372. @param {any} cssObj - Description for cssObj
  7373. @returns {any} - Result of the operation
  7374. */
  7375. this.defineCss = function (cssObj) {
  7376. self.log('defineCss');
  7377. self.styleObj = document.createElement("style");
  7378. document.head.appendChild(self.styleObj);
  7379. self.styleObj.appendChild(document.createTextNode(""));
  7380. /* self.styleObj.sheet.insertRule('@tailwind base;');
  7381. self.styleObj.sheet.insertRule('@tailwind components;');
  7382. self.styleObj.sheet.insertRule('@tailwind utilities;'); */
  7383. // shortcuts (must be improved / can't be extended)
  7384. /* if (self.json.shortcuts && self.json.shortcuts.class)
  7385. shortcuts = self.json.shortcuts.class; */
  7386. if (cssObj) {
  7387. if (Array.isArray(cssObj)) {
  7388. for (var cssElement of cssObj) {
  7389. //console.log(cssElement);
  7390. for (var elementName in cssElement) {
  7391. //console.log(elementName);
  7392. let valueWithData = self.replaceProperties(cssElement[elementName]);
  7393. self.addClassRule(elementName, valueWithData);
  7394. }
  7395. }
  7396. } else {
  7397. for (var elementName in cssObj) {
  7398. let valueWithData = self.replaceProperties(cssObj[elementName]);
  7399. self.addClassRule(elementName, valueWithData);
  7400. }
  7401. }
  7402. }
  7403. if (self.pluginsLoaded.tailwindcss) {
  7404. var plugin = self.findPlugin('tailwindcss');
  7405. //var config = (plugin) ? plugin.config : {preflight: false};
  7406. var config = (self.json.setup.config.tailwindcss) ? self.json.setup.config.tailwindcss : { preflight: false };
  7407. //if (self.json.style.theme) setup.theme = self.json.style.theme;
  7408. //loadPlugin(undefined, 'tailwind-config', undefined, undefined, JSON.stringify(config)) // version 2.2.0
  7409. if (tailwind)
  7410. tailwind.config = config;
  7411. else
  7412. console.log('tailwind object is undefined');
  7413. }
  7414. /* // OBSOLETE
  7415. if (self.pluginsLoaded.twind && window.twind) {
  7416. var plugin = self.findPlugin('twind');
  7417. var config = (plugin) ? plugin.config : {preflight: false, mode:'silent'};
  7418. //if (self.json.setup.target) setup.target = self.query(self.json.setup.target);
  7419. //if (self.json.style.theme) setup.theme = self.json.style.theme;
  7420. window.twind.setup(config);
  7421. } */
  7422. /* if (self.pluginsLoaded.windicss && window.windicssRuntimeOptions) {
  7423. var config = self.json.style.windi || {
  7424. // enabled preflight
  7425. preflight: false,
  7426. // scan the entire dom tree to infer the classnames on page loaded
  7427. extractInitial: false,
  7428. // generate mock classes for browser to do the auto-completeion
  7429. mockClasses: false,
  7430. // the windi config you are used to put in `windi.setup.js`
  7431. setup: {},
  7432. theme: {extend: {}}
  7433. };
  7434. if (self.json.style.theme) setup.theme.extend = self.json.style.theme;
  7435. window.windicssRuntimeOptions = config;
  7436. } */
  7437. /* if (self.pluginsLoaded.unocss) {
  7438. var config = self.json.style.unocss || { // -> self.json.plugins[].setup
  7439. rules: [
  7440. // custom rules...
  7441. ],
  7442. presets: [
  7443. // custom presets...
  7444. ],
  7445. // ...
  7446. };
  7447. if (self.json.style.theme) setup.theme = self.json.style.theme;
  7448. if (self.json.shortcuts) setup.shortcuts = self.json.shortcuts;
  7449. window.__unocss = config;
  7450. //alert(JSON.stringify(config));
  7451. } */
  7452. //self.do(data);
  7453. };
  7454. /*
  7455. /*
  7456. Method: createLoader
  7457. Description: Functionality for createLoader.
  7458. @param {any} data - Description for data
  7459. @returns {any} - Result of the operation
  7460. */
  7461. this.createLoader = function (data) {
  7462. // !--<div class="preloader-wrapper"><div class="preloader"><img alt="Loading..."/></div></div>-->
  7463. if (self.json.loader) $('.preloader img').attr('src', self.json.loader);
  7464. self.do(data);
  7465. } */
  7466. /*
  7467. /*
  7468. Method: preloadIcons
  7469. Description: Functionality for preloadIcons.
  7470. @param {any} data - Description for data
  7471. @returns {any} - Result of the operation
  7472. */
  7473. this.preloadIcons = function (data) {
  7474. self.log('preloadIcons');
  7475. // to do: check for duplicated ids
  7476. if (self.json.icons) {
  7477. if (!data.icons && self.json.icons) data.icons = self.cloneObject(self.json.icons);
  7478. if (data.icons) {
  7479. var iconSet = Object.keys(data.icons)[0];
  7480. var icons = data.icons[iconSet];
  7481. delete data.icons[iconSet];
  7482. if (icons.preload) {
  7483. var ajax = new XMLHttpRequest();
  7484. ajax.open("GET", icons.src, true);
  7485. ajax.onload = function(e) {
  7486. if (this.status >= 200 && this.status < 400) {
  7487. self.log('Icon set loaded ' + iconSet);
  7488. var result = this.response; // responseText
  7489. //self.log(result);
  7490. var div = document.createElement("div");
  7491. //var iconsHtml = new XMLSerializer().serializeToString(result);
  7492. var iconsHtml = result;
  7493. iconsHtml = self.replaceAll(iconsHtml, 'id="', 'id="' + iconSet + '_');
  7494. div.innerHTML = iconsHtml;
  7495. div.setAttribute("style", "display: none");
  7496. //div.setAttribute("aria-hidden", "true");
  7497. //document.getElementbyId('preloadIcons').appendChild(element);
  7498. document.body.insertBefore(div, null);
  7499. if (Object.keys(data.icons).length > 0)
  7500. self.preloadIcons(data);
  7501. else
  7502. self.do(data);
  7503. }
  7504. }
  7505. ajax.send();
  7506. } else {
  7507. if (Object.keys(data.icons).length > 0)
  7508. self.preloadIcons(data);
  7509. else
  7510. self.do(data);
  7511. }
  7512. } else
  7513. self.do(data);
  7514. } else {
  7515. self.do(data);
  7516. }
  7517. } */
  7518. /*
  7519. /*
  7520. Method: initApp
  7521. Description: Functionality for initApp.
  7522. @param {any} data - Description for data
  7523. @returns {any} - Result of the operation
  7524. */
  7525. this.initApp = function (data) {
  7526. self.log('initApp');
  7527. self.defineCss();
  7528. window.addEventListener('resize', self.resizeEvent);
  7529. if (self.json) { // can be self.json.init
  7530. //if (self.json.on.init)
  7531. if (self.json.on)
  7532. self.on(self.json.on);
  7533. //else
  7534. // self.log('no on init functions');
  7535. }
  7536. //self.do(data);
  7537. }
  7538. */
  7539. /*
  7540. /*
  7541. Method: createUI
  7542. Description: Functionality for createUI.
  7543. @param {any} data - Description for data
  7544. @returns {any} - Result of the operation
  7545. */
  7546. this.createUI = function (data) {
  7547. jsonic.do({
  7548. tasks:[
  7549. {task: self.firebaseInit},
  7550. {
  7551. task: self.firebaseVerifyUser,
  7552. params: {
  7553. code: self.params.oobCode
  7554. }
  7555. },
  7556. {task: self.getDevices, if: jsonic.userIn},
  7557. {task: self.defineCss},
  7558. {task: self.defineAnimations}, // animazioni css predefinite
  7559. {task: self.createHeader},
  7560. {task: self.createMenu, params: {
  7561. container: '#menu',
  7562. id: data.params.mode || 'guest'
  7563. }},
  7564. {task: jsonic.createPages}
  7565. ]
  7566. });
  7567. } */
  7568. /*
  7569. /*
  7570. Method: openPageFromUrl
  7571. Description: Functionality for openPageFromUrl.
  7572. @param {any} data - Description for data
  7573. @returns {any} - Result of the operation
  7574. */
  7575. this.openPageFromUrl = function(data){
  7576. jsonic.log('openPageFromUrl');
  7577. jsonic.log('self.params');
  7578. jsonic.log(self.params);
  7579. var pageId = '';
  7580. //if (localStorage.getItem('scanning')) {
  7581. // self.hashopenTask({id:localStorage.getItem('scanningFile')});
  7582. //} else {
  7583. //self.disableFileIcons();
  7584. //var noDevices = (jsonic.userIn() && (!var.db.devices || Object.keys(var.db.devices).length == 0));
  7585. //if (noDevices && !self.params.d && !self.params.m) {
  7586. // jsonic.gotoPage('devices');
  7587. //} else {
  7588. if (window.location.hash && window.location.hash !== '') {
  7589. //pageId = window.location.hash.substr(1);
  7590. self.hash();
  7591. } else {
  7592. if (self.params.p) // retro-compatibilità
  7593. pageId = self.params.p;
  7594. else
  7595. pageId = self.homePage();
  7596. self.gotoPage(pageId);
  7597. }
  7598. //}
  7599. self.do(data);
  7600. }
  7601. */
  7602. /*
  7603. // Load a script from given `url`
  7604. /*
  7605. Method: loadPlugin
  7606. Description: Functionality for loadPlugin.
  7607. @param {any} url - Description for url
  7608. @returns {any} - Result of the operation
  7609. */
  7610. var loadPlugin = function(url) {
  7611. return new Promise(function(resolve, reject) {
  7612. const script = document.createElement('script');
  7613. script.src = url;
  7614. script.addEventListener('load', function() {
  7615. // The script is loaded completely
  7616. resolve(true);
  7617. });
  7618. document.head.appendChild(script);
  7619. });
  7620. };
  7621. // Perform all promises in the order
  7622. /*
  7623. Method: waterfall
  7624. Description: Functionality for waterfall.
  7625. @param {any} promises - Description for promises
  7626. @returns {any} - Result of the operation
  7627. */
  7628. var waterfall = function(promises) {
  7629. return promises.reduce(
  7630. function(p, c) {
  7631. // Waiting for `p` completed
  7632. return p.then(function() {
  7633. // and then `c`
  7634. return c().then(function(result) {
  7635. return true;
  7636. });
  7637. });
  7638. },
  7639. // The initial value passed to the reduce method
  7640. Promise.resolve([])
  7641. );
  7642. };
  7643. // Load an array of scripts in order
  7644. /*
  7645. Method: loadScriptsInOrder
  7646. Description: Functionality for loadScriptsInOrder.
  7647. @param {any} arrayOfJs - Description for arrayOfJs
  7648. @returns {any} - Result of the operation
  7649. */
  7650. var loadScriptsInOrder = function(arrayOfJs) {
  7651. self.log('loadScriptsInOrder');
  7652. self.log(arrayOfJs);
  7653. const promises = arrayOfJs.map(function(url) {
  7654. self.log(url);
  7655. return loadScript(url);
  7656. });
  7657. return waterfall(promises);
  7658. };
  7659. */
  7660. /*
  7661. Method: hash
  7662. Description: Functionality for hash.
  7663. @param {any} path - Description for path
  7664. @param {any} args - Description for args
  7665. @returns {any} - Result of the operation
  7666. */
  7667. this.hash = function (path, args) {
  7668. self.log('hash');
  7669. var path = self.replaceProperties(path, args);
  7670. self.log(path);
  7671. window.location.hash = path;
  7672. };
  7673. /*
  7674. Method: page
  7675. Description: Functionality for page.
  7676. @param {any} path - Description for path
  7677. @param {any} args - Description for args
  7678. @returns {any} - Result of the operation
  7679. */
  7680. this.page = function (path, args) {
  7681. self.log('page');
  7682. var path = self.replaceProperties(path, args);
  7683. self.log(path);
  7684. if (path.startsWith('#'))
  7685. window.location.hash = path;
  7686. else
  7687. window.location.href = path;
  7688. //window.location.hash = path;
  7689. };
  7690. /*
  7691. Method: hashChangeEvent
  7692. Description: Functionality for hashChangeEvent.
  7693. @param {any} - No parameters
  7694. @returns {any} - Result of the operation
  7695. */
  7696. this.hashChangeEvent = function () {
  7697. self.log('hashChangeEvent');
  7698. self.log(window.location.hash);
  7699. /* if (window.location.hash && window.location.hash !== '') {
  7700. var hashParams = window.location.hash.substr(1).split('/');
  7701. self.gotoPage(hashParams[0], hashParams[1]);
  7702. } else {
  7703. //pageId = self.homePage();
  7704. if (self.json.setup && self.json.setup.wordpress && self.json.setup.wordpress.slug)
  7705. self.gotoPage(self.json.setup.wordpress.slug);
  7706. else
  7707. self.gotoPage(self.homePage());
  7708. }
  7709. if (json && json.app && json.app.on && json.app.on.page) { // page event
  7710. self.do(json.app.on.page);
  7711. }
  7712. if (json && json.actions && json.actions.init) { // obsolete
  7713. self.do(json.actions.init);
  7714. } */
  7715. };
  7716. /*
  7717. /*
  7718. Method: addPageListeners
  7719. Description: Functionality for addPageListeners.
  7720. @param {any} data - Description for data
  7721. @returns {any} - Result of the operation
  7722. */
  7723. this.addPageListeners = function (data) {
  7724. self.log('addPageListeners');
  7725. // Resize event
  7726. window.addEventListener('resize', self.resizeEvent);
  7727. // Location hash (url) event
  7728. window.addEventListener('hashchange', self.hashChangeEvent);
  7729. //$(window).on('hashchange', self.hashChangeEvent);
  7730. self.hashChangeEvent();
  7731. self.do(data);
  7732. } */
  7733. /* // testing
  7734. /*
  7735. Method: findValues
  7736. Description: Functionality for findValues.
  7737. @param {any} obj - Description for obj
  7738. @param {any} key - Description for key
  7739. @param {any} found - Description for found
  7740. @returns {any} - Result of the operation
  7741. */
  7742. let findValues = function(obj, key, found) {
  7743. for (let localKey in obj) {
  7744. if (obj.hasOwnProperty(localKey)) {
  7745. let val = obj[localKey];
  7746. //self.log(localKey)
  7747. if (localKey === key) {
  7748. found.add(val)
  7749. } else {
  7750. if (typeof val === 'object') {
  7751. findValues(val, key, found)
  7752. }
  7753. }
  7754. }
  7755. }
  7756. }
  7757. /*
  7758. Method: uniqueValue
  7759. Description: Functionality for uniqueValue.
  7760. @param {any} obj - Description for obj
  7761. @param {any} key - Description for key
  7762. @param {any} value - Description for value
  7763. @returns {any} - Result of the operation
  7764. */
  7765. function uniqueValue(obj, key, value) {
  7766. let found = new Set()
  7767. findValues(object, key, found)
  7768. return found.size === 1 && found.has(value);
  7769. } */
  7770. /*
  7771. Method: lookup
  7772. Description: Functionality for lookup.
  7773. @param {any} obj - Description for obj
  7774. @param {any} k - Description for k
  7775. @returns {any} - Result of the operation
  7776. */
  7777. this.lookup = function (obj, k) {
  7778. for (var key in obj) {
  7779. var value = obj[key];
  7780. if (k == key) {
  7781. return [k, value];
  7782. }
  7783. if (typeof (value) === "object" && !Array.isArray(value)) {
  7784. var y = lookup(value, k);
  7785. if (y && y[0] == k) return y;
  7786. }
  7787. if (Array.isArray(value)) {
  7788. // for..in doesn't work the way you want on arrays in some browsers
  7789. //
  7790. for (var i = 0; i < value.length; ++i) {
  7791. var x = lookup(value[i], k);
  7792. if (x && x[0] == k) return x;
  7793. }
  7794. }
  7795. }
  7796. return null;
  7797. };
  7798. /*
  7799. Method: findValues
  7800. Description: Functionality for findValues.
  7801. @param {any} obj - Description for obj
  7802. @param {any} key - Description for key
  7803. @returns {any} - Result of the operation
  7804. */
  7805. this.findValues = function (obj, key) {
  7806. //return Boolean(JSON.stringify(obj).indexOf('"' + string + '":') >= 0)
  7807. let matrix = [...JSON.stringify(obj).matchAll(new RegExp('\"?' + key + '\"?\:\s*\"([^,\"]+)', 'gi'))];
  7808. var results = [];
  7809. for (var element of matrix)
  7810. results.push(element[1]);
  7811. return results;
  7812. //return Boolean(JSON.stringify(obj).match(new RegExp('\"?' + key + '\"?\:\s+\"' + value + '\"'))) // JSON5 compatible
  7813. };
  7814. // testing
  7815. /*
  7816. Method: findKey
  7817. Description: Functionality for findKey.
  7818. @param {any} obj - Description for obj
  7819. @param {any} key - Description for key
  7820. @returns {any} - Result of the operation
  7821. */
  7822. function findKey(obj, key) {
  7823. for ([k, v] of Object.entries(obj)) {
  7824. if (k == key) return v;
  7825. if (typeof v === 'object' && v !== null) {
  7826. let found = findKey(v, key);
  7827. if (found) return found;
  7828. }
  7829. }
  7830. }
  7831. // lookup in json
  7832. /*
  7833. Method: keyInJson
  7834. Description: Functionality for keyInJson.
  7835. @param {any} obj - Description for obj
  7836. @param {any} string - Description for string
  7837. @returns {any} - Result of the operation
  7838. */
  7839. this.keyInJson = function (obj, string) {
  7840. //return Boolean(JSON.stringify(obj).indexOf('"' + string + '":') >= 0)
  7841. return Boolean(JSON.stringify(obj).match(new RegExp('\"?' + string + '\"?\:'))); // JSON5 compatible
  7842. };
  7843. // lookup in json
  7844. /*
  7845. Method: valueInJson
  7846. Description: Functionality for valueInJson.
  7847. @param {any} obj - Description for obj
  7848. @param {any} string - Description for string
  7849. @returns {any} - Result of the operation
  7850. */
  7851. this.valueInJson = function (obj, string) {
  7852. //return Boolean(JSON.stringify(obj).indexOf('"' + string + '":') >= 0)
  7853. return Boolean(JSON.stringify(obj).match(new RegExp('\"?' + string + '\"?'))); // JSON5 compatible
  7854. };
  7855. /*
  7856. /*
  7857. Method: keyInFiles
  7858. Description: Functionality for keyInFiles.
  7859. @param {any} string - Description for string
  7860. @returns {any} - Result of the operation
  7861. */
  7862. this.keyInFiles = function (string) {
  7863. var found = self.keyInJson(self.options, string); // in main app options: jsonic = jsonicApp(options)
  7864. for (fileName in self.modules) {
  7865. if (fileName !== 'resources' && self.keyInJson(self.modules[fileName], string))
  7866. found = true;
  7867. }
  7868. return found;
  7869. } */
  7870. /*
  7871. /*
  7872. Method: openPageFromUrl
  7873. Description: Functionality for openPageFromUrl.
  7874. @param {any} data - Description for data
  7875. @returns {any} - Result of the operation
  7876. */
  7877. this.openPageFromUrl = function (data) {
  7878. self.log('openPageFromUrl');
  7879. self.hashChangeEvent();
  7880. self.do(data);
  7881. }; */
  7882. /*
  7883. /*
  7884. Method: addEventListeners
  7885. Description: Functionality for addEventListeners.
  7886. @param {any} data - Description for data
  7887. @returns {any} - Result of the operation
  7888. */
  7889. this.addEventListeners = function (data) {
  7890. self.log('addEventListeners');
  7891. // Resize event
  7892. window.addEventListener('resize', self.resizeEvent);
  7893. // Location hash (url) event
  7894. window.addEventListener('hashchange', self.hashChangeEvent);
  7895. $(window).on('hashchange', self.hashChangeEvent);
  7896. self.hashChangeEvent(); // add here on.hashchange
  7897. // Fullscreen event
  7898. if (screenfull && screenfull.isEnabled) {
  7899. screenfull.on('change', () => {
  7900. self.log('Am I fullscreen?', screenfull.isFullscreen ? 'Yes' : 'No');
  7901. if (screenfull.isFullscreen) {
  7902. var.fullscreen = true;
  7903. if (var.onFullScreenOpen) self.do(var.onFullScreenOpen);
  7904. } else {
  7905. var.fullscreen = false;
  7906. if (var.onFullScreenClose) self.do(var.onFullScreenClose);
  7907. }
  7908. });
  7909. }
  7910. if (json && json.app && json.app.on) {
  7911. if (json.app.on.thunkable && json.app.on.thunkable.receiveMessage)
  7912. window.receiveMessage(function (message) {
  7913. //document.querySelector('#message').value = message;
  7914. jsonic.functions(json.app.on.thunkable.receiveMessage, message, undefined);
  7915. });
  7916. var container = json.app.container || 'body';
  7917. self.on(json.app.on, {container: container});
  7918. self.do(data);
  7919. } else {
  7920. self.do(data);
  7921. }
  7922. } */
  7923. /*
  7924. /*
  7925. Method: loadIconset
  7926. Description: Functionality for loadIconset.
  7927. @param {any} data - Description for data
  7928. @returns {any} - Result of the operation
  7929. */
  7930. this.loadIconset = function (data) {
  7931. self.log('loadIconset');
  7932. if (self.json.iconset) {
  7933. if (!self.pluginsLoaded['iconify']) {
  7934. let plugin = self.json.resources.pluginsFunctions['iconify'];
  7935. self.pluginsLoader([plugin], self.loadIconset, [data]);
  7936. } else {
  7937. var iconset;
  7938. if (!self.json.iconset[0])
  7939. iconset = [self.json.iconset];
  7940. else
  7941. iconset = self.json.iconset;
  7942. for (var index in iconset) {
  7943. if (Iconify.addCollection(iconset[index]))
  7944. self.log('added iconset '+ iconset[index].prefix);
  7945. else
  7946. self.log('can\t add iconset '+ iconset[index].prefix);
  7947. //alert(x);
  7948. }
  7949. self.do(data);
  7950. }
  7951. } else {
  7952. self.do(data);
  7953. }
  7954. } */
  7955. // Si potrebbe creare una nuova istanza di jsonicApp
  7956. /*
  7957. Method: start
  7958. Description: Functionality for start.
  7959. @param {any} - No parameters
  7960. @returns {any} - Result of the operation
  7961. */
  7962. this.start = function () {
  7963. self.log('start');
  7964. //if (params.onFullScreenOpen) var.onFullScreenOpen = params.onFullScreenOpen;
  7965. //if (params.onFullScreenClose) var.onFullScreenClose = params.onFullScreenClose;
  7966. // PWA
  7967. /* if ('serviceWorker' in navigator) {
  7968. // Register a service worker hosted at the root of the
  7969. // site using the default scope.
  7970. navigator.serviceWorker.register('/app/assets/pwa/sw.js').then(function(registration) {
  7971. self.log('Service worker registration succeeded:', registration);
  7972. }, function(error) {
  7973. self.log('Service worker registration failed:', error);
  7974. });
  7975. } else {
  7976. self.log('Service workers are not supported.');
  7977. } */
  7978. let deferredPrompt;
  7979. window.addEventListener('beforeinstallprompt', (e) => {
  7980. // Prevent Chrome 67 and earlier from automatically showing the prompt
  7981. e.preventDefault();
  7982. // Stash the event so it can be triggered later.
  7983. deferredPrompt = e;
  7984. });
  7985. window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
  7986. self.json.setup.darkMode = e.matches ? "dark" : false;
  7987. });
  7988. // DEFINE ICONSET (iconify)
  7989. if (self.json.iconset) {
  7990. if (!self.pluginsLoaded['iconify']) {
  7991. let plugin = self.json.resources.pluginsFunctions['iconify'];
  7992. self.pluginsLoader([plugin], self.start);
  7993. return false;
  7994. } else {
  7995. var iconset;
  7996. if (!self.json.iconset[0])
  7997. iconset = [self.json.iconset];
  7998. else
  7999. iconset = self.json.iconset;
  8000. for (var index in iconset) {
  8001. if (Iconify.addCollection(iconset[index]))
  8002. self.log('added iconset ' + iconset[index].prefix);
  8003. else
  8004. self.log('can\t add iconset ' + iconset[index].prefix);
  8005. //alert(x);
  8006. }
  8007. }
  8008. }
  8009. // DEFINE CSS
  8010. //self.defineCss(); // TO DO: only additional css (do it on load module success)
  8011. // ADD RESIZE LISTENER (for dynamic styles) TO DO: check it
  8012. window.addEventListener('resize', self.resizeEvent);
  8013. // PAGE
  8014. if (!self.json.setup.page) self.json.setup.page = {};
  8015. self.json.setup.page.hash = window.location.hash.substr(1);
  8016. // DO / ON
  8017. /* if (self.json) {
  8018. if (self.json.do)
  8019. self.do(self.json.do, undefined, self.json.container);
  8020. if (self.json.on)
  8021. self.on(self.json.on, self.json.container);
  8022. } */
  8023. var selector = self.json.selector || self.json.container;
  8024. /* if (self.json.do)
  8025. self.do(self.json.do, undefined, selector); */
  8026. // should go action/run
  8027. if (self.json.on)
  8028. self.on(self.json.on, selector);
  8029. };
  8030. /*
  8031. Method: extendJson
  8032. Description: Functionality for extendJson.
  8033. @param {any} jsonBase - Description for jsonBase
  8034. @param {any} jsonExtension - Description for jsonExtension
  8035. @returns {any} - Result of the operation
  8036. */
  8037. this.extendJson = function (jsonBase, jsonExtension) {
  8038. // TO DO: should be renamed in extendApp (or executeModule) because extend self.json and add CSS style
  8039. if (jsonExtension.css) self.defineCss(jsonExtension.css);
  8040. if (jsonExtension.functions) self.extendFunctions(jsonExtension.functions);
  8041. for (var key in jsonExtension) {
  8042. // AGGIUNGERE ALL'ARRAY DELLE AZIONI ON.INIT...
  8043. if (key == 'on') {
  8044. for (var subKey in jsonExtension[key]) {
  8045. if (typeof jsonExtension[key][subKey] !== 'string') {
  8046. //jsonBase[key][subKey] = self.extend({}, jsonBase[key][subKey], jsonExtension[key][subKey]);
  8047. if (!jsonBase[key][subKey]) jsonBase[key][subKey] = [];
  8048. jsonBase[key][subKey].push(jsonExtension[key][subKey]);
  8049. } else {
  8050. jsonBase[key][subKey] = jsonExtension[key][subKey];
  8051. }
  8052. }
  8053. } else if (key == 'parts' || key == 'shortcuts') { // combine subelements
  8054. for (var subKey in jsonExtension[key]) {
  8055. if (typeof jsonExtension[key][subKey] !== 'string')
  8056. jsonBase[key][subKey] = self.extend({}, jsonBase[key][subKey], jsonExtension[key][subKey]);
  8057. else
  8058. jsonBase[key][subKey] = jsonExtension[key][subKey];
  8059. }
  8060. /* } else if (key == 'css') {
  8061. for (var subKey in jsonExtension[key]) {
  8062. if (typeof jsonExtension[key][subKey] !== 'string')
  8063. jsonBase[key][subKey] = self.extend({}, jsonBase[key][subKey], jsonExtension[key][subKey]);
  8064. else
  8065. jsonBase[key][subKey] = jsonExtension[key][subKey];
  8066. } */
  8067. /* } else if (key == 'app') { // to do: obsolete
  8068. for (var subKey in jsonExtension[key]) {
  8069. if (typeof jsonExtension[key][subKey] !== 'string')
  8070. jsonBase[key][subKey] = self.extend({}, jsonBase[key][subKey], jsonExtension[key][subKey]);
  8071. else
  8072. jsonBase[key][subKey] = jsonExtension[key][subKey];
  8073. } */
  8074. } else if (key == 'iconset' || key == 'plugins') { // combine arrays
  8075. if (!jsonBase[key]) jsonBase[key] = [];
  8076. jsonBase[key] = jsonBase[key].concat(jsonExtension[key]);
  8077. } else {
  8078. if (key == 'css') {
  8079. } else {
  8080. jsonBase[key] = self.extend({}, jsonBase[key], jsonExtension[key]);
  8081. }
  8082. }
  8083. }
  8084. return jsonBase;
  8085. };
  8086. /*
  8087. Method: loadModuleFromDb
  8088. Description: Functionality for loadModuleFromDb.
  8089. @param {any} data - Description for data
  8090. @returns {any} - Result of the operation
  8091. */
  8092. this.loadModuleFromDb = function (data) {
  8093. self.log('loadModuleFromDb');
  8094. self.firebaseGet('jsonic', function (result) {
  8095. if (result.success) {
  8096. self.log('firebase get SUCCESS');
  8097. for (codeKey in result.data)
  8098. if (result.data[codeKey].code)
  8099. self.extendJson(json, result.data[codeKey].code);
  8100. //self.log('json');
  8101. //self.log(json);
  8102. //if (params.success) self.do(params.success,result.data);
  8103. } else {
  8104. self.log('firebase get ERROR');
  8105. //if (params.error) self.do(params.error, result.error);
  8106. // alert errore di connessione. alert riprova
  8107. }
  8108. self.do(data);
  8109. //self.do(data);
  8110. });
  8111. };
  8112. this.modules = {};
  8113. this.modulesLoading = {};
  8114. /*
  8115. Method: fileType
  8116. Description: Functionality for fileType.
  8117. @param {any} fileName - Description for fileName
  8118. @returns {any} - Result of the operation
  8119. */
  8120. this.fileType = function (fileName) {
  8121. return /(?:\.([^.]+))?$/.exec(fileName)[1];
  8122. };
  8123. /*
  8124. Method: jsoncToJson
  8125. Description: Functionality for jsoncToJson.
  8126. @param {any} jsoncText - Description for jsoncText
  8127. @returns {any} - Result of the operation
  8128. */
  8129. this.jsoncToJson = function (jsoncText) {
  8130. return jsoncText.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '$1').replace(/\r/, "\n").replace(/\n[\n]+/, "\n");
  8131. // https://stackoverflow.com/questions/244777/can-comments-be-used-in-json/24545329
  8132. };
  8133. //var json = jsoncToJson('https://fantacards.com/app/data.jsonc');
  8134. //console.log(json);
  8135. /*
  8136. Method: loadModule
  8137. Description: Functionality for loadModule.
  8138. @param {any} mod - Description for mod
  8139. @returns {any} - Result of the operation
  8140. */
  8141. this.loadModule = function (mod) {
  8142. /* self.log('loadModule');
  8143. self.log(mod); */
  8144. // params: {files, onComplete}
  8145. // self.cloneObject(params.json) to avoid to remove from initial params
  8146. //if (typeof setup.modules == 'string') setup.modules = [setup.modules];
  8147. if (!self.modulesLoading[mod.name] && !self.modules[mod.name]) {
  8148. self.modulesLoading[mod.name] = true;
  8149. return new Promise(function (resolve, reject) {
  8150. //mod = self.replaceProperties(mod);
  8151. //self.log(mod);
  8152. const getAPIData = new XMLHttpRequest();
  8153. getAPIData.open("GET", mod.url);
  8154. getAPIData.onload = function () {
  8155. self.modulesLoading[mod.name] = false;
  8156. //console.log(getAPIData);
  8157. let responseText = getAPIData.responseText;
  8158. if (self.fileType(getAPIData.responseURL) == 'jsonc')
  8159. responseText = self.jsoncToJson(responseText);
  8160. // try
  8161. const result = JSON.parse(responseText);
  8162. // error self.log('Wrong JSON in module '+ mod.name);
  8163. if (self.isJson(result)) {
  8164. self.modules[mod.name] = result;
  8165. self.extendJson(self.json, result);
  8166. self.log('Loaded module ' + mod.name, 'grey');
  8167. } else {
  8168. self.log('Wrong JSON in module ' + mod.name, 'red');
  8169. }
  8170. resolve();
  8171. };
  8172. getAPIData.onerror = function () {
  8173. self.modulesLoading[mod.name] = false;
  8174. };
  8175. getAPIData.send();
  8176. });
  8177. } else {
  8178. self.log('Module ' + mod.name + ' already loaded', 'orange');
  8179. }
  8180. };
  8181. /*
  8182. /*
  8183. Method: loadPlugin
  8184. Description: Functionality for loadPlugin.
  8185. @param {any} url - Description for url
  8186. @returns {any} - Result of the operation
  8187. */
  8188. var loadPlugin = function (url) {
  8189. //self.log('loading ' + url);
  8190. return new Promise(function(resolve, reject) {
  8191. var type = 'script';
  8192. if (url.endsWith('.css')) type = 'link';
  8193. let obj = document.createElement(type);
  8194. // obj.src = url;
  8195. obj.async = false;
  8196. obj.onload = function() {
  8197. resolve(url);
  8198. };
  8199. obj.onerror = function() {
  8200. self.log('error loading: '+url);
  8201. reject(url);
  8202. };
  8203. if (type === 'script') {
  8204. if (url) obj.src = url;
  8205. //if (code) obj.text = code;
  8206. obj.location = document.body;
  8207. document.body.appendChild(obj);
  8208. } else {
  8209. obj.href = url;
  8210. obj.rel = 'stylesheet';
  8211. obj.type = 'text/css';
  8212. obj.location = document.head;
  8213. document.head.appendChild(obj);
  8214. }
  8215. //self.log('obj');
  8216. //self.log(obj);
  8217. });
  8218. } */
  8219. /*
  8220. Method: loadPlugin
  8221. Description: Functionality for loadPlugin.
  8222. @param {any} params - Description for params
  8223. @returns {any} - Result of the operation
  8224. */
  8225. var loadPlugin = function (params) {
  8226. //self.log('loading ' + url);
  8227. return new Promise(function (resolve, reject) {
  8228. var tag = 'script', type = 'text/javascript';
  8229. if (params.type == 'script') { tag = 'script'; type = 'text/javascript'; }
  8230. else if (params.type == 'module') { tag = 'script'; type = 'module'; }
  8231. else if (params.type == 'tailwind-config') { tag = 'script'; type = 'tailwind-config'; }
  8232. else if (params.type == 'link') { tag = 'link'; type = 'text/css'; }
  8233. else if (params.type == 'font') { tag = 'link'; type = undefined; }
  8234. //if (!tag)
  8235. // tag = (url.endsWith('.js')) ? 'script' : 'link';
  8236. let obj = document.createElement(tag);
  8237. if (params.content)
  8238. obj.appendChild(document.createTextNode(params.content));
  8239. obj.async = false;
  8240. obj.onload = function () {
  8241. self.pluginsLoaded[params.name] = { version: "1.0.0" };
  8242. self.log('Loaded plugin ' + params.name, 'grey');
  8243. resolve(params.url);
  8244. };
  8245. obj.onerror = function () {
  8246. self.log('Error loading plugin ' + params.url, 'red');
  8247. reject(params.url);
  8248. };
  8249. if (tag === 'script') {
  8250. if (params.url) obj.src = params.url;
  8251. //if (code) obj.text = code;
  8252. obj.location = document.body;
  8253. obj.type = type || 'text/javascript';
  8254. /* if (type == 'tailwind-config') {
  8255. self.log('obj');
  8256. self.log(obj);
  8257. } */
  8258. document.body.appendChild(obj);
  8259. } else if (tag === 'link') {
  8260. obj.rel = params.rel || 'stylesheet';
  8261. obj.location = document.head;
  8262. if (params.url) obj.href = params.url;
  8263. if (type) obj.type = type;
  8264. if (params.as) obj.as = params.as;
  8265. document.head.appendChild(obj);
  8266. }
  8267. });
  8268. };
  8269. /*
  8270. /*
  8271. Method: loadPlugin
  8272. Description: Functionality for loadPlugin.
  8273. @param {any} url - Description for url
  8274. @param {any} tag - Description for tag
  8275. @param {any} rel - Description for rel
  8276. @param {any} as - Description for as
  8277. @returns {any} - Result of the operation
  8278. */
  8279. var loadPlugin = function (url, tag, rel, as) {
  8280. //self.log('loading ' + url);
  8281. //alert(url);
  8282. return new Promise(function(resolve, reject) {
  8283. if (tag == 'js') tag = 'script';
  8284. if (tag == 'css') tag = 'link';
  8285. if (!tag)
  8286. tag = (url.endsWith('.js')) ? 'script' : 'link';
  8287. let obj = document.createElement(tag);
  8288. obj.async = false;
  8289. obj.onload = function() {
  8290. self.log('loaded plugin: '+url);
  8291. resolve(url);
  8292. };
  8293. obj.onerror = function() {
  8294. self.log('error loading: '+url);
  8295. reject(url);
  8296. };
  8297. if (tag === 'script') {
  8298. if (url) obj.src = url;
  8299. //if (code) obj.text = code;
  8300. obj.location = document.body;
  8301. document.body.appendChild(obj);
  8302. } else {
  8303. obj.href = url;
  8304. obj.rel = rel || 'stylesheet';
  8305. if (obj.rel == 'stylesheet')
  8306. obj.type = 'text/css';
  8307. if (as)
  8308. obj.as = as;
  8309. obj.location = document.head;
  8310. document.head.appendChild(obj);
  8311. }
  8312. });
  8313. }
  8314. */
  8315. this.uiLoaded = {};
  8316. this.pluginsLoaded = {};
  8317. //The Firebase Realtime Database lets you store and query user data, and makes it available between users in realtime
  8318. /*
  8319. Method: findUrl
  8320. Description: Functionality for findUrl.
  8321. @param {any} array - Description for array
  8322. @param {any} url - Description for url
  8323. @returns {any} - Result of the operation
  8324. */
  8325. this.findUrl = function (array, url) {
  8326. for (var item of array) {
  8327. if (item.url == url)
  8328. return true;
  8329. }
  8330. };
  8331. /*
  8332. /*
  8333. Method: export
  8334. Description: Functionality for export.
  8335. @param {any} params - Description for params
  8336. @returns {any} - Result of the operation
  8337. */
  8338. this.export = function (params) {
  8339. // {name, data}
  8340. if (params && params.name && params.data) {
  8341. let element = document.createElement('a');
  8342. element.style.display = 'none';
  8343. element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(params.data)));
  8344. element.setAttribute('download', params.name);
  8345. document.body.appendChild(element);
  8346. element.click();
  8347. document.body.removeChild(element);
  8348. } else {
  8349. self.log('"export" requires name and data attributes');
  8350. }
  8351. } */
  8352. /*
  8353. /*
  8354. Method: exportData
  8355. Description: Functionality for exportData.
  8356. @param {any} path - Description for path
  8357. @returns {any} - Result of the operation
  8358. */
  8359. this.exportData = function (path) {
  8360. // data
  8361. const fileName = self.replaceAll(path, ' ', '.') + '.json';
  8362. const jsonData = self.element({path: path, root: params.root});
  8363. self.export({name: fileName, data: jsonData});
  8364. }
  8365. */
  8366. /*
  8367. Method: loadPlugins
  8368. Description: Functionality for loadPlugins.
  8369. @param {any} - No parameters
  8370. @returns {any} - Result of the operation
  8371. */
  8372. this.loadPlugins = function () {
  8373. //self.log('loadPlugins');
  8374. //var setup = json.setup;
  8375. // TEMPORAL API
  8376. // https://cdn.jsdelivr.net/npm/@cogitatio/tc39-temporal@0.0.12-alpha.2/index.js
  8377. // https://cdn.jsdelivr.net/npm/cogitatio-tc39-temporal@1.0.2/index.js
  8378. /* <!-- <script type="module">
  8379. import { initializeApp } from 'https://www.gstatic.com/firebasejs/9.0.2/firebase-app.js'
  8380. // If you enabled Analytics in your project, add the Firebase SDK for Google Analytics
  8381. import { analytics } from 'https://www.gstatic.com/firebasejs/9.0.2/firebase-analytics.js'
  8382. // Add Firebase products that you want to use
  8383. import { auth } from 'https://www.gstatic.com/firebasejs/9.0.2/firebase-auth.js'
  8384. import { firestore } from 'https://www.gstatic.com/firebasejs/9.0.2/firebase-firestore.js'
  8385. </script> --> */
  8386. var filesToLoad = [];
  8387. // plugins
  8388. if (self.json.plugins) {
  8389. for (var index in self.json.plugins) {
  8390. var plugin = self.json.plugins[index];
  8391. //self.log('loading ' + plugin.name + '...');
  8392. var version = plugin.version || '';
  8393. if (!plugin.ondemand) { // V. >= 1.0.2
  8394. if (plugin.url) { // directly loaded
  8395. // plugin.name and version are needed?
  8396. if (!self.findUrl(filesToLoad, plugin.url)) { // not included yet
  8397. filesToLoad.push({ name: plugin.name, url: plugin.url, type: plugin.type });
  8398. }
  8399. } else { // from resources (TO DO: remove)
  8400. var pluginsFiles = plugin.files || self.json.resources.pluginsFiles[plugin.name];
  8401. // moved in loadPlugin = ... onload
  8402. /* self.pluginsLoaded[plugin.name] = {
  8403. version: version
  8404. }; */
  8405. if (!Array.isArray(pluginsFiles))
  8406. pluginsFiles = [pluginsFiles];
  8407. for (item of pluginsFiles) {
  8408. var url = self.replaceAll(item.url, '{version}', version);
  8409. if (plugin.params) url += '?' + plugin.params;
  8410. let pluginName = plugin.name || item.name;
  8411. if (!url || !self.findUrl(filesToLoad, url)) // not included yet
  8412. filesToLoad.push({ name: pluginName, url: url, type: item.type, content: item.content });
  8413. }
  8414. }
  8415. }
  8416. }
  8417. }
  8418. // ui
  8419. /* for (var index in config.ui) {
  8420. var configUI = config.ui[index];
  8421. //self.log('loading ' + configUI.name + '...');
  8422. var version = configUI.version || '';
  8423. var uiFiles = self.json.resources.uiFiles[configUI.name];
  8424. if (!Array.isArray(uiFiles))
  8425. uiFiles = [uiFiles];
  8426. for (item of uiFiles) {
  8427. var url = self.replaceAll(item.url, '{version}', version);
  8428. if (!self.findUrl(filesToLoad, url)) // not included yet
  8429. filesToLoad.push({url: url, type: item.type, content: item.content});
  8430. }
  8431. } */
  8432. // Auto load Google Fonts
  8433. // TO DO: comment
  8434. for (fontName of self.findValues(self.json, 'font-family')) {
  8435. if (self.json.resources.googleFonts.indexOf(fontName) >= 0) {
  8436. //alert(fontName);
  8437. fontName = self.replaceAll(fontName, ' ', '+');
  8438. //filesToLoad.push({type: 'font', url:'https://fonts.googleapis.com/css2?family='+fontName+'&display=swap', rel:'preload', as:'font'});
  8439. filesToLoad.push({ type: 'link', url: 'https://fonts.googleapis.com/css2?family=' + fontName });
  8440. // +'&display=swap' // https://css-tricks.com/almanac/properties/f/font-display/
  8441. }
  8442. }
  8443. // Auto load plugins (firebase only)
  8444. /* if (config.plugins && config.plugins.autoload) {
  8445. self.log('plugins autoload');
  8446. //for (var index in self.json.resources.pluginsFunctions) {
  8447. var pluginFunctions = self.json.resources.pluginsFirebase; // pluginFunctions
  8448. for (var index in self.json.resources.pluginsFirebase) {
  8449. //self.log(index + ':' + self.keyInFiles(index));
  8450. if (self.keyInFiles(index)) {
  8451. if (pluginFunctions[index]) {
  8452. var plugins = [];
  8453. if (Array.isArray(pluginFunctions[index]))
  8454. plugins = pluginFunctions[index];
  8455. else
  8456. plugins = [pluginFunctions[index]];
  8457. for (plugin of plugins) {
  8458. self.log('loading ' + plugin.name + '...');
  8459. self.pluginsLoaded[plugin.name] = version;
  8460. var version = plugin.version || '';
  8461. var pluginsFiles = self.json.resources.pluginsFiles[plugin.name];
  8462. if (!Array.isArray(pluginsFiles))
  8463. pluginsFiles = [pluginsFiles];
  8464. for (item of pluginsFiles) {
  8465. var url = self.replaceAll(item.url, '{version}', version);
  8466. if (!self.findUrl(filesToLoad, url)) // not included yet
  8467. filesToLoad.push({url: url, type: item.type, content: item.content});
  8468. }
  8469. }
  8470. }
  8471. }
  8472. }
  8473. } */
  8474. // load multiple scripts in sequence
  8475. // https://bit.ly/3nT5Ky1
  8476. // one after another
  8477. // https://medium.com/@asimmittal/sequential-script-loading-in-javascript-a0b77ca9467c
  8478. // load multi js and css
  8479. // https://sphacks.io/load-multiple-js-scripts-dynamically-without-jquery/
  8480. // save all Promises as array
  8481. let promises = [];
  8482. //promises.push(loadPlugin("https:
  8483. filesToLoad.forEach(function (item) {
  8484. if (item.url)
  8485. promises.push(loadPlugin({ name: item.name, url: item.url, type: item.type, rel: item.rel, as: item.as, content: item.content }));
  8486. else
  8487. loadPlugin({ name: item.name, url: item.url, type: item.type, rel: item.rel, as: item.as, content: item.content });
  8488. });
  8489. Promise.all(promises).then(function () {
  8490. self.start();
  8491. }).catch(function (script) {
  8492. self.log('Failed to load');
  8493. self.log(script);
  8494. });
  8495. };
  8496. /*
  8497. Method: modulesList
  8498. Description: Functionality for modulesList.
  8499. @param {any} modulesObj - Description for modulesObj
  8500. @returns {any} - Result of the operation
  8501. */
  8502. this.modulesList = function (modulesObj) {
  8503. var modulesList = [];
  8504. if (modulesObj) {
  8505. for (key in modulesObj) {
  8506. var mod = self.replaceProperties(modulesObj[key]);
  8507. modulesList = modulesList.concat(mod);
  8508. }
  8509. }
  8510. return self.replaceProperties(modulesObj);
  8511. };
  8512. /*
  8513. Method: loadModules
  8514. Description: Functionality for loadModules.
  8515. @param {any} - No parameters
  8516. @returns {any} - Result of the operation
  8517. */
  8518. this.loadModules = function () {
  8519. if (self.json.setup.modules) {
  8520. var modules = self.replaceProperties(self.json.setup.modules);
  8521. var promises = [];
  8522. modules.forEach(function (item) {
  8523. if (!self.modulesLoading[item.name] && !self.modules[item.name]) {
  8524. promises.push(self.loadModule(item));
  8525. }
  8526. });
  8527. Promise.all(promises).then(function () {
  8528. self.loadPlugins();
  8529. }).catch(function (file) {
  8530. self.log('Failed to load');
  8531. self.log(file);
  8532. });
  8533. } else {
  8534. self.loadPlugins();
  8535. }
  8536. };
  8537. this.moduleExecuted = {};
  8538. /*
  8539. Method: addModule
  8540. Description: Functionality for addModule.
  8541. @param {any} params - Description for params
  8542. @returns {any} - Result of the operation
  8543. */
  8544. this.addModule = function (params) {
  8545. if (!self.modules[params.name]) {
  8546. var promises = [];
  8547. promises.push(self.loadModule(params));
  8548. Promise.all(promises).then(function () {
  8549. if (!self.moduleExecuted[params.name]) {
  8550. var module = self.modules[params.name];
  8551. if (module.html) {
  8552. self.moduleExecuted[params.name] = true;
  8553. self.html(module.html);
  8554. }
  8555. }
  8556. if (params.success)
  8557. self.do(params.success);
  8558. }).catch(function (file) {
  8559. self.log('Failed to load');
  8560. self.log(file);
  8561. if (params.error)
  8562. self.do(params.error);
  8563. });
  8564. } else {
  8565. if (params.success)
  8566. self.do(params.success);
  8567. }
  8568. };
  8569. /*
  8570. Method: loadModuleGlobal
  8571. Description: Functionality for loadModuleGlobal.
  8572. @param {any} - No parameters
  8573. @returns {any} - Result of the operation
  8574. */
  8575. this.loadModuleGlobal = function () {
  8576. self.log('loadModuleGlobal');
  8577. var promises = [];
  8578. var modules = [];
  8579. for (let key in self.json.setup.modules) {
  8580. var mod = self.replaceProperties(self.json.setup.modules[key]);
  8581. modules = modules.concat(self.cloneObject(mod));
  8582. }
  8583. for (let mod of modules)
  8584. promises.push(self.loadModule(mod));
  8585. Promise.all(promises).then(function () {
  8586. self.loadModules();
  8587. }).catch(function (file) {
  8588. self.log('Failed to load');
  8589. self.log(file);
  8590. });
  8591. };
  8592. /*
  8593. Method: code
  8594. Description: Functionality for code.
  8595. @param {any} params - Description for params
  8596. @param {any} selectorParams - Description for selectorParams
  8597. @returns {any} - Result of the operation
  8598. */
  8599. this.code = function (params, selectorParams) {
  8600. let container = self.selector(params.selector || params.container) || self.selector(selectorParams);
  8601. self.log("this.code");
  8602. self.log("container");
  8603. self.log(container);
  8604. var editorContainer = container.slice(1);
  8605. var editor = ace.edit(editorContainer);
  8606. var value = params.value;
  8607. if (!params.do || (params.do == 'set')) {
  8608. if (params.theme) editor.setTheme(params.theme);
  8609. var editorMode = params.mode || "ace/mode/json";
  8610. editor.getSession().setMode(editorMode);
  8611. var editorStyle = self.extend({
  8612. background: "rgba(255,255,255,0)"
  8613. }, params.style);
  8614. var codeOptions = self.extend({
  8615. fontSize: "11pt",
  8616. selectionStyle: "line",
  8617. highlightActiveLine: false,
  8618. wrap: true,
  8619. showLineNumbers: false,
  8620. showGutter: false,
  8621. fixedWidthGutter: false,
  8622. readOnly: true,
  8623. }, params.options);
  8624. editor.setOptions(codeOptions);
  8625. var codeString;
  8626. if (typeof value == 'string')
  8627. if (editorMode == "ace/mode/json")
  8628. codeString = JSON.stringify(JSON.parse(value), null, '\t');
  8629. else
  8630. codeString = value;
  8631. else {
  8632. if (editorMode == "ace/mode/json")
  8633. codeString = JSON.stringify(value, null, '\t');
  8634. else {
  8635. var functionObj = self.docElement(value.function);
  8636. var functionParams = value.params;
  8637. codeString = functionObj(functionParams);
  8638. }
  8639. }
  8640. var codeRows = codeString.split(/\r\n|\r|\n/).length;
  8641. editor.setValue(codeString, -1);
  8642. } else if (params.do == 'get') {
  8643. return editor.getValue();
  8644. } else {
  8645. self.log('"code" function requires value param');
  8646. }
  8647. };
  8648. /*
  8649. Method: init
  8650. Description: Functionality for init.
  8651. @param {any} appString - Description for appString
  8652. @param {any} modulesString - Description for modulesString
  8653. @returns {any} - Result of the operation
  8654. */
  8655. this.init = function (appString, modulesString) {
  8656. console.log('init');
  8657. if (typeof appString == 'string') {
  8658. let modules = [{ "name": "app", "url": appString }];
  8659. let modulesNames = (modulesString) ? modulesString.split(",") : [];
  8660. for (let modName of modulesNames) {
  8661. modules.push({ "name": modName, "url": "jsonic/modules/" + modName + ".json" });
  8662. }
  8663. self.json.setup = { "modules": modules };
  8664. } else {
  8665. if (appString) self.extendJson(self.json, appString);
  8666. if (appString.css) self.defineCss(appString.css);
  8667. }
  8668. self.loadModuleGlobal();
  8669. };
  8670. /*
  8671. Method: toJsonNode
  8672. Description: Functionality for toJsonNode.
  8673. @param {any} xml - Description for xml
  8674. @returns {any} - Result of the operation
  8675. */
  8676. function toJsonNode(xml) {
  8677. let obj = {};
  8678. if (xml.nodeType == 1) {
  8679. if (xml.attributes.length > 0) {
  8680. obj["attr"] = {};
  8681. for (let j = 0; j < xml.attributes.length; j++) {
  8682. let attribute = xml.attributes.item(j);
  8683. obj["attr"][attribute.nodeName] = attribute.nodeValue;
  8684. }
  8685. }
  8686. }
  8687. if (xml.hasChildNodes()) {
  8688. for (let i = 0; i < xml.childNodes.length; i++) {
  8689. let item = xml.childNodes.item(i);
  8690. let nodeName = item.nodeName;
  8691. if (item.nodeType == 3 && nodeName == "#text") {
  8692. if (/^\s+$/.test(item.nodeValue)) {
  8693. } else obj.text = item.nodeValue;
  8694. } else {
  8695. if (typeof obj[nodeName] == "undefined") {
  8696. obj[nodeName] = toJsonNode(item);
  8697. } else {
  8698. if (!Array.isArray(obj[nodeName]))
  8699. obj[nodeName] = [obj[nodeName]];
  8700. obj[nodeName].push(toJsonNode(item));
  8701. }
  8702. }
  8703. }
  8704. }
  8705. return obj;
  8706. }
  8707. /*
  8708. Method: htmlToJson
  8709. Description: Functionality for htmlToJson.
  8710. @param {any} text - Description for text
  8711. @returns {any} - Result of the operation
  8712. */
  8713. this.htmlToJson = function (text) {
  8714. let xmlDoc = new DOMParser().parseFromString(text, "text/xml");
  8715. return JSON.stringify(toJsonNode(xmlDoc), null, "\t");
  8716. };
  8717. /*
  8718. Method: elementToJson
  8719. Description: Functionality for elementToJson.
  8720. @param {any} selector - Description for selector
  8721. @returns {any} - Result of the operation
  8722. */
  8723. this.elementToJson = function (selector) {
  8724. let el = document.querySelector(selector);
  8725. return self.htmlToJson(el.getHTML());
  8726. };
  8727. /*
  8728. Method: clearSelection
  8729. Description: Functionality for clearSelection.
  8730. @param {any} - No parameters
  8731. @returns {any} - Result of the operation
  8732. */
  8733. function clearSelection() {
  8734. if (window.getSelection) { window.getSelection().removeAllRanges(); }
  8735. else if (document.selection) { document.selection.empty(); }
  8736. }
  8737. /*
  8738. Method: importHtml
  8739. Description: Functionality for importHtml.
  8740. @param {any} htmlText - Description for htmlText
  8741. @returns {any} - Result of the operation
  8742. */
  8743. this.importHtml = function (htmlText) {
  8744. if (!htmlText)
  8745. htmlText = prompt("html/xml");
  8746. if (htmlText) {
  8747. let jsonDoc = self.htmlToJson(htmlText);
  8748. let textarea = document.createElement("textarea");
  8749. textarea.value = jsonDoc;
  8750. textarea.style = "position: absolute; z-index: 999999; background: white; width:100vw; height:100vh";
  8751. document.body.appendChild(textarea);
  8752. textarea.addEventListener('click', function () {
  8753. textarea.remove();
  8754. navigator.clipboard.writeText(textarea.value).then(() => console.log('copied!'));
  8755. });
  8756. }
  8757. };
  8758. if (typeof options == 'object') {
  8759. } else if (options)
  8760. self.init(arguments[0], arguments[1]);
  8761. }
  8762. var jsonApp = new jsonAppObj();
  8763. var js = jsonApp;
  8764. var jsonic = jsonApp;