/*-----------------------------
JSONIC V. 1.0.13
jsonic.io
-------------------------------*/
// CHANGELOG
// 1.0.13 jsonApp removed; [replaceProperties: include event properties]
// 1.0.12 jsonApp; if is array option
// 1.0.11 block blocks -> parts
// 1.0.10 for: {name} work also with {value:name with path} (function replaceValue)
// 1.0.8 for: {name} replaced with {value:name}
// 1.0.5 set: if array of, the assignments follow the order
// 1.0.4 deprecated: to assign without set (too ambiguous now that the key can be function, window.function, etc)
// 1.0.3 "x": "2*3" if the value is a string, -> self.js(value)
// 1.0.2 plugins ondemand
// 1.0.1 jsonc support
// 1.0.0 FUNCTIONS
// 0.9.9 RESOURCES: Inside modules (resources will be deprecated)
// 0.9.3 DEBUG: Rimosso break in docElement
// 0.9.4 NOTE: In this.nested, commented and decommented nested.animate = partObj.animate; nested.if partObj.if, ...
// 0.9.5 CLASS: "div btn": "content" =
content
// 0.9.6 DEBUG: in this.createElement newSelector (newSelector should be a dedicated function separated from selector)
// 0.9.7 REMOVE: method to remove an element from the DOM / Restored html {attr} to set the attributes of an element
// https://minify-js.com Input: 624.1 kB; Output: 95.46 kB; Compression: 84.7%, saving: 528.64 kB;
// README
// PRIORITY
// in attr -> addStyle / removeStyle
// instead of shortcuts the user can use {data shortcuts}
// {arguments:value|default} -> ({arguments:value}) ? {arguments:value} : default
// use (typeof id == "undefined") to understand if id is defined and is = 0
// css should call defineCss in any part of code
// attr (addClass, removeClass, changeStyle direct methods?) can be changed (in element?) to avoid confusion with the use inside html
// add remove element from array
// debug of "set" key
// can be useful to define pointers (shortcode/path of the objects)
// https://dev.to/ternentdotdev/json-compression-in-the-browser-with-gzip-and-the-compression-streams-api-4135
// a method to append an image to the DOM in base64 format methods? no
// check this.html notes
// anime can be a part/block/key function? called with "ui:anime" asking for the relative plugin?
// if the name of the block/part includes ":" it is more explicit
// blocks or parts or keys or nodes?
// parts -> blocks considering jsblocks.com?
// Dynamic modules loading? What if we ask for a node that is in the main modules?
// remove console from methods and add log in browser functions
// add log of the error if the app or json module is not in json format
// init, run, start -> do
// if selector is an array, repeat the action (do)
// think about html/do. Is it possible to avoid html object? Any unknown object is an html tag
// in parts, {setup:on.success} or {setup:config.color} doesn't work
// setup -> arguments
// part ui:icon: {selector:, config:} can be a js function () {var part = {}; self.run(config); }
// {arguments[0] arguments[1]. {1.setup} }
// improve shortcuts (in extendJsonFromElement and in attr)
// this.text -> this.content
// html attribute of html method -> content (should be an html but can be multilingual)
// property validation like the sintax (\w[\w+d+]) of the "name" in the "for" method )
// default "html" al posto di "text": ogni contenuto testuale viene inserito con innerHTML anziché innerTEXT
// html [] tipo array e "" stringa (innerHTML) ok, html {} deprecato
// "p": "text" -> p.innerTHTML('text')
// "p": [] -> se item è oggetto -> htmlTag, se stringa dovrebbe fare append della stringa html sempre nello p. Ora invece crea più p.innerText
// ADD: append. empty true fixed on html
/*
1 page -> url (method and property)
2 dynamic class with ternary condition
3 swal button style
4 components copy bugs
5 installation guide
6 self.page -> not the variable but the real window path and window hash (can be jsonic.url)
7 page -> url
8 "roles" -> "only"
9 add localStorage actions -> ANY WINDOW method
10 add dataStorage
10 in parts {string} instead of {value} ?
11 on load image solution (should already work on: load -> animate -> fadein)
*/
// BUGS
// BUG from Tailwind 3.3.2
// Sembra richiesto tailwind nel plugin Jsonic e non caricato dinamicamente come su eliokit.com
// Different rendering width or without spaces after commans "alert": " {js:(1 == 2) ? \"test\" : \"false condition\"} "
// HOW IT WORKS
// loadModules -> loadPlugins -> Run
// KNOWN BUGS
// in museomira.it cerca "socialIcons", rimuovendo data-value l'icona finisce dentro contatti perché il newSelector è a:eq(5)
// è necesario creare una funzione selector destinata ai nuovi elementi
// PARTS
// 1. Responsive header menu
// 2. Alert
// 3. Slide
// 4. Form
// 5. Table
// GOAL
// Reduce custom js code in Jsonic and move the functions in modules
// Requires an extension of js method to make it more flexible
// js {function: String, params: Array}
// TO DO
// inline use: data-jsonic -> jsonic.run(data-jsonic, selector); (es. in body)
// init = run (or play)
// in parts {setup} should get subreferences link {setup:on.success}
// i plugins possono includere direttamente l'url
// la gestione dei plugin dovrebbe essere centralizzata (riferimento a jsonic e non all'oggetto)
// si potrebbe definire la distinsione tra oggetti specifici e oggetti globali (jsonic)
// verificare se oggetto function con {name: , params: []} è assegnabile a variabili
// addClass, removeClass etc with array
// change the behaviour of p: [] become a a list of content, not a list of p
// to do it, search and change "div": [ "p": [ "span": [ "li": [ "button": [
// hypothesis (no, more complete with actions): class="ui:button{text:#333;bg:#fff}" -> bg-[white] text-[#333] hover:bg-[#fff] hover:text-[white]
// OPTIMIZATION: pluginsRequiredByTag only for self.json.resources.pluginsFunctions keys or better only for parts that requires plugins. alert -> ui:alert
// getJSON: load json (id: exampleApp, url: ...), success-> {getJSON:exampleApp}
// Ajax: load ajax (id: exampleApp, url: ...), success-> {ajax:exampleApp}
// DOM: queryAll(selector) -> value is string, el.before(value) and all the other methods of an element of the dom
// properties {dom:title}
// https://www.w3schools.com/jsref/dom_obj_all.asp
// DOCUMENT
// https://www.w3schools.com/jsref/dom_obj_document.asp
// {document: {title: 'test'}}
// properties {document:title}
// ON: https://www.w3schools.com/jsref/dom_obj_event.asp
// "selector" can be "query" / no selector recalls querySelector
// or APPEND/PREPEND
// https://registry.npmjs.com/-/v1/search?text=tailwindcss&size=1
//https://api.npms.io/v2/package/tailwindcss
// https://api-docs.npms.io
/*
TO DO
1. ajax call with an id to identify the data in case of simultaneous requests
1. database path should be separated by spaces (or slashes)
replaceProperties default:
check if
if p1 is a function, if p2 -> value = p1(p2), if p3 -> value = p1(p2(p3))
if p1 is a value, and not p2, value = p1
self.methods[p1] or...
p1 is a function
{alert:string}
{window.f}
{window f1:window f2:window x} = window.f1(window.f2(window.x))
{querySelector:'.class':append} = window.f(jsonic.json.var.x)
ESEMPI
{new Date:'December 17, 1995 03:24:00'}
{new Date().getDay}
{console.log:'test'}
{window.innerHeight} invece di {window:innerHeight} (specifica) o {js:window.innerHeight}
il vantaggio di questo schema è che si evita un livello di parentesi annidate
quando sono coinvolte variabili jsonic:
{querySelector:var obj x:append}
che puo diventare
{querySelector:var {item} x:append}
LIMITE
questo metodo preclude l'accesso ad eventuali oggetti javascript var o data
SOLUZIONE
in realtà, var e data devono essere elementi definiti nel json
altrimenti non sono trovati dall'interprete che può vagliare l'esistenza
di una funzione js
{path to a data} is a reference to a value in the data node of the Jsonic app
if the action context (do)
{path to an action} is a reference to a method or a sub app in the "parts" node of the Jsonic app
if the html rendering context (html)
{window.f:var x} = window.f(jsonic.json.var.x)
{window.f:num} if is number
{window.f:array} if isArray (more than one parameter)
{window.f:'string'}
{jsonic.f:var x}
do: [
"functionName": [] // parameters
]
check if functionName is a function
html tags can't have a space or points...
Align with ELIO Language:
1. "if": {"is": ["a", "=", "b","and"...] (retrocompatibile: se is è un array...)
2. "set": ["a", "+=", "1","*", "3"...] (retrocompatibile: se set è un array...)
3. "div classes": ...
CODE REDUCING
1. string in "html" object that starts with a tag and continue with classes
"html": [
"span appsDeviceListName ms-2 me-2 text-[16px] text-left w-[80%] leading-tight|content"
]
NOTES
// datapicker and other input fiels now are native https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date
COMPONENTS
MONACO TAILWINDCSS AUTOCOMPLETE (check Tailwindcss VS Code extensions)
https://github.com/remcohaszing/monaco-tailwindcss
FIREBASE STRUCTURE DATA
If you create your own keys, they must be UTF-8 encoded, can be a maximum of 768 bytes, and cannot contain ., $, #, [, ], /, or ASCII control characters 0-31 or 127. You cannot use ASCII control characters in the values themselves, either.
24.4KB gzipped (85.24KB minified)
25.2KB minified + gzipped in 100ms
65ms 3G 3 Mbps (375 KBs)
10ms 4G 20 Mbps (2,5 MBs)
<1ms 5G/Fiber 200 Mbps (25 MBs)
TEST
tailwindcss
104 KB 105 ms
INTEGRATIONS:
https://b2bsaasleads.com
NEW PLUGINS:
http://jakim.me/Toasty.js/
https://tingle.robinparisi.com
GUIDE:
COMPONENTS: reusable components / architectural philosophy
ENGINE, (no hidden code) all the parts of the app is exposed to the developer / can set the layout and the behaviour
JSON E' il modello di struttura ad albero usato da JSONIC per descrivere i dati, lo stile, e le azioni dell'applicazione
SHORTCUTS: combinations of utility names (classes) to reuse in "class" property (from WindiCSS)
// preloaded js/css plugins
{
"attr": {
"class": "py-2 text-center"
},
"subTitle": {
"lang": {
"it": "L'albero JSON dell'app può contenere i seguenti rami principali:",
"en": "The JSON app tree may contain the following main branches:",
"es": "El árbol de la aplicación JSON puede contener los siguientes ramas principales:"
}
}
},
PROPERTIES
With {property}, a string delimited by braces you can refer to any sub-branch the app tree and special properties.
-----------------------
HOME PARAGRAPHS
-----------------------
AUTO-LOADED PLUGINS
NESTED CSS
HTML has a clear nested and visual hierarchy but CSS doesn't. JSONIC let you nest your CSS definitions in a way that follows the same visual hierarchy of your HTML. It's similar to the SAAS extension but without the need to compile the code. In modo simile al linguaggio SAAS, è necessario compilare il codice
// BP
Questo dimostra che c'è bisogno di semplificazione più di quanto non si possa pensare
IDE
Special char (or shortener or autocomplete) with { } etcetera)
PRIORITY:
tags:
button: "title"
or
button: {
text: title
color: color
on: ...
}
buttonOutline: {
text: title
color: color
on: ...
}
------------------------
qualunque metodo:
[
{"path": args},
{"path": args}
{"path": args}
]
------------------------
DEBUG
class must be a string otherwise log error
style in attr must work (now error)
CONFIG (now setup)
extend the main branch {b:config}
ACTIONS (now parts)
extend the main branch {b:actions}
DO
execute one or an array of functions
"do": "actionID" (string) execute the actions.actionID function
CONTAINER (now selector)
change the context to the element {b:container}
Can be an object like {id, class, data-value}
or a string with a CSS selector like "body > div:nt-child(2)"
or a jquery-like selector like "body > div:eq(2)"
------------------------
bootstrap menu -> tailwind
------------------------
IDEAS
- share the modules in the object "jsonic" with the other jsonic objects in the page
- jsonic.registerJsMethod(name, function) register new js method to be inserted in jsonic.methods and called with "method": {params}
- choose can contain the methods "next":"1" / "previous":"1" or step "+1"/"-1"
- calendar can return the object {lang: {...}}
- self.js can be embedded in self.compile (if typeof params == 'string')
- Page doesn't exist / if admin / want to create it?
- if no jsonic file for the page, create it on save
- AUTH (debug) + GITHUB
- preload font flag
- IDE: Wordpress API new page
- window methods in (docs)
- for -> addTag (?)
- setup: form to set setup properties
- Method ARRAY
"array": {
"push": "{var:num}" (pop, shift, unshift, length)
DONE:
remove JSONIC references: jsonic.firebaseEventAction / jsonic.resizeEvent
- HOME: docs / examples / integrations
- wordpress: access to media API
- iconify
- iconify remove SVG old
- colors -> setup (mmm) (like logo)
- styles -> css -> senza categorie, solo elements '#div' -> https://transform.tools/css-to-js DONE
}
BUGS:
- version è necessario in pluginsFunctions
- shortcut as a node: attr / class values doesn't overwrite the shortcut
WORDPRESS:
(_embed to your URL will add the wp:featuremedia)
https://jsonic.io/wp-json/wp/v2/media?&context=embed&per_page=100
https://jsonic.io/wp-json/wp/v2/media?&context=embed&after=2017-11-07T00:00:00
https://jsonic.io/wp-json/wp/v2/media?include=1681,491
// https://github.com/schlosser/pig.js
NOTE:
- autoupdate only if the previous update is complete (we need a param in config complete:true/false)
- Play (create your app!)
- add a tag in menu buttons ?
- inViewport -> 'enter'/'exit' ?
- inViewport solo la prima volta?
- ('on': 'in'/out NO) confirm 'init'?
- IDE: backup timeline
- duplicato di this.selector dedicata a ottenere il selector di un nuovo elemento (su append e poco altro)
- col: [1,2,3] -> row with col1 col2 col3 ? or tailwind grid solution (ragionare su soluzione di tag. esempio: flex: [])
- in examples, test in posizione assoluta sul codice (utile su mobile)
KEY BENEFITS
- Integration (Jsonic code includes the logic, the layout and the style of the app on in one JSON object)
- Accelerator
*/
// JQUERY to Vanilla: https://youmightnotneedjquery.com | http://vanilla-js.com
// Jquery plus: https://atypiccraft.com/insights/reasons-why-we-still-use-jquery
// https://cyrilletuzi.github.io/javascript-guides/jquery-to-javascript.html
// Tools to integrate: https://bestofjs.org/tags
// MINIFY: https://closure-compiler.appspot.com/home
// https://api.giphy.com/v1/gifs/random?api_key=dc6zaTOxFJmzC&tag=cat
// INTEGRATIONS
// https://www.dropzone.dev/js/
// uploadcare
// zaiper
// a graph js tool
// anime.js
// transition.style // analogo ad animate.style
/* There were issues affecting this run of Lighthouse:
There may be stored data affecting loading performance in this location: IndexedDB. Audit this page in an incognito window to prevent those resources from affecting your scores.
// UI
https://windicss.org/play.html
https://basscss.com
https://twind.dev
https://emotion.sh/docs/introduction
https://cssinjs.org/?v=v10.8.2
https://picturepan2.github.io/spectre/
https://get.foundation
https://ant.design/
https://purecss.io
https://onsen.io/
https://shuffle.dev/
*/
//{"type": "js", "url":"https://cdn.jsdelivr.net/npm/tailwindcss@{version}/lib/index.min.js"},
//$.fn.jsonic = function(options) {return new jsonicObject(options);};
//jsonicApp = function(options) {return new jsonicObject(options);};
var jsonAppObj = function(options) {
var self = this;
console.log();
//this.options = options;
/* var json = { // the jsonic app tree
setup: {},
blocks: {}, // to be removed
parts: {},
// plugins: {}, // TO DO: remove the error if included
// css: {},
do: {},
on: {},
shortcuts: {},
texts: {},
data: {},
var: {}
}; */
//var var = json.var;
//this.setup = json.setup;
// for external access
this.json = {
setup: {},
blocks: {}, // to be removed
parts: {},
// plugins: {}, // TO DO: remove the error if included
// css: {},
functions: {},
do: {},
on: {},
shortcuts: {},
texts: {},
data: {},
var: {}
};
this.app = this.json;
//var json = self.json; // TO DO: remove
var alertObj = {};
var alertValues = {};
this.params = {}; // maybe can be removed
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'];
// Source: https://www.w3schools.com/js/js_reserved.asp
var nodes = {
//parts: ['text', 'div', 'ul', 'p', 'a', 'button', 'input', 'span', 'img', 'video', 'audio', 'source', 'figure', 'figcaption', 'textarea', 'iframe', 'table', 'thead', 'tbody', 'tfoot', 'tr', 'th', 'td', 'svg', 'path', 'g', 'd', 'polygon', 'circle', 'small', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'form', 'form-group', 'label', 'select', 'option', 'optgroup', 'nav', 'tab', 'header', 'main', 'footer', 'ide', 'model-viewer', 'i', 'icon', 'pre', 'code','animateMotion','animateTransform','circle','clipPath','defs','desc','discard','ellipse','feBlend','feColorMatrix','feComponentTransfer','feComposite','feConvolveMatrix','feDiffuseLighting','feDisplacementMap','feDistantLight','feDropShadow','feFlood','feFuncA','feFuncB','feFuncG','feFuncR','feGaussianBlur','feImage','feMerge','feMergeNode','feMorphology','feOffset','fePointLight','feSpecularLighting','feSpotLight','feTile','feTurbulence','filter','foreignObject','g','hatch','hatchpath','image','line','linearGradient','marker','mask','metadata','mpath','path','pattern','polygon','polyline','radialGradient','rect','script','set','stop','switch','symbol','text','textPath','title','tspan','use','view'],
//functions: ['do', 'function', 'for', 'run', 'module', 'page', 'html', 'text', 'empty', 'alert', 'blocks', 'attr', 'color', 'set', 'array', 'replace', 'var', 'js', 'javascript', 'if', 'switch', 'choose', 'delay', 'ajax', 'hide', 'show', 'toggle', 'in', 'out', 'link', 'scroll', 'lang', 'find', 'data', 'reload', 'calendar', 'moment', 'dayjs', 'log', 'setInterval', 'clearInterval', 'offcanvas', 'firebase', 'database', 'qrcode', 'editor', 'ace', 'code', 'thunkable', 'animate', 'sortablejs', 'uiUpdate'], // 'String', 'Number', 'Math',
//functionsWithContainer: ['for', 'editor', 'ace', 'code', 'qrcode', 'lottie', 'animate', 'html', 'hide', 'show', 'toggle', 'in', 'out', 'if', 'ajax', 'attr', 'run', 'delay'],
// not execute
extend: ['setup', 'blocks', 'parts', 'css', 'actions', 'texts', 'data', 'functions'], // also plugins? (TO DO: remove actions)
params: ['style', 'on', 'matchMedia', 'action', 'code', 'roles', 'plugins', 'css'], // 'if', 'attr', 'text'. 'html'
exclude: ['setup', 'container', 'selector', 'info', 'note', 'comment', 'lang', 'tag', 'plugins', 'template']
};
/*
* Converts a JSON object to a JSON Schema
* @param {any} json
* @param {object} options
* @returns {object} a json schema
*/
// [{"name": "vito", "gallery": {"name":2, "date":"10-10-2012"}, "num":3, "bool":true, "color": "#ff0000"}]
const FORMAT_REGEX = {
email: /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/,
url: /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/,
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]?)$/,
// J. Meijer / Stackoverflow / 15491894
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})$/,
// Joey / Stackoverflow / 1636350
color: /^#(?:[0-9a-fA-F]{3}){1,2}$|#(?:[0-9a-fA-F]{3,4}){1,2}$/,
};
this.jsonToSchema = function (json, options = {}) {
// https://github.com/mohsen1/json-to-json-schema
if (typeof json === 'function') {
throw new TypeError('Can not convert a function');
}
if (json === undefined) {
return {};
}
// primitives
if (typeof json === 'string') {
if (FORMAT_REGEX.url.test(json)) return { type: 'string', format: 'url' };
else if (FORMAT_REGEX.email.test(json)) return { type: 'string', format: 'email' };
else if (FORMAT_REGEX.ip.test(json)) return { type: 'string', format: 'ip' };
else if (FORMAT_REGEX.date.test(json)) return { type: 'string', format: 'date' };
else if (FORMAT_REGEX.color.test(json)) return { type: 'string', format: 'color' };
else return { type: 'string' };
}
else if (typeof json === 'boolean') return { type: 'boolean' };
else if (typeof json === 'number') {
if (Number.isInteger(json)) {
return { type: 'integer' };
} else {
return { type: 'number' };
}
}
else if (Array.isArray(json)) {
let schema = { type: 'array' };
if (!json.length) {
schema.items = {};
return schema;
}
let schemas = json.map(self.jsonToSchema);
// if all schemas are the same use that schema for items
if (schemas.every(s => self.isEqual(s, schemas[0]))) {
schema.items = schemas[0];
// if there are multiple schemas use oneOf
} else {
schema.items = { oneOf: unique(schemas) };
}
return schema;
}
if (json === null) {
return { type: 'null' };
}
let schema = { type: 'object' };
if (!Object.keys(json).length) {
return schema;
}
schema.properties = Object.keys(json).reduce((properties, key) => {
properties[key] = self.jsonToSchema(json[key]);
return properties;
}, {});
return schema;
};
this.isEqual = function (a, b) {
return (JSON.stringify(a) == JSON.stringify(b));
};
//var canvasElement = document.getElementById("canvas");
// * this is not important for PDFMake, it's here just to render the result *
// It's a Mozilla lib called PDFjs that handles pdf rendering directly on the browser
/* this.pdfjs = function (params, selectorParams) {
var url = params.url;
var options = params.options || { scale: 1.4 };
let container = self.selector(params.selector || params.container) || self.selector(selectorParams);
var canvasContainer = self.query(container);
function renderPage(page) {
var viewport = page.getViewport(options.scale);
var wrapper = document.createElement("div");
wrapper.className = "canvas-wrapper";
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
canvas.height = viewport.height;
canvas.width = viewport.width;
wrapper.appendChild(canvas)
canvasContainer.appendChild(wrapper);
page.render(renderContext);
}
function renderPages(pdfDoc) {
for(var num = 1; num <= pdfDoc.numPages; num++)
pdfDoc.getPage(num).then(renderPage);
}
PDFJS.disableWorker = true;
PDFJS.getDocument(url).then(renderPages);
} */
//renderPDF('https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/examples/learning/helloworld.pdf', document.querySelector('#canvas'));
/* this.localStorage = function (params) {
// -> use self.method
if (params.getItem) return localStorage.getItem(params.get);
else if (params.setItem) return localStorage.setItem(params.setItem.name, params.setItem.value);
} */
// UTILITY
/** A storage solution aimed at replacing jQuerys data function.
* Implementation Note: Elements are stored in a (WeakMap)[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap].
* This makes sure the data is garbage collected when the node is removed.
*/
this.dataStorage = {
_storage: new WeakMap(),
set: function (element, key, obj) {
if (!this._storage.has(element)) {
this._storage.set(element, new Map());
}
this._storage.get(element).set(key, obj);
},
get: function (element, key) {
return this._storage.get(element).get(key);
},
has: function (element, key) {
return this._storage.has(element) && this._storage.get(element).has(key);
},
remove: function (element, key) {
var ret = this._storage.get(element).delete(key);
if (!this._storage.get(element).size === 0) {
this._storage.delete(element);
}
return ret;
}
};
// JQUERY cross-over
this.extend = function (out) {
if (typeof arguments[0] == 'boolean' && arguments[0] == true)
return deepExtend(out);
else {
out = out || {};
for (var i = 1; i < arguments.length; i++) {
if (!arguments[i])
continue;
for (var key in arguments[i]) {
if (arguments[i].hasOwnProperty(key))
out[key] = arguments[i][key];
}
}
return out;
}
};
var deepExtend = function (out) {
out = out || {};
for (var i = 1; i < arguments.length; i++) {
var obj = arguments[i];
if (!obj) continue;
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === "object" && obj[key] !== null) {
if (obj[key] instanceof Array) out[key] = obj[key].slice(0);
else out[key] = deepExtend(out[key], obj[key]);
} else out[key] = obj[key];
}
}
}
return out;
};
/* this.actionResult = function(value, args) { // value -> params
// Methods with a result
if (value && typeof value == 'object') {
// jsonic methods
if (value.js) {
return self.js(value.js, args);
} else if (value.array) {
return self.array(value.array, args);
} else if (value.calendar) {
return self.calendar(value.calendar, args);
} else if (value.data) {
return self.data(value.data, args);
} else if (value.var) {
return self.var(value.var, args);
} else if (value.module) {
return self.module(value.module, args);
} else if (value.color) {
return self.color(value.color, args);
} else if (value.css) {
return self.css(value.css, undefined, args);
} else if (value.if) {
return self.if(value.if, undefined, args);
} else if (value.switch) {
return self.switch(value.switch, args);
} else if (value.database) {
return self.database(value.database, args);
// js methods
} else if (value.Math) {
return self.Math(value.Math, args);
} else if (value.Number) {
return self.Number(value.Number, args);
} else if (value.String) {
return self.String(value.String, args);
// plugin methods
} else if (value.ace) {
return self.ace(value.ace, args);
// else if (value.code) {
// return self.code(value.code, args);
} else if (value.moment) {
return self.moment(value.moment, args);
} else if (value.dayjs) {
return self.dayjs(value.dayjs, args);
} else if (value.function) { // TO DO: remove (replaced by do)
return self.function(value.function, value.params);
} else {
return value;
}
} else {
return value
}
//} else if (typeof value == 'string') {
// return self.javascript(value, args);
} */
this.var = function (params, args) {
if (Array.isArray(params)) {
for (var index in params)
self.var(params[index], args);
} else {
//self.log('var');
var name;
var value;
var varValue;
if (params.path && !params.name)
name = self.path(params.path, args, '.');
if (typeof params == 'string') {
// gives a variable value
name = self.replaceProperties(params, args);
/* self.log('name');
self.log(name); */
/* self.log('typeof params == string');
self.log('params');
self.log(params);
self.log('name');
self.log(params); */
varValue = self.docElement('self.json.var.' + name);
/* self.log('varValue');
self.log(varValue); */
} else {
/* self.log('var');
self.log('params');
self.log(params);
self.log('args');
self.log(args); */
//self.log('params');
//self.log(params);
var paramsReplaced = self.replaceProperties(params, args);
//self.log('paramsReplaced');
//self.log(paramsReplaced);
name = paramsReplaced.name;
value = paramsReplaced.value;
var operator = paramsReplaced.operator;
var type = paramsReplaced.type;
/* self.log('extend');
self.log(extend); */
if (name) {
var pathString = 'self.json.var.' + name;
var pathLast = pathString.substr(pathString.lastIndexOf(".") + 1);
var pathBase = pathString.substr(0, pathString.lastIndexOf("."));
var varObj = self.docElement(pathBase);
/* self.log('name');
self.log(name);
self.log('pathBase');
self.log(pathBase);
self.log('pathLast');
self.log(pathLast);
self.log('varObj');
self.log(varObj); */
if (value !== undefined) {
//if (value == 'string')
// value = self.docElement('self.json.var.'+value); // todo
//else
value = self.actionResult(value, args);
// typization
switch (type) {
case 'string': value = String(value); break;
case 'number': value = Number(value); break;
case 'boolean': value = Boolean(value); break;
case 'array': value = JSON.parse(value); break;
case 'object': value = JSON.parse(value); break;
}
//self.log('value');
//self.log(value);
/*
// reset
if (value == undefined && typeof value == 'string') value = '';
if (value == undefined && typeof value == 'number') value = 0;
if (value == undefined && typeof value == 'object') value = {}; */
/* self.log('operator');
self.log(operator);
self.log('pathLast');
self.log(pathLast);
self.log('varObj[pathLast]');
self.log(varObj[pathLast]); */
if (varObj && pathLast) {
switch (operator) {
case '+=': varObj[pathLast] += value; break;
case '-=': varObj[pathLast] -= value; break;
case '/=': varObj[pathLast] /= value; break;
case '*=': varObj[pathLast] *= value; break;
default: varObj[pathLast] = value; break;
}
/* operators: [
'=', '>', '<', '!', '~', '?', ':', '==', '<=', '>=', '!=',
'&&', '||', '++', '--', '+', '-', '*', '/', '&', '|', '^', '%',
'<<', '>>', '>>>', '+=', '-=', '*=', '/=', '&=', '|=', '^=',
'%=', '<<=', '>>=', '>>>='
], */
//self.log('varObj[pathLast]');
varValue = varObj[pathLast];
} else {
/* self.log('pathString');
self.log(pathString); */
//varValue = self.docElement(pathString, value);
//varValue = value;
self.docElement(pathString, value);
/* self.log('name');
self.log(name);
self.log('var '+name);
self.log(self.var(name)); */
}
/* self.log('pathLast');
self.log(pathLast);
self.log('varObj[pathLast]');
self.log(varObj[pathLast]); */
/* //alert(value);
//value = self.replaceProperties(value, args);
if (value == 'string') {
//self.json.var[name] = self.docElement('self.json.var.'+value);
varObj[pathLast] = self.docElement('self.json.var.'+value);
} else {
//self.json.var[name] = self.actionResult(value, args);
varObj[pathLast] = self.actionResult(value, args);
} */
//self.log('varObj[pathLast]');
//if (self.isJson(self.json.var[name]))
// self.json.var[name] = self.parse(self.json.var[name]);
} else if (paramsReplaced.push) {
if (varObj && pathLast && varObj[pathLast]) {
varObj[pathLast] = varObj[pathLast].push(paramsReplaced.push);
varValue = varObj[pathLast];
}
} else if (paramsReplaced.extend) {
if (varObj && pathLast && varObj[pathLast]) {
varObj[pathLast] = self.extend({}, varObj[pathLast], paramsReplaced.extend);
varValue = varObj[pathLast];
}
} else {
// no "value" property: return the value of the var "name"
varValue = varObj[pathLast];
/* varValue = self.replaceProperties(varObj[pathLast], args);
alert(JSON.stringify(varValue)); */
}
//varValue = self.json.var[name] || {}; // to check
} else {
self.log('var name undefined');
self.log(params);
varValue = undefined;
}
if (params.do && params.do.length > 0) {
self.log('this.var params.do');
self.log(params.do);
//alert(JSON.stringify(params.do));
//self.do(params.do, args);
self.do(params.do, undefined, args);
}
}
return varValue;
}
};
this.find = function (params, args) {
if (params.in) {
var list = self.replaceProperties(params.in, args);
return list.filter(function (item) {
if (params.value) {
if (typeof params.value == 'string') {
if (JSON.stringify(item).indexOf(params.value) >= 0)
return item;
} else { // if (typeof params.value == 'string') {
for (var key in params.value) {
if (params.value[key] == item[key])
return item;
}
}
}
});
}
};
/* this.data = function (params, args) {
if (typeof params == 'string')
return self.db(params, args);
else
self.firebase(params, args);
} */
this.array = function (params, args) {
/* self.log("---- this.array ----");
self.log('params');
self.log(params); */
if (args)
params = self.replacePropertyWithPrefix(params, 'result', args);
for (var par in params) {
var paramReplaced = self.replaceProperties(params[par], args);
//value[par](params[par]) // ipotesi di eseguire in automatico qualunque funzione js su stringhe
/* self.log("par");
self.log(par);
self.log("params[par]");
self.log(params[par]);
self.log("paramReplaced");
self.log(paramReplaced); */
params[par] = paramReplaced;
}
//self.log("params");
//self.log(params);
var value = self.element({ path: params.name }) || [];
/* self.log("value");
self.log(...value); */
if (params.push) {
if (Array.isArray(params.push))
value.push(...params.push);
else
value.push(params.push);
}
if (params.unshift) value.unshift(...params.unshift);
if (params.pop) return value.pop(params.pop);
if (params.shift) return value.shift(params.shift);
self.element({ path: params.name, value: value });
};
this.replace = function (params, args) {
// self.log("---- this.replace ----");
params = self.replacePropertyWithPrefix(params, 'result', args);
/* self.log("params");
self.log(params); */
var value = self.element({ path: params.path }) || [];
var to = params.to || '';
var type = typeof value;
/* self.log("type");
self.log(type); */
if (type !== "string") value = JSON.stringify(value);
/* self.log("value 1");
self.log(value); */
if (params.from) value = self.replaceAll(value, params.from, to);
/* self.log("value2 ");
self.log(value); */
switch (type) {
case "number":
value = Number(value);
break;
case "boolean":
value = Boolean(value);
break;
case "object":
value = JSON.parse(value);
break;
}
/* self.log("value 3");
self.log(value); */
//return value;
return self.element({ path: params.path, value: value });
};
this.unshift = function (params, args) {
for (var param in params) {
var path = self.replaceProperties(param, args);
var value = self.replaceProperties(params[param], args);
if (value) {
var obj = self.element({ path: path }) || [];
obj.unshift(value);
self.element({ path: path, value: obj });
}
}
};
this.set = function (params, args) {
if (Array.isArray(params)) { // 1.0.5
for (var obj of params)
self.set(obj, args);
} else {
for (var param in params) {
var value = params[param];
if (value) value = self.replaceProperties(value, args, false); // TO DO: check
if (value && args) value = self.replacePropertyWithPrefix(value, 'result', args); // backward compatibility TO DO: remove
self.element({ path: param, value: value });
}
}
//return true
};
this.get = function (element) {
//self.log('self.get');
if (element.startsWith('\''))
return String(element.match(/\'([^\']*)\'/)[1]); // stringa racchiusa tra apici (serve?)
else if (element.startsWith('Boolean'))
return Boolean(element.match(/Boolean\(([^\)]*)\)/)[0]); // Boolean(x)
else if (element.startsWith('Number'))
return Number(element.match(/Number\(([^\)]*)\)/)[0]); // Number(x)
else if (element.startsWith('String'))
return String(element.match(/String\(([^\)]*)\)/)[0]); // String(x)
else
return (self.docElement(element)); // ora le tipizzazioni sono già in docElement grazie a eval
};
this.getJSON = function (url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'json';
xhr.onload = function () {
var status = xhr.status;
if (status === 200) {
callback(null, xhr.response);
} else {
callback(status, xhr.response);
}
};
xhr.send();
};
/*---------------------
var
---------------------*/
var database, auth, storage;
this.listeners = {};
this.resizeActions = {};
/* var iconsFile;
this.device = false; // touch device
this.touch = 'mousedown'; if (this.device) {this.touch = 'touchstart';}
var animations = {};
var tweenLoading;
var tasksIntervals = {};
var timedTasks = {'yearly':{},'monthly':{},'daily':{},'hourly':{}, '10mins':{}, '5mins':{}, '30mins':{}, '1min':{}, '30sec': {}, '10sec': {}, '1sec': {}}; */
/* this.dateSelection; // = {day:0, month:0, year:0};
this.timeSelection = {hour:0, min:0, sec:0, ampm:'AM', allday:true};
this.timeSelectionCallback = null; */
/*--------------------
FIREBASE
--------------------*/
//var firebaseInitialized = false;
this.firebaseVerifyUser = function (data) {
self.log('firebaseVerifyUser');
//self.log(data);
//self.log(data.code);
if (self.params.oobCode) {
var oobCode = self.params.oobCode;
auth.applyActionCode(oobCode).then(function (resp) {
// self.log('resp');
// self.log(resp);
self.alert({
//toast: true,
icon: "success",
title: "titVerifyEmail",
html: "msgVerifyEmail",
confirmButtonText: "btnOk",
//showCancelButton: false,
confirm: function () {
//self.reload();
// self.do(data);
window.location.href = "/app/index.html";
}
});
}).catch(function (error) {
self.log('error');
self.alert({
icon: "error",
title: "titWarning",
html: error.code + " - " + error.message,
confirmButtonText: "btnOk",
//showCancelButton: false,
confirm: function () {
// self.reload();
// self.do(data);
window.location.href = "/app/index.html";
}
});
});
// verifica su auth
}
//data.code / data.params.code
//self.do(data);
self.do(data);
};
/* this.firebaseInit = function (data) {
self.log("firebaseInit");
if (json.setup && json.setup.firebase) {
//var.databaseURL = json.setup.firebase.databaseURL;
firebase.initializeApp(json.setup.firebase);
database = firebase.database();
auth = firebase.auth();
// if (self.json.plugins['firebase-storage'].active) OR find in self.json.plugins name: 'firebase-storage'
//storage = firebase.storage();
auth.onAuthStateChanged(user => {
self.json.var.user = user;
if (!user) {
// No user logged in
self.log('onAuthStateChanged:GUEST\n');
// non bisognerebbe chiedere sempre di fare login
} else {
// User logged in
self.log('onAuthStateChanged:USER\n');
self.log('name: '+self.user('displayName') + '\nemail: '+user.email + '\nuid: '+ user.uid);
}
//self.log('firebaseInitialized');
//self.log(firebaseInitialized);
if (!firebaseInitialized) {
firebaseInitialized = true;
self.do(data);
}
});
} else {
self.do(data);
}
} */
this.sendMail = function (data) {
self.log('sendMail');
var emailParams = {
Host: "smtp.mailgun.com",
Username: "vito@nuvolaria.com",
Password: "bee02191be84c784a665fa98c61e03ce-915161b7-d32cb9d0",
From: data.from,
To: data.to,
Subject: data.subject,
Body: data.html
};
Email.send(emailParams).then(
message => self.alert({
icon: 'success',
title: 'titEmailSuccess',
confirmButtonText: 'btnClose'
})
);
/*
"from": "gianfrancoguglielmi@gmail.com",
"to": "vito.minchilli@gmail.com",
"subject": "Prova oggetto",
"html": "Prova testo",
"text": "Prova testo"
*/
/*
var SERVER_NODEJS_BASEURL='https://app.fixo.io:4002';
var params = {
rom: data.from,
to: data.to,
subject: data.subject,
html: data.html,
text: data.text
};
$.ajax({
type: "POST",
'beforeSend': function(xhr) {
xhr.setRequestHeader('Accept', 'application/json');
xhr.setRequestHeader('Content-Type', 'application/json');
},
data: JSON.stringify(params),
url: SERVER_NODEJS_BASEURL + '/sendMail',
success: function(data) {
self.log('sendMail SUCCESS');
self.log(data);
self.do(data);
},
error: function(error) {
self.log('sendMail ERROR');
self.log(error);
self.do(data);
}
});
*/
};
//var multipleFiles = [];
/* this.fileDownload = function (url) {
self.log('fileDownload');
self.log(url);
var fileArr = url.split('?');
self.log(fileArr);
//var file = fileArr[0];
var urlArr = fileArr[0].split('/');
self.log(urlArr);
var name = urlArr[urlArr.length-1];
self.log(name);
var token = self.getParameterByName('token', url);
self.log(token);
window.location.href = '/app/php/proxy.php?name='+ name + '&url='+ url;
} */
/* this.fileUrl = function (params) {
// da nome file a l'url Firebase Storage inclusiva del token
self.log('fileUrl');
self.log(params);
// self.log('storage');
// self.log(storage);
if (storage) {
var storageRef = storage.ref();
var pathReference = storageRef.child(params.user+'/'+params.name);
pathReference.getDownloadURL().then(function(url) {
if (params.callback) params.callback(url);
}).catch(function(error) {
if (error && error.code && params.error) {
self.log(self.firebaseStorageError(error.code));
params.error(error.code);
}
// A full list of error codes is available at
// https://firebase.google.com/docs/storage/web/handle-errors
});
} else {
self.log('storage undefined');
}
} */
/* this.firebaseStorageError = function (errorCode) {
switch (errorCode) {
case 'storage/object-not-found':
// File doesn\'t exist
return 'File doesn\'t exist';
case 'storage/unauthorized':
// User doesn\'t have permission to access the object
return 'User doesn\'t have permission to access the object';
case 'storage/canceled':
// User canceled the upload
return 'User canceled the upload';
case 'storage/unknown':
// Unknown error occurred, inspect the server response
return 'Unknown error occurred, inspect the server response';
default:
return 'No error'
}
} */
var x = [{ if: 3 }, function () { }, 3, []];
this.firebaseAddListener = function (params) {
/* self.log('firebaseAddListener');
self.log(params); */
// {path, orderByChild, equalTo}
//self.log(params.path);
if (database) {
// Aggiunge listener in ascolto su params.path che esegue params.action
if (params.action) {
if (!self.listeners[params.path]) self.listeners[params.path] = [];
/* alert('params.action:'+params.action);
alert('type params.action:' + typeof params.action);
alert(params.path+':'+JSON.stringify({
action: params.action
})); */
//if (Array.isArray(params.action))
// self.listeners[params.path].concat(params.action);
//else
self.listeners[params.path].push(params.action);
}
/* if (params.success !== undefined) {
alert('params.success:'+params.success);
alert('type params.success:' + typeof params.success);
alert(params.path+':'+JSON.stringify({
success: params.success
}));
self.listeners[params.path].push(params.success);
} */
//self.log('params.path: '+ params.path);
//self.listeners[params.path] = params.action;
//alert(self.listeners[params.path]);
/*
limitToFirst() Sets the maximum number of items to return from the beginning of the ordered list of results.
limitToLast() Sets the maximum number of items to return from the end of the ordered list of results.
startAt() Return items greater than or equal to the specified key or value, depending on the order-by method chosen.
startAfter() Return items greater than the specified key or value depending on the order-by method chosen.
endAt() Return items less than or equal to the specified key or value, depending on the order-by method chosen.
endBefore() endBefore() Return items less than the specified key or value depending on the order-by method chosen.
equalTo() Return items equal to the specified key or value, depending on the order-by method chosen.
orderByChild() Order results by the value of a specified child key or nested child path.
orderByKey() Order results by child keys.
orderByValue() Order results by child values.
orderByPriority() Order results by priority
https://firebase.google.com/docs/reference/js/v8/firebase.database.Query
*/
//Firestore.collection(collectionName).orderBy(field).where(field, ">=", keyword.toUpperCase()).where(field, "<=", keyword.toUpperCase() + "\uf8ff").get()
// https://medium.com/feedflood/filter-by-search-keyword-in-cloud-firestore-query-638377bf0123
// https://firebase.google.com/docs/database/rest/retrieve-data?hl=it#range-queries
// startAt , endAt , limitToFirst , limitToLast o equalTo
//databaseReference.orderByChild('_searchLastName').startAt(queryText).endAt(queryText+"\uf8ff")
// where ("string, "in"/"not-in", array)
// https://firebase.google.com/docs/firestore/query-data/queries?hl=it#in_and_array-contains-any
var dbRef = database.ref(params.path);
dbRef.off();
if (params.orderByChild) dbRef = dbRef.orderByChild(params.orderByChild);
if (params.orderByKey) dbRef = dbRef.orderByKey(params.orderByKey);
if (params.orderByValue) dbRef = dbRef.orderByValue(params.orderByValue);
if (params.equalTo) dbRef = dbRef.equalTo(params.equalTo);
if (params.startAt) dbRef = dbRef.startAt(params.startAt);
if (params.startAfter) dbRef = dbRef.startAfter(params.startAfter);
if (params.endAt) dbRef = dbRef.endAt(params.endAt);
if (params.endBefore) dbRef = dbRef.endBefore(params.endBefore);
if (params.limitToFirst) dbRef = dbRef.limitToFirst(params.limitToFirst);
if (params.limitToLast) dbRef = dbRef.limitToLast(params.limitToLast);
if (params.where) dbRef = dbRef.where(params.where[0], params.where[1], params.where[2]); // maybe params.where in enough
var feedback = dbRef.on('value', firebaseEvent);
//console.log(feedback);
/* console.log('dbRef');
console.log(dbRef);
*/
/* if (params.orderByChild && params.equalTo)
dbRef.orderByChild(params.orderByChild).equalTo(params.equalTo).on('value', firebaseEvent);
else
dbRef.on('value', firebaseEvent); */
} else {
self.log('database undefined');
// Restart the db
}
};
var firebaseEvent = function (snapshot) {
console.log(snapshot.val());
var ref = snapshot.ref;
if (snapshot.val() !== undefined) {
var dbVal = snapshot.val();
var path = snapshot.ref.toString();
//if (!dbVal) dbVal = {};
var pathArr = path.split(/\.\w+\//);
var dbPath = pathArr[1];
self.log('firebaseEvent: ' + dbPath);
//if (var.databaseURL) dbPath = path.substr(var.databaseURL.length+1);
//else dbPath = path;
/* self.log('path: '+ path);
//self.log('var.databaseURL: '+ var.databaseURL);
self.log('dbPath: '+ dbPath); */
if (dbVal)
self.localDbUpdate(dbVal, dbPath);
else {
var dbObj = self.element({ path: 'self.json.var.db.' + self.replaceAll(dbPath, '/', '.') });
if (dbObj)
dbObj = null;
//delete dbObj;
}
//self.do(self.listeners[dbPath], dbVal);
}
};
this.localDbUpdate = function (newObj, dbPath) {
/* self.log('localDbUpdate');
self.log(newObj);
self.log(dbPath); */
//var path = newObj.path;
//delete newObj.path;
/* self.do(
{
var: {
name: "db."+self.replaceAll(dbPath, '/', '.'),
value: newObj,
//success: function () {
// self.do(self.listeners[dbPath], newObj);
//}
}
}
); */
//alert('db.'+self.replaceAll(dbPath, '/', '.'));
/* var dbUpdateAction = {
var: {
name: 'db.'+self.replaceAll(dbPath, '/', '.'),
value: newObj
//do: (self.listeners[dbPath] && self.listeners[dbPath].length > 0) ? self.listeners[dbPath] : undefined
}
};
if (self.listeners[dbPath] !== undefined && self.listeners[dbPath] !== null && self.listeners[dbPath].length > 0)
dbUpdateAction.var.do = self.listeners[dbPath];
newObj.path = dbPath;
self.do(dbUpdateAction, newObj); */
// TO DO: decide l'utente dove salvare i dati
newObj = Object.fromEntries(Object.entries(newObj).reverse());
//newObj = Object.keys(newObj).reverse();
self.element({ path: 'self.json.var.db.' + self.replaceAll(dbPath, '/', '.'), value: newObj });
if (self.listeners[dbPath] !== undefined && self.listeners[dbPath] !== null && self.listeners[dbPath].length > 0) {
newObj.path = dbPath;
if (self.listeners[dbPath]) {
self.methods.firebaseEvent.action(newObj);
//self.do(self.listeners[dbPath], newObj);
self.do(self.listeners[dbPath], undefined, newObj);
}
}
};
this.firebaseRemoveListener = function (params) {
// Rimuove listener in ascolto su data.path
self.log('firebaseRemoveListener');
if (self.listeners[params.path]) {
delete self.listeners[params.path];
var dbRef = database.ref(params.path);
dbRef.off();
}
};
// Rimuove un elemento del database
this.firebaseRemove = function (path, callback) {
self.log('firebaseRemove');
self.log(path);
if (database) {
var result, dbRef;
if (path) {
dbRef = database.ref().child(path);
} else {
dbRef = database.ref();
}
return dbRef.remove(function (error) {
//Dati impostati con successo
if (error == null) {
self.log('set SUCCESS');
result = { success: true };
} else {
self.log('set ERROR');
//Errore inserimento dati
result = { success: false, error: error };
}
if (callback) callback(result);
});
} else {
self.log('database not initialized');
}
};
// Write or replace data to a defined path
this.firebaseSet = function (path, value, callback) {
/*
set Write or replace data to a defined path, like messages/users/
update Update some of the keys for a defined path without replacing all of the data
push Add to a list of data in the database. Every time you push a new node onto a list, your database generates a unique key, like messages/users//
transaction Use transactions when working with complex data that could be corrupted by concurrent updates
*/
if (database) {
var result, dbRef;
if (path) {
dbRef = database.ref().child(path);
} else {
dbRef = database.ref();
}
return dbRef.set(value, function (error) {
//Dati impostati con successo
if (error == null) {
self.log('set SUCCESS');
result = { success: true };
} else {
self.log('set ERROR');
//Errore inserimento dati
result = { success: false, error: error };
}
if (callback) callback(result);
});
} else {
self.log('database not initialized');
}
};
// Update some of the keys for a defined path without replacing all of the data
this.firebaseUpdate = function (path, value, callback) {
self.log('firebaseUpdate');
self.log('path');
self.log(path);
self.log('value');
self.log(value);
if (database) {
var result, dbRef;
if (path) {
dbRef = database.ref().child(path);
} else {
dbRef = database.ref();
}
return dbRef.update(value, function (error) {
//Dati impostati con successo
if (error == null) {
self.log('update SUCCESS');
result = { success: true };
} else {
self.log('update ERROR');
//Errore inserimento dati
result = { success: false, error: error };
}
if (callback) callback(result);
});
} else {
self.log('database not initialized');
}
};
// Add to a list of data in the database. Every time you push a new node onto a list, your database generates a unique key, like messages/users//
this.firebasePush = function (path, value, callback) {
self.log('firebasePush');
self.log(path);
if (database) {
var result, dbRef;
if (path) {
dbRef = database.ref().child(path);
} else {
dbRef = database.ref();
}
return dbRef.push(value, function (error) {
//Dati impostati con successo
if (error == null) {
self.log('push SUCCESS');
result = { success: true };
} else {
self.log('push ERROR');
//Errore inserimento dati
result = { success: false, error: error };
}
if (callback) callback(result);
});
} else {
self.log('database not initialized');
}
};
// https://firebase.google.com/docs/database/security/rules-conditions
// tutte le get / o listeners / potrebbero essere basate su orderByChild("owner")
/*
rooms": {
// this rule applies to any child of /rooms/, the key for each room id
// is stored inside $room_id variable for reference
"$room_id": {
"topic": {
// the room's topic can be changed if the room id has "public" in it
".write": "$room_id.contains('public')"
}
}
}
*/
/* this.firebaseQuery = function(params) {
self.log('firebaseQuery');
self.log(params);
// path = 'users/'+self.user('email')
// value = 'guest'
var dbRef = database.ref(params.path);
if (!params.result) params.result = {};
if (params.value && !Array.isArray(params.value)) {
var buffer = params.value;
params.value = [];
params.value[0] = buffer;
}
//self.log('params.value');
//self.log(params.value);
if (params.value && params.value.length > 0) {
var value = params.value.shift();
//self.log('value');
//self.log(value);
//self.log('params.key');
//self.log(params.key);
dbRef.orderByChild(params.key).equalTo(value).once('value', (object) => {
self.log('object');
self.log(object);
if(object) {
params.result = self.extend(params.result, object.val());
if (params.value.length > 0)
self.firebaseQuery(params);
else
params.callback({
success: true,
error: null,
data: params.result
});
} else {
//self.log('firebaseQuery ERROR');
//result = {success:false, error:8};
params.callback({
success:true,
error:null,
data: params.result
});
}
});
} else {
params.callback({success:false, error:null});
}
} */
this.firebaseGetPart = function (params) {
self.log('firebaseGetPart');
let remotePath = self.replaceAll(params.localPath, '.', '/');
self.log('localPath:' + params.localPath);
//self.log('remotePath:'+remotePath);
if (self.partContainers[params.localPath]) {
self.partContainers[params.localPath].push(params);
} else {
self.partContainers[params.localPath] = [];
self.partContainers[params.localPath].push(params);
dbRef = database.ref().child(remotePath);
return dbRef.once('value').then(function (object) {
//Dati recuperati con successo
if (object) {
self.log('firebaseGetPart SUCCESS');
self.log(object);
// local db update
if (object.val() !== undefined) {
window.dbVal = object.val();
var dbVal = object.val();
self.log('dbVal');
self.log(dbVal);
if (dbVal !== null) {
let fullPath = object.ref.toString();
let pathArr = fullPath.split(/\.\w+\//); // split on the domain extension
let dbPath = pathArr[1]; // path after the domain extension
let localPath = self.replaceAll(dbPath, '/', '.');
//var dbPath = path.substr(var.databaseURL.length+1);
self.log('dbPath: ' + dbPath);
self.log('localPath: ' + localPath);
//self.log('self.partContainers[localPath]');
//self.log(self.partContainers[localPath]);
self.element({ path: localPath, value: dbVal });
for (partObj of self.partContainers[localPath]) {
/* self.log('partObj');
self.log(partObj); */
let part = self.replacePropertyWithPrefix(dbVal, 'setup', partObj.setup);
part = self.replacePropertyWithPrefix(part, 'arg', partObj.arg);
self.extendJsonFromElement(part); // or selectorParams
/* self.log('part');
self.log(part); */
self.html(part, partObj.container);
//self.run(part, partObj.container);
//self.run(dbVal, container);
}
}
}
} else {
self.log('firebaseGetPart ERROR');
result = { success: false, error: 8 };
}
//self.log(result);
//callback(result);
});
}
};
/* {
"database": {
"do": "get",
"path": "apps/dev/{setup:key}",
"on": {
"success": [
{ */
this.firebaseIncrease = function (params) {
console.log('firebaseIncrease');
self.firebaseGet(params.path, function (result) {
console.log(result);
if (result.success) {
if (result.data === null || result.data === undefined || typeof result.data == 'number') {
var counter = Number(result.data) + 1;
console.log('counter:' + counter);
self.firebaseSet(params.path, counter, function (result) {
if (result.success) {
self.log('firebaseIncrease SUCCESS');
if (params.on && params.on.success) self.do(params.on.success, undefined, result);
} else {
if (params.on && params.on.error) self.do(params.on.error, undefined, result);
}
});
} else {
if (params.on && params.on.error) self.do(params.on.error, undefined, result);
}
} else {
if (params.on && params.on.error) self.do(params.on.error, undefined, result);
}
});
};
this.firebaseGet = function (path, callback) {
self.log('firebaseGet:' + path);
var result = { success: false, error: 7 };
if (path) {
// try, if path is wrong "Uncaught TypeError: Cannot read properties of undefined (reading 'ref')"
dbRef = database.ref().child(path);
} else {
dbRef = database.ref();
}
/* if (false) { //path == 'files') {
//alert(self.user('email'));
return dbRef.orderByChild('users/'+self.user('email')).equalTo('guest').on('value', (object) => {
//return dbRef.orderByChild('prefs/authorId').equalTo(self.user('uuid')).on('value', (object) => {
//return dbRef.orderByChild('users').equalTo(self.user('email')).on('value', (object) => {
//self.log(object);
//var user = object.val();
//Dati recuperati con successo
if(object) {
result = {success:true, error:null, data: object.val()};
} else {
self.log('get ERROR');
//Errore recupero dati
result = {success:false, error:8};
}
//self.log(result);
callback(result);
});
} else { */
// ATTENZIONE: va intercettato e loggato l'errore di accesso negato dalle regole
return dbRef.once('value').then(function (object) {
//Dati recuperati con successo
if (object) {
self.log('get SUCCESS');
result = { success: true, error: null, data: object.val() };
// local db update
if (object.val() !== undefined) {
var dbVal = object.val();
var path = object.ref.toString();
if (!dbVal) dbVal = {};
var pathArr = path.split(/\.\w+\//); // split on the domain extension
var dbPath = pathArr[1]; // path after the domain extension
//var dbPath = path.substr(var.databaseURL.length+1);
self.log('dbPath: ' + dbPath);
self.localDbUpdate(dbVal, dbPath);
}
} else {
self.log('get ERROR');
//Errore recupero dati
result = { success: false, error: 8 };
}
//self.log(result);
callback(result);
});
//}
};
this.stringToKey = function (str) {
return str.replace(/\./g, '%2E');
};
this.keyToString = function (key) {
return key.replace(/%2E/g, '.');
};
this.firebaseKey = this.getKey = function (path) {
var dbRef = database.ref(path);
return dbRef.child(path).push().getKey();
};
// --------------
// SELECTOR
// --------------
this.exist = function (selector) {
console.log('selector');
console.log(selector);
console.log(Boolean(self.query(selector)));
return Boolean(self.query(selector));
};
this.count = function (selector) {
//self.log('count:'+selector+ '='+ self.queryAll(selector).length);
return self.queryAll(selector).length;
/* if (selector) {
var routes = selector.split(/[ >]+/);
if (!element) element = document;
for (var index in routes) {
var route = routes[index];
//onsole.log('route');
//self.log(route);
var routeParts = route.match(/(.*):eq\((\d*)\)/);
//self.log('routeParts');
//self.log(routeParts);
if (routeParts) {
var routeElement = String(routeParts[1]);
var routeIndex = Number(routeParts[2]);
element = element.querySelectorAll(routeElement)[routeIndex];
} else {
element = element.querySelectorAll(route)[0];
}
} */
/* var elements = self.query(selector);
if (elements)
return elements.querySelectorAll().length;
else
return 0 */
/* if (self.exist(selector))
return document.querySelectorAll(selector).length;
else
return 0 */
};
var log = function (id, value) {
self.log(id);
self.log(value);
};
this.classSelector = function (selClass) {
if (selClass.indexOf('.') == 0) { selClass = String(selClass).substr(1); } // backward compatibility
let classes = selClass.split(' ');
selClass = classes[0];
/* self.log('selClass');
self.log(selClass); */
// avoid dynamic classes as selector
var regex = new RegExp('[\-][\[]');
if (selClass && selClass.match(regex)) selClass = classes[1];
if (selClass && selClass.match(regex)) selClass = classes[2];
return selClass;
};
this.selector = function (params, containerParams, selectAll) {
// {container, class, value, id}
var selector;
if (params) {
if (typeof params == 'string') {
/* self.log('this.selector');
self.log(params); */
return params;
} else if (Array.isArray(params)) {
return params;
} else {
var selContainer;
if (params.selector || params.container)
selContainer = params.selector || params.container;
else if (containerParams)
selContainer = containerParams.selector || containerParams.container;
//var selContainer = container; //data.container;
var attr = (params.attr) ? params.attr : {};
var selId = (attr.id) ? attr.id : params.id;
var selClass = (attr.class) ? attr.class : params.class;
var selValue = (attr.value) ? attr.value : params.value;
var selDataValue = (attr['data-value']) ? attr['data-value'] : params['data-value'];
selValue = selDataValue || selValue;
if (selId) selId = self.replaceProperties(selId);
if (selValue) selValue = self.replaceProperties(selValue);
if (selClass) selClass = self.replaceProperties(selClass);
/* if (selId) selId = self.compile(selId);
if (selValue) selValue = self.compile(selValue);
if (selClass) selClass = self.compile(selClass); */
// use the first class as selector
if (selClass)
selClass = self.classSelector(selClass);
//if (!selectAll) selClass = undefined;
if (selId) {
selector = '#' + selId;
} else if (selValue && selClass) {
selector = '.' + selClass + '[data-value="' + selValue + '"]';
} else if (selValue && params.tag) {
selector = params.tag + '[data-value="' + selValue + '"]';
} else if (selClass && selectAll) {
selector = '.' + selClass;
//if (!selectAll)
// selector += ':eq(' + self.count(selector) + ')';
// qui c'è / c'era un baco:
// quando proviamo a eseguire un'azione su un elemento esistente
// usando solo la classe come selector, $(selector).length = 1
// quindi prova a selezionare il secondo elemento eq(1), non il primo eq(0)
} else if (params.tag) {
//if (selContainer) selector = selContainer;
selector = params.tag;
if (selContainer) {
selector = selContainer + ' > ' + params.tag;
if (!selectAll) {
//if (count !== $(selector).length) self.log('>> '+ selector + ' count:'+ self.count(selector) + ' !== ' + $(selector).length );
selector += ':eq(' + self.count(selector) + ')';
//selector += '[' + self.count(selector) + ']';
//selector += ':eq(' + $(selector).length + ')';
}
} else {
if (!selectAll) {
selector += ':eq(' + self.count(selector) + ')';
//selector += '[' + self.count(selector) + ']';
}
}
} else {
selector = selContainer;
};
}
return selector;
}
};
// --------------
// TEXTS
// --------------
this.stringify = function (obj) {
if (typeof obj == 'object')
try {
return JSON.stringify(obj);
} catch (error) {
return obj;
}
else
return obj;
};
this.parse = function (str) {
if (typeof str == 'string')
try {
return JSON.parse(str); // json
} catch (error) {
return str; // non json
}
else
return str;
};
/* this.removeEventProperties = function (params) {
var paramsObj = self.cloneObject(params);
if (paramsObj && paramsObj.on) {
paramOn = self.cloneObject(paramsObj.on);
delete paramsObj.on;
}
if (paramsObj && paramsObj.success) {
paramSuccess = self.cloneObject(paramsObj.success);
delete paramsObj.success;
}
return paramsObj;
}; */
self.setupId = 0;
this.replacePropertyWithPrefix = function (params, prefix, args) {
var paramsString;
if (typeof params == 'object')
paramsString = self.stringify(params);
else
paramsString = String(params);
/* let argsWithProperties = (args) ? JSON.stringify(args) : '';
paramsString = self.replaceAll(paramsString, '"{'+prefix+'}"', argsWithProperties); // obsolete */
//if (typeof args == undefined)
// self.log('replacePropertyWithPrefix args is undefined', 'yellow');
if (paramsString && paramsString.indexOf('{' + prefix) >= 0) {
paramsString = paramsString.replace(new RegExp('"{' + prefix + '[:\\s]?([\\w\\d\\s\\.\\|]*)}"', 'g'), function (match, path) {
if (path) {
let value = self.replaceUndefined({ match: match, path: path, root: args, removeUndefined: true });
//let value = self.element({path:path, root: args});
/* if (typeof value == undefined) {
self.log(match + ' not found', 'orange');
value = '';
} else */
if (value === undefined) {
return '""';
} else if (typeof value == 'object')
return JSON.stringify(value);
else if (typeof value == 'string')
return '"' + value + '"';
else
return value;
} else {
if (typeof args == 'object')
return JSON.stringify(args);
else if (typeof args == 'string')
return '"' + args + '"';
else
return args;
}
});
/* if (paramsString && paramsString.indexOf('Contacts')>= 0) {
self.log(paramsString, 'green');
} */
paramsString = paramsString.replace(new RegExp('{' + prefix + '[:\\s]?([\\w\\d\\s\\.]*)}', 'g'), function (match, path) {
if (path) {
let value = self.replaceUndefined({ match: match, path: path, root: args, removeUndefined: true });
//let value = self.element({path:path, root: args});
/* if (typeof value == undefined) {
self.log(match + ' not found', 'orange');
value = '';
} else */
if (value === undefined)
return '';
else if (typeof value == 'object') // when object inside a string?
return JSON.stringify(value);
else
return value;
} else {
if (typeof args == 'object')
return JSON.stringify(args);
else
return args;
}
});
if (self.isJsonString(paramsString)) {
var paramsObj = self.parse(paramsString);
return paramsObj;
} else {
return paramsString;
}
} else {
return params;
}
};
/* this.replaceProperty = function (params, name, args) { // TO DO: change name in replaceArguments
//console.log('replaceProperty:'+name);
//var actions = {};
if (typeof params == 'object') {
params = self.stringify(params);
}
if (typeof args !== 'string') {
let argsWithProperties = (args) ? JSON.stringify(args) : '';
params = self.replaceAll(params, '"{'+name+'}"', argsWithProperties); // obsolete
// TO DO: get self.element({path:key, root: args});
for (let key in args) {
if (typeof args[key] !== undefined) {
if (typeof args[key] == 'object')
params = self.replaceAll(params, '"{'+name+' '+key+'}"', JSON.stringify(args[key]));
else
params = self.replaceAll(params, '{'+name+' '+key+'}', args[key]);
} else {
params = self.replaceAll(params, '{'+name+' '+key+'}', '');
self.log('{'+name+' '+key+'}' + ' not found', 'yellow');
}
}
for (let key in args) {
if (args[key]) {
if (typeof args[key] == 'object')
params = self.replaceAll(params, '"{'+name+':'+key+'}"', JSON.stringify(args[key]));
else
params = self.replaceAll(params, '{'+name+':'+key+'}', args[key]);
} else {
params = self.replaceAll(params, '{'+name+':'+key+'}', '');
}
}
} else {
//console.log('args STRINGA');
params = self.replaceAll(params, '{'+name+'}', args);
}
if (self.isJson(params)) {// (typeof params == 'object')
var paramsObj = self.parse(params);
return paramsObj;
} else {
//alert(paramsString);
return params;
}
}
*/
this.replaceResult = function (params, args) {
var paramOn, paramSuccess, paramError;
if (typeof params == 'object') {
var paramsObj = self.cloneObject(params);
if (paramsObj && paramsObj.on) {
paramOn = self.cloneObject(paramsObj.on);
delete paramsObj.on;
}
if (paramsObj && paramsObj.success) {
paramSuccess = self.cloneObject(paramsObj.success);
delete paramsObj.success;
}
params = self.stringify(params);
}
if (typeof args !== 'string') {
params = self.replaceAll(params, '"{result}"', JSON.stringify(args));
} else {
params = self.replaceAll(params, '{result}', args);
}
/* self.log('replaceResult');
self.log('params');
self.log(params); */
if (self.isJson(params)) { // (typeof params == 'object')
var paramsObj = self.parse(params);
if (paramOn) paramsObj.on = paramOn;
if (paramSuccess) paramsObj.success = paramSuccess;
if (paramError) paramsObj.error = paramError;
return paramsObj;
} else {
//alert(paramsString);
return params;
}
};
/*
this.replaceTags = function (params, selectorParams) {
self.log('replaceTags');
var undef = false;
if (params.text && (typeof params.text == 'string' || typeof params.text == 'object')) {
//alert(params.text);
params.text = self.stringify(params.text);
// i tag speciali sono contenuti tra i caratteri { e }
if (params.text.indexOf('{') >= 0) {
// alert(params.text.indexOf('{'));
// <{visible:element}>
params.text = params.text.replace(/\<\{visible\:([^\}]*)\}\>/g, function(match, p1, offset, string) {
var value = ($(p1).is(':visible'));
return value;
});
// <{var:var.object}>
params.text = params.text.replace(/\<\{this\:([^\}]*)\}\>/g, function(match, p1, offset, string) {
var value = self.json[p1];
if (!value) undef = true;
return self.stringify(value);
});
// <{data:value}>
params.text = params.text.replace(/\<\{data\:([^\}]*)\}\>/g, function(match, p1, offset, string) {
var value = self.json.var[p1];
if (!value) undef = true;
return self.stringify(value);
});
params.text = params.text.replace(/\<\{var\:([^\}]*)\}\>/g, function(match, p1, offset, string) {
var value = self.get(p1);
if (!value) undef = true;
return self.stringify(value);
});
params.text = params.text.replace(/\<\{param\:([^\}]*)\}\>/g, function(match, p1, offset, string) {
var value = self.params[p2];
if (!value) undef = true;
return value;
});
// <{value:[id]}>
params.text = params.text.replace(/\<\{value\:([^\}]*)\}\>/g, function(match, p1, offset, string) {
var value = $('#'+p1).val();
// https://www.geeksforgeeks.org/html-value-attribute/
if (!value) undef = true;
return value;
});
// <{user:[fieldName]}>
params.text = params.text.replace(/\<\{user\:([^\}]*)\}\>/g, function(match, p1, offset, string) {
var value = self.user(p1);
if (!value) undef = true;
return self.stringify(value);
});
// <{time:timestamp}>
params.text = params.text.replace(/\<\{time\:timestamp\}\>/g, self.getTimestamp());
// <{result}>
if (params.args) {
params.args = self.stringify(params.args);
params.text = params.text.replace(/\<\{result\}\>/g, params.args);
}
// <{function:app.mac}>
params.text = params.text.replace(/\\{function:([^\}]*)\}\>?/g, function(match, p1, offset, string) {
var functionName = self.docElement(p1);
return functionName(selectorParams);
});
// <{random}>
params.text = params.text.replace(/\<\{random\:([^\-]+)\-([^\}]+)\}\>/g, function(match, p1, p2, offset, string) {
return Number(p1)+Math.round((p2-p1)*Math.random());
});
// <{firebaseKey:path}>
params.text = params.text.replace(/\<\{firebaseKey\:([^\}]*)\}\>/g, function(match, p1, offset, string) {
return self.firebaseKey(p1);
});
}
if (undef) return undefined
else return self.parse(params.text);
} else {
//self.log('params.text undefined or number or boolean');
return params.text;
}
} */
this.langText = function (textId) {
// find text in language and follow the capitalization of textId
// we could need text in langId language
if (textId) {
var textValue = textId;
if (typeof textId == 'string') {
if (self.json.texts[textId]) {
textValue = self.json.texts[textId];
if (typeof textValue == 'object')
textValue = textValue[self.json.setup.language] || textValue['en'] || textValue[Object.keys[0]];
}
else
textValue = textId;
} else if (typeof textId == 'object') {
textValue = textId[self.json.setup.language] || textId['en'] || textId[Object.keys[0]];
//textValue = textObj[langId] || textObj[self.json.setup.language] || textObj['en'];
}
return textValue;
} else {
return textId;
}
/* if (self.json.texts[textId])
textObj = self.json.texts[textId];
else if (self.json.texts[textId.toLowerCase()])
textObj = self.json.texts[textId.toLowerCase()];
//else if (self.json.texts[textId.toUpperCase()])
// textObj = self.json.texts[textId.toUpperCase()];
if (textObj) {
var textValue = textObj[self.json.setup.language] || textObj['en'] || textId;
if (textId.charAt(0) == textId.charAt(0).toUpperCase()) // first char uppercase
if (textId.charAt(1) == textId.charAt(1).toUpperCase())
return textValue.toUpperCase();
else
return textValue.replace(/\b\w/, l => l.toUpperCase()); // capitalize
// textValue = textValue.charAt(0).toUpperCase() + name.slice(1)
// style: text-transform: capitalize;
else
return textValue.toLowerCase();
} else {
return textId;
} */
/* } else {
self.log('textId undefined in langText');
} */
};
this.lang = function (params, args) {
if (args) {
var value = self.replaceProperties(params, args);
self.json.setup.language = value;
//alert(value);
self.log('lang');
self.log(value);
document.querySelectorAll('[data-text]').forEach(function (element, index) {
//$('*[data-text]').each(function( index ) {
var dataParams = self.dataStorage.get(element, 'params');
var selector = self.dataStorage.get(element, 'selector');
/* self.log('index');
self.log(index);
self.log('dataParams');
self.log(dataParams);
*/
//alert(JSON.stringify(dataParams));
self.html(dataParams, { selector: selector });
//self.text($(this).data('params'), {container: this});
});
/*
var elements = document.querySelectorAll('[data-text]');
self.log('elements');
self.log(elements);
//var elements = document.querySelectorAll(selector);
if (elements)
elements.forEach(function (element, index) {
self.log(index);
//var dataParams = self.dataStorage.get(element, 'params');
var dataSelector = self.attribute(element, 'data-selector');
//self.text(dataParams, {container: dataSelector});
self.text($(dataSelector).data('params'), {container: dataSelector});
});
*/
} else {
return self.json.setup.language;
}
};
// Determine whether is possible to write an image/text to the clipboard.
var isClipboardWritingAllowed = function () {
return new Promise(function (resolve, reject) {
try {
navigator.permissions.query({ name: "clipboard-write" }).then(function (status) {
// PermissionStatus object
// {
// onchange: null,
// state: "granted" (it could be as well `denied` or `prompt`)
// }
self.log(status);
resolve((status.state == "granted"));
});
} catch (error) {
// This could be caused because of a Browser incompatibility or security error
// Remember that this feature works only through HTTPS
reject(error);
}
});
};
this.codeSearch = function (params) {
let selector = params.selector || params.container;
// {container, word}
if (selector && params.word) {
var element = self.query(selector);
var editor = ace.edit(element);
var range = editor.find(params.word, {
wrap: true,
caseSensitive: true,
wholeWord: true,
regExp: false,
preventScroll: false // do not change selection
});
editor.session.selection.clearSelection();
editor.setOption("highlightActiveLine", true);
/* range.start.column = 0;
range.end.column = Number.MAX_VALUE;
//editor.session.replace(range, "x" + editor.session.getLine(range.start.row) + "x");
editor.selection.setRange(range); */
}
};
this.ace = function (params, selectorParams) {
// https://codepen.io/zymawy/pen/XwbxoJ
//self.log('code');
//self.log(params);
var selector = params.selector || params.container;
var container = selector || self.selector(selectorParams);
//paramsReplaced = self.cloneObject(params);
//paramsReplaced.value = self.actionResult(paramsReplaced.value);
var value = params.value;
// item from library
if (params.blocks && self.json.blocks)
if (self.json.blocks[params.blocks])
value = self.json.blocks[params.blocks];
else
self.log('"code" method can\'t find in "blocks" the element ' + params.blocks);
// json file
if (params.module) {
let moduleName = self.replaceProperties(params.module);
if (moduleName && self.modules[moduleName] !== undefined) {
value = self.modules[moduleName];
/* self.log('value');
self.log(value);
self.log(value); */
}
else
self.log('"code" method can\'t find the file ' + params.file);
}
if (params.var)
if (self.json.var)
value = self.var(params.var);
else
self.log('"code" method can\'t find the variable ' + params.blocks);
var element = self.query(container);
//var containerId = $(container).attr('id');
//self.log('containerId');
//self.log(containerId);
//var containerId = $(container).attr('id');
if (element) {
//var containerId = self.attribute(element, 'id'); // or assign a random unique id
var editor = ace.edit(element);
/* var keywordMapper = this.createKeywordMapper({
"tag" : 'div|ul|p|a|button|input|span|img|video|audio|source|figure|figcaption|textarea|iframe|table|thead|tbody|tfoot|tr|th|td|svg|small|h1|h2|h3|h4|h5|h6|form|form-group|label|select|option|optgroup|nav|lottie-player|qrcode|tab|model-viewer'
}, "identifier"); */
/* var staticWordCompleter = {
getCompletions: function(editor, session, pos, prefix, callback) {
var wordList = ['div', 'ul', 'p', 'a', 'button', 'input', 'span', 'img', 'video', 'audio', 'source', 'figure', 'figcaption', 'textarea', 'iframe', 'table', 'thead', 'tbody', 'tfoot', 'tr', 'th', 'td', 'svg', 'small', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'form', 'form-group', 'label', 'select', 'option', 'optgroup', 'nav', 'lottie-player', 'qrcode', 'tab', 'model-viewer'];
callback(null, wordList.map(function(word) {
return {
caption: word,
value: word,
meta: "static"
};
}));
}
}
//langTools.setCompleters([staticWordCompleter])
// or
editor.completers = [staticWordCompleter] */
/* if (editor)
AceColorPicker.load(ace, editor); */
//var value = paramsReplaced.value; // else value = params;
if (!params.do || (params.do == 'set')) {
//var langTools = ace.require('ace/ext/language_tools');
if (params.theme)
editor.setTheme(params.theme); // "ace/theme/monokai"
var editorMode = params.mode || "ace/mode/json";
editor.getSession().setMode(editorMode);
if (params.options)
editor.setOptions(params.options);
//AceColorPicker.load(ace, editor, {hideDelay: 1000});
//import AceColorPicker from 'ace-colorpicker';
/* editor.getSession().setMode(editorMode, () => {
AceColorPicker.load(ace); // , {hideDelay: 1000}
}); */
var editorStyle = self.extend({
//background: "rgba(255,255,255,0)"
}, params.style);
//$(container).css(editorStyle); //editor.container.style
self.css({
style: editorStyle
}, {
selector: container
});
//var aceOptions = params.options;
/* var aceOptions = self.extend({
fontSize: "12pt",
selectionStyle: "line",
//showGutter: false,
highlightGutterLine: false,
fixedWidthGutter: false,
//vScrollBarAlwaysVisible: true,
tabSize: 3,
//readOnly: true,
//enableBasicAutocompletion: false,
//enableSnippets: false,
//enableLiveAutocompletion: false,
}, params.options); */
// https://github.com/ajaxorg/ace/wiki/Configuring-Ace
var codeString;
if (typeof value == 'string')
if (editorMode == "ace/mode/json")
codeString = JSON.stringify(JSON.parse(value), null, '\t'); // json formatting
else
codeString = value;
else {
if (editorMode == "ace/mode/json")
codeString = JSON.stringify(value, null, '\t');
else {
var functionObj = self.docElement(value.function); //?
var functionParams = value.params;
codeString = functionObj(functionParams);
}
}
// should be {lines:dividcode}
if (codeString) {
var codeRows = codeString.split(/\r\n|\r|\n/).length;
/* $(container).css({
height: Number(21 * (codeRows)) + 'px'
}); */
/* self.log('element');
self.log(element);
self.log('container');
self.log(container);
self.log('codeRows');
self.log(codeRows); */
element.style.height = Number(21 * codeRows) + 'px';
//element.querySelector('.ace_scroller').querySelector('.ace_content').height = Number(21 * codeRows) + 'px';
/* self.css({
style: {
height: Number(21 * codeRows) + 'px'
}
}, {
container: container
}); */
editor.setValue(codeString, -1); // -1 unselect the code
//editor.renderer.updateFull(true);
//AceColorPicker.load(ace, ace.edit(containerId));
self.uiUpdate(); // resize event trigger
// workaround known ACE bug (.ace_content element doesn't follow the height until window resize)
}
if (params.on) {
var containerId = self.attribute(element, 'id'); // or assign a random unique id
self.codeChangeFunctions[containerId] = params.on;
//self.editorChangeFunctions[editor.id] = params.on;
if (params.on.change) {
editor.on('change', function (event, obj) {
/* self.log('event');
self.log(event);
self.log('obj');
self.log(obj); */
if (self.isJson(obj.getValue())) {
var code = JSON.parse(obj.getValue());
var action = self.codeChangeFunctions[obj.container.id].change;
//var methods = self.replaceResult(action, code);
var methods = self.replaceResult(action, code);
//var methods = self.replaceProperties(action, code);
// check on jsonic.io/play (methods is string instead of object)
/* self.log('code');
self.log(code);
self.log('method');
self.log(method);
self.log('-------------'); */
//self.do(methods);
self.do(methods);
//self.do(code, self.editorChangeFunctions[obj.id]);
//var container = self.editorChangeFunctions[obj.id].change.container;
} else {
// syntax error
}
//self.do(self.editorChangeFunctions[obj.id].change, JSON.parse(obj.getValue()));
//self.log(obj);
//self.blocks(JSON.parse(obj.getValue()), {container: });
});
}
// save key
// https://michilehr.de/overwrite-cmds-and-ctrls-in-javascript
}
} else if (params.do == 'get') {
return JSON.parse(editor.getValue());
} else if (params.do == 'update') {
self.uiUpdate(); // resize event trigger
// workaround known ACE bug (.ace_content element doesn't follow the height until window resize)
} else if (params.do == 'search') {
if (params.word) {
var range = editor.find(params.word, {
wrap: true,
caseSensitive: true,
wholeWord: true,
regExp: false,
preventScroll: false // do not change selection
});
editor.session.selection.clearSelection();
editor.setOption("highlightActiveLine", true);
/* range.start.column = 0;
range.end.column = Number.MAX_VALUE;
//editor.session.replace(range, "x" + editor.session.getLine(range.start.row) + "x");
editor.selection.setRange(range); */
}
} else if (params.do == 'find') {
// toggle
editor.execCommand('find');
//editor.searchBox.show();
} else if (params.do == 'copy') {
// Select the whole content of the editor
editor.selectAll();
// Store text that will be copied to clipboard
let copyText = editor.getCopyText();
// Verify if clipboard writing is allowed
isClipboardWritingAllowed().then(function (allowed) {
// Write to clipboard if allowed
if (allowed) {
navigator.clipboard.writeText(copyText).then(function () {
editor.getSession().selection.clearSelection();
//self.log("Code copied!");
});
}
}).catch(function (err) {
self.log("Cannot copy to clipboard", err);
});
} else {
self.log('"code" function requires value param');
}
} else {
self.log('"code" method can\'t select the container');
self.log('container');
self.log(container);
self.log('element');
self.log(element);
}
};
// TO DO: should be in the app var and reset on a new execution
this.codeChangeFunctions = {};
this.editorChangeFunctions = {};
this.quillElements = {};
this.text = function (params, selectorParams, args) {
/*
{
"text": / "string": / textId -> textId "{text:textId}"
"case": [up, down, capitalize]
}
*/
/* if (Array.isArray(params)) {
for (var obj of params)
self.text(obj, selectorParams, args);
} else { */
var textKey;
var textCase;
var textArgs;
var textLang;
var langId;
var selector, element;
//var textAction;
if (typeof params == 'object') {
if (selectorParams && selectorParams.isConnected) { // Check if an element is attached to DOM
element = selectorParams;
//selector = self.dataStorage.get(element, 'selector');
//selector = element.getAttribute('data-selector');
selector = self.elementToSelector(element); // 1.0.12
} else {
selector = self.selector(self.extend({}, params, selectorParams));
element = self.query(selector);
}
// todo: REMOVE (check the menu)
//textAction = self.actionResult(params, textArgs);
//textAction = params;
//textKey = params.string; // || params.text || params.title; // params.key to be removed?
textCase = params.case; // use text-transform uppercase lowercase capitalize
textArgs = params.args; // deve diventare args (secondo parametro) al posto di caseFunction
//langId = params.langId;
if (typeof params == 'object') {
textKey = params.key || params.string || params; // || params.text || params.title; // params.key to be removed?
//textCase = params.case; // use text-transform uppercase lowercase capitalize
//textArgs = params.args; // deve diventare args (secondo parametro) al posto di caseFunction
//langId = params.langId;
} else {
textKey = params;
}
/* self.log('textKey');
self.log(textKey); */
} else if (typeof params == 'string') {
textKey = params;
/* self.log('textKey');
self.log(textKey); */
//textCase = caseFunction;
if (selectorParams) {
if (selectorParams.isConnected) { // Check if an element is attached to DOM
element = selectorParams;
selector = self.dataStorage.get(element, 'selector');
} else {
selector = self.selector(selectorParams);
element = self.query(selector);
}
} else {
// here when windowTitle += ' ' + self.text(page.title); // window title
}
}
if (typeof textKey == 'string') {
/* // TO DO: remove
if (textKey.startsWith('js:')) textKey = self.js(textKey.substr(3));
else if (textKey.startsWith('db:')) textKey = self.element({path: 'var.db.'+textKey.substr(3)});
else if (textKey.startsWith('var:')) textKey = self.element({path: 'var.'+textKey.substr(4)});
else if (textKey.startsWith('data:')) textKey = self.element({path: 'data.'+textKey.substr(5)});
else
// ----- */
/* console.log('textKey');
console.log(textKey); */
textKey = self.replaceProperties(textKey, textArgs);
/* console.log('textKey');
console.log(textKey); */
}
//self.log('selector');
//self.log(selector);
//self.log(selector.isConnected);
/* self.log('HOTSPOT');
self.log(params);
self.log(self.json.setup.language); */
if (params && params.lang) { // multi-language text
//self.log('params.lang definito');
textLang = self.langText(params.lang); // , langId
//textLang = params.lang[self.json.setup.language] || params.lang['en'] || params.lang[Object.keys[0]];
textLang = self.replaceProperties(textLang, textArgs);
/* self.log('textLang');
self.log(textLang);
self.log('element');
self.log(element); */
if (textCase) textLang = self.textCase(textLang, textCase);
//self.log('textLang');
//self.log(textLang);
if (element) {
element.textContent = textLang;
self.attribute(element, 'data-text', true); // textKey instead of lang?
self.dataStorage.set(element, 'params', params);
//$(selector).data('params', params);
}
} else {
//self.log('params.lang non definito');
//if (!textKey) textKey = params;
if (textKey) {
//textKey = self.compile(textKey, textArgs); // TO DO: verify
/* self.log('textKey');
self.log(textKey); */
//if (!textKey) alert(JSON.stringify(params));
//if (typeof textKey == 'object') {
// textLang = JSON.stringify(textKey, null, '\t');
//} else {
//textLang = params.lang[self.json.setup.language] || params.lang['en'] || params.lang[Object.keys[0]];
if (textKey.lang) // multi-language text
textLang = self.langText(textKey.lang); // , langId
else
textLang = textKey;
/* self.log('textLang1');
self.log(textLang); */
textLang = self.replaceProperties(textLang, textArgs); // move after textLang = self.langText(textKey.lang);
if (textCase) textLang = self.textCase(textLang, textCase);
//}
/* self.log('textLang2');
self.log(textLang); */
//if (selector) { // set
if (element) { // set
if (self.json.texts[textKey]) {
// save data-text for lang change
//$(selector).data('params', params);
//$(selector).attr('data-text', textKey);
self.attribute(element, 'data-text', true);
self.dataStorage.set(element, 'params', params);
}
// obsolete
/* if (params.background) $(selector).css({'background': params.background});
if (params.color) $(selector).css({'color': params.color});
if (params.size) $(selector).css({'font-size': params.size}); */
if (params.style)
self.css({
style: params.style
}, {
selector: selector
});
//$(selector).css(params.style);
element.textContent = textLang; // put text in element
//$(selector).text(textLang);
} else { // get
return textLang;
}
} else {
/* self.log('"string" parameter required in text object');
self.log(params); */
return params;
}
}
};
var caseUp = function (string) {
return string.toUpperCase();
};
var caseDown = function (string) {
return string.toLowerCase();
};
var capitalize = function (string) {
return self.capitalize(string);
};
this.textCase = function (textParam, caseParam) {
if (textParam) {
var text = textParam;
switch (caseParam) {
case 'up':
text = text.toUpperCase();
break;
case 'down':
text = text.toLowerCase();
break;
case 'capitalize':
text = self.capitalize(text);
break;
}
return text;
} else {
self.log('textParam undefined in textCase');
}
};
/* this.textFit = function (selector,params) {
if (params.alignHoriz == undefined) {
params.alignHoriz = true;
}
if (params.alignVert == undefined) {
params.alignVert = true;
}
if (params.minFontSize) {
params.minFontSize = parseInt(params.minFontSize, 10); // remove px
}
if (params.maxFontSize) {
params.maxFontSize = parseInt(params.maxFontSize, 10); // remove px
}
// textFit va in errore se l'oggetto diventa invisibile
// mentre sta elaborando la dimensione del testo
if (!$(selector).children('span').hasClass('textFitted')) {
$(selector).each(function(i, obj) {
if ($(obj).is(":visible")
&& ($(obj).css("display") !== 'none')
&& ($(obj).css('width'))
&& ($(obj).css('height'))) {
textFit($(obj), params);
}
});
}
} */
/* this.data = function (path, value) {
if (!value) return self.json.var;
}
this.setvar = function (data) {
var = self.data();
self.data(data);
} */
// --------------
// PAGES
// --------------
/* this.lastInteraction = function () {
// uso: self.lastInteraction().asMinutes()
var lastInteraction = 0;
if (var.touchTime) lastInteraction = moment(var.touchTime);
var thisMoment = moment();
var duration = moment.duration(thisMoment.diff(lastInteraction));
return duration
} */
// --------------
// icons e
// --------------
/* this.icons = this.icon = function (params, selectorParams, args) {
// { [container, class, value, id]
// [html, text, append, prepend] }
if (Array.isArray(params)) {
for (var index in params)
{self.icons(params[index], selectorParams);}
} else {
if (params.items) {
var itemsArray = params.items;
delete params.items;
for (var index in itemsArray) {
self.icons(self.replaceItems(params, itemsArray[index]), selectorParams);
}
} else {
//if (selectorParams) params = self.extend(params, selectorParams);
var paramsReplaced = self.replaceProperties(params, args);
self.log('icons');
self.log('paramsReplaced');
self.log(paramsReplaced);
if (paramsReplaced) {
if (paramsReplaced.disabled == true)
self.disableIcon(paramsReplaced, selectorParams);
else if (paramsReplaced.disabled == false)
self.enableIcon(paramsReplaced, selectorParams);
else if (paramsReplaced.change)
self.changeItem(paramsReplaced, selectorParams);
else
self.addItem(paramsReplaced, selectorParams);
}
if (paramsReplaced.firebase) self.addFirebaseTag(paramsReplaced);
var selector = self.selector(self.extend(paramsReplaced, selectorParams));
if (paramsReplaced.span) // text near icon
self.addTag(paramsReplaced, {container: selector});
}
}
} */
/* this.buttons = this.tab = function (params, selectorParams) {
// { [container, class, value, id]
// [html, text, append, prepend] }
if (Array.isArray(params)) {
for (var index in params)
self.tab(params[index], selectorParams);
} else {
if (params.items) {
var itemsArray = params.items;
delete params.items;
for (var index in itemsArray) {
self.tab(self.replaceItems(params, itemsArray[index]), selectorParams);
}
} else {
// se necessario, replaceProperties dovrebbe escludere il contenuto di events/action
// in quanto verrà ripetuto sulle azioni in tempo reale solo dove necessario
//params = self.replaceProperties(params);
if (!params.class) params.class = '';
var classes = params.class.split(' ');
if (params.change) {
if (classes.includes('icon'))
self.changeItem(params, selectorParams);
else // if (classes.includes('tabs'))
self.changeTab(params, selectorParams);
} else {
if (classes.includes('icon'))
self.addItem(params, selectorParams);
else // if (classes.includes('tabs'))
self.addTab(params, selectorParams);
}
if (params.firebase) self.addFirebaseTag(params);
}
}
}
*/
/*
this.replacePropertyNew = function (params, name, args) {
console.log('replacePropertyNew');
// like replaceProperties but only for {name:...} property
var paramsString;
if (typeof paramsString !== 'string') {paramsString = JSON.stringify(self.cloneObject(params));}
// remove string quotes for object property
if (args && paramsString && paramsString.indexOf('{')>= 0) {
//if (args && paramsString && /{\w/.test(paramsString)) {
paramsString = paramsString.replace(/\"\{(\w+\:)?([\w\s\.\:]+)\}\"/g, function(match, p1, p2, offset, string) {
var value;
if (p1 && p1.endsWith(':')) {p1 = p1.slice(0, -1);}
console.log('match:'+match);
console.log('p1:'+p1);
console.log('p2:'+p2);
if (p1 == name || (!p1 && p2 == name)) {
let nameFound = p1 || p2;
let pathFound = (p1) ? p2 : undefined;
console.log(nameFound+':'+pathFound);
if (typeof args !== 'string') {
//return self.replaceAll(self.stringify(args), '\"', '\'');
return self.stringify(args);
} else {
return '"' + args + '"';
}
} else
return match;
});
//console.log('paramsString without quotes');
//console.log(paramsString);
paramsString = paramsString.replace(/\{(\w+\:)?([\w\s\.\:]+)\}/g, function(match, p1, p2, offset, string) {
var value;
if (p1 && p1.endsWith(':')) {p1 = p1.slice(0, -1);}
if (p1 == name || (!p1 && p2 == name)) {
let nameFound = p1 || p2;
let pathFound = (p1) ? p2 : undefined;
console.log(nameFound+':'+pathFound);
self.partSetup = args;
if (pathFound) {
value = self.docElement('self.partSetup.'+pathFound);
} else {
value = args;
}
console.log('value:'+value);
delete self.partSetup;
} else {
value = match
}
if (typeof value !== 'string') value = self.stringify(value);
return value;
});
if (self.isJsonString(paramsString)) {// (typeof params == 'object')
console.log('isJsonString');
var paramsObj = self.parse(paramsString);
return paramsObj;
} else {
console.log('NOT isJsonString');
console.log(paramsString);
// TO DO: log of wrong json string
return paramsString;
}
} else {
return params
}
}
*/
this.replaceUndefined = function (params) {
let value, defaultValue;
//if (params.path == 'badge') alert();
if (typeof params.path !== undefined) {
if (params.path.indexOf('|') > 0)
[params.path, defaultValue] = params.path.split('|');
value = self.element({ path: params.path, root: params.root });
}
if (value == undefined || value == null) { // empty string is false
if (typeof defaultValue !== undefined)
value = defaultValue;
else {
if (params.removeUndefined) { //p1 == 'args' || p1 == 'selector') {
value = ''; // remove undefined values
} else {
value = params.match;
self.log(value + ' not found', 'yellow');
}
}
} else {
//console.log('match:'+params.match);
//if (params.removeUndefined) value = '';
}
return value;
};
//value = self.replaceUndefined({match: '{'+match+'}', id:p1, removeUndefined: removeUndefined});
this.replaceProperties = function (params, args, removeUndefined) {
// TO DO: remove fieldsObj. can't find replaceProperties with 3 args
// the third parameter can be removeUndefined
// test with a firebase app like elio
var paramsString;
var paramOn, paramDo, paramSuccess, paramError, paramEvents, paramConfirm;
if (typeof params == 'string') {
paramsString = params;
} else {
//paramsString = JSON.stringify(params);
var paramsObj = self.cloneObject(params);
if (paramsObj) {
if (paramsObj.on) { paramOn = paramsObj.on; delete paramsObj.on; }
if (paramsObj.success) { paramSuccess = paramsObj.success; delete paramsObj.success; }
if (paramsObj.error) { paramError = paramsObj.error; delete paramsObj.error; }
if (paramsObj.events) { paramEvents = paramsObj.events; delete paramsObj.events; } // TO DO: remove
if (paramsObj.confirm) { paramConfirm = paramsObj.confirm; delete paramsObj.confirm; } // TO DO: check it
if (paramsObj.do) { paramDo = paramsObj.do; delete paramsObj.do; }
}
paramsString = JSON.stringify(paramsObj);
}
/* self.log("paramsString");
self.log(paramsString); */
if (paramsString && paramsString.indexOf('{') >= 0) {
paramsString = paramsString.replace(/\"\{([\w\s\.]+)\}\"/g, function (match, p1, offset, string) {
var value;
if (p1) {
//self.log('p1:' + p1);
//value = self.element({path: p1}); // || match;
value = self.replaceUndefined({ match: '{' + match + '}', path: p1, removeUndefined: removeUndefined });
if (value) {
if (value.isConnected) return self.elementToSelector(value); // DOM element to CSS selector
if (typeof value !== 'string')
return self.stringify(value); // object or array to string (TO DO: check numbers)
else {
//console.warn('we are here');
return '"' + value + '"';
}
}
else
return '""';
} else {
return '""';
}
});
paramsString = paramsString.replace(/\{(\w+\:)?([\w\s\->|\/=\.:#&;,\[\]\']+)\}/g, function (match, p1, p2, offset, string) {
/*
Firebase references may contain any unicode characters except:
. (period)
$ (dollar sign)
[ (left square bracket)
] (right square bracket)
# (hash or pound sign)
/ (forward slash)
*/
/* self.log("paramstring");
self.log(match, p1, p2); */
// self.log(match, p1, p2);
var value;
if (p1) {
if (p1.endsWith(':')) {
p1 = p1.slice(0, -1); // remove the final ":"
// check if is a function name (in this.json.functions)
if (self.functions[p1]) {
//value = self.functions[p1](JSON.parse(p2));
let funcArgs = p2.split('|');
/* console.warn('p2');
console.warn(p2);
console.warn('funcArgs');
console.warn(funcArgs); */
// if Number(funcArgs[i]) == funcArgs[i] -> funcArgs[i] = Number(funcArgs[i]);
value = self.function({ name: p1, arguments: [funcArgs] });
} else {
switch (p1) {
/* case 'hasClass':
var element = document.querySelector(p2);
if (p3)
value = self.hasClass(el,p3);
else
value = false; el:selector.class (esiste l'elemento selector.class o l'elemento selector ha la classe class)
break; */
// 'isVisible', 'isHidden', 'isDisplay', 'inViewport', 'outViewport', 'notClass', 'hasClass'
// hasClass da aggiungere come funzione css
// html markups
// 'b:string' 'i:string' 'u:string' 'a:STRING|URL'
/* case 'i': case 'b': case 'u': case 'strong': case 'em': case 'mark': case 'del': case 'ins': case 'sub': case 'sup':
value = '<'+p1+'>'+p2+''+p1+'>';
break;
case 'a':
// example: "{a:text|href:....|target:_blank}"
let props = p2.split('|'); // or indexOf(':') prima occorrenza
let string = props.shift();
var propsString = '';
for (var prop of props) {
//let propArr = prop.split(':'), propName = propArr[0], propValue = propArr[1];
propsString += ' ' + prop;
}
if (propsString == '') propsString = ' href="'+string+'"';
value = ''+string+'';
// https://stackoverflow.com/questions/1547899/which-characters-make-a-url-invalid
// https://www.w3schools.com/tags/tag_a.asp
break;
*/
// DOM properties
case 'visible':
var element = document.querySelector(p2); // self.query(p2);
value = (element && self.isVisible(element));
//value = ($(p2).is(':visible'));
break;
case 'number':
value = Number(p2);
break;
case 'string':
value = String(p2);
break;
case 'js': // deprecated (too much special characters like {})
try {
value = eval(p2);
} catch (error) {
value = '';
self.log('javascript error on ' + p2);
self.log(error);
}
break;
/* case 'item':
if (fieldsObj) {
//self.log('fieldsObj['+p2+']:'+fieldsObj[p2]);
value = fieldsObj[p2] || ''; //|| p2+'=NULL';
} else {
//self.log('p2:'+p2);
//self.log('fieldsObj == undefined');
value = '{'+p1+':'+p2+'}';
}
break; */
/* case 'item':
case 'items':
value = self.docElement('self.json.items.'+p2);
break; */
/* case 'frame':
var element = self.query(p2);
element.contentWindow
break; */
/* case 'field':
if (fieldsObj) {
//self.log('fieldsObj['+p2+']:'+fieldsObj[p2]);
value = fieldsObj[p2] || ''; // || p2+'=NULL';
} else {
//self.log('p2:'+p2);
//self.log('fieldsObj == undefined');
value = '';
}
break; */
/* case 'setup':
value = self.docElement('self.json.setup.'+p2) || match;
break; */
/*
case 'setup':
if (args) {
self.partSetup = args;
value = self.docElement('self.partSetup.'+p2);
delete self)Setup;
} else {
value = '';
}
break; */
case 'wp':
case 'wordpress':
// TO DO: should get/set data with jsonic.get/setWordpressData
// setWordpressData can be done automatically in the init
value = self.docElement('self.json.setup.wordpress.' + p2) ?? match;
//alert(value);
//if (value.indexOf('"') >= 0)
// value = self.replaceAll(value, '"', '\\"');
// the first should replace only " and not \" but it doesn't works
//value = value.replaceAll(/([^\\\"])\"/g, '$1\\"');
break;
case 'plugins':
value = self.json.resources.pluginsFunctions[p2];
if (value && !Array.isArray(value)) value = [value];
else value = [];
/* self.log('plugins');
self.log('value');
self.log(value); */
/* value = plugins;
for (plugin of plugins) {
value = self.json.resources.pluginsFunctions[p2].name || 'unknown plugin required';
} */
break;
case 'database':
case 'db':
value = self.docElement('self.json.var.db.' + self.replaceProperties(p2, args));
break;
// shorteners (useful?)
case 'media': // or m or src
if (self.json.setup && self.json.data.media)
value = self.docElement('self.json.data.media.' + p2) || match;
else
value = match;
break;
case 'color': // or col
if (self.json.data && self.json.data.colors)
value = self.docElement('self.json.data.colors.' + p2) || match;
else
value = match;
break;
case 'class': // or cla
if (self.json.data && self.json.data.class)
value = self.docElement('self.json.data.class.' + p2) || match;
else
value = match;
break;
case 'text':
value = self.langText(p2);
break;
case 'param':
value = self.params[p2] || ''; // || p2+'=NULL';
break;
case 'height':
/* self.log('{height:p2}');
self.log('p2');
self.log(p2); */
var element = document.querySelector(p2); // self.query(p2);
if (element) // && self.isVisible(element)
//value = getComputedStyle(element, null).height;
value = element.offsetHeight + 'px';
//if ($(p2).is(':visible'))
//value = $(p2).height() + 'px'
else
value = '0px';
break;
case 'offsetWidth':
var element = document.querySelector(p2); // self.query(p2);
if (element) // && self.isVisible(element)
//value = getComputedStyle(element, null).height;
value = element.offsetWidth;
//if ($(p2).is(':visible'))
//value = $(p2).height() + 'px'
else
value = '0';
break;
case 'width':
var element = document.querySelector(p2); // self.query(p2);
if (element) // && self.isVisible(element)
//value = getComputedStyle(element, null).height;
value = element.offsetWidth + 'px';
//if ($(p2).is(':visible'))
//value = $(p2).height() + 'px'
else
value = '0px';
break;
case 'local':
value = self.methods.local.get(p2);
//self.log('{localStorage:cart}');
//self.log(value);
break;
case 'ace':
var element = document.querySelector(p2);
if (element) {
var editor = ace.edit(element);
value = JSON.parse(editor.getValue());
}
//self.log('{localStorage:cart}');
//self.log(value);
break;
/* case 'innerText':
var element = document.querySelector(p2);
value = (element) ? element.innerText : undefined;
self.log('p1:'+p1);
self.log('p2:'+p2);
self.log('value:'+value);
//.trisBox[data-value="0"]
break;
case 'innerHtml':
var element = document.querySelector(p2);
value = (element) ? element.innerHTML : undefined;
break; */
case 'shuffle':
value = self.element({ path: p2 });
value = self.methods.shuffle(value);
break;
case 'select':
case 'input':
case 'value': // deprecated
var element = document.querySelector(p2); // self.query(p2);
value = (element) ? String(element.value || '') : '';
//value = $('#'+p2).val() || ''; //|| p2+'=NULL';
// input field value
// https://www.geeksforgeeks.org/html-value-attribute/
break;
case 'user':
if (p2 == 'in') {
value = self.userIn();
} else if (p2 == 'out')
value = self.userOut();
else
value = self.user(p2) || match; //|| p2+'=NULL';
break;
// can go in objects
case 'length':
var varObj = self.element({ path: p2 }); // to get also js objects length
//var varObj = self.docElement('self.json.'+p2);
if (varObj)
if (typeof varObj == 'object')
value = Object.keys(varObj).length;
else
value = varObj.length;
else
self.log('' + p2 + ' is undefined');
break;
case 'Date':
case 'time':
if (p2 == 'timeZone') value = new Intl.DateTimeFormat().resolvedOptions().timeZone;
else if (p2 == 'weekday') value = self.weekday();
else if (p2 == 'stamp') value = self.getTimestamp();
else if (p2 == 'timestamp') value = self.getTimestamp();
else if (p2 == 'getTimestamp') value = self.getTimestamp();
else if (p2 == 'getDay') value = new Date().getDay();
else if (p2 == 'getDate') value = new Date().getDate();
else if (p2 == 'getMonth') value = new Date().getMonth();
else if (p2 == 'getFullYear') value = new Date().getFullYear();
else if (p2 == 'getTime') value = new Date().getTime(); // timestamp
else if (p2 == 'getSeconds') value = new Date().getSeconds();
else if (p2 == 'getMinutes') value = new Date().getMinutes();
else if (p2 == 'getHours') value = new Date().getHours();
// second, minute, hour, weekday, day, month, year
else value = p2 + '=NULL';
break;
case 'now':
// ...
break;
case 'month':
var month = (p2 == 'today' || p2 == undefined) ? new Date().getMonth() : Number(p2);
value = self.month(month);
break;
case 'weekday': // format: long, short, narrow
var day = (p2 == 'today' || p2 == undefined) ? new Date().getDay() : Number(p2);
value = self.calendar({ index: Number(day), unit: 'weekday', format: 'long' });
break;
case 'weekdayNarrow': // format: long, short, narrow
var day = (p2 == 'today' || p2 == undefined) ? new Date().getDay() : Number(p2);
value = self.calendar({ index: Number(day), unit: 'weekday', format: 'narrow' });
break;
case 'weekdayShort': // format: long, short, narrow
var day = (p2 == 'today' || p2 == undefined) ? new Date().getDay() : Number(p2);
value = self.calendar({ index: Number(day), unit: 'weekday', format: 'short' });
break;
case 'moment':
var timeFormat = (p2) ? p2 : '';
value = moment().format(timeFormat);
break;
case 'dayjs': // TO DO: check
var timeFormat = (p2) ? p2 : '';
value = dayjs().format(timeFormat);
break;
case 'Math':
value = self.Math(p2);
break;
case 'action':
case 'do':
self.log('do');
self.log('p2');
self.log(p2);
//value = self.do(p2); // || match; // TO DO: log error
value = self.do(p2); // || match; // TO DO: log error
//var functionName = self.docElement(p2);
//value = (functionName) ? functionName(functionName) : p2+'=NULL'
break;
/* WITH ARGS */
case 'method':
var method = self.element({ path: p2, root: self.methods });
if (method) {
value = method(args); // how to pass args? needs p3
} else {
value = match;
}
break;
case 'function': // TO DO: remove
var func = self.element({ path: p2, root: self.functions });
if (func) {
value = func(args); // how to pass args? needs p3
} else {
value = match;
}
break;
case 'on':
/* self.log('args');
self.log(args); */
if (args) {
self.onResult = args;
value = self.docElement('self.onResult.' + p2);
//alert(JSON.stringify(value));
delete self.onResult;
} else {
//alert(JSON.stringify(value));
value = match;
}
//value = ($(p2).is(':visible'));
break;
case 'ajax':
if (args) {
self.ajaxResult = args; // -> self.json.var.ajaxData[self.json.var.ajaxId] = args.response
//alert(JSON.stringify(args));
value = self.docElement('self.ajaxResult.' + p2);
delete self.ajaxResult;
} else {
//alert(JSON.stringify(value));
value = match;
}
//value = ($(p2).is(':visible'));
break;
/* case 'function': // TO DO: remove
//self.log('function');
//self.log('p2');
//self.log(p2); // app.mac
value = self.function(p2) || match; // TO DO: log error
//var functionName = self.docElement(p2);
//value = (functionName) ? functionName(functionName) : p2+'=NULL'
break; */
case 'if': // TO DO: remove (can't manage spacial characters !<>'' etc)
p2 = self.replaceProperties(p2);
var ifArr = p2.split('|');
if (self.js(ifArr[0])) value = true;
if (ifArr.length > 1 && value) value = ifArr[1];
if (ifArr.length > 2 && !value) value = ifArr[2];
break;
case 'random':
/* var random = p2.replace(/([^\-]+)\-([^\}]+)/g, function(match, n1, n2, offset, string) {
return Number(n1)+Math.round((n2-n1)*Math.random());
}); */
value = String(Math.floor(Number(p2) * Math.random()));
//self.log('random value: '+value);
//value = random; //p2+' format is wrong'
// CHANGE TO {math.random:max}
break;
case 'getKey':
case 'firebaseKey':
value = self.firebaseKey(p2);
// https://firebase.google.com/docs/reference/android/com/google/firebase/database/DataSnapshot
// CHANGE TO {data.exists:path/to/record}
//"alert.close" functions(alert, do:close)
break;
case 'window':
/* try {
value = eval('window.'.p2);
} catch (error) {
self.log('javascript error on '+ p2);
value = match;
} */
//value = self.js('window.'.p2) || match;
value = self.docElement(p2) || match;
break;
/* case 'args':
// often replaceProperties is called without args
value = match;
break; */
default:
// ci finiamo dentro con {setup:value}
/* var element = document.querySelector(p2);
value = (element) ? element[p1] : '';
self.log('p1 ' + p1);
self.log('p2 ' + p2);
self.log('value ' + value);
if (!element)
self.log('can\'t match ' + match, 'color:red'); */
break;
/* default:
var node = self.docElement('self.json.'+p1);
self.log('node');
self.log(node);
if (node) value = node[p2] // example: p1 = styles.colors p2 = colorName
else value = '<{'+p1+':'+p2+'}>';
break;
*/
}
} // not self.functions[p1]
}
} else if (p2) {
// can be a FUNCTION: from modules
let keyPrefix = p2.split(' ')[0]; // /\s\./
if (self.functions[keyPrefix]) {
value = self.function({ name: keyPrefix });
value = self.element({ path: p2, root: value }); // example: {pathFromHash 0}
console.log(keyPrefix);
console.log(value);
}
else
value = self.replaceUndefined({ match: match, path: p2, removeUndefined: removeUndefined });
//value = self.element({path: p2});
}
// value is a DOM element
if (value && value.isConnected) value = self.elementToSelector(value); // DOM element to CSS selector
if (!value) {
// TO DO: should be (typeof value == undefined)
// t's a critical change. It changes the result of "is": "'{data id}' !== ''"
if (removeUndefined)
value = '';
else {
if (typeof value == undefined)
self.log(match + ' is undefined', 'yellow');
}
}
if (typeof value !== 'string') value = self.stringify(value); // object or array to string (TO DO: check numbers)
return value;
});
// js property TO DO: check it
if (paramsString.startsWith('{js:') && paramsString.endsWith('}'))
paramsString = self.js(paramsString.substr(4, paramsString.length - 1 - 4));
//if (self.isJson(paramsString)) {// (typeof params == 'object')
if (self.isJsonString(paramsString)) { // (typeof params == 'object')
var paramsObj = self.parse(paramsString);
// restore event nodes
if (paramOn) paramsObj.on = paramOn;
if (paramDo) paramsObj.do = paramDo;
if (paramConfirm) paramsObj.confirm = paramConfirm;
if (paramSuccess) paramsObj.success = paramSuccess;
if (paramError) paramsObj.success = paramError;
if (paramEvents) paramsObj.events = paramEvents; // obsolete
return paramsObj;
} else {
// TO DO: log of wrong json string
//alert(paramsString);
/* if (Array.isArray(self.parse(paramsString)))
return self.parse(paramsString)
else */
return paramsString;
}
} else {
// restore event nodes
if (paramOn) params.on = paramOn;
if (paramDo) params.do = paramDo;
if (paramConfirm) params.confirm = paramConfirm;
if (paramSuccess) params.success = paramSuccess;
if (paramError) params.error = paramError;
if (paramEvents) params.events = paramEvents; // obsolete
return params;
}
};
/* if (!value) undef = true;
if (undef) return undefined
else return params;
*/
this.isJsonString = function (str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
};
this.isJson = function (item) {
item = typeof item !== "string" ? JSON.stringify(item) : item;
try {
item = JSON.parse(item);
} catch (e) {
return false;
}
if (typeof item === "object" && item !== null) {
return true;
}
return false;
};
this.replaceStringInObject = function (obj, stringToReplace, value) {
var paramsString, valueString;
if (typeof obj == 'string') paramsString = obj; else paramsString = JSON.stringify(obj);
if (typeof value == 'string') valueString = value; else valueString = JSON.stringify(value);
paramsString = self.replaceAll(paramsString, stringToReplace, valueString);
if (self.isJson(paramsString))
return self.parse(paramsString);
else
return paramsString;
};
/* this.replaceResult = function (params, args) {
paramsString = paramsString.replace(/(\"\s*)\{[result]\:(\w+)\}(\s*\")/g, function(match, p1, p2, p3, offset, string) {
});
}
*/
this.replaceItems = function (params, item, name) {
// check this: http://mir.aculo.us/2011/03/09/little-helpers-a-tweet-sized-javascript-templating-engine/
// params:
<{item:name}>
, item: Vito or item: {name: Vito}
//var paramString = self.replaceProperties(params, undefined, item);
var paramsString;
var specialPattern;
var itemName = name || 'item';
/* if (name) {
self.log('replaceItems');
self.log('params');
self.log(params);
self.log('item');
self.log(item);
self.log('name');
self.log(name);
} */
if (typeof params == 'string') paramsString = params; else paramsString = JSON.stringify(params);
/* paramsString = paramsString.replace(/\{item\}/g, function(match, p1, offset, string) {
var value;
if (item) {
value = item;
} else {
value = '';
}
if (typeof value == 'object') value = self.stringify(value);
return value;
}); */
if (typeof item == 'object' || Array.isArray(item)) { // || Array.isArray(item) not needed
paramsString = self.replaceAll(paramsString, '"{' + itemName + '}"', JSON.stringify(item));
for (let key in item) {
if (typeof item[key] == 'object')
paramsString = self.replaceAll(paramsString, '"{' + itemName + ':' + key + '}"', JSON.stringify(item[key]));
else
paramsString = self.replaceAll(paramsString, '{' + itemName + ':' + key + '}', item[key]);
}
} else {
paramsString = self.replaceAll(paramsString, '{' + itemName + '}', String(item));
}
//if (itemName == 'hour') alert(paramsString);
/* if (itemName !== 'item') { // TO DO: remove
var propertyPattern = new RegExp('\{'+itemName+'\:([^\}]+)\}', 'g');
paramsString = paramsString.replace(propertyPattern, function(match, p1, p2, p3, offset, string) {
var value = self.docElement(p1, undefined, item);
if (value)
return value
else
return match;
});
} */
//specialPattern = new RegExp(/\"\{(\w+)\}\"/, "g");
// item: inside double quotes (to manage objects inside double string)
//specialPattern = new RegExp(`(\")\{${itemName}\:(\w+)\}(\")`, 'g');
//paramsString = paramsString.replace(specialPattern, function(match, p1, p2, p3, offset, string) {
//specialPattern = new RegExp('(\"\s*)\{'+itemName+'\:(\w+)\}(\s*\")', 'g');
paramsString = paramsString.replace(/(\"\s*)\{item\:(\w+)\}(\s*\")/g, function (match, p1, p2, p3, offset, string) {
var value;
if (item)
value = item[p2] || '';
else
value = '';
if (typeof value == 'object')
value = self.stringify(value);
else if (Array.isArray(value))
value = value;
else
value = p1 + value + p3; // p1 and p3 are the " matched by (\"\s*) and (\s*\")
return value;
});
/*
specialPattern = new RegExp('\{'+itemName+'\:([^\}]*)\}', 'g');
paramsString = paramsString.replace(specialPattern, function(match, p2, offset, string) {
//paramsString = paramsString.replace(/\{item\:([^\}]*)\}/g, function(match, p2, offset, string) {
var value;
if (item)
value = item[p2] || '';
else
value = '';
if (typeof value == 'object')
value = self.stringify(value);
return value;
}); */
if (self.isJson(paramsString))
return self.parse(paramsString);
else
return paramsString;
//if (typeof params == 'object') return self.parse(paramsString); else return paramsString;
};
/* this.replaceItems = function (objWithNames, name) {
//self.log('replaceItems');
var paramString = self.stringify(objWithNames);
//self.log(paramString);
if (!name) name = '';
paramString = self.replaceAll(paramString, '{item}', name);
//self.log(paramString);
//paramString = self.replaceTags({text:paramString});
//self.log(paramString);
//paramString = self.replaceProperties(paramString);
//self.log(paramString);
if (typeof objWithNames == 'object') return self.parse(paramString); else return paramString;
} */
this.color = function (params, args) {
var paramsReplaced = self.replaceProperties(params, args);
//if (self.json.styles.colors)
// return self.json.styles.colors[paramsReplaced];
if (self.json.data && self.json.data.colors)
return self.json.data.colors[paramsReplaced];
};
// ----------------------------
// ELEMENT METHODS
// ----------------------------
this.empty = function (params) {
/* self.log('empty');
self.log(params); */
var el = self.query(params);
if (el) {
while (el.firstChild)
el.removeChild(el.firstChild);
} else {
self.log('"empty" is unable to select element');
self.log(params);
}
};
this.isArray = function (value) {
return Array.isArray(self.js(value));
};
this.isVisible = function (el) {
return (el.style.display !== 'none' && !self.hasClass(el, 'd-none'));
};
this.isHidden = function (el) {
return (el.offsetParent === null);
};
this.isDisplay = function (el, displayValue) {
//var style = window.getComputedStyle(el);
/* self.log('isDisplay');
self.log('el.style');
self.log(el.style);
self.log('displayValue');
self.log(displayValue); */
return (el.style.display === displayValue);
};
this.inViewport = function (el) {
const rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
};
this.outViewport = function (el) {
return !self.outViewport(el);
};
this.notClass = function (el, className) {
return !self.hasClass(el, className);
};
this.hasClass = function (el, className) {
if (el.classList)
return el.classList.contains(className);
else
return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'));
};
this.addClass = function (el, className) {
if (el.classList)
el.classList.add(className);
else if (!self.hasClass(el, className)) el.className += " " + className;
};
this.removeClass = function (el, className) {
if (el.classList)
el.classList.remove(className);
else if (self.hasClass(el, className)) {
var reg = new RegExp('(\\s|^)' + className + '(\\s|$)');
el.className = el.className.replace(reg, ' ');
}
};
this.toggleClass = function (el, className) {
if (self.hasClass(el, className))
self.removeClass(el, className);
else
self.addClass(el, className);
};
this.choose = this.select = function (params, selectorParams, args) {
// "choose OR options / "select" is deprecated because select is an html tag
// {selection: selection class, id: selected id}
// or: choosed, choosable, selection
// or: selector, selectable, selection
// or: opted, options, selection
/* self.log('select');
self.log('params');
self.log(params);
self.log('args');
self.log(args); */
if (Array.isArray(params)) {
for (var obj of params)
self.choose(obj, args);
} else {
//if (selectorParams) params = self.extend({}, selectorParams, params);
var selId, selClass, selValue;
selValue = params['data-value']; // || params.value
if (params.id) selId = self.replaceProperties(params.id, args);
if (params.class) selClass = self.replaceProperties(params.class, args);
if (selValue) selValue = self.replaceProperties(selValue, args);
//var selector = self.selector(params.selector, undefined, true) || self.selector(selectorParams, undefined, true);
if (params.selection) {
var selectionClass = params.selection;
/* self.log('selClass');
self.log(selClass);
self.log('selValue');
self.log(selValue);
self.log('selectionClass');
self.log(selectionClass); */
var selector = self.selector({ class: selClass });
var elements = document.querySelectorAll('.' + selClass); // convert to any string selector (move the point to the code)
elements.forEach(function (element, index) {
self.removeClass(element, selectionClass);
});
//$(selector).removeClass(selectionClass);
if (selId || selValue) {
var selector = self.selector({ id: selId, class: selClass, 'data-value': selValue });
//self.log('selector');
//self.log(selector);
//var elements = self.query(selector);
//self.log('elements');
//self.log(elements);
//if (elements)
//self.addClass(elements, selectedIconClass);
var elements = document.querySelectorAll(selector);
elements.forEach(function (element, index) {
self.addClass(element, selectionClass);
});
}
} else {
/* self.log('select');
self.log('selClass');
self.log(selClass);
self.log('selValue');
self.log(selValue);
self.log('selectionClass');
self.log(selectionClass); */
self.hide({
"selector": {
"class": selClass
}
});
self.show({
"selector": {
"id": selId,
"class": selClass,
"data-value": selValue
}
});
//self.log('selectselection" class parameter is required in "select" object');
}
//self.updateCodeEditors(); // workaround known ACE bug
self.uiUpdate(); // resize event trigger
}
};
/* this.select = function (params, selectorParams) {
// { [container, class, value, id]
self.log('self.select');
if (Array.isArray(params)) {
for (var index in params)
self.choose(params[index], selectorParams);
} else {
if (selectorParams) params = self.extend({}, selectorParams, params);
params = self.replaceProperties(params);
//params = self.replaceTags({text:params});
self.selectItem(params);
}
}
*/
this.toggle = function (params, selectorParams, args) {
self.log('toggle');
self.log(params);
if (Array.isArray(params)) {
for (var index in params)
self.toggle(params[index], selectorParams, args);
} else {
var selector;
if (typeof params == 'string')
selector = params;
else
selector = self.selector(params.selector || params.container, undefined, true) || self.selector(selectorParams, undefined, true);
var element = self.query(selector);
/* self.log('selector');
self.log(selector);
self.log('element');
self.log(element);
self.log('self.isVisible(element)');
self.log(self.isVisible(element)); */
//if ($(selector).is(":visible"))
if (self.isVisible(element))
//self.fadeOut(params, selectorParams);
self.out(params, selectorParams, args);
else
//self.fadeIn(params, selectorParams);
self.in(params, selectorParams, args);
//$(selector).toggle(500); // jquery bugs // , self.resizeEvent
}
};
this.in = function (params, selectorParams, args) {
if (Array.isArray(params)) {
for (var index in params)
self.in(params[index], selectorParams, args);
} else {
var selector;
if (typeof params == 'string')
selector = params;
else
selector = self.selector(params.selector || params.container, undefined, true) || self.selector(selectorParams, undefined, true);
var transition = params.transition || 'fadeIn';
var duration = params.duration || '500ms';
//self.log('selector');
//self.log(selector);
var start = [{
"show": {
"selector": selector,
}
}];
var end = [
{
"do": self.resizeEvent
}
];
if (params.on && params.on.start)
start.push(params.on.start);
if (params.on && params.on.end)
end.push(params.on.end);
var animation = {
"animate": {
"selector": selector,
"transition": transition,
"duration": duration,
"on": {
"start": start,
"end": end
}
}
};
//self.do(animation, args);
self.do(animation, undefined, args);
//self.resizeEvent();
}
};
this.out = function (params, selectorParams, args) {
if (Array.isArray(params)) {
for (var index in params)
self.out(params[index], selectorParams);
} else {
var selector;
if (typeof params == 'string')
selector = params;
else
selector = self.selector(params.selector || params.container, undefined, true) || self.selector(selectorParams, undefined, true);
var transition = params.transition || 'fadeOut';
var duration = params.duration || '500ms';
var start = [];
var end = [
{
"hide": {
"selector": selector,
}
},
{
"do": self.resizeEvent
}
];
if (params.on && params.on.start)
start.push(params.on.start);
if (params.on && params.on.end)
end.push(params.on.end);
var animation = {
"animate": {
"selector": selector,
"transition": transition,
"duration": duration,
"on": {
"start": start,
"end": end
}
}
};
//self.do(animation, args);
self.do(animation, undefined, args);
}
};
this.show = function (params, selectorParams, args) {
if (Array.isArray(params)) {
for (var index in params)
self.show(params[index], selectorParams);
} else {
var selector;
if (typeof params == 'string')
selector = params;
else
selector = self.selector(params.selector || params.container, undefined, true) || self.selector(selectorParams, undefined, true);
var elements = self.queryAll(selector);
elements.forEach(function (element, index) {
self.removeClass(element, 'hidden');
self.removeClass(element, 'opacity-0');
self.removeClass(element, 'invisible');
self.removeClass(element, 'd-none'); // bootstrap
//element.style.display = 'block';
element.style.visibility = 'visible';
/*
container = element.getAttribute('data-selector');
//container = self.dataStorage.get(element, 'selector');
var action = [
{
"if": {
"container": container,
"hasClass": "opacity-0",
"then": {
"attr": {
"container": container,
"removeClass": "opacity-0"
}
}
}
},
{
"if": {
"container": container,
"hasClass": "invisible",
"then": {
"attr": {
"container": container,
"removeClass": "invisible" // bootstrap & tailwind
}
}
}
},
{
"if": {
"container": container,
"hasClass": "d-none",
"then": {
"attr": {
"container": container,
"removeClass": "d-none" // bootstrap
}
}
}
},
{
"if": {
"container": container,
"hasClass": "hidden",
"then": {
"attr": {
"container": container,
"removeClass": "hidden" // taliwind
}
}
}
},
{
"if": { // should be if style.display == none
"container": container,
"isDisplay": "none",
"then": {
"attr": {
"container": container,
"style": {
"display": ""
}
}
}
}
}
];
//element.style.display = ' ';
//alert(JSON.stringify(element.style));
if (element.style.visibility && element.style.visibility !== 'visible')
element.style.visibility = 'visible';
//self.do(action, args);
//self.do(action, undefined, args);
self.do(action, undefined, args); */
});
}
};
this.hide = function (params, selectorParams, args) {
if (Array.isArray(params)) {
for (var index in params)
self.hide(params[index], selectorParams);
} else {
var selector;
if (typeof params == 'string')
selector = params;
else
selector = self.selector(params.selector || params.container, undefined, true) || self.selector(selectorParams, undefined, true);
var elements = self.queryAll(selector);
elements.forEach(function (element, index) {
self.addClass(element, 'hidden');
/* container = element.getAttribute('data-selector');
var action = [
{
"attr": {
"container": container,
"addClass": "d-none" // bootstrap (to be removed)
}
},
{
"attr": {
"container": container,
"addClass": "hidden" // tailwind
}
}
];
//self.do(action, args);
self.do(action, undefined, args); */
});
}
};
/* this.fadeIn = function (params, selectorParams, args) {
//self.log('fadeIn');
//self.log(params);
if (Array.isArray(params)) {
for (var index in params)
self.fadeIn(params[index], selectorParams);
} else {
//params.container = params.container || self.selector(selectorParams);
//var selector = self.selector(params);
var selector = self.selector(self.extend({}, params, selectorParams), {}, true);
var duration = params.duration || 500;
var done = (params.done) ? function () {
self.resizeEvent();
self.do(params.done);
} : null;
$(selector).stop().fadeIn(duration, done);
}
}
this.fadeOut = function (params, selectorParams, args) {
//self.log('fadeOut');
//self.log(params);
// add onComplete and duration
if (Array.isArray(params)) {
for (var index in params)
self.fadeOut(params[index], selectorParams);
} else {
//params.container = params.container || self.selector(selectorParams);
//var selector = self.selector(params);
var selector = self.selector(self.extend({}, params, selectorParams), {}, true);
var duration = params.duration || 500;
var done = (params.done) ? function () {
self.do(params.done);
} : null;
$(selector).stop().fadeOut({
duration: duration,
done: function () {
self.resizeEvent();
self.do(params.done);
}
});
}
} */
/* this.show = function (params, selectorParams, args) {
//self.log('show');
//self.log(JSON.stringify(params));
if (Array.isArray(params)) {
for (var index in params)
self.show(params[index], selectorParams);
} else {
//params.container = params.container || self.selector(selectorParams);
//var selector = self.selector(params);
var selector = self.selector(self.extend({}, params, selectorParams), {}, true);
//self.log('selector');
//self.log(selector);
$(selector).show();
self.resizeEvent();
}
}
this.hide = function (params, selectorParams, args) {
//self.log('hide');
//self.log(JSON.stringify(params));
if (Array.isArray(params)) {
for (var index in params)
self.hide(params[index], selectorParams);
} else {
//params.container = params.container || self.selector(selectorParams);
//var selector = self.selector(params);
var selector = self.selector(self.extend({}, params, selectorParams), {}, true);
//self.log('selector');
//self.log(selector);
$(selector).hide();
self.resizeEvent();
}
} */
this.matchMedia = function (mediaAction, mediaEvent) {
const mediaQuery = window.matchMedia(mediaEvent);
mediaQuery.addListener(function (e) {
/* self.log('matchMedia');
self.log('e');
self.log(e); */
if (e.matches) {
self.do(mediaAction);
//self.do(mediaAction);
}
});
//self.do(mediaAction);
};
/* this.firebaseEventAction = function (newObj) {
var path = newObj.path;
delete newObj.path;
document.querySelectorAll('[data-firebase="'+path+'"]').forEach(function (element, index) {
var pathString = 'self.json.var.db.' + self.replaceAll(element.getAttribute('data-firebase'), '/', '.'); // data('firebase')
var dbObj = self.docElement(pathString);
var firebaseValue = newObj[element.getAttribute('data-value')]; // TODO: not works for nested nodes
var container = element.getAttribute('data-selector');
//var template = element.getAttribute('data-template');
var template = self.dataStorage.get(element, 'data-template');
if (element.tagName == 'UL') { // se $(this) è un ul
var liTemplate = template.li;
//$(container).empty();
element.innerHTML = '';
var items = newObj;
for (itemKey in items) {
var item = items[itemKey];
item.key = itemKey;
//if (dbPath == 'lessons')
//prompt(JSON.stringify(liTemplate));
var dbParams = self.replaceItems(liTemplate, item, 'item') || '';
// var dbParams = self.replaceProperties(liTemplate, undefined, item) || '';
self.li(dbParams, {container: container});
}
//} else if ( $(element).is('span') || $(element).is('p')) {
} else if (element.tagName == 'SPAN' || element.tagName == 'P') {
//$(element).text(firebaseValue);
element.textContent = firebaseValue;
} else { // se $(this) non è un ul
if (template.blocks || template.html) {
var blocksTemplate = template.html || template.blocks;
//$(container).empty();
element.innerHTML = '';
var items = newObj;
self.log('newObj');
self.log(newObj);
for (itemKey in items) {
var item = items[itemKey];
item.key = itemKey;
var dbParams = self.replaceProperties(blocksTemplate, undefined, item) || '';
self.html(dbParams, {container: container});
}
}
if (template.init) self.do(template.init);
}
});
}; */
/* self.jsonic = function () {
} */
this.addFirebaseTag = function (params) {
// self.log('addFirebaseTag');
var dataObj = params.database;
if (dataObj) {
dataObj = self.replaceProperties(dataObj);
/* self.log('dataObj');
self.log(dataObj); */
//var path = self.replaceTags({text:params.firebase});
var path, success;
if (typeof dataObj == 'string') {
path = dataObj;
} else {
path = dataObj.path;
success = dataObj.success;
}
if (path) {
var selector = self.selector(params, undefined, false);
//var element = self.query(selector);
var elements = self.queryAll(selector);
//var elements = document.querySelectorAll(selector);
if (elements)
elements.forEach(function (element, index) {
var listenerObj = {
path: path
//success: dataObj.success
};
var elementsDataPath = document.querySelectorAll('[data-firebase="' + path + '"]');
//if ($('[data-firebase="'+path+'"]').length == 0) {
if (elementsDataPath.length == 0) {
listenerObj.action = [
/* {
"firebaseEvent.action": {} // should use self.get function to parse "self"
// todo: remove "jsonic". The function firebaseEventAction can be stored in self.do (or?)
} */
];
if (dataObj.success)
listenerObj.action.push(dataObj.success);
}
//$(selector).attr('data-firebase', path);
//$(selector).data('data-template', params);
if (element) {
element.setAttribute('data-firebase', path);
self.dataStorage.set(element, 'data-template', params);
} else {
self.log('!element selector:' + selector + ' / firebase path:' + path);
self.log('params');
self.log(params);
}
//if (params.on && params.on.data) $(selector).data('ondata', params.on.data); // maestry
if (dataObj.orderByChild !== undefined) listenerObj.orderByChild = dataObj.orderByChild;
if (dataObj.equalTo !== undefined) listenerObj.equalTo = dataObj.equalTo;
self.firebaseAddListener(listenerObj);
});
} else {
self.log('data object requires path parameter');
self.log(params);
}
}
};
this.dbObject = function (path) {
var pathString = 'self.json.var.db.' + self.replaceAll(path, '/', '.');
return self.docElement(pathString);
};
this.only = function (permissions, user) {
// "visitor" or "only"
if (user) {
return (user == self.user('uid'));
} else {
var permission = (permissions) ? String(permissions).split(',') : false;
return (!permission || (permissions.indexOf(self.userRole()) >= 0));
}
};
this.extendJsonFromElement = function (p) {
/* self.log('extendJsonFromElement');
self.log(p); */
var params = self.cloneObject(p);
// properties
if (params.resources) self.extendJson(self.json, { "resources": params.resources });
if (params.plugins) self.extendJson(self.json, { "plugins": params.plugins });
if (params.parts) self.extendJson(self.json, { "parts": params.parts });
if (params.blocks) self.extendJson(self.json, { "blocks": params.parts }); // obsolete
if (params.shortcuts) self.extendJson(self.json, { "shortcuts": params.shortcuts });
if (params.css) self.extendJson(self.json, { "css": params.css });
if (params.setup) self.extendJson(self.json, { "setup": params.setup });
if (params.data) self.extendJson(self.json, { "data": params.data });
if (params.var) self.extendJson(self.json, { "var": params.var });
if (params.texts) self.extendJson(self.json, { "texts": params.texts }); // maybe used in self.text
// can't be extended "setup" (is relative to the full app) and "on" (is relative to the element)
};
this.query = function (selector, element) {
//self.log('query: '+selector);
if (selector) {
if (typeof selector == 'object')
selector = self.selector(selector, undefined, true);
var routes = selector.split(/[ >]+/);
if (!element) element = document;
for (var index in routes) {
if (element && element[0]) element = element[0];
if (element && element.isConnected) {
var route = routes[index];
/* route.replace(/([^\s])\[/g, function(match, p1) { // -> .class [data-value=...]
return p1 + ' ['
}); */
//self.log('route');
//self.log(route);
var routeParts = route.match(/(.*):eq\((\d*)\)/);
//self.log('routeParts');
//self.log(routeParts);
if (routeParts) {
var routeElement = String(routeParts[1]);
var routeIndex = Number(routeParts[2]);
if (routeElement.startsWith('.'))
routeElement = '.' + self.classSelector(routeElement);
//if (self.exist(routeElement))
element = element.querySelectorAll(routeElement)[routeIndex];
/* self.log('routeElement');
self.log(routeElement);
self.log('routeIndex');
self.log(routeIndex); */
} else {
//if (self.exist(route))
if (route.startsWith('.'))
route = '.' + self.classSelector(route);
element = element.querySelectorAll(route)[0];
}
} else {
element = undefined;
}
}
//element.innerHTML = 'test';
//element.style.display = 'none';
//self.log(element);
//if (element && !Array.isArray(element)) element = [element];
if (!element)
self.log('can\'t find the element "' + selector + '" ("query" function)');
return element;
} else {
//self.log('function "query" without selector parameters');
// BUG: many calls from addtag
}
};
/* this.queryAllTest = function (selector, element) {
//self.log('query: '+selector);
if (selector) {
//route = self.replaceAll(route, '[', ' [');
selector.replace(/([^\s])\[/g, function(match, p1) { // -> .class [data-value=...]
return p1 + '['
});
var routes = selector.split(/[ >]+/);
if (!element) element = document;
self.log('routes');
self.log(routes);
for (var index in routes) {
self.log('index');
self.log(index);
if (element.isConnected) {
var route = routes[index];
var routeParts = route.match(/([^:]*):eq\((\d*)\)/);
self.log('routeParts');
self.log(routeParts);
if (routeParts) {
var routeElement = String(routeParts[1]);
var routeIndex = Number(routeParts[2]);
//if (self.exist(routeElement))
element = element.querySelectorAll(routeElement)[routeIndex];
self.log('routeElement');
self.log(routeElement);
self.log('routeIndex');
self.log(routeIndex);
} else {
//if (self.exist(route))
self.log('route');
self.log(route);
element = element.querySelectorAll(route);
}
} else {
self.log('Not in the DOM '+ selector);
self.log('route');
self.log(route);
element = [];
}
}
//element.innerHTML = 'test';
//element.style.display = 'none';
//if (element && !Array.isArray(element)) element = [element];
//self.log(element);
return element;
} else {
self.log('DOM "query" without selector parameters');
}
} */
/* this.convertRoute = function (route) {
var routeElement, routeValue;
route = route.replace(/([^\s])\[/g, function(match, p1) { // -> .class [data-value=...]
return p1 + ' ['
});
if (route.indexOf(' ')) {
var parts = route.split(' ');
routeElement = parts[0];
routeValue = parts[1];
} else {
routeElement = route
}
self.log(routeElement);
self.log(routeValue);
if (routeElement.startsWith('.'))
routeQuery = '[class='+routeElement+']';
else if (routeElement.startsWith('#'))
routeQuery = '[id='+routeElement+']';
else
routeQuery = routeElement + routeValue;
if (routeValue)
routeQuery += ' ' + routeValue;
return routeQuery;
} */
/*
// https://www.examplefiles.net/cs/1222124
var querySelectorAllWithEq = function(selector, document) {
var remainingSelector = selector;
var baseElement = document;
var firstEqIndex = remainingSelector.indexOf(':eq(');
while (firstEqIndex !== -1) {
var leftSelector = remainingSelector.substring(0, firstEqIndex);
var rightBracketIndex = remainingSelector.indexOf(')', firstEqIndex);
var eqNum = remainingSelector.substring(firstEqIndex + 4, rightBracketIndex);
eqNum = parseInt(eqNum, 10);
var selectedElements = baseElement.querySelectorAll(leftSelector);
if (eqNum >= selectedElements.length) {
return [];
}
baseElement = selectedElements[eqNum];
remainingSelector = remainingSelector.substring(rightBracketIndex + 1).trim();
// Note - for now we just ignore direct descendants:
// 'a:eq(0) > i' gets transformed into 'a:eq(0) i'; we could maybe use :scope
// to fix this later but support is iffy
if (remainingSelector.charAt(0) === '>') {
remainingSelector = remainingSelector.substring(1).trim();
}
firstEqIndex = remainingSelector.indexOf(':eq(');
}
if (remainingSelector !== '') {
return Array.from(baseElement.querySelectorAll(remainingSelector));
}
return [baseElement];
}; */
this.queryAll = function (selector, element) {
//self.log('queryAll: '+selector);
if (selector) {
if (Array.isArray(selector)) {
let elements = self.queryAll(selector[0]);
selector.shift();
for (let str of selector) {
elements = Array.prototype.slice.call(elements).concat(Array.prototype.slice.call(self.queryAll(str)));
//elements = elements.concat(self.queryAll(str));
}
/* console.log('queryAll');
console.log(elements); */
return elements;
} else {
/*
if (selector.indexOf(',')>= 0) {
return element.querySelectorAll(selector)
}
// TO DO: check why all the rest
*/
var routes = selector.split(/[ >]+/);
if (!element) element = document;
/* self.log('routes');
self.log(routes); */
/* self.log('element[0]');
self.log(element[0]); */
for (var index in routes) {
if (element && element[0]) element = element[0];
/* self.log('element');
self.log(element); */
if (element && element.isConnected) {
var route = routes[index];
var routeParts = route.match(/([^:]*):eq\((\d*)\)/);
/* self.log('route');
self.log(route);
self.log('routeParts');
self.log(routeParts); */
if (routeParts) {
var routeElement = String(routeParts[1]);
var routeIndex = Number(routeParts[2]);
/* self.log('routeElement');
self.log(routeElement);
self.log('routeIndex');
self.log(routeIndex); */
if (routeElement.startsWith('.'))
routeElement = '.' + self.classSelector(routeElement);
//if (self.exist(routeElement))
element = element.querySelectorAll(routeElement)[routeIndex];
if (index == (routes.length - 1) && element) {
/* console.log('index:'+index);
console.log('routes.length:'+routes.length); */
element = [element];
}
} else {
//if (self.exist(route))
if (route.startsWith('.'))
routeElement = '.' + self.classSelector(route);
/* self.log('route');
self.log(route); */
element = element.querySelectorAll(route);
}
} else {
//self.log('!element.isConnected');
element = [];
}
}
//if (element && !Array.isArray(element)) element = [element];
//if (element && !element.length) element = [element];
if (!element)
self.log('No element selected by ' + selector);
//else
// if (!Array.isArray(element))
// element = [element];
return element;
}
} else {
console.log('%cDOM queryAll requires selector argument', 'color: orange');
//self.log('DOM "query" without selector parameters');
}
};
/* this.queryAll = function (selector, element) {
//self.log('query: '+selector);
if (selector) {
var routes = selector.split(/[ >]+/);
if (!element) element = document;
for (var index in routes) {
var route = routes[index];
//onsole.log('route');
//self.log(route);
var routeParts = route.match(/(.*):eq\((\d*)\)/);
//self.log('routeParts');
//self.log(routeParts);
if (routeParts) {
var routeElement = String(routeParts[1]);
var routeIndex = Number(routeParts[2]);
//if (self.exist(routeElement))
element = [element.querySelectorAll(routeElement)[routeIndex]];
} else {
//if (self.exist(route))
element = element.querySelectorAll(route);
}
}
//element.innerHTML = 'test';
//element.style.display = 'none';
//if (element && !Array.isArray(element)) element = [element];
//self.log(element);
return element;
} else {
self.log('DOM "query" without selector parameters');
}
} */
/* var querySelectorAllWithEq = function(selector, document) {
var remainingSelector = selector;
var baseElement = document;
var firstEqIndex = remainingSelector.indexOf(':eq(');
while (firstEqIndex !== -1) {
var leftSelector = remainingSelector.substring(0, firstEqIndex);
var rightBracketIndex = remainingSelector.indexOf(')', firstEqIndex);
var eqNum = remainingSelector.substring(firstEqIndex + 4, rightBracketIndex);
eqNum = parseInt(eqNum, 10);
var selectedElements = baseElement.querySelectorAll(leftSelector);
if (eqNum >= selectedElements.length) {
return [];
}
baseElement = selectedElements[eqNum];
remainingSelector = remainingSelector.substring(rightBracketIndex + 1).trim();
// Note - for now we just ignore direct descendants:
// 'a:eq(0) > i' gets transformed into 'a:eq(0) i'; we could maybe use :scope
// to fix this later but support is iffy
if (remainingSelector.charAt(0) === '>') {
remainingSelector = remainingSelector.substring(1).trim();
}
firstEqIndex = remainingSelector.indexOf(':eq(');
}
if (remainingSelector !== '') {
return Array.from(baseElement.querySelectorAll(remainingSelector));
}
return [baseElement];
}; */
this.jitcss = function (classes) {
// https://tailwindcss.com/docs/just-in-time-mode
if (classes.indexOf('-[') > -1) {
let classesArr = classes.split(' '); // change to one or more spaces
// (sm\:|md\:|lg\:|xl\:|2xl\:)?
self.log('jitcss');
for (cl of classesArr) {
self.log(cl);
let par = [...cl.matchAll(new RegExp('([^-]+)[\-][\[](.+)\]', 'g'))];
self.log('jitcss');
self.log(par);
}
}
/* sm:w-1
.w-1 {
width: 1em;
}
@media (min-width: 640px) {
.sm\:w-1 { width: 1em }
}
*/
};
this.compileClasses = function (string) {
var classesString = string;
// classes shortcuts
if (self.json.shortcuts && self.json.shortcuts.class) {
for (shortcut in self.json.shortcuts.class) {
if (string.indexOf(shortcut) > -1) {
classesString = self.replaceAll(string, shortcut, self.json.shortcuts.class[shortcut]);
}
}
}
// dynamic classes
if (string.indexOf('(') >= 0) {
//self.log('compileClasses');
classesString = '';
let classesArr = string.split(' ');
for (cl of classesArr) {
/* self.log('cl');
self.log(cl); */
if (cl.indexOf('(') >= 0 && cl.endsWith(')')) {
let classArr = cl.split('(');
classArr[1] = classArr[1].slice(0, -1); // remove )
//let par = [...cl.match(new RegExp('([^\(]+)\(([^\)]+)\)$'))]; // doesn't work
/* self.log('classArr');
self.log(classArr);
self.log('classArr[1]');
self.log(classArr[1]);
self.log('self.js(classArr[1])');
self.log(self.js(classArr[1])); */
if (Boolean(self.js(classArr[1]))) {
if (classesString !== '') classesString += ' ';
classesString += classArr[0];
}
} else {
if (classesString !== '') classesString += ' ';
classesString += cl;
}
}
if (string == classesString) {
self.log('wrong dynamic class syntax');
self.log(string);
}
}
return classesString;
};
this.createElement = function (params, selectorParams) {
let selector = params.selector || params.container;
var container = selector || self.selector(selectorParams);
var containerElement = self.query(container);
var newSelector = self.selector(params, selectorParams); // from 0.9.6: must stay before document.createElement
/* console.log('append');
console.log('selector:'+selector);
console.log('container:'+container);
console.log('newSelector:'+newSelector); */
var newElements = [];
//if (containerElement)
//containerElements.forEach(function (containerElement, index) {
if (containerElement) {
if (!params) params = {};
var element = document.createElement(params.tag);
containerElement.appendChild(element);
if (params.attr) {
// shortcuts (windy property not in twind) and dynamic classes with js condition
if (params.attr.class) {
// replace shortcuts and dynamic classes: class(condition)
params.attr.class = self.compileClasses(params.attr.class);
}
}
//if (container) element.setAttribute('data-selector', self.selector(params, selectorParams));
//if (container) element.setAttribute('data-selector', newSelector); // from 0.9.6. removed 1.0.12
// for IDE
self.dataStorage.set(element, 'code', params);
self.dataStorage.set(element, 'key', params.key);
/* if (params.attr && params.attr.class)
self.jitcss(params.attr.class); */
newElements.push(element);
if (params.attr) self.setAttributes(newElements, params.attr);
if (params.style) self.css(params, newSelector); // TO DO: deprecated / to be removed;
/* // attributes TO DO: move up / call self.attr
if (params.attr)
for (var attrId in params.attr)
self.attribute(newElements, attrId, self.replaceProperties(params.attr[attrId]));
//self.log(self.replaceProperties(params.attr[attrId]));
//$(selector).attr(attrId, params.attr[attrId]); */
}
//});
return newElements;
/* for (let element of elements) {
element.appendChild(string);
} */
};
/* this.newSelector = function (params, selectorParams) {
var container = self.selector(self.extend({}, params, selectorParams), undefined, true);
if (container) {
var selectorObj = {
container: container,
//class: params.class,
//value: params.value,
//'data-value': params['data-value']
}; // , selectorParams);
self.log('container');
self.log(container);
var index = document.querySelectorAll(container).length;
if (index > 1) selectorObj.index = index-1;
self.log('newSelector');
self.log(selectorObj);
return selectorObj;
} else {
self.log('container undefine in newSelector');
self.log('params');
self.log(params);
self.log('selectorParams');
self.log(selectorParams);
}
}
*/
/*
this.editor = function (params, selectorParams, args) {
self.log('editor');
self.log('params');
self.log(params);
var selector = self.selector(selectorParams, undefined, true); // self.selector(params, undefined, true) ||
if (selector) {
var element = self.query(selector);
if (element) {
if (!self.quillElements[selector]) {
self.quillElements[selector] = new Quill(element, {
modules: params.modules || { // or default modules
toolbar: [
[{ header: [1, 2, false] }],
['bold', 'italic', 'underline'],
['image', 'code-block']
]
},
// scrollingContainer: '#scrolling-container',
placeholder: params.placeholder || 'Write here',
theme: params.theme || 'bubble'
});
}
if (self.quillElements[selector]) {
if (params.setContents) {
var contents = self.replaceProperties(params.setContents, args);
self.quillElements[selector].setContents(contents);
}
if (params.getContents) {
self.quillElements[params.getContents].getContents();
}
if (params.on) {
for (var eventId in params.on) {
self.editorChangeFunctions[selector] = params.on;
if (params.on[eventId]) {
self.quillElements[selector].on(eventId, function(delta, oldDelta, source) {
var action = self.editorChangeFunctions[selector][eventId];
var actionWithResult = self.replaceResult(action, delta);
//self.do(actionWithResult);
self.do(actionWithResult);
});
}
}
}
}
} else {
self.log('can\'t find the element "'+ selector + '" ("editor" function)');
self.log(params);
}
} else {
self.log('the "editor" function has a wrong selector');
self.log(params);
}
}
*/
this.do = this.action = this.execute = function (params, selectorParams, args) {
/* self.log('params');
self.log(params);
self.log('selectorParams');
self.log(selectorParams);
self.log('args');
self.log(args); */
if (params !== undefined && params !== null) { // empty string is ok
/*
// problematic for nested {args} / {selector}
if (selectorParams && typeof selectorParams == 'string') {
params = self.replaceProperty(params, 'selector', selectorParams);
}
if (args) {
params = self.replaceProperty(params, 'args', args);
}
*/
if (typeof params == 'string')
params = self.replaceProperties(params, args);
let pluginsRequired = self.pluginsRequired(params);
/* self.log('pluginsRequired');
self.log(pluginsRequired); */
if (pluginsRequired.length > 0)
//let params = [params, args, selectorParams];
self.pluginsLoader(pluginsRequired, self.do, [params, selectorParams, args]);
else {
if (Array.isArray(params))
for (var obj of params)
self.do(obj, selectorParams, args); // -> execute dopo aver portato qui pluginsLoaded
else if (typeof params == 'object') {
/* if (params.after) {
let paramsAfter = params.after;
let paramsWithoutAfter = self.cloneObject(params);
delete paramsWithoutAfter.after;
self.timer({
after: paramsAfter,
do: paramsWithoutAfter
});
} else {
*/
if (params.if == undefined || self.if(params.if)) { // || Boolean(self.js(params.if))) { // , args
/* console.log('IF---------------');
console.log(params.if);
console.log(params); */
if (self.only(params.roles, params.user)) {
//if (!params) params = {};
//var newContainer; //self.newSelector(params, selectorParams); // {container: selector}
// Add an element in the DOM
if (params.tag) {
var selector = self.selector(params, selectorParams);
/* self.log('selector');
self.log(selector); */
self.extendJsonFromElement(params); // or selectorParams
//newContainer = {selector: selector};
//if (1) //self.user('uid') == 'L0y20rjPp6a6ejqVuDXuTWCU2rH3') //'ocXuFBV4aWcy7KZMAmi6mICFi872')
// create new html element
var newElements = self.createElement(params, selectorParams);
/* if (params.key == 'text')
//let element = self.query(self.selector(params.selector));
newElements.innerText = self.text(nested); */
if (params.matchMedia) {
for (var mediaEvent in params.matchMedia) {
self.matchMedia(params.matchMedia[mediaEvent], mediaEvent);
}
}
if (params.html) {
self.html(params.html, selector, args);
} else {
// nested html tags as property
for (var par in params) // && (par !== 'attr')
if ((nodes.exclude.indexOf(par) < 0) && (nodes.params.indexOf(par) < 0))
self.nested({ key: par, obj: params[par], selector: { selector: selector }, args: args });
}
self.on(params.on, { selector: selector });
} else {
var selector = self.selector(params, selectorParams);
for (var par in params)
if ((nodes.exclude.indexOf(par) < 0) && (nodes.params.indexOf(par) < 0))
self.nested({ key: par, obj: params[par], selector: selector, args: args });
if (params.on)
self.on(params.on, { selector: selector });
}
} // end of self.only
}
//}
} else if (typeof params == 'function')
return params(selectorParams);
else
self.log('can\'t execute: ' + params);
}
}
};
this.callback = function (params) {
/* console.log('callback');
console.log(params); */
// {do, find, replace}
if (params) {
var path = params.to;
if (params.var) path = 'var ' + params.var; // TO DO: remove
let selector;
let element = params.element; // elementToSelector ?
if (element && element.isConnected) params.value = self.elementToSelector(element);
if (path) {
var context = self.context(path);
self.element({ path: path, value: params.value, root: context });
}
if (params.do)
self.do(params.do, selector);
}
};
this.nested = function (params) {
/* console.log('nested');
console.log(params); */
// check plugins required
let pluginsRequired = self.pluginsRequired(params.key);
if (pluginsRequired.length > 0) {
self.pluginsLoader(pluginsRequired, self.nested, [params]);
} else {
// TO DO: regular expression like in this.element (should include setup and also :)
if (params.key.startsWith('set ')) {
self.setData({ key: params.key.substr(4), value: params.obj });
} else if (params.key.startsWith('var ') || params.key.startsWith('data ') || params.key.startsWith('set ')) {
// TO DO: remove this option. Is too ambiguous for debug -> use set
// deprecated from 1.0.4
console.log('%cdeprecated key: "' + params.key + '". Use "set key": "value"}', 'color:orange');
// Data setting prefix
// should be removed and replaced with the method "set" to improve the compatibility
// with the other possible keys (js functions, jsonic methods, html tags ex. )
// https://www.w3schools.com/tags/tag_data.asp
self.setData({ key: params.key, value: params.obj });
} else {
// CHECK IF KEY IS METHOD
//console.log('check if is a method');
var method = self.element({ path: params.key, root: self.methods });
if (method) { // search in jsonic.methods
self.log('METHOD: ' + params.key, 'grey');
var methodArgs = params.obj;
/* if (params.key == 'swiper init') {
self.log('method: ' + params.key);
self.log('methodArgs');
self.log(methodArgs);
self.log('params.selector');
self.log(params.selector);
self.log('-----------');
} */
//methodArgs = self.replaceProperty(methodArgs, 'selector', params.selector);
method(methodArgs, params.selector, params.args);
/* } else if (params.key == 'set') { // TO DO: REMOVE
// JS METHOD (old)
var actionObj = {};
actionObj[params.key] = params.obj;
self.do(actionObj, params.selector); */
/* } else if (nodes.functions.indexOf(params.key) >= 0) { // TO DO: REMOVE
// JS METHOD (old)
var actionObj = {};
actionObj[params.key] = params.obj;
//self.do(actionObj, undefined, params.selector);
self.do(actionObj, params.selector); */
} else {
// CHECK IF KEY IS A PARTS
//console.log('check if is a part');
// shortcut: content
let nested;
let part;
var jsonicPart = false;
if (self.json.parts) { // && par.match(/[.>]+/))
part = self.element({ path: self.replaceAll(params.key, ':', '.'), root: self.json.parts });
/* if (par.indexOf(':')>0 && !part) {
jsonicPart = true;
self.firebaseGetPart({localPath:localPath, container: params.selector, arg:params.obj});
} */
}
if (part) {
self.log('PART: ' + params.key, 'grey');
/* console.log('params');
console.log(params); */
var partObj = params.obj;
//nested = self.replaceProperty(part, 'value', params.obj); // obsolete?
//nested = self.replaceProperty(part, 'arg', partObj); // obsolete
//if (typeof partObj == 'string' && partObj.indexOf('{') >= 0) { // obsolete?
// TO DO: this should be already inside self.do
partObj = self.replaceProperties(partObj);
// for backward compatibility can be partObj, null, true) // true is removeUndefined
//}
/* console.log('partObj');
console.log(partObj);
*/
//var partSelector = params.selector || partObj.selector;
// TO DO: Check this
// seems a workaround for fantacards/ui:qrcode
// parts can receive the parameters {selector:..., setup:...}
partObj.selector = partObj.selector || params.selector;
// TO DO: deprecated fantacards:setPlayer
if (partObj.setup) partObj = partObj.setup;
// overwrites partObj.selector but execute receive params.selector
// TO DO: replaceProperty should be improved to get also sub values like {arguments:on.success}
//nested = self.replaceProperty(part, 'setup', partObj); // {setup} -> {arguments}
//nested = self.replaceProperty(nested, 'arguments', partObj);
//nested = self.replacePropertyWithPrefix(part, 'setup:', partObj); // {setup} -> {arguments}
//nested = self.replacePropertyWithPrefix(nested, 'arguments:', partObj);// to tix
nested = self.replacePropertyWithPrefix(part, 'setup', partObj); // {setup} -> {arguments}
nested = self.replacePropertyWithPrefix(nested, 'arguments', partObj); // to tix
self.extendJsonFromElement(nested); // or selectorParams
//self.do(nested, partSelector, partObj);
self.do(nested, params.selector, partObj);
/*
self.log('nested');
self.log(nested);
self.log('part key');
self.log(params.key);
self.log('part obj');
self.log(part);
*/
} else { // if (!jsonicPart) { // should be if (par !== 'on', 'attr', 'style', 'items/data')
// params.key is not var/data, a method, a part
//var jsFunction = self.element({path: params.key, root: self.functions});
if (self.json && self.json.functions && params.key && self.json.functions[params.key]) {
//if (self.json.functions[params.key]) {
self.log('FUNCTION: ' + params.key, 'grey');
/* self.log('pluginsRequired');
self.log(pluginsRequired); */
let args = self.replaceProperties(params.obj, undefined, true); // undefined properties -> ''
/* console.log('%cargs', 'color:red');
console.log(args); */
if (!args || !Array.isArray(args)) args = [args];
if (self.json.functions[params.key].requires) {
let pluginsRequired = [];
for (let plugin of self.json.functions[params.key].requires) {
if (!self.pluginsLoaded[plugin])
pluginsRequired.push({ "name": plugin, version: "" });
}
if (pluginsRequired.length > 0)
//self.pluginsLoader(pluginsRequired, self.functions[params.key], args);
self.pluginsLoader(pluginsRequired, self.function, [{ name: params.key, arguments: args }]);
else {
self.log('Plugins already loaded: ' + params.key, 'grey');
self.function({ name: params.key, arguments: args });
//self.functions[params.key](...args);
}
} else {
/* let args = self.replaceProperties(params.obj);
if (!args || !Array.isArray(args)) args = [args]; */
self.log('Function without plugin required: ' + params.key, 'grey');
self.function({ name: params.key, arguments: args }); // TO DO: check why here it can't have []
//self.functions[params.key](...args);
}
} else {
var windowFunction = self.element({ path: params.key, root: window });
if (typeof windowFunction === 'function') {
self.log('WINDOW function: ' + params.key, 'grey');
windowFunction(self.replaceProperties(params.obj, undefined, true)); // undefined properties -> ''
//windowFunction(self.replaceProperties(params.obj));
} else if (windowFunction !== undefined) {
self.log('window.' + params.key + ' is not a function', 'red');
//self.log(params.key + ' not found', 'red');
// use set for window assignment
/*
self.element({path: params.key, value:params.obj, root: window}); */
} else {
// NESTED HTML
// Need to be improved. with nestedAction and nestedTag
// here we can search only nestedAction
// and from html we can search only for nestedTag's
//nested = params.obj; // removed in 1.0.1
// if is a nested html params.selector is required
// impossible to understand if we are inside an html method
// because the html tags can be nested and with any name
if (params.selector) { // added in 1.0.1
self.log('TAG: ' + params.key, 'grey');
// should be also in this.html function if params is an array
let pluginsRequired = self.pluginsRequiredByTag(params.obj, params.key);
if (pluginsRequired.length > 0) {
let htmlTagParams = [params.obj, params.selector, params.key];
self.pluginsLoader(pluginsRequired, self.htmlTag, htmlTagParams);
} else {
self.htmlTag(params.obj, params.selector, params.key); // tagParam = params.key
//if (nested.database) self.addFirebaseTag(self.extend({}, nested, params.selector));
}
} else {
self.log(params.key + ' not found', 'red');
}
}
}
}
}
}
}
};
this.setData = function (params) {
//self.log('setData');
let setObj = {};
setObj[params.key] = params.value;
self.set(setObj);
/* if (params.path.indexOf('{') >= 0)
params.path = self.replaceProperties(params.path);
if (typeof params.value == 'string' && params.value.indexOf('{') >= 0)
params.value = self.replaceProperties(params.value);
self.element({path: params.path, value: params.value}); */
/* self.log(params.path);
self.log(self.element({path: params.path})); */
};
this.partContainers = {};
this.pluginsRequiredByTag = function (params, tagKey) {
// self.log('pluginsRequiredByTag');
/* self.log('params');
self.log(params);
self.log('par');
self.log(par); */
if (self.json.resources) {
// analize function object or array of objects
const pluginsTags = self.json.resources.pluginsTags;
const pluginsAttr = self.json.resources.pluginsAttr;
var pluginsRequired = [];
if (pluginsTags[tagKey] && !self.pluginsLoaded[pluginsTags[tagKey].name])
pluginsRequired.push(pluginsTags[tagKey]);
if (typeof params == 'string') {
// for example: "tagName": "string" where tagName requires a plugin
} else if (typeof params == 'object') {
var objArray;
if (Array.isArray(params)) objArray = params; else objArray = [params];
for (var obj of objArray) {
if (obj.attr) { // attr
var attr = 'data-icon';
if (obj.attr[attr]) {
if (pluginsAttr[attr] && !self.pluginsLoaded[pluginsAttr[attr].name])
pluginsRequired.push(pluginsAttr[attr]);
}
}
}
}
return pluginsRequired;
} else {
// should load resources
return false;
}
};
/*
'locale': {
unit: month, weekday
format: long, short, narrow
index: 1,
lang: page:language
*/
this.calendar = function (params, args) {
const localeName = (self.json.setup.language !== 'en') ? self.json.setup.language : 'en-US';
let calendarArr, todayIndex;
if (params.unit) {
switch (params.unit) {
case 'month':
const monthFormat = params.format || 'long';
var format = new Intl.DateTimeFormat(localeName, { month: monthFormat }).format;
calendarArr = [...Array(12).keys()].map((m) => format(new Date(Date.UTC(2021, m))));
todayIndex = new Date().getMonth();
break;
case 'weekday':
const weekdayFormat = params.format || 'long';
var format = new Intl.DateTimeFormat(localeName, { weekday: weekdayFormat }).format;
calendarArr = [...Array(7).keys()].map((day) => format(new Date(Date.UTC(2021, 5, day))));
todayIndex = self.weekday();
break;
default:
self.log('"calendar" function can\'t recognize "unit" parameter');
self.log(params.unit);
break;
}
if (calendarArr) {
if (params.index !== undefined) {
params.index = self.js(params.index);
let index = Number(self.replaceProperties(params.index, args));
return calendarArr[index];
} else {
return calendarArr[todayIndex];
}
} else {
self.log('"calendar" function can\'t recognize "unit" or "format" parameters');
}
} else {
self.log('"calendar" function requires "unit" parameter');
}
};
this.month = function (params, monthFormat = 'long') {
const localeName = (self.json.setup.language !== 'en') ? self.json.setup.language : 'en-GB';
const format = new Intl.DateTimeFormat(localeName, { month: monthFormat }).format;
const weekdayArr = [...Array(12).keys()].map((m) => format(new Date(Date.UTC(2021, m))));
if (params !== undefined) {
var index = Number(self.replaceProperties(params));
return weekdayArr[index];
}
else
return weekdayArr;
};
this.weekday = function (params, weekdayFormat) {
//weekdayFormat = weekdayFormat || 'long';
const localeName = (self.json.setup.language !== 'en') ? self.json.setup.language : 'en-GB';
const format = new Intl.DateTimeFormat(localeName, { weekday: weekdayFormat }).format;
const weekdayArr = [...Array(7).keys()].map((day) => format(new Date(Date.UTC(2021, 5, day))));
var result;
if (params !== undefined) {
var index = Number(self.replaceProperties(params));
result = weekdayArr[index];
}
else
result = weekdayArr;
//if (weekdayFormat == 'short') result = result.substring(0,3);
return result;
};
/* this.array = function (params, args) { // TO DO: to be removed
self.log('array');
self.log(params);
if (Array.isArray(params))
return params;
else if (typeof params == 'string')
return self.docElement(params);
else if (typeof params == 'object') {
if (params && Object.keys(params).length > 0) { // actionObj !== {}
var actionKey = Object.keys(params)[0]; // -> for
var actionFunction = self.docElement('Array.prototype.' + actionKey); // method in window
var actionValue = params[actionKey];
//actionValue = self.compile(actionValue, args); // array -> undefined
if (!Array.isArray(actionValue))
actionValue = [actionValue];
if (actionFunction) {
if (typeof actionFunction == 'function')
return actionFunction.call(actionValue);
else
return actionFunction;
} else {
self.log('unknown window function');
return params; // return the same object
}
} else {
self.log('empty function');
//self.log(actionObj);
return undefined
}
}
} */
this.method = function (params, args) {
var value;
if (typeof params == 'string') {
return self.docElement(params);
} else {
if ((params.if == undefined) || self.if(params.if, undefined, args)) {
if (self.notEmptyObject(params)) {
var actionKey = Object.keys(params)[0]; // -> for
var actionFunction = self.docElement(actionKey); // method in window
var actionValue = params[actionKey];
//actionValue = self.compile(actionValue, args);
if (!Array.isArray(actionValue))
actionValue = [actionValue];
if (actionFunction) {
if (typeof actionFunction == 'function')
return actionFunction(...actionValue);
else
return actionFunction;
} else {
self.log('unknown function');
self.log(params);
return params; // return the same object
}
} else {
//self.log('empty function');
//self.log(params);
return undefined;
}
}
}
/*
var methodArgs = self.compile(actionValue, args);
if (value !== undefined) {
if (!Array.isArray(methodArgs))
methodArgs = [methodArgs];
self.log('params');
self.log(params);
for (let method of methodArgs) {
for (let key in method) {
if (key !== 'args') {
self.log('key');
self.log(key);
if (value[key])
if (method[key] && method[key] !== '') { // va aggiunto? -> && value[key](method[key]) method[key] !== undefined &&
methodArgs = method[key];
self.log('methodArgs');
self.log(methodArgs);
if (!Array.isArray(methodArgs))
methodArgs = [methodArgs];
for (let index in methodArgs) {
let methodArg = self.compile(methodArgs[index], args);
//if (typeof methodArg == 'string' && methodArg !== '' && methodArg == Number(methodArg)) // can be in compile
methodArgs[index] = methodArg; // Number(methodArg)
}
//try {
//} catch (error) {
// self.log('Dayjs function error');
if (typeof value[key] == 'function')
value = value[key](...methodArgs); // ES6 way
} else
if (typeof value[key] == 'function')
value = value[key]();
else
value = value[key];
} else {
self.log('Method ' + key + ' in ' + methodName + ' not exist');
}
}
}
} else {
self.log('method '+ methodName +' undefined');
}
*/
};
this.Number = function (params, args) {
self.log('Number');
return self.method({ "Number": params }, args);
};
this.String = function (params, args) {
self.log('String');
return self.method({ "String": params }, args);
// jsonic.compile({String:{args:'1',padStart:[2, '0']}})
/*
"text": {
"String": {
"args": "{hour}",
"padStart": [
"0",
2
]
}
}
*/
};
this.Math = function (params, args) {
return self.method(params, args, 'Math');
/* if (!Array.isArray(params))
params = [params];
for (let method of params) {
for (let key in method) {
self.log(key);
if (method[key] && method[key] !== '' && value[key](method[key])) {
//methodArgs = self.compile(method[key]);
methodArgs = method[key];
if (!Array.isArray(methodArgs))
methodArgs = [methodArgs];
for (let index in methodArgs) {
let methodArg = self.compile(methodArgs[index]);
if (typeof methodArg == 'string' && methodArg !== '' && methodArg == Number(methodArg)) // can be in compile
methodArgs[index] = Number(methodArg);
}
value = value[key](...methodArgs); // ES6 way
} else
value = value[key]();
}
}
return value; */
};
this.dayjs = function (params, args) {
return self.method(params, args, 'dayjs');
/* self.log('dayjs');
var value = dayjs();
if (params.time)
value = dayjs(params.time);
//value = self.compile(value);
if (!Array.isArray(params))
params = [params];
for (let method of params) {
for (let key in method) {
if (key == 'time') {
} else if (value[key]) {
if (method[key] && method[key] !== '' && value[key](method[key])) {
//methodArgs = self.compile(method[key]);
methodArgs = method[key];
if (!Array.isArray(methodArgs))
methodArgs = [methodArgs];
for (let index in methodArgs) {
let methodArg = self.compile(methodArgs[index]);
if (typeof methodArg == 'string' && methodArg !== '' && methodArg == Number(methodArg)) // can be in compile
methodArgs[index] = Number(methodArg);
}
value = value[key](...methodArgs); // ES6 way
} else
value = value[key]();
} else {
try {
} catch (error) {
self.log('Dayjs function error');
self.log(error);
self.log('key');
self.log(key);
self.log('method[key]');
self.log(method[key]);
}
}
}
self.log('value');
self.log(value);
}
return value; */
};
this.moment = function (params, args) {
return self.method(params, args, 'moment');
/* self.log('moment');
var value = moment();
if (params.time)
value = moment(params.time);
if (!Array.isArray(params))
params = [params];
for (let method of params) {
for (let key in method) {
if (key !== 'time') {
if (key == 'add') {
value = value.add(Number(method[key].value), method[key].unit);
} else if (key == 'subtract') {
value = value.add(Number(method[key].value), method[key].unit);
} else if (method[key] && method[key] !== '' && value[key](method[key])) {
value = value[key](method[key]);
} else {
self.log('Moment function error: ');
self.log('key');
self.log(key);
self.log('method[key]');
self.log(method[key]);
}
}
}
self.log('value');
self.log(value);
}
return value;
*/
};
/* const methodsList = ['day, format', 'year', 'years', 'quarter', 'dayOfYear', 'month', 'months', 'date', 'minute', 'minutes', 'hour', 'hours', 'second', 'seconds', 'millisecond', 'milliseconds', 'weekday', 'weekdays', 'isoWeekday', 'weekYear', 'isoWeekYear', 'weeksInYear', 'week', 'isoWeek', 'set', 'max', 'min', 'local', 'parseZone', 'unix', 'utc', 'utcOffset', 'zone', 'isValid', 'invalid', 'valueOf', 'startOf', 'endOf', 'fromNow', 'toNow', 'from', 'to', 'calendar', 'diff', 'daysInMonth', 'toDate', 'toArray', 'toJSON', 'toString', 'toISOString', 'toObject', 'inspect', 'isBefore', 'isSame', 'isAfter', 'isSameOrBefore', 'isSameOrAfter', 'isBetween', 'isDST', 'isLeapYear', 'isDate', 'locale', 'localeData', 'lang', 'monthsShort', 'weekdaysShort', 'weekdaysMin', 'defineLocale', 'updateLocale', 'monthsParse', 'weekdaysParse', 'longDateFormat', 'isPM', 'meridiem', 'relativeTime', 'pastFuture', 'ordinal', 'preparse', 'postformat', 'invalidDate', 'firstDayOfWeek', 'firstDayOfYear', 'duration', 'clone', 'humanize', 'asMilliseconds'];
for (var method in methodsList) {
if (params[method]) value = value[method](params[method]);
} */
/* for (let param in params) {
if (param !== 'time') {
if (typeof value == 'object') {
//if (param == 'day') value = value.day(Number(params[param]));
if (param == 'add') {
self.log('params.add.value');
self.log(params.add.value);
self.log('params.add.unit');
self.log(params.add.unit);
self.log('value');
self.log(value);
value.add(Number(5), params.add.unit);
self.log('value.format(H)');
self.log(value.format('H'));
}
else if (param == 'subtract') value.add(Number(params.subtract.value), params.subtract.unit);
else if (value[param] && value[param](params[param]))
value = value[param](params[param]);
else
self.log('Moment function error: '+ params[param]);
}
self.log('value');
self.log(value);
}
}
*/
/* this.addNestedTag = function (params, selectorParams) {
var selector = self.selector(self.extend({}, params, selectorParams));
// remove tag params
var nestedParams = self.cloneObject(params);
var tagParams = ['tag', 'container', 'id', 'class', 'value', 'data-value', 'style', 'attr', 'title', 'text', 'animation', 'action', 'on', 'src', 'media', 'color', 'background', 'width', 'height', 'margin', 'padding', 'firebase'];
for (var par in nestedParams) {
if (tagParams.indexOf(par) >= 0)
delete nestedParams[par]
}
// serach for nested params
var mainTags = ['div', 'ul', 'p', 'span', 'a', 'button', 'input', 'textarea', 'iframe', 'table', 'thead', 'tbody', 'tfoot', 'tr', 'th', 'td', 'figure', 'figcaption', 'svg', 'small', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'icons'];
for (var par in nestedParams) {
self.log(par + ' NESTED IN ' + selector);
if (mainTags.indexOf(par) >= 0) {
self.htmlTag(nestedParams[par], {container: selector}, mainTags[mainTags.indexOf(par)]);
}
}
} */
this.dynamicCss = function (selector, property, value) {
if (value.indexOf('{') >= 0) {
var resizeData = self.dataStorage.get(element, "resize");
//var resizeData = $(selector).data('resize');
if (!resizeData) resizeData = {};
resizeData[property] = value;
var resizeData = self.dataStorage.set(element, "resize", resizeData);
//$(selector).data('resize', resizeData);
if (!self.resizeActions[selector]) self.resizeActions[selector] = {};
self.resizeActions[selector][property] = value;
var result = self.replaceProperties(value) || '';
//$(selector).css(property, result); // al cambio di pagina su this.page applichiamo self.resizeEvent()
/* self.log('----------------------');
self.log('dynamicCss');
self.log('selector');
self.log(selector);
self.log('property');
self.log(property);
self.log('value');
self.log(value);
self.log('result');
self.log(result);
self.log('----------------------');
*/
} else {
var style = {};
style[property] = value;
self.css({
style: style
});
//$(selector).css(property, value);
}
};
/* this.calc = function (selector, property, value) {
if (value.indexOf('{')>= 0) {
//var calcFunction = String(element.match(/calc\(([^\)]*)\)/)[0]);
var result = self.replaceProperties(value) || '';
return result;
} else {
return value;
}
} */
/* this.hTag = function (params, selectorParams, index) { // this.img already exist
if (Array.isArray(params)) {
for (var index in params)
self.hTag(params[index], selectorParams);
} else {
if (params.items) {
var itemsArray = params.items;
delete params.items;
for (var index in itemsArray) {
self.hTag(self.replaceItems(params, itemsArray[index]), selectorParams);
}
} else {
if (typeof params == 'string') {params = {text: params}};
params.tag = 'h'+index;
var paramsReplaced = self.replaceProperties(params);
self.addTag(paramsReplaced, selectorParams);
}
}
} */
/* this.img = function (params, selectorParams, args) {
//self.log('img');
var tagParam = 'img';
var mainParam = 'src';
if (Array.isArray(params)) {
for (var index in params)
self.img(params[index], selectorParams);
} else {
if (params.items) {
var itemsArray = params.items;
delete params.items;
for (var index in itemsArray) {
self.img(self.replaceItems(params, itemsArray[index]), selectorParams);
}
} else {
if (typeof params == 'string') {params = {src: params}};
params.tag = 'img';
//if (params.media) params.src = '{media:' + params.media + '}'; // can go under replaceProperties
var paramsReplaced = self.replaceProperties(params, args);
//var container = params.container || self.selector(selectorParams);
self.addTag(paramsReplaced, selectorParams);
}
}
} */
/* this.small = function (params, selectorParams) { // bootstrap
var mainParam = 'text';
if (Array.isArray(params)) {
for (var index in params)
self.small(params[index], selectorParams);
} else {
if (params.items) {
var itemsArray = params.items;
delete params.items;
for (var index in itemsArray) {
self.small(self.replaceItems(params, itemsArray[index]), selectorParams);
}
} else {
if (typeof params == 'string') {params = {text: params}};
params.tag = 'small';
self.addTag(params, selectorParams);
if (params.firebase) self.addFirebaseTag(self.extend({}, params, selectorParams));
}
}
} */
/* this.button = function (params, selectorParams) { // bootstrap
var mainParam = 'text';
if (Array.isArray(params)) {
for (var index in params)
self.button(params[index], selectorParams);
} else {
if (params.items) {
var itemsArray = params.items;
delete params.items;
for (var index in itemsArray) {
self.button(self.replaceItems(params, itemsArray[index]), selectorParams);
}
} else {
if (typeof params == 'string') {params = {text: params}};
params.tag = 'button';
self.addTag(params, selectorParams);
if (params.firebase) self.addFirebaseTag(self.extend({}, params, selectorParams));
}
}
} */
/*
this.input = function (params, selectorParams) {
var tagParam = 'input';
var mainParam = 'text';
if (Array.isArray(params)) {
for (var index in params)
self.input(params[index], selectorParams);
} else {
if (params.items) {
var itemsArray = params.items;
delete params.items;
for (var index in itemsArray) {
self.input(self.replaceItems(params, itemsArray[index]), selectorParams);
}
} else {
self.addTag(self.createTagParams(params, tagParam, mainParam), selectorParams);
if (params.firebase) self.addFirebaseTag(self.extend({}, params, selectorParams));
}
}
}
this.span = function (params, selectorParams) {
var mainParam = 'text';
if (Array.isArray(params)) {
for (var index in params)
self.span(params[index], selectorParams);
} else {
if (params.items) {
var itemsArray = params.items;
delete params.items;
for (var index in itemsArray) {
self.span(self.replaceItems(params, itemsArray[index]), selectorParams);
}
} else {
params.tag = 'span';
// qui ci andrebbe replaceProperties
if (typeof params == 'string') {params = {text: params}};
self.addTag(params, selectorParams);
if (params.firebase) self.addFirebaseTag(self.extend({}, params, selectorParams));
}
}
}
*/
/* this.a = function (params, selectorParams) {
var mainParam = 'text';
var tagParam = 'a';
if (Array.isArray(params)) {
for (var index in params)
self.a(params[index], selectorParams);
} else {
if (params.items) {
var itemsArray = params.items;
delete params.items;
for (var index in itemsArray) {
self.a(self.replaceItems(params, itemsArray[index]), selectorParams);
}
} else {
if (typeof params == 'string') {params = {text: params}};
params.tag = 'a';
self.addTag(params, selectorParams);
if (params.firebase) self.addFirebaseTag(self.extend({}, params, selectorParams));
}
}
} */
/* this.p = function (params, selectorParams) {
var mainParam = 'html';
if (Array.isArray(params)) {
for (var index in params)
self.p(params[index], selectorParams);
} else {
if (params.items) {
var itemsArray = params.items;
delete params.items;
for (var index in itemsArray) {
self.p(self.replaceItems(params, itemsArray[index]), selectorParams);
}
} else {
if (typeof params == 'string') {params = {html: params}};
params.tag = 'p';
self.addTag(params, selectorParams);
if (params.firebase) self.addFirebaseTag(self.extend({}, params, selectorParams));
}
}
} */
/* this.lottie = function (params, selectorParams, args) {
self.htmlTag(params, selectorParams, 'lottie-player', 'src');
} */
//this.lottie = function (params, selectorParams, args) {
// self.htmlTag(params, selectorParams, 'lottie-player', 'src');
/* self.log('lottie');
var mainParam = 'src';
var tagParam = 'lottie-player';
if (Array.isArray(params)) {
for (var index in params)
self.lottie(params[index], selectorParams);
} else {
if (params.items) {
var itemsArray = params.items;
delete params.items;
for (var index in itemsArray) {
self.lottie(self.replaceItems(params, itemsArray[index]), selectorParams);
}
} else {
var container = params.container || self.selector(selectorParams);
// qui ci andrebbe replaceProperties
//this.alert(self.selector(self.extend({}, params, selectorParams)));
self.addTag(self.createTagParams(params, tagParam, mainParam), {container: container});
//if (params.firebase) self.addFirebaseTag(self.extend({}, params, selectorParams));
}
} */
//}
/* this.iframe = function (params, selectorParams) {
var mainParam = 'src';
if (Array.isArray(params)) {
for (var index in params)
self.iframe(params[index], selectorParams);
} else {
if (params.items) {
var itemsArray = params.items;
delete params.items;
for (var index in itemsArray) {
self.iframe(self.replaceItems(params, itemsArray[index]), selectorParams);
}
} else {
if (typeof params == 'string') {params = {src: params}};
params.tag = 'iframe';
var paramsReplaced = self.replaceProperties(params);
self.addTag(paramsReplaced, selectorParams);
}
}
} */
/* this.textarea = function (params, selectorParams) {
if (Array.isArray(params)) {
for (var index in params)
self.textarea(params[index], selectorParams);
} else {
if (params.items) {
var itemsArray = params.items;
delete params.items;
for (var index in itemsArray) {
self.textarea(self.replaceItems(params, itemsArray[index]), selectorParams);
}
} else {
if (!params.tag) params.tag = 'textarea';
//params.container = params.container || self.selector(selectorParams);
self.addTag(params, selectorParams);
}
}
} */
/*
this.div = function (params, selectorParams) {
if (params.firebase) {
self.log('==========');
self.log('div');
self.log(params);
self.log('==========');
}
var tagParam = 'div';
var mainParam = 'text';
if (Array.isArray(params)) {
for (var index in params)
self.div(params[index], selectorParams);
} else {
if (params.items) {
var itemsArray = params.items;
delete params.items;
for (var index in itemsArray) {
self.div(self.replaceItems(params, itemsArray[index]), selectorParams);
}
} else {
self.addTag(self.createTagParams(params, tagParam, mainParam), selectorParams);
if (params.firebase) self.addFirebaseTag(self.extend({}, params, selectorParams));
}
}
}
this.ul = function (params, selectorParams) {
if (Array.isArray(params)) {
for (var index in params)
self.ul(params[index], selectorParams);
} else {
if (params.items) {
var itemsArray = params.items;
delete params.items;
for (var index in itemsArray) {
self.ul(self.replaceItems(params, itemsArray[index]), selectorParams);
}
} else {
params.tag = 'ul';
var paramsReplaced = self.replaceProperties(params);
self.addTag(paramsReplaced, selectorParams);
if (params.firebase) self.addFirebaseTag(params);
}
}
}
*/
this.li = function (params, selectorParams) {
if (Array.isArray(params)) {
for (var index in params)
self.li(params[index], selectorParams);
} else {
if (params.items) {
var itemsArray = (typeof params.items == 'string') ? self.json.items[params.items] : params.items;
//var itemsArray = params.items;
delete params.items;
for (var index in itemsArray) {
if (self.only(itemsArray[index].roles))
self.li(self.replaceItems(params, itemsArray[index]), selectorParams);
}
} else {
if (typeof params == 'string') { params = { html: params }; };
params.tag = 'li';
//params.container = params.container || self.selector(selectorParams);
self.do(params, selectorParams);
}
}
};
this.remove = function (params, selectorParams, args) {
var selector = self.selector(params.selector || self.selector(selectorParams));
if (selector) {
var elements = self.queryAll(selector);
if (elements) {
elements.forEach(function (element, index) {
element.remove();
});
}
}
};
this.dispatchEvent = function (params, selectorParams, args) {
var selector = self.selector(params.selector || self.selector(selectorParams));
if (selector) {
var elements = self.queryAll(selector);
if (elements) {
elements.forEach(function (element, index) {
element.dispatchEvent(new Event(params.name));
});
}
}
};
/* this.element with "selector" and "method": (remove/dispatchEvent) */
this.html = function (params, selectorParams, args) {
/* self.log('html');
self.log('params');
self.log(params);
self.log('selectorParams');
self.log(selectorParams); */
// TO DO: update
// html properties can be only:
// selector, attr, html, on, for, if
// can't be:
// animate (should go inside on: init?)
// tags (div etc) because it should go inside html
// do
// functions, window functions...
// text should be alternative to html tag. if inside html, it should give an error
// TO DO: verificare se args viene portato agli elementi annidati (non andava con svg)
if (params) {
if (Array.isArray(params)) {
// TO DO: shoud check if params require plugins
for (var obj of params)
self.html(obj, selectorParams, args);
} else {
//if (params.container == '#weatherReport') alert()
//var container = (selectorParams) ? self.selector(selectorParams) : params.container; // unused
//var selector = self.selector(self.extend({}, params, selectorParams), undefined, true); //), undefined, true);
/*
self.log('selector');
self.log(selector); */
var container = self.selector(params.selector || params.container) || self.selector(selectorParams);
//var container = self.selector(selectorParams, undefined, true) || self.selector(params, selectorParams, true);
/* self.log('container');
self.log(container); */
/* var element = self.query(container);
self.log('element');
self.log(element);
*/
if (container) {
var element = self.query(container);
// empty or not? probably yes (like jquery) but we need append/prepend method
// append only all the items in the array
// TO DO: queryAll -> elements
if (element) {
if (typeof params == 'string') {
//var paramsCompiled = self.compile(params, args);
var paramsCompiled = self.replaceProperties(params, args);
//$(container).append(paramsCompiled); // should be .html not append
//element.appendChild(paramsCompiled);
if (paramsCompiled) {
if (typeof paramsCompiled == 'object') {
// should be a nested tag or actions on,for,if,empty
self.do(paramsCompiled, { selector: container }, args);
} else if (typeof paramsCompiled == 'string') {
element.innerHTML += paramsCompiled; // TO DO: now is like append. Is it correct?
}
}
} else {
if (params.empty || params.do == 'empty') {
element.innerHTML = '';
delete params.empty;
}
if (params.tag) {
self.do(params, container, args);
//self.nested({key: params.tag, obj: params[par], selector: {selector: container}, args: args});
}
else if (params.html) {
// replace \" to "
//var htmlCompiled = self.compile(params.html, args); // is undefined
// TO DO: replace all the following "compile" with replaceProperties?
/* self.log('params.html');
self.log(params.html); */
var htmlCompiled = self.replaceProperties(params.html, args);
/* self.log('htmlCompiled');
self.log(htmlCompiled); */
self.html(htmlCompiled, { selector: container });
} else if (params.lang) {
//alert(self.json.setup.language);
var textLang = params.lang[self.json.setup.language] || params.lang['en'] || params.lang[Object.keys[0]];
if (Array.isArray(textLang)) {
var paragraphs = [];
for (var paragraph of textLang)
paragraphs.push({ p: paragraph });
self.html(paragraphs, selectorParams, args);
}
else
element.innerHTML = self.replaceProperties(textLang, args);
if (element) {
self.attribute(element, 'data-text', true); // textKey instead of lang?
self.dataStorage.set(element, 'params', params);
}
} else if (params.text) { // string
//params.text = self.replaceTags({text:params.text});
//params.text = self.text(params.text); // verifica presenza di tags e traduzioni
//$(selector).text(self.compile(params.text, args));
element.textContent = self.replaceProperties(params.text, args);
//} else if (params.empty || params.do == 'empty') {
// element.innerHTML = '';
} else if (params.append) { // string
//params.append = self.replaceTags({text:params.append});
//$(selector).append(self.compile(params.append, args));
//element.appendChild(self.compile(params.append, args));
element.innerHTML += self.replaceProperties(params.append, args);
} else if (params.prepend) { // string
//params.prepend = self.replaceTags({text:params.prepend});
//$(selector).prepend(self.compile(params.prepend, args));
//element.insertBefore(self.compile(params.prepend, args));
element.innerHTML = self.replaceProperties(params.prepend, args) + element.innerHTML;
} else if (params.blocks) { // obsolete
self.blocks(params.blocks, { selector: container }, args);
} else {
let nestedParams = self.cloneObject(params);
if (nestedParams.style) delete nestedParams.style;
if (nestedParams.attr) delete nestedParams.attr;
console.warn('UNKNOWN TAG');
console.warn(params);
// on, for, if... (can be changed to include also html)
self.do(nestedParams, { selector: container }, args);
if (element.isConnected) {
// case "html":{selector:... attr: }
// the wrong use "html":{selector, attr, html:...}
// now doesn't work (because is inside the last else)
/* if (params.on) {
alert(container);
self.on(params.on, { selector: container }, args);
} */
if (params.attr) self.setAttributes(element, params.attr, args);
if (params.style) self.css(params, selectorParams, args); // to be removed
// TO DO: params.style is deprecated (now in attr or css)
}
//self.blocks(params, selectorParams, args);
}
}
} else { // !element
}
} else {
self.log('"html" object requires selector property', 'red');
self.log(params);
//self.log(selectorParams);
}
//}
//}
}
} else {
self.log('"html" object without params');
}
};
/* this.add = function (params) { // obsoleto, sostituito da html
var selector = self.selector(params);
if (params.inverse)
$(selector).append(params.html);
else
$(selector).prepend(params.html);
} */
/* this.attr = function (params, selectorParams, args) {
var selector = self.selector(params);
var element = self.query(selector);
for (var attribute in params.attr)
elements.forEach(function (element, index) {
element.setAttribute(attrId, attrValue);
});
}
*/
/* this.empty = function (params) {
// { [container, class, value, id] }
var selector = self.selector(params);
$(selector).empty();
} */
/* this.addClass = function (params) {
var selector = self.selector(params);
$(selector).addClass(params);
}
this.removeClass = function (params) {
self.log('removeClass');
var selector = self.selector(params);
$(selector).removeClass(params);
} */
/* this.toggleClass = function (params) {
var selector = self.selector(params);
$(selector).toggleClass(params);
} */
//"#wifi > ul > li > span[data-field=share]:contains('Private')"
this.setAttributes = function (elements, attrs, args) {
for (var attribute in attrs)
if (attrs[attribute])
self.attribute(elements, attribute, self.replaceResult(attrs[attribute], args));
else
self.attribute(elements, attribute, "");
//self.attribute(elements, attribute, attrs[attribute]);
//self.attribute(elements, attribute, self.replaceWithPrefix(attrs[attribute], 'result', args)); // TO DO: check
// before remove and check all the {result} occurrence (result excludes do/then/success etc.)
// replaceResult replace {result} from Alert (should be obsolete)
// check in the actual apps if {result} is used
};
/* this.setAttributes = function (elements, attrs, args) {
if (!Array.isArray(elements)) elements = [elements];
elements.forEach(function (element, index) {
for (var attribute in attrs) {
if (typeof attrs[attribute] == 'boolean' && attrs[attribute]) { // it consider also firebase (empty values are removed)
element.setAttribute(attribute, "");
} else {
//if (attrs[attribute] == undefined) attrs[attribute] = '';
element.setAttribute(attribute, self.replaceProperties(attrs[attribute]));
}
}
});
self.attribute(elements, attribute, self.replaceResult(attrs[attribute], args));
}; */
// TO DO: distinguish setAttribute from getAttribute
// because we need to set attribute empty
this.attribute = function (elements, attrId, attrValue) {
if (typeof attrValue !== undefined) {
if (!Array.isArray(elements)) elements = [elements];
elements.forEach(function (element, index) {
if (typeof attrValue == 'boolean' && attrValue) { // it consider also firebase (empty values are removed)
element.setAttribute(attrId, "");
} else {
element.setAttribute(attrId, self.replaceProperties(attrValue));
}
});
} else {
if (!Array.isArray(elements))
return elements.getAttribute(attrId); // todo: intercept the error "Cannot read properties of undefined (reading 'getAttribute"
else
return elements[0].getAttribute(attrId);
}
};
this.attr = function (params, selectorParams, args) {
// deprecated. to be replaced with "css" {selector, style, addClass, removeClass, toggleClass}
// css is used as an action to apply addClass removeClass toggleClass
// and to apply style: {...}
//params = self.replaceProperties(params);
self.css(self.replaceProperties(params), selectorParams, args);
};
this.styleElement = function (params, element, args) {
for (var styleName in params) {
if (styleName.startsWith('--'))
element.style.setProperty(styleName, self.replaceProperties(params[styleName], args));
else
element.style[styleName] = self.replaceProperties(params[styleName], args);
}
};
this.css = function (params, selectorParams, args) {
// {selector, style, addClass, removeClass, toggleClass}
/* console.log('selectorParams');
console.log(selectorParams);
console.log('css');
console.log(params); */
if (Array.isArray(params)) {
for (var obj of params)
self.css(obj, selectorParams, args);
/* } else if (params.selector && Array.isArray(params.selector)) {
for (let selector of params.selector) {
let obj = self.cloneObject(params);
obj.selector = selector;
self.css(obj, selectorParams, args); */
} else {
var selector = self.selector(params.selector || params.container, undefined, true) || self.selector(selectorParams, undefined, true);
var elements = self.queryAll(selector);
//var selector = params.selector || selectorParams;
//var elements = document.querySelectorAll(selector);
//console.log(elements);
if (elements) {
elements.forEach(function (element, index) {
if (element) {
if (typeof params.style == 'object') {
self.styleElement(params.style, element, args);
}
if (params.addClass)
self.addClass(element, params.addClass);
if (params.removeClass)
self.removeClass(element, params.removeClass);
if (params.toggleClass)
self.toggleClass(element, params.toggleClass);
} else {
self.log('the function "css" can\'t find the selector ' + selector);
self.log(params);
self.log(selectorParams);
}
});
} else {
self.log('"css" function is unable to select: ' + selector);
self.log('params');
self.log(params);
self.log('selectorParams');
self.log(selectorParams);
}
}
};
/* this.class = function (params) { // obsolete -> css
self.log('self.class');
self.log(params);
// { [container, class, value, id]
// [style, addClass, removeClass] }
var selector = self.selector(params);
if (params.style)
$(selector).css(params.style);
if (params.add)
$(selector).addClass(params.add);
if (params.remove)
$(selector).removeClass(params.remove);
if (params.toggle)
$(selector).toggleClass(params.toggle);
} */
/* this.createPage = function (data) {
// SPOSTATA SOTTO fixo.pages.js
//self.log('createPage');
//self.log(data);
if (!$('#'+data.id).length) {
$(data.container).append('');
if (data.background) {
$('#'+data.id).css({
'background-color': data.background
});
}
}
} */
/* this.iconPng = function(icon) {
return 'https://'+self.domain+'/app/files/icons/100white/'+icon+'.png';
} */
/* this.imgTag = function (data) {
// DIPENDENZA CON iconPng
var imgId = data.id || '';
var imgClass = data.class || '';
var imgValue = data.value || '';
var imgStyle = data.style || ''; // || 'width: 84px; margin:6px 10px;'; // ATTENZIONE: stile predefinito da rimuovere
var onClick = (data.action) ? 'onclick="javascript:self.do(\''+data.action+'\',\''+imgValue+'\')" ' : '';
return '';
} */
/* this.setImg = function (data) {
// Sembra inutilizzata
// DIPENDENZA CON iconPng
// data = {icon, style}
var selector = self.selector(data);
var imgValue = data.value || '';
$(selector).attr('src', self.iconPng(data.icon));
if (data.style) $(selector).css(style);
if (data.action) {
$(selector).attr('onclick', 'javascript:self.do(\''+data.action+'\',\''+imgValue+'\')');
}
} */
// --------------
// SVG
// --------------
/* this.svgSet = function (params) {
//self.log('svgSet');
//self.log(params);
if (self.json && self.json.icons) {
//if (self.json.setup && self.json.setup.icons) {
if (params.icon) {
var iconObj = {};
iconObj.icon = (params.icon.indexOf(':')) ? params.icon.split(/:/)[1] : string;
iconObj.set = (params.icon.indexOf(':')) ? params.icon.split(/:/)[0] : undefined;
var svgIcons = self.json.icons || {}; // {src, prefix, suffix}
//var svgIcons = self.json.setup.icons || {}; // {src, prefix, suffix}
if (iconObj.set)
if (svgIcons[iconObj.set])
svgIcons = svgIcons[iconObj.set];
else
self.log('Can\'t find the icons set "'+iconObj.set+'" in "icons"');
iconObj.src = svgIcons.src || ''; // serve?
var svgPrefix = svgIcons.prefix || '';
var svgSuffix = svgIcons.suffix || '';
//if (iconObj.src !== '' && iconObj.icon) iconObj.src = '#' + svgPrefix + iconObj.icon + svgSuffix;
if (iconObj.icon) {
if (!svgIcons.preload)
// siamo vicini
iconObj.src = svgIcons.src + '#' + svgPrefix + iconObj.icon + svgSuffix;
else
iconObj.src = '#' + iconObj.set + '_' + svgPrefix + iconObj.icon + svgSuffix;
}
iconObj.viewbox = svgIcons.viewbox; // || '0 0 25 25';
return iconObj; // {src, set, name, viewbox}
} else {
self.log('icon "name" parameter undefined');
}
} else {
self.log('Can\'t find "icons" in "setup"');
}
}
this.svgChange = function (data) {
self.log('svgChange');
self.log(data);
var selector = self.selector(data); //), undefined, true);
var containerElement = self.query(selector);
var elementSvg = containerElement.querySelectorAll('svg')[0];
var elementSvgUse = elementSvg.querySelectorAll('use')[0];
var elementSvgText = elementSvg.querySelectorAll('text')[0];
var elementSvgCircle = elementSvg.querySelectorAll('circle')[0];
var iconObj = self.svgSet(data); // {src, set, name, viewbox}
if (iconObj.src)
elementSvgUse.setAttribute('xlink:href', iconObj.src);
//$(data.container + ' > svg > use').attr('xlink:href', iconObj.src);
if (data.text !== undefined) {
elementSvgText.textContent = data.text;
// $(data.container + ' > svg > text').text(data.text);
var textY = 6.5; // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor
if (data.textSize !== undefined) {textY = data.textSize/2;}
if (data.textPosition == 'bottom') { // textPosition should be removed
elementSvgUse.setAttribute('transform', 'translate(0, -20) scale(0.80)');
//$(data.container + ' > svg > use').attr("transform", "translate(0, -20) scale(0.80)");
textY += 26;
}
elementSvgText.setAttribute('y', textY);
//$(data.container + ' > svg > text').attr('y',textY);
elementSvgText.style['font-size'] = data.textSize+'px';
//$(data.container + ' > svg > text').css('font-size',data.textSize+'px');
} else {
elementSvgText.textContent = '';
//$(data.container + ' > svg > text').text('');
}
if (data.background !== undefined){
elementSvgCircle.setAttribute('fill', data.background);
elementSvgCircle.setAttribute('fill-opacity', 1);
elementSvgCircle.style['stroke'] = data.background;
}
if (data.border !== undefined) {
elementSvgCircle.setAttribute('stroke-opacity', 1);
elementSvgCircle.style['stroke'] = data.border;
}
if (data.color !== undefined && data.color !== 'colored') {
elementSvgUse.style['fill'] = data.color;
}
if (data.textColor !== undefined){
elementSvgText.style['fill'] = data.textColor;
} else if (data.color) {
elementSvgText.style['fill'] = data.color;
}
}
this.svgImage = function (data) {
//$(data.container).hide();
//$(data.container).css({opacity:0});
var selector = self.selector(data); //), undefined, true);
var containerElement = self.query(selector);
//var containerElement = self.query(data.container);
//if (data.value !== undefined) $(data.container).data('value', data.value);
var iconObj = self.svgSet(data); // {src, set, name, viewbox}
var viewBox = iconObj.viewbox || '-50 -50 100 100';
var htmlString = '';
if (containerElement) {
containerElement.innerHTML = htmlString;
//$(data.container).append('');
var elementSvg = containerElement.querySelectorAll('svg')[0];
var elementSvgUse = elementSvg.querySelectorAll('use')[0];
var elementSvgText = elementSvg.querySelectorAll('text')[0];
var elementSvgCircle = elementSvg.querySelectorAll('circle')[0];
elementSvgUse.setAttribute('xlink:href', iconObj.src);
//$(data.container + ' > svg > use').attr('xlink:href', iconObj.src);
if (data.text !== undefined) {
elementSvgText.textContent = data.text;
// $(data.container + ' > svg > text').text(data.text);
var textY = 6.5; // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor
if (data.textSize !== undefined) {textY = data.textSize/2;}
if (data.textPosition == 'bottom') { // textPosition should be removed
elementSvgUse.setAttribute('transform', 'translate(0, -20) scale(0.80)');
//$(data.container + ' > svg > use').attr("transform", "translate(0, -20) scale(0.80)");
textY += 26;
}
elementSvgText.setAttribute('y', textY);
//$(data.container + ' > svg > text').attr('y',textY);
elementSvgText.style['font-size'] = data.textSize+'px';
//$(data.container + ' > svg > text').css('font-size',data.textSize+'px');
}
if (data.background !== undefined) {
elementSvgCircle.setAttribute('fill', data.background);
elementSvgCircle.setAttribute('fill-opacity', 1);
elementSvgCircle.style['stroke'] = data.background;
}
if (data.border !== undefined){
elementSvgCircle.setAttribute('stroke-opacity', 1);
elementSvgCircle.style['stroke'] = data.border;
//$(data.container + ' > svg > circle').attr('stroke-opacity', 1);
// FORSE DEVE DIVENTARE attr ANZICHE' css
//$(data.container + ' > svg > circle').css({'stroke': data.border});
}
//if ((data.color === undefined) && (data.color !== 'colored')) {data.color = '#fff';}
if (data.color !== undefined && data.color !== 'colored') {
elementSvgUse.style['fill'] = data.color;
//$(data.container + ' > svg > use').css({'fill': data.color});
//$(data.container + ' > svg > text').css({'fill': data.color});
}
if (data.textColor !== undefined){
elementSvgText.style['fill'] = data.textColor;
//$(data.container + ' > svg > text').css({'fill': data.textColor});
} else {
elementSvgText.style['fill'] = data.color;
//$(data.container + ' > svg > text').css({'fill': data.color});
}
self.css({style: data.style}, {container: data.container + ' > svg'});
}
}
this.svg = function (params, selectorParams, args) {
var paramsReplaced = self.replaceProperties(params, args);
//var container = self.selector(self.extend({}, params, selectorParams));
var container = self.selector(paramsReplaced, undefined, true) || self.selector(selectorParams, undefined, true);
var element = self.query(container);
var color = paramsReplaced.color || getComputedStyle(element).color;
//if (element.getElementsByTagName('SVG').length == 0) {
//if (element.querySelectorAll('svg').length == 0) {
self.svgImage({
container: container,
// special param
icon: paramsReplaced.icon,
text: paramsReplaced.text,
textSize: paramsReplaced.textSize, // verify (obsolete when span will be nested)
textPosition: paramsReplaced.textPosition, // verify (obsolete when span will be nested)
textColor: paramsReplaced.textColor, // verify (obsolete when span will be nested)
background: paramsReplaced.background,
border: paramsReplaced.border,
color: paramsReplaced.color || color, // $(container).css("color"),
style: paramsReplaced.style, // da fare css in svgImage
class: paramsReplaced.class
//hoverBackground: data.hoverBackground, // verify
//hoverBorder: data.hoverBorder, // verify
//hoverColor: data.hoverColor, // verify
});
} */
// --------------
// ITEM
// --------------
/*
this.checkItem = function (data) {
var selectedIconClass = data.selection || 'selectedIcon'; // self.json.setup.classes.selectedIcon;
//self.log('checkItem');
//self.log(data);
var checked = 0;
// var selector = '';
var selector = self.selector(data);
if (data.style === undefined) {data.style = selectedIconClass;}
if (data.checked !== undefined) {
checked = self.replaceProperties(data.checked);
//checked = self.replaceTags({text:data.checked});
checked = data.checked;
if (data.checked) {
$(selector).addClass(data.style);
} else {
$(selector).removeClass(data.style);
}
} else {
checked = $(selector).hasClass( data.style );
}
return checked;
} */
/*
this.toggleItem = function (data) { // modificato 20180709 da changeCheckItem in toggleItem
self.log('toggleItem');
//self.log(data);
var checked;
checked = self.checkItem({
id: data.id,
class: data.class,
value: data.value
//style: data.style
});
checked = !checked; // inverte il valore
self.checkItem({
id: data.id,
class: data.class,
value: data.value,
checked: checked
//style: data.style,
});
return checked;
}
*/
/* this.selectItem = function (data) {
var selectedIconClass = self.json.setup.classes.selectedIcon;
var selector = self.selector({container: data.container, class: data.class});
if (data.style === undefined) {data.style = selectedIconClass;}
$(selector).removeClass(data.style);
self.log('selector');
self.log(selector);
if (data.value || data.id) {
selector = self.selector(data);
$(selector).addClass(data.style);
}
}
this.unselectItems = function (data) {
var selectedIconClass = self.json.setup.classes.selectedIcon;
//if (data.style)
if (data.style === undefined) {data.style = selectedIconClass;}
if (data.class.indexOf('.') < 0) {data.class = '.' + data.class}
$(data.class).removeClass(data.style);
}
*/
/* this.removeImage = function (data) {
var selector = self.selector(data);
$(selector).css({'background-image':'url()'});
}
this.loadImage = function (data) {
var selector = self.selector(data);
//if (!data.style) data.style = {};
//if (data.background) data.style['background-color'] = data.background;
if (data.image || data.image === '') {
self.getImage({ // ex fixo.loadImage
object: selector,
url: data.image
//style: data.style,
//animation: data.animation,
});
} else {
self.removeImage(data);
}
} */
/* this.changeItem = function (data, selectorParams, args) {
self.log('changeItem');
self.log(data);
var container = (selectorParams) ? self.selector(selectorParams) : data.container;
var selector = self.selector(self.extend({}, data, selectorParams));
var iconClass = ''; //self.json.setup.classes.icon || '';
var badgeClass = 'iconBadge'; //self.json.setup.classes.badge || '';
if (data.svg || data.text || data.background || data.border || data.color) {
$(selector + ' > svg').css({opacity:1});
self.svgChange({
container: selector,
name: data.svg,
text: data.text,
background: data.background,
border: data.border,
color: data.color,
});
} else {
$(selector + ' > svg').css({opacity:0});
}
// IMMAGINE
if (data.image && data.image !== '') {
var imgData = data;
imgData.style = {
width: '82px',
height: '82px',
'margin-bottom': '27px'
};
if (data.background) imgData.style['background-color'] = data.background;
self.loadImage(imgData);
$(selector + ' > svg').css({opacity:0});
} else {
self.removeImage(data);
$(selector + ' > svg').css({opacity:1});
}
if (data.badgeIcon || data.badgeText) {
if (!$('.'+badgeClass).length)
$(selector).append('');
self.svgImage({
container: selector + ' > .'+badgeClass,
icon: data.badgeIcon,
text: data.badgeText,
background: data.badgeBackground,
border: data.badgeBorder,
color: data.badgeColor,
});
} else {
$(selector + ' > .'+badgeClass).remove();
}
if (data.titleColor)
$(selector + ' > span').css({'color':data.titleColor});
else if (data.color)
$(selector + ' > span').css({'color':data.color});
if (data.titleSize) $(selector + ' > span').css({'font-size':data.titleSize});
if (data.title) {
$(selector+' > span').text(data.title);
if ($(selector+' > span').hasClass('textFitted')) {
self.textFit($(selector+' > span'), {
alignHoriz: false,
multiLine: false,
alignVert: false,
minFontSize: 10,
maxFontSize: data.titleSize || 12,
});
}
}
if (data.checked !== undefined) {
self.checkItem({
container: data.container,
class: data.class,
value: data.value,
id: data.id,
checked: data.checked
//style: data.style,
});
}
// action (obsolete)
if (data.action) {
var onData = $(selector).data('onData');
onData.action = data.action;
$(selector).data('onData', onData); // nuova versione
}
// events
if (data.on) self.on(data.on, {container: selector});
} */
/* this.enableIcon = function (params, selectorParams) {
var container = (selectorParams) ? self.selector(selectorParams) : params.container;
var selector = self.selector(self.extend({}, params, selectorParams));
$(selector).css({'opacity':'1'});
$(selector).off().on(self.touch, function(event){
event.stopPropagation();
self.onEvent(this, event);
});
}
this.disableIcon = function (params, selectorParams) {
var badgeClass = self.json.setup.classes.badge || '';
var container = (selectorParams) ? self.selector(selectorParams) : params.container;
var selector = self.selector(self.extend({}, params, selectorParams));
$(selector + ' > .'+badgeClass).remove();
$(selector).css({'opacity':'0.5'});
$(selector).off();
}
*/
/* this.getFileExtension = function (path) {
var dotPosition=path.lastIndexOf(".");
var stringLength=path.length;
var extensionFile=path.substring(dotPosition+1,stringLength);
return extensionFile;
} */
// --------------------
// SLIDER
// --------------------
/* var slides = {};
var sliderLib = 'fixoSlider';
var sliderWrapperClass = 'fixoSlider';
//var sliderSlideClass = 'fixoSlidez';
var sliderSelectedClass = 'slideSelected'; */
/*
var sliderLib = 'flickity';
var sliderWrapperClass = 'fixoSlider';
var sliderSlideClass = 'fixoSlide';
var sliderSelectedClass = 'is-selected';
*/
/*
var sliderLib = 'sliderpro';
var sliderWrapperClass = 'sp-slides';
var sliderSlideClass = 'sp-slide';
var sliderSelectedClass = 'sp-selected';
*/
/*
var sliderLib = 'swiper';
var sliderWrapperClass = 'swiper-wrapper';
var sliderSlideClass = 'swiper-slide';
var sliderSelectedClass = 'swiper-slide-active';
*/
/*
this.sliderResume = function (data) {
var selector = self.selector(data);
if (slides[selector]) slides[selector].object.resume();
}
this.sliderFreeze = function (data) {
var selector = self.selector(data);
if (slides[selector]) slides[selector].object.freeze();
}
this.sliderNext = function(data) {
var selector = self.selector(data);
if (sliderLib == 'fixoSlider') slides[selector].object.next();
//if (sliderLib == 'flickity') slides[selector].object.flickity('next');
}
this.sliderPrev = function(data) {
var selector = self.selector(data);
if (sliderLib == 'fixoSlider') slides[selector].object.prev();
//if (sliderLib == 'flickity') slides[selector].object.flickity('previous');
}
this.autoSliderEvent = function() {
var selector = self.selector(data);
if (self.sliderSelected)
slides[self.sliderSelected].object.autoSliderEvent();
}
this.addSlideIcon = function(data) {
// creata per rendere più leggibile createSlide
var selector = self.selector(data);
var isImage = self.getFileExtension(data.icon);
if (isImage == 'gif' || isImage == 'jpg' || isImage == 'jpeg' || isImage == 'png')
fixo.loadImage({
object: selector + ' > .slideIcon',
url: data.icon,
style: {height: '150px',
width: '150px',
marginTop: '25px',
marginLeft: '-75px',
backgroundSize: 'cover'
}
});
else
//if (data.icon)
self.svgImage({
container: selector + ' > .slideIcon',
icon: data.icon,
color: '#fff',
});
if (data.iconName)
$(selector + ' > .slideIconName').html(data.iconName); // da cancellare?
if (data.iconAction) {
var value = data.iconValue || '';
$(selector + ' > .slideIcon').attr('onclick', 'javascript:self.do(\''+data.iconAction+'\', \''+value+'\')');
}
}
this.changeSlideIcon = function(data) {
var selector = self.selector(data);
// verificare se si può usare changeItem
if (data.icon)
self.svgChange({
container: selector + ' > .slideIcon',
name: data.icon,
color: '#fff',
});
if (data.iconName)
$(selector + ' > .slideIconName').html(data.iconName);
}
this.updateSlide = function(data) {
self.log('updateSlide');
if (!data.class) data.class = 'fixoSlide';
var selector = self.selector(data);
// ICONA
self.changeSlideIcon(data);
// BACKGROUND
if (data.background) $(selector).css({'background-color':data.background});
// TITOLO E TESTO
var alertTitleObj = $(selector).children('.slideTitle');
var alertTextObj = $(selector).children('.slideText');
var titleAndText = (alertTitleObj.text() !== '' && alertTextObj.text() !== '');
if (titleAndText) {
alertTitleObj.css({'margin-top':'-225px'});
} else {
alertTitleObj.css({'margin-top':'-60px'});
}
if (data.title !== undefined) {
alertTitleObj.html(data.title);
self.textFit(titleObj, {alignHoriz: true, multiLine: false, alignVert: true, minFontSize: 40, maxFontSize: 56});
}
if (data.text !== undefined) {
alertTextObj.html(data.text);
self.textFit(textObj, {alignHoriz: true, multiLine: false, alignVert: !titleAndText, minFontSize: 17, maxFontSize: 40});
}
// BOTTONE
if (data.button !== undefined) {
if (data.button) {
if (data.buttonLabel) {
$(selector + ' > .slideButton').html(data.buttonLabel);
}
if (data.buttonAction) {
$(selector + ' > .slideButton').data('action', data.buttonAction);
$(selector + ' > .slideButton').data('value', data.value);
$(selector + ' > .slideButton').attr('onclick', 'javascript:self.do(\'' + data.buttonAction + '\',\''+data.value+'\')');
}
$(selector + ' > .slideButton').show();
} else {
$(selector + ' > .slideButton').hide();
}
// aggiungere changeItem dell'icona
}
}
this.slideTextFit = function() {
//self.log('slideTextFit');
//if (!data.class) data.class = 'fixoSlide';
//var selector = self.selector(data);
var slideSelector = self.sliderSelected + ' > .' + sliderSelectedClass;
titleObj = $(slideSelector).children('.slideTitle');
textObj = $(slideSelector).children('.slideText');
var titleAndText = (titleObj.text() !== '' && textObj.text() !== '');
if (titleAndText) {
titleObj.css({'margin-top':'-225px'});
//textObj.css({'top':(384+125-30)+'px'});
} else {
titleObj.css({'margin-top':'-60px'});
}
self.textFit(titleObj, {alignHoriz: true, multiLine: false, alignVert: true, minFontSize: 40, maxFontSize: 56});
self.textFit(textObj, {alignHoriz: true, multiLine: false, alignVert: !titleAndText, minFontSize: 17, maxFontSize: 40});
}
this.sliderTo = function(data) {
// apre la slide data.index
self.log('sliderTo');
var selector = self.selector(data);
if (data.index !== undefined) // comprende il caso = 0
if (slides[selector] && slides[selector].object)
slides[selector].object.to(data.index);
//if (sliderLib == 'swiper')
// slides[selector].object.slideToLoop(data.index); // slideToLoop
//if (sliderLib == 'flickity')
// slides[selector].object.flickity('select', data.index);
//if (sliderLib == 'extraslider')
// $(selector+' > .extra-slider').trigger('extra:slider:goto', data.index);
if (data.value !== undefined) { // comprende il caso = 0
self.log(self.selector(data));
if (!data.class) data.class = 'fixoSlide';
var slideToSelect = self.selector(data);
var index = $(slideToSelect).index();
if (index > -1) slides[selector].object.to(index);
//var slideToSelect = '.' + sliderSlideClass + '[data-value="' + data.prefix + data.value + '"]';
}
//if (sliderLib == 'flickity')
// slides[selector].object.flickity('selectCell', slideToSelect);
}
this.sliderExist = function(data) { // si può cancellare?
var selector = self.selector(data);
//alert(($(selector + ' > .extra-slider').length > 0));
return ($(selector + ' > .extra-slider').length > 0)
// return (slides[selector])
}
this.createSlide = function(data) {
self.log('createSlide');
//if (!data.prefix) data.prefix = "";
if (!data.class) data.class = "fixoSlide";
//var containerSelector = self.selector(data);
var slideContent = '';
if (data.inverse) {
$(data.container).prepend(slideContent);
} else {
$(data.container).append(slideContent);
}
var selector = self.selector(data);
var infoButtons = data.infoButtons || {};
// STORE DATA
$(selector).data('container', data.container);
if (data.value) $(selector).data('value', data.value);
//if (data.id) $(selector).data('id', data.id);
//if (data.prefix) $(selector).data('prefix', data.prefix);
var textHtml = (data.text) ? data.text.replace(/\r?\n/g, ' ') : '';
// PRICE
//if(data.price && data.price !== '') textHtml += ' € '+data.price;
// BACKGROUND
if (data.background) $(selector).css({'background-color':data.background});
// IMAGE
if (data.image && data.image !== '') {
if (data.title !== '' || textHtml !== '' )
{
//$(selector).css({'background-image':'linear-gradient(to right,rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url('+data.image+')'});
//} else {
//$(selector).css({'background-image':'url('+data.image+')'});
$(selector).append('')
}
if (sliderLib == 'fixoSlider') {
$(selector).css({'background-image':'url('+data.image+')'});
// DA GESTIRE INTERNAMENTE A fixo.slider.js
// DOVRA' CARICARE SOLO SLIDE ATTUALE, PREC. E SUCC
//fixo.loadImage({
// object: selector,
// url: data.image,
// animation: 'fadeIn',
//});
}
//if (sliderLib == 'swiper') {
// $(selector).addClass('swiper-lazy');
// $(selector).attr('data-background', data.image);
//}
//if (sliderLib == 'flickity') {
// $(selector).attr('data-flickity-bg-lazyload', data.image);
//}
} else {
$(selector).css({'background-image':'none'});
// SERVICE ICON
//$(selector).append('');
//self.addSlideIcon(data);
// if (data.icon)
// self.svgImage({
// container: selector + ' > .slideIcon',
// icon: data.icon,
// color: '#fff',
// });
// if (data.iconName)
// $(selector + ' > .slideIconName').html(data.iconName);
// if (data.icon)
// self.svgImage({
// container: selector + ' > .slideIcon',
// icon: data.icon,
// color: '#fff',
// });
// if (data.iconName)
// $(selector + ' > .slideIconName').html(data.iconName);
}
// ICONA
$(selector).append('');
self.addSlideIcon(data);
// TITLE & TEXT
$(selector).append('');
var alertTitleObj = $(selector + ' > .slideTitle');
var alertTextObj = $(selector + ' > .slideText');
var alertInfoObj = $(selector + ' > .slideInfo');
// BOTTONI INFO
var btnInfo = '';
for (var i in infoButtons) {
if (infoButtons[i].icon !== '')
btnInfo += self.imgTag({
icon: infoButtons[i].icon,
action: infoButtons[i].action,
class: infoButtons[i].class,
value: infoButtons[i].value,
//style: 'width: 84px; margin:6px 10px;'
});
//alertInfoObj.html(btnInfo);
}
alertInfoObj.html(btnInfo);
// TESTO
if (data.title && data.title !== '') {
alertTitleObj.html(data.title);
} else {
alertTitleObj.html(data.iconName);
}
alertTextObj.html(textHtml);
//alertInfoObj.html()
// if (data.link && data.link !== '') { // serviva a costruire il div con il qrcode, sostituito dal link per aprire lo swal alert
// var link = data.link;
// self.log('DATALINK: '+link);
// if (link.indexOf('musement.com') || link.indexOf('booking.com')) {
// link = link.replace(/^https?:\/\//,''); //rimuovo https dal link
// self.log('link: '+link);
// link = 'https://c83.travelpayouts.com/click?shmarker=219111&promo_id=2015&source_type=customlink&type=click&custom_url=' + link;
// }
// self.log('DATALINK1: '+link);
// $(selector).append('');
// self.qrCode({
// container: selector,
// class: 'slideQrCode',
// text: link,
// size: 100
// });
// // attributo sul Codice QR per la visualizzazione dell'alert
// $('.slideQrCode > img').attr('onclick','javascript:self.do(\'app.hot.alertQRCode\')');
// } else {
$(selector).append('');
if (data.button) {
if (data.buttonLabel) {
$(selector + ' > .slideButton').html(data.buttonLabel);
}
if (data.buttonAction) {
$(selector + ' > .slideButton').data('action', data.buttonAction);
$(selector + ' > .slideButton').data('value', data.value);
$(selector + ' > .slideButton').attr('onclick', 'javascript:self.do(\'' + data.buttonAction + '\',\''+data.value+'\')');
}
$(selector + ' > .slideButton').show();
// $(selector + ' > .slideButton').off().on(self.touch, function(){
// var action = $(this).data('action');
// var key = $(this).data('value');
// self.do(action, value);
// });
} else {
$(selector + ' > .slideButton').hide();
}
//} chiude l'IF del data.link
var titleAndText = (alertTitleObj.text() !== '' && alertTextObj.text() !== '');
// POSIZIONE TITOLO
var titleTop = -70 -170 * (titleAndText);
alertTitleObj.css({'margin-top': titleTop + 'px'});
self.textFit(alertTitleObj, {alignHoriz: true, multiLine: false, alignVert: true, minFontSize: 30, maxFontSize: 56});
// ALTEZZA TESTO
var textHeight = 340 - 100 * (infoButtons.length > 0);
alertTextObj.css({'height': textHeight + 'px'});
//self.textFit(alertTitleObj, {alignHoriz: true, multiLine: false, alignVert: true, minFontSize: 30, maxFontSize: 56});
//self.textFit(alertTextObj, {alignHoriz: true, multiLine: false, alignVert: !titleAndText, minFontSize: 15, maxFontSize: 45});
//self.log('END createSLIDE');
}
this.createSlider = function (data) {
self.log('createSlider');
//if (!data.prefix) data.prefix = "";
var selector = self.selector(data);
var startIndex = data.index || 0;
//self.log('pre DATAINDEX: '+data.index);
// RIMUOVE ISTANZA PRECEDENTE
if (slides[selector] && slides[selector].object) {
// Memorizza posizione
var slideSelector = selector + ' > .' + sliderSelectedClass;
//self.log('slideSelector di self.createSlider: '+slideSelector);
startIndex = data.index || $(slideSelector).index();
// Rimuove slider precedente
//self.log('startIndex: di '+data.index+' .index() '+$(slideSelector).index());
$(selector).empty();
delete slides[selector].object;
}
slides[selector] = {};
// FRECCE
// if (data.buttons) {
// if (sliderLib == 'swiper') {
// $(selector).append('');
// $(selector).append('');
// }
// }
for (var key in data.slides) {
var slide = data.slides[key];
slide.inverse = data.inverse;
//slide.container = selector; //+' > .' + sliderWrapperClass;
slide = self.extend({
container: selector,
class: 'fixoSlide', //sliderSlideClass,
value: data.value, //data.prefix + data.value
}, slide);
self.createSlide(slide);
}
// CREAZIONE OGGETTO SLIDER
if (sliderLib == 'fixoSlider') {
var params = {
container: selector, //+' > .' + sliderWrapperClass,
play: data.play,
interval: data.interval, // ms
onChange: data.onChange,
onChangeStart: self.slideTextFit,
index: startIndex // prima slide
// direction: 1, // from right to left
// opts.swipeDuration: 0.6, // sec
// opts.swipeTreshold: 0.2, // Swipe from +/-20%
};
slides[selector].object = $.fn.slide(params);
}
//self.log('END createSlider');
}
*/
/*
this.getSelectedSlide = function (data) {
self.log('getSelectedSlide');
//self.log(data);
var selector = self.selector(data);
if (sliderLib == 'fixoSlider') {
var slideSelector = selector + ' > .' + sliderSelectedClass;
self.log($(slideSelector).data('value'));
return $(slideSelector).data('value');
}
}
var sliderSelect = function (currentItem, currentIndex) { //si può cancellare?
var id = $(currentItem).parent().parent().parent().attr('id');
self.log('slideId:'+id);
self.log('currentItem:'+currentItem);
self.log('currentIndex:'+currentIndex);
slides[id].currentItem = currentItem;
slides[id].currentIndex = currentIndex;
}
var sliderPause = function (currentItem, currentIndex) { // si può cancellare?
$(currentItem).parent().parent().trigger('extra:slider:pause');
var id = $(currentItem).parent().parent().parent().attr('id');
self.log('slideId:'+id);
self.log('currentItem:'+currentItem);
self.log('currentIndex:'+currentIndex);
slides[id].currentItem = currentItem;
slides[id].currentIndex = currentIndex;
}
var sliderPlay = function (currentItem, currentIndex) { // si può cancellare?
$(currentItem).parent().parent().trigger('extra:slider:pause');
$(currentItem).parent().parent().trigger('extra:slider:resume');
var id = $(currentItem).parent().parent().parent().attr('id');
self.log('slideId:'+id);
self.log('currentItem:'+currentItem);
self.log('currentIndex:'+currentIndex);
slides[id].currentItem = currentItem;
slides[id].currentIndex = currentIndex;
}
var sliderResume = function (currentItem, currentIndex) { //si può cancellare?
var id = $(currentItem).parent().parent().parent().attr('id');
if (slides[id].active) {
sliderPlay(currentItem, currentIndex);
} else {
sliderPause(currentItem, currentIndex);
}
}
var sliderClick = function (currentItem, currentIndex) { // si può cancellare ?
var id = $(currentItem).parent().parent().parent().attr('id');
if (slides[id].active) {
slides[id].active = false;
} else {
slides[id].active = true;
}
} */
/* this.addItem = function (data, selectorParams) { // obsolete
var container = (selectorParams) ? self.selector(selectorParams) : data.container;
var selector = self.selector(self.extend({}, data, selectorParams));
// app default
// aggiungere anche dimensione di default
var iconClass = self.json.setup.classes.icon || '';
var badgeClass = self.json.setup.classes.badge || '';
var style = (data.style) ? data.style : {};
// retro-compatibility
if (data.size) {
if (data.size == 'small')
style.width = '50px';
else if (data.size == 'medium')
style.width = '80px';
else if (data.size == 'big')
style.width = '120px';
else if (data.size)
style.width = data.size;
}
style = self.extend({}, style, { // retrocompatibilità / obsoleto
color: data.color,
background: data.background,
border: data.border,
display: data.display,
margin: data.margin,
padding: data.padding,
width: data.width,
height: data.height
});
// Create
if (data.id === undefined) {data.id = '';}
if (data.value === undefined) {data.value = data.id};
if (data.class === undefined) {data.class = iconClass} else if (data.class !== iconClass) {data.class += ' ' + iconClass};
var itemDiv = '';
if (data.prepend) {
$(data.container).prepend(itemDiv);
} else {
$(data.container).append(itemDiv);
}
self.css({style: {
width: style.width,
display: style.display,
padding: style.padding,
margin: style.margin
}}, {container: selector});
// SVG
if (data.svg || data.text) {
self.svgImage({
container: selector,
icon: data.svg,
text: data.text,
textSize: data.textSize, // verify (obsolete when span will be nested)
textPosition: data.textPosition, // verify (obsolete when span will be nested)
textColor: data.textColor, // verify (obsolete when span will be nested)
background: style.background,
border: style.border,
color: style.color
//hoverBackground: data.hoverBackground, // verify
//hoverBorder: data.hoverBorder, // verify
//hoverColor: data.hoverColor, // verify
});
} else {
}
// image
if (data.image) {
var imgData = data;
imgData.style = {
width:'82px',
height:'82px',
'margin-bottom':'27px'
};
if (style.background) imgData.style['background-color'] = style.background;
self.loadImage(imgData);
}
// badge
if (data.badgeIcon || data.badgeText) {
$(selector).append('');
self.svgImage({
container: selector + ' > .'+badgeClass,
icon: data.badgeIcon,
text: data.badgeText,
background: data.badgeBackground,
border: data.badgeBorder,
color: data.badgeColor,
});
}
if (data.title) {
//data.title = self.text(data.title);
data.titleColor = data.titleColor || style.color;
if (data.titleColor == undefined) {data.titleColor = ''}
if (data.titleSize == undefined) {data.titleSize = ''}
//if (data.titleSizeMin == undefined) {data.titleSize = '7px'}
$(selector).append('');
$(selector + ' > span').css({
color: data.titleColor,
'font-size': data.titleSize
});
//if (typeof data.title == 'object') alert(data.title.text);
self.text(data.title, {container: selector + ' > span'});
//var title = self.text(data.title);
//$(selector + ' > span').text(title);
//self.text(data.title);
// itemSelectedBorderWhite GESTITO IN INDEX.CSS
// questo stile dovrebbe essere fisso e con posizione assoluta
if (data.image)
$(selector + ' > span').css({
'margin-top':'89px',
position: 'absolute'
});
if (data.textFit !== false) {
self.textFit($(selector+' > span'), {
alignHoriz: false,
multiLine: false,
alignVert: false,
minFontSize: 10,
maxFontSize: data.titleSize,
});
}
}
// action (obsolete)
if (data.action || data.functions) {
var.functions[selector] = data.functions || data.action; // obsoleto
$(selector).data('onData', data); // nuova versione
$(selector).off().on(self.touch, function(event){
event.stopPropagation();
self.onEvent(this, event);
});
}
// matchMedia
if (data.matchMedia) {
for (var mediaEvent in data.matchMedia) {
self.matchMedia(data.matchMedia[mediaEvent], mediaEvent);
}
}
// events
if (data.on) self.on(data.on, {container: selector});
if (data.checked !== undefined) {
self.checkItem({
container: data.container,
class: data.class,
value: data.value,
id: data.id,
checked: data.checked
//style: data.style,
});
}
} */
// --------------
// TABS
// --------------
/* this.addTab = function (data, selectorParams) {
//self.log('addTab');
//self.log(data);
var containerParams = self.cloneObject(selectorParams);
data.container = containerParams.container;
var selector = self.selector(data);
var tabClass = ''; //self.json.setup.classes.button || '';
var badgeClass = 'iconBadge'; //self.json.setup.classes.badge || '';
var style = (data.style) ? data.style : {};
// span height
//style["line-height"] = (style.height) ? style.height : '42px';
style = self.extend({}, style, {
color: data.color,
background: data.background,
border: data.border,
display: data.display,
margin: data.margin,
padding: data.padding,
width: data.width,
height: data.height
});
if (data.id === undefined) {data.id = '';}
if (data.value === undefined) {data.value = data.id};
if (data.class === undefined) {data.class = tabClass} else if (data.class !== tabClass) {data.class += ' ' + tabClass};
var tabDiv = '';
$(data.container).append(tabDiv);
self.css({style: style}, {container: selector});
//if (data.key) {$(selector).data('key', data.key);}
//var iconColor = style.color || $(selector).css("color");
// ICON
if (data.icon) {
self.addItem({
class: 'icon',
value: data.value,
svg: data.icon,
image: data.image,
style: {
color: style.color || $(selector).css("color"),
width: style.height
}
}, {container: selector});
}
// TEXT
if (data.text !== undefined) {
//alert(JSON.stringify(data.text));
$(selector).append('');
self.text(data.text, {container: selector + ' > span'});
} else {
//alert(JSON.stringify(data.text));
}
if (data.icon) $(selector + ' > span').css({'padding-left': '0px'});
// SPAN
if(style.color) $(selector + ' > span').css({'color':style.color});
// BADGE
if (data.badgeIcon || data.badgeText) {
if (!$('.'+badgeClass).length)
$(selector).append('');
self.svgImage({
container: selector + ' > .'+badgeClass,
icon: data.badgeIcon,
text: data.badgeText,
background: data.badgeBackground,
border: data.badgeBorder,
color: data.badgeColor,
});
} else {
$(selector + ' > .'+badgeClass).remove();
}
// data
if (data.action || data.functions){
var.functions[selector] = data.functions || data.action; // obsoleto
$(selector).data('onData', data); // nuova versione
$(selector).off().on(self.touch, function(event){
event.stopPropagation();
self.onEvent(this, event);
//$(this).data('value')
//var selector = $(this).data('selector');
//var action = var.functions[selector];
//self.do($(this).data('onData').action, $(this).data('value'));
});
}
// matchMedia
if (data.matchMedia) {
for (var mediaEvent in data.matchMedia) {
self.matchMedia(data.matchMedia[mediaEvent], mediaEvent);
}
}
// events
if (data.on) self.on(data.on, {container: selector});
if (data.selected) self.selectTab(data);
} */
/* this.changeTab = function (data, selectorParams) {
var container = (selectorParams) ? self.selector(selectorParams) : data.container;
var selector = self.selector(self.extend({}, data, selectorParams));
if (data.icon && data.value) {
self.changeItem({
container: selector,
class: 'icon',
value: data.value,
svg: data.icon,
color: data.color,
background: data.background
});
}
if(data.background) $(selector).css({'background':data.background});
if(data.color) $(selector + ' > span').css({'color':data.color});
if (data.text) {
//$(selector + ' > span').text(self.text(data.text));
self.text(data.text, {container: selector + ' > span'});
}
if (data.action){
$(selector).off().on(self.touch, function(){
data.action(data.value)
});
}
// events
if (data.on) self.on(data.on, {container: selector});
if (data.selected) self.selectTab(data);
} */
/* this.unselectTabs = function (data) {
var selectionClass = data.selection || 'selectedButton';
//var selectionClass = self.json.setup.classes.selectedButton;
if (data.style) selectionClass = data.style;
$(data.class).removeClass(selectionClass);
}
this.toggleTab = function (data) {
data.toggle = true;
return self.selectTab(data);
}
this.selectTab = function (data) {
var selectionClass = data.selection || 'selectedButton';
//var selectionClass = self.json.setup.classes.selectedButton;
if (data.style) selectionClass = data.style;
var selector = self.selector(data);
if (data.deselectClass)
if (data.class) $('.'+data.class).removeClass(selectionClass);
if (data.checked !== undefined) {
if (data.checked == false) $(selector).removeClass(selectionClass);
else $(selector).addClass(selectionClass);
} else if (data.toggle !== undefined) {
// da toggleTab
if ($(selector).hasClass(selectionClass)) {
$(selector).removeClass(selectionClass);
return false;
} else {
//if (data.class) $('.'+data.class).removeClass(selectionClass);
$(selector).addClass(selectionClass);
return true;
}
} else {
//if (data.class) $('.'+data.class).removeClass(selectionClass);
$(selector).addClass(selectionClass);
}
} */
// ---------------------------
// FUNZIONI DATEPICKER
// ---------------------------
/*
// basato su: http://www.daterangepicker.com/#options
this.createDatePicker = function (data) {
self.log('createDatePicker');
var calendarVisible = false;
if (!data.field) data.field = data.container + ' > .daterange';
if (!$(data.field).length) {
calendarVisible = true; // Crea e nasconde campo testo e mostra calendario
$(data.container).html('');
}
var weekD = self.weekdaysShort(1, capitalize);
weekD = weekD.unshift(weekD[6]);
var monthsOfYear = ["January","February","March","April","May","June","July","August","September","October","November","December"];
if (data.language) {
monthsOfYear = moment.localeData(data.language).months();
for (var index in monthsOfYear) {
monthsOfYear[index] =
monthsOfYear[index].substr(0,1).toUpperCase()
+ monthsOfYear[index].substr(1);
}
}
//var datarange = $('#daterange');
$(data.field).daterangepicker({
singleDatePicker: data.single,
parentEl: data.container,
startDate: data.start,
endDate: data.end,
autoApply: true,
autoUpdateInput: false,
locale: {
format: 'DD/MM/YYYY',
daysOfWeek: weekD,
monthNames: monthsOfYear,
firstDay: 1 // monday
}
});
$(data.field).on('cancel.daterangepicker', function(ev, picker) {
data.onCancel();
});
$(data.field).on('apply.daterangepicker', function(ev, picker) {
data.onChange({
start: picker.startDate.format('YYYYMMDD'),
end: picker.endDate.format('YYYYMMDD')
});
if (picker.startDate && picker.endDate && picker.startDate !== picker.endDate) {
$(data.field).val(picker.startDate.format('DD/MM/YYYY') + '-' + picker.endDate.format('DD/MM/YYYY'));
} else {
$(data.field).val(picker.startDate.format('DD/MM/YYYY'));
}
});
self.unselectDatePicker({container: data.container});
}
var disableDates = [];
this.updateDatePicker = function(data) {
var datePicker = $(data.container + ' > .daterange').data('daterangepicker');
if (data.disableDates) {disableDates = data.disableDates;}
// alert(datePicker+'-'+data.container);
datePicker.isInvalidDate = function(date) {
return (disableDates.indexOf(date.format('YYYYMMDD')) >= 0)
}
datePicker.updateView();
if (data.start && data.end) {
self.setDatePicker({
container: data.container,
start: data.start,
end: data.end,
});
} else {
self.unselectDatePicker({container: data.container});
}
}
this.unselectDatePicker = function(data) {
$(data.container).find('.start-date').removeClass('start-date active');
$(data.container).find('.end-date').removeClass('end-date active');
$(data.container).find('.in-range').removeClass('in-range');
}
this.setDatePicker = function (data) {
var datePicker = $(data.container + ' > .daterange').data('daterangepicker');
datePicker.setStartDate(data.start);
datePicker.setEndDate(data.end);
datePicker.updateView();
}
this.getDatePicker = function (data) {
var start = $(data.container + ' > .daterange').data('daterangepicker').startDate(data.start);
var end = $(data.container + ' > .daterange').data('daterangepicker').endDate(data.end);
//alert('ok: '+data.container);
return {start: start, end: end}
}
// ---------------------------
// FUNZIONI TIMEPICKER
// ---------------------------
this.createTimePicker = function (data) {
$(data.container).html('');
$(data.container + ' > .datetimepicker').datetimepicker({
icons: {
up: "fixoNavUp",
down: "fixoNavDown",
previous: "fixoNavBackward",
next: "fixoNavForward"
},
inline: true,
sideBySide: true,
//locale: 'it'
locale: {
format: 'DD/MM/YYYY',
daysOfWeek: weekD,
monthNames: monthsOfYear,
firstDay: 1 // monday
}
});
//self.log('now: '+Date.now()+' moment: '+moment());
self.setTimePicker({
container: data.container,
time: data.time
});
$(data.container + ' > .datetimepicker').off().on('dp.change', function(event) {
var datePicked = moment(event.date).unix();
//alert(datePicked);
data.onChange(datePicked);
});
}
this.setTimePicker = function (data) {
//self.log('>>> setTimePicker --> data container: '+data.container+' data time: '+data.time+' moment: '+moment.unix(data.time).calendar());
$(data.container + ' > .datetimepicker').data('DateTimePicker').date(moment.unix(data.time));//.format('LLL'));
}
this.getTimePicker = function (data) {
//alert('ok: '+data.container);
$(data.container + ' > .datetimepicker').data('DateTimePicker').date();
}
*/
// ---------------------------
// TIME SLIDER
// ---------------------------
/*
this.createTimeSlider = function(data){
var container = data.container;
var id = data.id;
// c'è un'anomalia nella libreria bootstrap-slider
// crea il contenitore dello slider con lo stesso id del campo input
// va verificata la possibilità di configurazione della funzione .slider
$('#'+data.container).append('');
$('#'+id).slider();
$('#'+id).off().on("slide slideStop", function(event) {
self.log(event);
self.changeItem({
id:'stepbackwardSlider'+id,
text: self.numberToHour({value: event.value[0], max: 48})
});
self.changeItem({
id:'stepforwardSlider'+id,
text: self.numberToHour({value: event.value[1], max: 48})
});
if (data.onChange) {
data.onChange({
start: self.numberToHour({value: event.value[0], max: 48}),
end: self.numberToHour({value: event.value[1], max: 48})
})
}
});
// ICONS Slider
self.addItem({
container:'#'+id+' > .min-slider-handle',
class: 'sliderIconLeft',
id: 'stepbackwardSlider'+id,
background: '#fff',
color: 'black',
border: 1,
text: '00:00'
});
self.addItem({
container:'#'+id+' > .max-slider-handle',
class: 'sliderIconRight',
id: 'stepforwardSlider'+id,
background: '#fff',
color: 'black',
border: 1,
text: '24:00'
});
//$('#'+sliderId+' .slider-selection').css({'background': '#fff'});
}
this.setTimeSlider = function(data){
//Change value on slider left/right icon
self.changeItem({
id:'stepbackwardSlider'+data.id,
text: data.start
});
self.changeItem({
id:'stepforwardSlider'+data.id,
text: data.end
});
//Convert value in 0-48 format
var start = self.hourToNumber({value: data.start, max: 48});
var end = self.hourToNumber({value: data.end, max: 48});
// Set value on slider
$('input[id="'+data.id+'"]').slider('setValue',[start,end]);
}
this.getTimeSlider = function(data){
var slideStart = $('input[id="'+data.id+'"]').slider('getValue')[0] || 0;
var slideEnd = $('input[id="'+data.id+'"]').slider('getValue')[1] || 48;
var start = self.numberToHour({value: slideStart, max: 48});
var end = self.numberToHour({value: slideEnd, max: 48});
if (start == '24:00') {start = '00:00'}
var timetable = {
start: start || '00:00',
end: end || '24:00'
}
return timetable;
}
*/
this.numberToHour = function (data) {
var fraction = data.value / data.max;
var dayMin = Math.round(24 * 60 * fraction);
var hour = parseInt(dayMin / 60);
var min = dayMin - hour * 60;
var hourString = String(hour < 10 ? '0' : '') + String(hour);
var minString = String(min < 10 ? '0' : '') + String(min);
return hourString + ':' + minString;
};
this.hourToNumber = function (data) {
var timeArr = data.value.split(':');
var dayMin = (60 * Number(timeArr[0])) + Number(timeArr[1]);
var fraction = dayMin / (24 * 60);
return Math.round(fraction * data.max);
};
this.pannellum = function (params, selectorParams, args) {
self.log('pannellum');
var container = params.selector || params.container;
var selector = self.selector(container) || self.selector(selectorParams);
var element = self.query(selector);
pannellum.viewer(element, params);
};
this.qrcode = function (params, selectorParams, args) {
self.log('qrcode');
var container = params.selector || params.container;
var selector = self.selector(container) || self.selector(selectorParams);
var element = self.query(selector);
// var obj = self.compile(data);
self.log(selector);
self.log('element');
self.log(element);
var QRCodeOptions = {
text: self.replaceProperties(params.text, args) || 'jsonic.io',
width: params.size || 128,
height: params.size || 128,
useSVG: true,
colorDark: params.colorDark || '#000000',
colorLight: params.colorLight || '#ffffff',
correctLevel: QRCode.CorrectLevel.H
};
self.log('QRCodeOptions');
self.log(QRCodeOptions);
element.textContent = '';
var qrcode = new QRCode(element, QRCodeOptions);
self.log('qrcode');
self.log(qrcode);
return qrcode;
//qrcode.clear(); // clear the code.
//qrcode.makeCode(text); // make another code
};
/* this.qrcode = function (data) {
self.log('qrcode');
var selector = self.selector(data);
var options = {
// render method: 'canvas', 'image' or 'div'
render: 'image',
// version range somewhere in 1 .. 40
minVersion: 1,
maxVersion: 40,
// error correction level: 'L', 'M', 'Q' or 'H'
ecLevel: 'L',
// offset in pixel if drawn onto existing canvas
left: 0,
top: 0,
// size in pixel
size: data.size || 200,
// code color or image element
fill: data.color || '#000',
// background color or image element, null for transparent background
background: data.background || null,
// content
text: self.replaceProperties(data.text) || 'no text',
// corner radius relative to module width: 0.0 .. 0.5
radius: 0,
// quiet zone in modules
quiet: 0,
// modes
// 0: normal
// 1: label strip
// 2: label box
// 3: image strip
// 4: image box
mode: 0,
mSize: 0.1,
mPosX: 0.5,
mPosY: 0.5,
label: data.label || 'no label',
fontname: data.fontname || 'sans',
fontcolor: data.fontcolor || '#000',
image: null
}
$(selector).empty().qrcode(options);
} */
this.weekdaysShort = function (length, caseFunction) {
if (!caseFunction) caseFunction = caseUp;
var language = 'en';
var fixoLang = fixo.getFixoLanguage();
var userLang = fixo.getUserLanguage();
if (fixo.device) language = fixoLang; else language = userLang;
var weekDays = self.cloneObject(moment.localeData(language).weekdays());
weekDays[7] = weekDays[0];
weekDays.shift();
for (var i = 0; i < 7; i++) {
if (length) weekDays[i] = weekDays[i].substr(0, length);
if (caseFunction) weekDays[i] = caseFunction(weekDays[i]);
}
return weekDays;
};
this.weekDaysToString = function (days) {
var text = '';
for (var i in days) {
if (days[i]) {
if (text !== '') text += '/';
text += self.weekdaysShort(3, capitalize)[i];
}
}
return text;
};
// -----------
// DRAG
// -----------
/*
var draggingData;
this.sortable = function (data) {
var rootEl = $(data.container)[ 0 ];
var dragEl;
draggingData = data;
var selector = self.selector(data);
$(selector).attr('draggable', 'true');
$(data.exclude).attr('draggable', 'false');
// Function responsible for sorting
function onDragOver(event) {
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
var dragTarget = event.target; // target.nextSibling ||
if ($(dragTarget).hasClass(draggingData.class))
$( dragEl ).insertAfter( $(dragTarget) );
if ($(dragTarget).parent().hasClass(draggingData.class))
$( dragEl ).insertAfter( $(dragTarget).parent() );
}
// End of sorting
function onDragEnd(event){
event.preventDefault();
$(dragEl).css({'opacity':'100%'});
rootEl.removeEventListener('dragover', onDragOver, false);
rootEl.removeEventListener('dragend', onDragEnd, false);
// Notification about the end of sorting
draggingData.target = dragEl;
draggingData.onDragEnd(draggingData);
}
// Sorting starts
rootEl.addEventListener('dragstart', function (event){
dragEl = event.target; // Remembering an element that will be moved
$(dragEl).css({'opacity':'50%'});
// Limiting the movement type
event.dataTransfer.effectAllowed = 'move';
event.dataTransfer.setData('Text', dragEl.textContent);
// Subscribing to the events at dnd
rootEl.addEventListener('dragover', onDragOver, false);
rootEl.addEventListener('dragend', onDragEnd, false);
setTimeout(function () {
// If this action is performed without setTimeout, then
// the moved object will be of this class.
$(dragEl).css({'opacity':'100%'});
}, 0)
}, false);
}
*/
/*
this.setWeekDays = function(data){
if (!data.days) data.days = {};
for (var i=1; i<7; i++){
self.selectTab({
container: data.container,
class: 'fixoTabsWeekDays',
value: String(i),
checked: data.days[String(i)] || false
});
}
}
this.createWeekDays = function(data){
//var selector = self.selector(data);
var weekDays = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];
self.log('data.language '+data.language);
if (data.language) weekDays=moment.localeData(data.language).weekdaysShort();
for (var i=0; i<7; i++){
var weekDay = weekDays[i];
self.addTab({
container: data.container,
class: data.class,
value: String(i),
id: data.container + i,
background: 'black',
color: 'white',
border: '1px solid rgba(0, 0, 0, 1)',
text: weekDay,
action: function(value){
//alert($(this).attr(id));
// il toggleTab deselezionava sempre gli altri giorni
// risolto usando il selectTab col parametro checked
// va sistemato toggleTab
if (!data.days) data.days = {};
var checked = !Boolean(data.days[value]);
self.selectTab({
container: data.container,
class: 'fixoTabsWeekDays',
value: value,
checked: checked
});
data.days[value] = checked;
}
});
}
}
*/
//--------------------------
// DA FIXO.JS
//--------------------------
/*---------------------
UTILS
---------------------*/
var sortField;
var dynamicSort = function (data) {
var sortOrder = 1;
if (data.reverse) { sortOrder = -1; }
sortField = data.field;
return function (a, b) {
var result = (a[sortField] < b[sortField]) ? -1 : (a[sortField] > b[sortField]) ? 1 : 0;
return result * sortOrder;
};
};
this.sort = function (data) {
// fixo.sort({object:{}, add: {}, field:'time', reverse:true})
if (data.object !== undefined) {
if (Array.isArray(data.object)) {
return data.object.sort(dynamicSort({
field: data.field,
reverse: data.reverse
}));
} else {
var arr = self.objectToArray({
object: data.object,
add: data.add,
});
return arr.sort(dynamicSort({
field: data.field,
reverse: data.reverse
}));
}
} else {
self.log('sort of undefined');
return [];
}
};
this.objectToArray = function (data) {
// data: {object:{}, add: {}}
var arr = [];
var obj = data.object;
if (obj !== undefined) {
for (var key in obj) {
obj[key].id = key; // aggiunge la chiave dell'oggetto come proprietà
if (data.add) obj[key] = Object.assign(obj[key], data.add);
arr.push(obj[key]);
}
}
return arr;
};
/*
this.itemsFound = function(items, field, value) {
return $.grep(items, function(e){ return e.name == value; });
}
*/
/* this.itemFound = function(items, field, value) {
var itemFound = false;
for (var i=0; i 0);
} else {
return ($(data.class).length > 0);
}
} */
this.equal = function (obj1, obj2) {
if (obj1 && obj2) {
return (JSON.stringify(obj1).replace('"', '') == JSON.stringify(obj2).replace('"', ''));
} else {
return (obj1 == obj2);
}
};
/* this.arraysEquals = function(arr1,arr2) {
return ($(arr1).not(arr2).length === 0 && $(arr2).not(arr1).length === 0);
} */
var escapeRegExp = function (str) {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
};
this.replaceAll = function (str, find, replace) {
if (str !== undefined) {
let result;
if (typeof str == 'string') result = str; else result = JSON.stringify(str);
if (str) {
if (find) { // && replace
//if (typeof str !== 'string') self.log(str);
result = String(str).replace(new RegExp(escapeRegExp(find), 'g'), replace);
//if (typeof str == 'string') return result; else return JSON.parse(result);
if (typeof str == 'object' && result) return JSON.parse(result);
else
return result;
} else {
/* self.log('str:'+str);
self.log('find:'+find);
self.log('replace:'+replace); */
return str;
}
}
} else {
return str;
}
};
this.capitalize = function (str) {
return str.replace(/\b\w/g, l => l.toUpperCase());
};
/*---------------------
URL UTILS
---------------------*/
this.getPageName = function (url) {
var index = url.lastIndexOf("/") + 1;
var filenameWithExtension = url.substr(index);
var filename = filenameWithExtension.split(".")[0]; // <-- added this line
return filename; // <-- added this line
};
this.goToMainUrl = function () {
window.location = self.mainUrl;
};
this.getParameterByName = function (name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^]*)|&|#|$)"), results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
};
var paramsToObject = function (params) {
params = params.split('#')[0];
return JSON.parse('{"' + params.replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') + '"}');
};
var objectToParams = function (object) {
var str = '';
for (var key in object) str += '&' + key + '=' + object[key];
if (str) str = str.substr(1);
return encodeURI(str);
};
this.getParams = function () {
var params = {};
var url = window.location.href.split('#')[0];
if (url.indexOf('?') > -1) {
var urlParams = decodeURI(url.split('?')[1]);
self.log(urlParams);
if (urlParams) {
var k = self.getParameterByName('k', url);
//self.log(k);
if (k) {
params = self.atob(k);
} else {
params = paramsToObject(urlParams);
}
}
}
return params;
};
this.atob = function (k) {
self.log('atob');
var params = paramsToObject(atob(k)); // base64 -> query -> object
// decompress params
if (params.h) // hotel
params.h = String(parseInt(String(params.h), 36)); // base36
if (params.c) // customer
params.c = String(parseInt(String(params.c), 36)); // base36
if (params.n) { // phone
params.n = String(parseInt(String(params.n), 36)); // base36
params.n = '+' + params.n;
}
//if (params.s) params.s = var.services.id[params.s];
self.log(params);
return params;
};
this.btoa = function (params) {
self.log('btoa');
//if (params.s) params.s = var.services.id.indexOf(params.s);
if (params.h) // hotel
params.h = Number(params.h).toString(36); // base36
if (params.c) // customer
params.c = Number(params.c).toString(36); // base36
if (params.n) { // phone
if (params.n.startsWith('+')) params.n = params.n.substr(1);
params.n = params.n.replace(/ /g, '');
params.n = params.n.replace(/-/g, '');
params.n = Number(params.n).toString(36); // base36
}
self.log(params);
return btoa(objectToParams(params)); // query -> base64
};
/*
var encodeNum = function(num) { // 0..1296 es:customer
var hex = c.toString(36);
return c.toString(36);
}
var decodeNum = function(str) {
return str.parseInt(36); // .length == 1 ? "0" + hex : hex
}
*/
this.colorToRgba = function (hex, opacity) {
if (hex == 'white') { hex = '#fff'; }
if (hex == 'black') { hex = '#000'; }
var c;
if (/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) {
c = hex.substring(1).split('');
if (c.length == 3) {
c = [c[0], c[0], c[1], c[1], c[2], c[2]];
}
c = '0x' + c.join('');
return 'rgba(' + [(c >> 16) & 255, (c >> 8) & 255, c & 255].join(',') + ',' + opacity + ')';
} else {
self.log('Bad Hex:' + hex);
}
};
var hueToRGB = function (m1, m2, h) {
h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h);
if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
if (h * 2 < 1) return m2;
if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6;
return m1;
};
var HSLToRGB = function (hsl) {
var m1, m2, r, g, b;
var h = hsl[0], s = hsl[1], l = hsl[2];
m2 = (l <= 0.5) ? l * (s + 1) : l + s - l * s;
m1 = l * 2 - m2;
return [hueToRGB(m1, m2, h + 0.33333),
hueToRGB(m1, m2, h),
hueToRGB(m1, m2, h - 0.33333)];
};
var packRGB = function (rgb) {
var r = Math.round(rgb[0] * 255);
var g = Math.round(rgb[1] * 255);
var b = Math.round(rgb[2] * 255);
// '#' +
return (r < 16 ? '0' : '') + r.toString(16) +
(g < 16 ? '0' : '') + g.toString(16) +
(b < 16 ? '0' : '') + b.toString(16);
};
this.degToRGB = function (deg) {
return packRGB(HSLToRGB([deg / 360, 1, 0.5]));
};
this.stripHtml = function (html) {
var tmp = document.createElement("DIV");
tmp.innerHTML = html;
return tmp.textContent || tmp.innerText || "";
};
//--------------------------
// TASK MANAGER
//--------------------------
this.log = function (value, color) {
if (self.json.setup && self.json.setup.log) { // log enabled
if (typeof value === 'string')
console.log('%c' + value, 'color:' + color);
else
console.log(value);
}
};
var varlog = function (str) {
self.log(str);
self.log(window[str]); // 'var' -> var
};
this.logJson = function (jsonPar) { self.log(JSON.stringify(jsonPar)); };
this.getTimestamp = function () {
// we need also an API to get the time
// like .getTime()?
return Math.floor(Date.now());
};
this.cloneObject = function (obj) {
var newObj = JSON.stringify(obj);
return self.parse(newObj);
};
/*------------------------
TEXT
------------------------*/
/* var caseUp = function (string) {
if (!string) string = '';
return string.toUpperCase();
}
var caseDown = function (string) {
if (!string) string = '';
return string.toLowerCase();
}
var capitalize = function(string) {
if (!string) string = '';
return self.capitalize(string);
}
var text = function (key, caseFunction) {
var t = self.json.text[key] || '';
if (caseFunction) return caseFunction(t); else return t;
} */
this.setElement = function (elementString, elementValue) {
var context = window;
var namespaces = elementString.split(".");
var func = namespaces.pop();
if (namespaces[0] == 'frame') {
namespaces.shift();
var frameName = namespaces.shift();
if (frameName && document.getElementById(frameName) !== null)
context = document.getElementById(frameName).contentWindow;
} else if (namespaces[0] == 'admin') { // fixo
namespaces.shift();
context = fixoAdmin;
}
for (var i = 0; i < namespaces.length; i++) {
if (context[namespaces[i]]) { // var
context = context[namespaces[i]];
} else {
if (elementValue) // scrittura
context[namespaces[i]] = {}; // crea contesto inesistente
}
}
context[func] = elementValue;
};
this.context = function (path) {
const re = /^(setup|var|data|texts|parts)[\.\s]/; // reserved namespaces
if (re.test(path)) {
/* self.log('MATCHED setup|var|data|parts');
console.log(params); */
return self.json;
} else {
return window;
}
};
this.element = function (params) {
// {root, path, value}
// in respect to docElement, it includes replaceProperties for path and value
// but only if value is a string. TO DO: check it
let context;
let path = self.replaceProperties(params.path, params.args);
let value = (params.value && typeof params.value == 'string') ? self.replaceProperties(params.value, params.args) : params.value;
// NOTE: log error if the params.root is equal to the first element of the path? (window.window works)
if (!params.root) {
context = self.context(path);
} else {
context = params.root;
}
return self.docElement(path, value, context, params.delete);
//self.log(value);
/* if (value && typeof value == 'string') {
if (value.startsWith('js:')) value = self.js(value.substr(3));
else if (value.startsWith('+=')) value = self.element({path: path}) + self.js(value.substr(2));
else if (value.startsWith('-=')) value = self.element({path: path}) - self.js(value.substr(2));
else if (value.startsWith('/=')) value = self.element({path: path}) / self.js(value.substr(2));
else if (value.startsWith('*=')) value = self.element({path: path}) / self.js(value.substr(2))
} */
// self.log(value);
/* if (value.startsWith('number:')) value = Number(self.js(value.substr(6)));
alert('dopo number:'+value);
if (value.startsWith('boolean:')) value = Boolean(self.js(value.substr(7)));
if (value.startsWith('string:')) value = String(self.js(value.substr(6)));
if (value.startsWith('+:')) value = self.element({path: path}) + self.js(value.substr(2));
if (value.startsWith('-:')) value = self.element({path: path}) - self.js(value.substr(2));
if (value.startsWith('/:')) value = self.element({path: path}) / self.js(value.substr(2));
if (value.startsWith('*:')) value = self.element({path: path}) / self.js(value.substr(2)); */
/* // verificare...
if (value.startsWith('push:')) {var obj = self.docElement(path, undefined, root); return obj.push(value.substr(3));}
if (value.startsWith('unshift:')) {var obj = self.docElement(path, undefined, root); return obj.unshift(value.substr(3));}
if (value.startsWith('pop:')) {var obj = self.docElement(path, undefined, root); return obj.pop(value.substr(3));}
if (value.startsWith('shift:')) {var obj = self.docElement(path, undefined, root); return obj.shift(value.substr(3));} */
};
this.docElement = function (elementString, elementValue, context, elementDelete) {
if (!context) context = window; // TO DO: remove
var namespaces = elementString.split(/[.\s]+/); // path nodes separed by dot or spaces
/* console.log('<-------');
console.log('context');
console.log(context);
console.log('path');
console.log(elementString);
console.log('value');
console.log(elementValue);
console.log('------>');
*/
var lastElement = namespaces.pop();
/* if (namespaces[0] == 'self') {
namespaces.shift();
context = self;
} else if (namespaces[0] == 'frame') {
namespaces.shift();
var frameName = namespaces.shift();
if (frameName && document.getElementById(frameName) !== null)
context = document.getElementById(frameName).contentWindow;
} */
/* console.log('namespaces');
console.log(namespaces); */
for (var i = 0; i < namespaces.length; i++) {
if (context[namespaces[i]]) { // var
context = context[namespaces[i]];
} else {
if (elementValue !== undefined && elementValue !== null) { // wants to assign a value
context[namespaces[i]] = {}; // it create the context context[namespaces[i]] if it doesn't exist
context = context[namespaces[i]];
/* self.log('crea context inesistente');
self.log('namespaces[i]: '+namespaces[i]); */
/* self.log('elementValue');
self.log(elementValue);
self.log('context[namespaces[i]]');
self.log(context[namespaces[i]]); */
} else {
/* self.log(elementString + ' undefined');
self.log('lastElement:' + lastElement);
self.log(elementValue); */
}
//break; // perché? rendeva impossibile creare un listener su un nodo secondario (solo su app e non su app/dev)
}
}
if (elementValue !== undefined) { // write
//self.log(lastElement+'='+elementValue);
if (typeof elementValue == 'string') elementValue = self.js(elementValue); // 1.0.3
context[lastElement] = elementValue;
// elementValue can be a js function
/* self.log('context');
self.log(context);
self.log('context[lastElement]');
self.log(context[lastElement]);
self.log('====='); */
}
if (elementDelete) delete context[lastElement];
/* self.log('context');
self.log(context); */
/* console.log('namespaces');
console.log(namespaces);
self.log('lastElement');
self.log(lastElement);
self.log('context[lastElement]');
self.log(context[lastElement]); */
if (context[lastElement] && context[lastElement].isConnected)
return self.elementToSelector(context[lastElement]);
else
return context[lastElement];
};
/* this.openCloseDropdown = function(key) {
self.log('openCloseDropdown');
self.log("key");
self.log(key);
//$('.dropdown-menu').css('display','none');
var selector = self.selector({
"id": "dropdown" +key,
"class": 'points',
"value": key,
});
self.log("selector");
self.log(selector);
if ($(selector + ' > .dropdown-menu').css('display') == 'none') {
$(selector + ' > .dropdown-menu').css('display', 'block');
} else {
$(selector + ' > .dropdown-menu').css('display', 'none');
}
} */
this.timeToMs = function (string) {
// bug
var timeArray = string.match(/(\d+)(\w+)/); // es: 1s / 100ms
if (timeArray) {
var value = Number(timeArray[0]);
var unit = timeArray[1];
var unitInMs = {
ms: 1,
s: 1000,
m: 1000 * 60,
h: 1000 * 60 * 60,
d: 1000 * 60 * 60 * 24,
milliseconds: 1,
seconds: 1000,
minutes: 1000 * 60,
hours: 1000 * 60 * 60,
days: 1000 * 60 * 60 * 24
};
if (value)
if (unitInMs[unit])
return value * unitInMs[unit];
else
self.log('wrong unit in the time string [value][unit]: ' + string);
else
self.log('wrong value in the time string [value][unit]: ' + string);
}
else
return Number(string);
};
this.intervals = {};
this.timer = function (params, args) {
// can go in "browser.json / functions (JS Browser BOM)
// https://www.w3schools.com/js/js_window.asp
let name = self.replaceProperties(params.name);
if (!name)
name = self.getTimestamp() + Math.random(1000);
if (params.play !== undefined && params.play == 0) {
if (self.intervals[name]) {
self.clearInterval({
name: name
}, args);
}
if (self.timeouts[name]) {
self.clearTimeout({
name: name
}, args);
}
}
else if (params.every !== undefined) {
let every = self.replaceProperties(params.every);
if (every) {
self.setInterval({
name: name,
duration: every,
do: params.do
}, args);
}
}
else if (params.after !== undefined) {
let after = self.replaceProperties(params.after);
if (after) {
self.setTimeout({
name: name,
duration: after,
do: params.do
}, args);
} else {
self.do(params.do, null, args);
}
}
};
this.setInterval = function (params, args) {
// could include the param "fromNow": true to execute the function
/* self.log('setInterval');
self.log(params); */
if (params.name && params.duration) {
if (self.intervals[params.name])
clearInterval(self.intervals[params.name]);
//self.do(params.do);
self.do(params.do);
self.intervals[params.name] = setInterval(function () {
//self.do(params.do);
self.do(params.do);
return params.name;
}, Number(params.duration)); // self.timeToMs
}
else
self.log('"setInterval" function requires "name" and "duration" parameters');
};
this.clearInterval = function (params, args) {
/* self.log('params');
self.log(params);
self.log('self.intervals[params.name]');
self.log(self.intervals[params.name]); */
if (self.intervals[params.name]) {
clearInterval(self.intervals[params.name]);
delete self.intervals[params.name];
}
// else
// self.log('"clearInterval" name not found: ' + params.name);
};
this.timeouts = {};
this.setTimeout = function (params, args) {
// could include the param "fromNow": true to execute the function
/* self.log('setTimeout');
self.log(params); */
if (params.name && params.duration) {
if (self.timeouts[params.name])
clearInterval(self.timeouts[params.name]);
//self.do(params.do);
//self.do(params.do);
self.timeouts[params.name] = setTimeout(function () {
//self.do(params.do);
self.do(params.do);
return params.name;
}, Number(params.duration)); // self.timeToMs
}
else
self.log('"setTimeout" function requires "name" and "duration" parameters');
};
this.clearTimeout = function (params, args) {
/* self.log('params');
self.log(params);
self.log('self.timeouts[params.name]');
self.log(self.timeouts[params.name]); */
if (self.timeouts[params.name]) {
clearTimeout(self.timeouts[params.name]);
delete self.timeouts[params.name];
}
//else
// self.log('"clearInterval" name not found: ' + params.name);
};
this.on = function (params, selectorParams) {
//let selector = params.selector || params.container;
var container = (selectorParams) ? self.selector(selectorParams) : params.selector; // 1.0.9 instead of params.container
/* self.log('on');
self.log(params);
self.log('container');
self.log(container); */
//var selector = self.selector(self.extend({}, params, selectorParams));
//$(container).data('onData', {events: params, container: container});
var element;
if (container) {
element = self.query(container); // shoud be foreach elements...
if (element)
self.dataStorage.set(element, "onData", { on: params, selector: container });
else {
self.log('can\'t find the element "' + container + '" ("on" function)');
self.log('params');
self.log(params);
self.log('selectorParams');
self.log(selectorParams);
}
} /* else {
self.log('"on" function with selector undefined');
self.log('params');
self.log(params);
self.log('selectorParams');
self.log(selectorParams);
} */
for (var eventId in params) {
//var eventAction = params[eventId];
//$(selector).data('onData').action = eventAction;
/* if (eventId == 'thunkable') {
self.thunkable(params[eventId]);
} else */
if (eventId == 'init') {
//self.log(params.init);
//self.do(params.init, undefined, selectorParams);
self.do(params.init, selectorParams);
} else if (eventId == 'hashchange') {
self.onHashChange.push(params.hashchange);
window.addEventListener('hashchange', function () {
self.json.setup.page.hash = window.location.hash.substr(1); // potrebbe essere esplicitato sulla app
//var action = self.cloneObject(params.app.on.hashchange);
//self.replaceAll("{result}", window.location.hash);
//self.do(self.onHashChange);
self.do(self.onHashChange);
self.uiUpdate();
});
} else if (eventId == 'scroll') {
self.onScroll.push(params.scroll);
window.addEventListener('scroll', function () {
//self.do(self.onScroll);
self.do(self.onScroll);
});
} else if (eventId == 'resize') {
self.onResize.push(params.resize);
window.addEventListener('resize', function () {
//self.do(self.onResize);
self.do(self.onResize);
});
} else if (eventId == 'in') { // like inViewport but only one time
if (container) {
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(function (entry) {
/* self.log('entry');
self.log(entry);
self.log('entry.target');
self.log(entry.target); */
/* self.log(entry);
self.log(entry.intersectionRatio);
self.log(entry.isIntersecting);
self.log(entry.isVisible); */
// isIntersecting, isVisible
//var element = self.query(entry.target);
//self.log(entry.intersectionRatio);
if (entry.intersectionRatio == 1) { // .isIntersecting?
var el = entry.target;
if (el.getAttribute('in') !== 'true') {
el.setAttribute('in', 'true'); // change with dataStorage
self.onEvent(entry.target, { type: 'in' });
}
}
});
}, {
rootMargin: '0px',
threshold: [0, 1] // if 0.5 is the half-height of the elmement
});
//const element = self.query(container);
observer.observe(self.query(container));
}
} else if (eventId == 'inViewport') {
if (container) {
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(function (entry) {
/* self.log('entry');
self.log(entry);
self.log('entry.target');
self.log(entry.target); */
/*
self.log(entry.intersectionRatio);
self.log(entry.isIntersecting);
self.log(entry.isVisible); */
// isIntersecting, isVisible
//var element = self.query(entry.target);
//self.log(entry.intersectionRatio);
if (entry.intersectionRatio > 0) {
self.onEvent(entry.target, { type: 'inViewport' });
}
});
}, {
rootMargin: '0px',
threshold: [0, 1] // if 0.5 is the half-height of the elmement
});
//const element = self.query(container);
observer.observe(self.query(container));
}
} else if (eventId == 'outViewport') {
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(function (entry) {
/* self.log(entry);
self.log(entry.isIntersecting);
self.log(entry.isVisible); */
// isIntersecting, isVisible
//var element = self.query(entry.target);
//self.log(entry.intersectionRatio);
if (entry.intersectionRatio == 0) {
self.onEvent(entry.target, { type: 'outViewport' });
/* var el = entry.target;
if (el.getAttribute('in') == 'true') {
el.setAttribute('in', 'false');
self.onEvent(entry.target, {type: 'out'});
} */
}
});
}, {
rootMargin: '0px',
threshold: [0, 1] // if 0.5 is the half-height of the elmement
});
const element = self.query(container);
observer.observe(element);
} else if (eventId !== 'selector') {
/* if (container == '.nav-link[data-value="docs"]') {
alert(JSON.stringify(params));
//element = element[0];
$(element).hide();
} */
//element.removeEventListener(eventId);
// $(container).off(eventId);
if (element) {
// TO DO: verify
//if (element.getAttribute('listener') !== 'true') { // only one mouse event
//self.log('addEventListener: ' + eventId);
element.addEventListener(eventId, function (event) {
//$(container).off(eventId).on(eventId, function (event) {
/* self.log('event');
self.log(event); */
element.setAttribute('listener', 'true');
//event.preventDefault();
//event.stopPropagation();
self.onEvent(this, event);
});
//}
if (eventId == 'mousedown' || eventId == 'mouseup' || eventId == 'click')
element.style.cursor = 'pointer';
}
/* $(container).off(eventId).on(eventId, function (event) {
//$(container).off(eventId).on(eventId, function (event) {
self.log('event');
self.log(event);
event.preventDefault();
event.stopPropagation();
self.onEvent(this, event);
}); */
//$(container).css({cursor: 'pointer'});
}
}
};
/* this.addAction = function (params, selectorParams) {
var container = (selectorParams) ? self.selector(selectorParams) : params.container;
var selector = self.selector(self.extend({}, params, selectorParams));
$(selector).data('onData', params);
//$(selector).data('onData', {action: params.action, params: params.args});
$(selector).off().on(this.touch, function (event) {
event.stopPropagation();
self.onEvent(this, event);
});
$(selector).css({cursor: 'pointer'});
} */
/* this.ace = function (params) {
params.container = 'blockCode';
var editor = ace.edit("blockCode");
var langTools = ace.require('ace/ext/language_tools');
editor.setTheme("ace/theme/monokai"); // ambiance
editor.getSession().setMode("ace/mode/json");
//editor.renderer.setOption('showLineNumbers', false);
editor.container.style.background="rgba(255,255,255,0)";
var staticWordCompleter = {
getCompletions: function(editor, session, pos, prefix, callback) {
var wordList = ["app", "setup", "pages"];
callback(null, wordList.map(function(word) {
return {
caption: word,
value: word,
meta: "static"
};
}));
}
}
editor.completers = [staticWordCompleter];
// https://github.com/ajaxorg/ace/wiki/Configuring-Ace
editor.setOptions({
fontSize: "11pt",
selectionStyle: "text",
highlightActiveLine: true,
wrap: true,
showLineNumbers: false,
showGutter: false,
fixedWidthGutter: false,
readOnly: true,
//enableBasicAutocompletion: true,
//enableSnippets: true,
//enableLiveAutocompletion: true,
});
editor.setValue(var.code, -1);
} */
/* this.edit = function (item) {
//var.code = JSON.stringify(item, null, '\t');
self.do( {
"alert": {
"background": "rgba(255,255,255,0.9)",
"width": "93%",
"showCancelButton": true,
"cancelButtonText": 'Cancel',
"confirmButtonText": 'Save',
"html": ''
}
});
//self.code(JSON.stringify(item, null, '\t'),);
self.code(item, {container: '#blockCode'});
//setTimeout(function () {
//alert(var.blockCode);
// https://codepen.io/jjsjjja/pen/VoGYRB
//}, 100);
} */
this.money = function (value) {
/* if (value && value.indexOf(',') == -1 && value.indexOf('.') == -1) {
value = value + '.00';
} */
var rounded = Math.round(Number(value) * 100) / 100;
var string = String(rounded);
if (rounded == Math.floor(rounded))
string += ',00';
string = String(string).replace('.', ',');
return string;
};
this.offcanvas = function (params) {
self.log('offcanvas');
self.log('params');
self.log(params);
// https://getbootstrap.com/docs/5.0/components/offcanvas/
// to add: toggle, getInstance, getOrCreateInstance
var container = params.selector || params.container;
var selector = self.selector(container);
var element = self.query(selector);
self.log('offcanvas');
self.log(params);
self.log('selector');
self.log(selector);
self.log('element');
self.log(element);
// do: show (default) / hide (see boostrap Offcanvas docs)
if (element) {
if (params.do == 'hide') {
self.css({
removeClass: 'show'
}, params);
//new bootstrap.Offcanvas(element).hide(); // doesn't work
} else {
new bootstrap.Offcanvas(element).show();
}
} else {
self.log('"offcanvas" method can\'t find the selected element');
}
};
/**
* Converts a DOM element to its CSS selector string representation
* @param {HTMLElement} element - The DOM element to convert
* @returns {string} The CSS selector string that uniquely identifies the element
*/
this.elementToSelector = function (element) {
// 1. Use ID if available
if (element.id) {
return '#' + element.id;
}
// 2. Use data-value if unique
if (element.dataset?.value) {
const sameDataValue = document.querySelectorAll(`[data-value="${element.dataset.value}"]`);
if (sameDataValue.length === 1) {
return `[data-value="${element.dataset.value}"]`;
}
}
// 3. Use class if unique
if (element.classList && element.classList.length > 0) {
for (const className of element.classList) {
if (className) {
const sameClass = document.querySelectorAll('.' + className);
if (sameClass.length === 1) {
return '.' + className;
}
}
}
}
// 4. Use tag if unique
const tagName = element.tagName.toLowerCase();
const sameTag = document.querySelectorAll(tagName);
if (sameTag.length === 1) {
return tagName;
}
// 5. Fallback to tag + nth-child path
let path = [];
while (element.parentNode) {
let selector = element.tagName.toLowerCase();
const index = Array.from(element.parentNode.children).indexOf(element) + 1;
selector += `:nth-child(${index})`;
path.unshift(selector);
element = element.parentNode;
}
return path.join(' > ');
};
this.onEvent = function (element, event) {
//self.log('element');
//self.log(element);
/* self.log('event');
self.log(event); */
/* if (event) {
event.preventDefault(); // verify
event.stopPropagation();
} */
/* var item = {};
if (self.dataStorage.has(element, 'onData'))
item = self.dataStorage.get(element, 'onData'); */
var item = self.dataStorage.get(element, 'onData');
var code = self.dataStorage.get(element, 'code') || '';
//var item = $(element).data('onData');
//var code = $(element).data('code');
//var value = String($(element).data('value'));
//var selector = $(element).data('selector');
//var value = String(self.dataStorage.get(element, 'value'));
var value = element.getAttribute('data-value');
//var selector = element.getAttribute('data-selector');
var selector = self.elementToSelector(element); // 1.0.12
/* self.log('value');
self.log(value);
self.log('args');
self.log(args); */
var eventType = (event.type && item.on) ? item.on[event.type] : undefined;
/* self.log('onEvent');
self.log('item');
self.log(item);
self.log('selector');
self.log(selector);
self.log('event.type');
self.log(event.type); */
/*
if (event) {
args = {
value: value,
event: eventType
}
}
*/
/* self.log('event.type');
self.log(event.type);
self.log('event');
self.log(event); */
var action, specialKey;
if (item.on) {
if (event.button == '2' && event.type == 'mousedown') { // right click / long touch
if (item.on['contextmenu'])
action = item.on['contextmenu'];
} else if (event.type && item.on[event.type]) {
var eventAction = item.on[event.type];
//const specialKeys = ['shiftKey', 'altKey', 'cmdKey'];
if (eventAction) {
if (eventAction.shiftKey && event.shiftKey) {
specialKey = 'shiftKey';
action = eventAction.shiftKey;
} else if (eventAction.altKey && event.altKey) {
specialKey = 'altKey';
action = eventAction.altKey;
} else if (eventAction.cmdKey && event.cmdKey) {
specialKey = 'cmdKey';
action = eventAction.cmdKey;
} else if (!eventAction.shiftKey && !eventAction.altKey && !eventAction.cmdKey) {
action = item.on[event.type];
}
}
}
}
if (action) {
//console.dir(action);
//action = self.replaceProperty(action, '{on:target}', targetId);
if (event.target) {
//self.log(event);
var actionString;
var targetId = event.target.id;
var targetClass = event.target.className;
var targetValue = event.target.dataset.value;
var targetSelector = event.target.dataset.selector; // deprecated
/* self.log('event');
self.log(event); */
//if (targetValue) alert(targetValue);
targetSelector = self.replaceAll(targetSelector, '"', '\''); // TO DO: if JSON5?
action = self.stringify(action);
if (typeof targetId !== 'string') targetId = '';
if (typeof targetClass !== 'string') targetClass = '';
/* actionString = self.replaceAll(action, '{event.target.id}', targetId);
actionString = self.replaceAll(actionString, '{event.altKey}', event.altKey);
actionString = self.replaceAll(actionString, '{event.target.className}', targetClass);
actionString = self.replaceAll(actionString, '{event.target.data-value}', targetValue); // obsolete
actionString = self.replaceAll(actionString, '{event.target.dataset.value}', targetValue);
actionString = self.replaceAll(actionString, '{event.target.dataset.selector}', targetSelector); */
actionString = self.replaceAll(action, '{on:target.id}', targetId);
actionString = self.replaceAll(actionString, '{on:altKey}', event.altKey);
actionString = self.replaceAll(actionString, '{on:target.className}', targetClass);
actionString = self.replaceAll(actionString, '{on:target.data-value}', targetValue); // obsolete
actionString = self.replaceAll(actionString, '{on:target.dataset.value}', targetValue);
actionString = self.replaceAll(actionString, '{on:target.dataset.selector}', targetSelector); // deprecated
actionString = self.replaceAll(actionString, '{on:which}', event.which);
actionString = self.replaceAll(actionString, '{on:clientY}', event.clientY);
actionString = self.replaceAll(actionString, '{on:clientX}', event.clientX);
// custom
actionString = self.replaceAll(actionString, '{on:value}', targetValue);
actionString = self.replaceAll(actionString, '{on:dragging}', (event.which > 0));
//actionString = self.replaceProperty(actionString, 'on', event);
if (this.isJson(actionString))
action = self.parse(actionString);
else
action = actionString;
}
// TODO: let decide to the user the parameter to pass
var args = item.args; // || item.params || item.value || value;
//args.event = event;
//if (args)
// action = self.replaceResult(action, args);
let specialKeyLog = (specialKey) ? ' + ' + specialKey : '';
//self.log('event ' + event.type + specialKeyLog);
//self.log('action');
//self.log(action);
/* self.log('args');
self.log(args);
self.log('{container: selector}');
self.log({container: selector}); */
//self.do(action, args, {selector: selector}); // TO DO: only if mouse over or
self.do(action, { selector: selector }, args);
} // (action)
};
this.pluginsFunctionAvailable = []; // should use pluginsLoaded
self.pluginsLoader = function (packs, callback, params) {
/* self.log('pluginsLoader');
self.log('packs');
self.log(packs);
self.log('callback');
self.log(callback);
self.log('params');
self.log(params); */
//self.pluginsFunctionAvailable.push(name); // posizione giusta
var filesToLoad = [];
for (pack of packs) {
/* self.log('pack');
self.log(pack); */
if (self.pluginsLoaded[pack.name] == undefined) {
self.log('require plugin ' + pack.name, 'grey');
var plugin = self.findPlugin(pack.name);
let version;
var pluginsFiles;
if (plugin) {
pluginsFiles = plugin.files || plugin;
version = plugin.version;
} else {
pluginsFiles = self.json.resources.pluginsFiles[pack.name]; // TO DO: obsolete, remove
version = pack.version;
}
/* if (params) {
if (!Array.isArray(params[0])) params[0] = [params[0]];
if (!self.pluginsCallbacks[pack.name]) self.pluginsCallbacks[pack.name] = [];
self.pluginsCallbacks[pack.name].concat(params[0]);
} */
self.pluginsLoaded[pack.name] = version; // should contain the queue of actions to do after the plugin loads
// TO DO: move in Promise.all(promises).then(function() {
// it needs to feed a queue of actions to do after the plugin loads
if (!Array.isArray(pluginsFiles)) // multi-file plugin
pluginsFiles = [pluginsFiles];
/* self.log('pluginsFiles');
self.log(pluginsFiles); */
for (item of pluginsFiles) {
var url = self.replaceAll(item.url, '{version}', version);
if (!self.findUrl(filesToLoad, url)) // not included yet
filesToLoad.push({ name: item.name, url: url, type: item.type });
}
}
}
//self.log(filesToLoad);
if (filesToLoad.length > 0) {
let promises = [];
filesToLoad.forEach(function (item) {
promises.push(loadPlugin({ name: item.name, url: item.url, type: item.type, rel: item.rel, as: item.as, content: item.content }));
//promises.push(loadPlugin(url));
});
Promise.all(promises).then(function (files) {
// all filesToLoad are loaded (all the Promise in loadPlugin are solved)
/* self.log('all plugin files are loaded');
self.log(files);
self.log(params); */
callback(...params); // change with ...
//callback(params[0], params[1], params[2]); // change with ...
}).catch(function (script) {
self.log('failed to load error');
self.log(item);
self.log(script);
});
}
};
this.pluginsRequired = function (params) {
/* self.log('pluginsRequired');
self.log(params); */
// analize function object or array of objects
if (self.json.resources) {
const pluginsFunctions = self.json.resources.pluginsFunctions;
var pluginsRequired = [];
if (typeof params == 'string') {
/* self.log('params');
self.log(params); */
if (pluginsFunctions[params]) {
if (!self.pluginsLoaded[pluginsFunctions[params].name])
pluginsRequired.push(pluginsFunctions[params]);
}
} else if (typeof params == 'object') {
var objArray;
if (Array.isArray(params)) objArray = params; else objArray = [params];
/* self.log('objArray');
self.log(objArray); */
for (var obj of objArray) {
/* self.log('obj');
self.log(obj); */
for (var key in obj) {
var mainFunction = (key.indexOf('.') >= 0) ? key.substr(0, key.indexOf('.')) : key;
//self.log('mainFunction');
//self.log(mainFunction);
if (pluginsFunctions[mainFunction]) {
if (!self.pluginsLoaded[pluginsFunctions[mainFunction].name])
pluginsRequired.push(pluginsFunctions[mainFunction]);
} /* else if (key == 'var') {
const functionName = self.functionName(obj.var.value);
if (functionName) {
if (!self.pluginsLoaded[pluginsFunctions[functionName].name])
pluginsRequired.push(pluginsFunctions[functionName]);
}
} */
}
}
}
return pluginsRequired;
} else {
return [];
}
};
this.functionName = function (obj) {
if (obj == 'object') {
const name = Object.keys(obj)[0];
const pluginFunctions = ['database', 'ace', 'moment', 'dayjs'];
if (pluginFunctions.indexOf(name) >= 0)
return name;
}
};
/*
this.runParts = function (actionObj, container, argumentsPar, handleOtherActions) {
console.log('runParts');
console.log(actionObj);
if (Array.isArray(actionObj)) {
for (var action in actionObj)
self.runParts(action);
} else {
var otherMethods = false;
var otherActions = {};
for (var partKey in actionObj) {
if (partKey.startsWith('var ') || partKey.startsWith('data ') || partKey.startsWith('set '))
self.setData({path: partKey, value: actionObj[partKey]});
else {
var methodOrPart = false;
var method = self.element({path: partKey, root: self.methods});
if (method) { // search in jsonic.methods
methodOrPart = true;
if (typeof method == 'function') {
//self.docElement(actionObj[partKey]);
self.log('method: ' + partKey);
method(actionObj[partKey], container, argumentsPar);
}
} else if (self.json.parts) { // search in self.json.parts
var part = self.element({path: 'parts.'+self.replaceAll(partKey,':','.')});
if (part) {
part = self.replaceProperty(part, 'arg', actionObj[partKey]);
if (actionObj[partKey].setup)
part = self.replaceProperty(part, 'setup', actionObj[partKey].setup);
console.log('part');
console.log(part);
self.run(part, container);
methodOrPart = true; // if (!actionFound) { will go in the else (!part)
}
}
if (!methodOrPart) otherActions[partKey] = actionObj[partKey];
else otherMethods = true;
}
}
//if (handleOtherActions) handleOtherActions(otherActions, container, argumentsPar);
return otherMethods;
}
}
*/
/* this.jsonicMethods = function (actions, container, argumentsPar) {
// 'icons' should be removed from the json files
var withContainer;
var functionFound = false;
for (var actionKey in actions) {
//if (nodes.functions.indexOf(actionKey) >= 0) {
switch (actionKey) {
case 'for':
case 'editor':
case 'ace':
case 'code':
case 'qrcode':
case 'lottie':
case 'animate':
case 'html':
case 'hide':
case 'show':
case 'toggle':
case 'in':
case 'out':
case 'if':
case 'ajax':
case 'attr':
case 'run':
case 'delay':
case 'css': withContainer = true; break;
default: withContainer = false;
}
var functionObj = actions[actionKey];
if (functionObj) {
functionFound = true;
if ((functionObj.if == undefined) || self.if(functionObj.if, container, argumentsPar)) {
return self.doFunction({
name: nodes.functions[actionKey],
function: functionObj,
args: argumentsPar,
selector: container,
withContainer: withContainer
});
} else {
if (functionObj.if !== undefined) {
self.log(self.js(functionObj.if, argumentsPar));
}
}
} else if (nodes.params.indexOf(actionKey) < 0)
return self.method(actions[actionKey], argumentsPar);
}
} */
/* this.do = function (actionPar, argumentsPar, selectorParams) { // ex this.action
if (actionPar !== undefined && actionPar !== null) { // !== undefined
// check plugins required
let pluginsRequired = self.pluginsRequired(actionPar);
if (pluginsRequired.length > 0) {
let params = [actionPar, argumentsPar, selectorParams];
self.pluginsLoader(pluginsRequired, self.do, params);
} else {
if (Array.isArray(actionPar)) {
if (actionPar.length > 0) {
var actionArray = [];
for (var index in actionPar)
if (typeof actionPar[index] == 'object')
actionArray[index] = self.cloneObject(actionPar[index]);
else
actionArray[index] = actionPar[index];
//actionArray = actionArray.concat(actionPar);
//actionArray = self.cloneObject(actionPar);
var actionFunction = actionArray.shift();
self.do(actionFunction, argumentsPar, selectorParams);
if (actionArray.length > 0)
self.do(actionArray, argumentsPar, selectorParams);
}
} else {
if (typeof actionPar == 'function') {
return actionPar(argumentsPar);
} else if (typeof actionPar == 'string') {
var actionPart = self.element({path: 'parts.' + actionPar}); // it includes replaceProperties
self.log('actionPar stringa');
self.log(actionPar);
if (actionPart)
return self.do(actionPart, argumentsPar);
//else if (json.actions[actionPar]) // obsolete
// return self.do(json.actions[actionPar], argumentsPar);
else
return actionPar; //return self.js(actionPar); // TO DO: finisce qui anche una stringa di un tag p ("p": "string")
} else if (typeof actionPar == "object") {
var actionObj = actionPar;
var container = actionObj.selector || actionObj.container || selectorParams;
// events
if (actionObj.on) {self.on(actionObj.on, container);}
if (self.notEmptyObject(actionObj)) {
var actionFound = self.runParts(actionObj, container, argumentsPar, self.jsonicMethods);
if (!actionFound) {
var functionFound = false;
for (var index in nodes.functions) {
//if (nodes.params.indexOf(actionKey) < 0)
//var action = Object.keys(actionObj)[0];
var withContainer = (nodes.functionsWithContainer.indexOf(nodes.functions[index]) >=0 );
var functionObj = actionObj[nodes.functions[index]];
if (functionObj) {
functionFound = true;
if ((functionObj.if == undefined) || self.if(functionObj.if, container, argumentsPar)) {
//if ((functionObj.if == undefined) || Boolean(self.js(functionObj.if, argumentsPar))) {
return self.doFunction({
name: nodes.functions[index],
function: functionObj,
args: argumentsPar,
selector: selectorParams,
withContainer: withContainer
});
} else {
if (functionObj.if !== undefined) {
self.log(self.js(functionObj.if, argumentsPar));
}
}
}
}
if (!functionFound) {
self.log('actionPar');
self.log(actionPar);
self.log('!functionFound');
self.log(actionObj);
return self.method(actionObj, argumentsPar);
}
}
}
} else {
//self.log('Function not found');
//self.log(actionPar);
//self.log(argumentsPar);
return actionPar;
// functions from this.do
//actionPar(argumentsPar);
}
}
}
} else {
// TO DO: check
//self.log('function with actionPar undefined');
}
}
*/
/* this.jsonicMethod2 = function (actionObj, selectorParams, argumentsPar) {
var functionFound = false;
for (var action in actionObj) {
var functionObj = actionObj[action];
if (functionObj) {
var withContainer = (nodes.functionsWithContainer.indexOf(action) >=0 );
functionFound = true;
if ((functionObj.if == undefined) || Boolean(self.js(functionObj.if, argumentsPar))) {
return self.doFunction({
name: action,
function: functionObj,
args: argumentsPar,
selector: selectorParams,
withContainer: withContainer
});
}
}
if (!functionFound) {
self.log('!functionFound');
self.log('actionObj');
self.log(actionObj);
return self.method(actionObj, argumentsPar);
}
}
} */
this.for = function (params, selectorParams, args) {
/* self.log('for');
self.log(params); */
let container = self.selector(params.selector || params.container) || self.selector(selectorParams);
// TO DO: doesn't go as an automous function (needs to be inside a div)
/* self.log('for');
self.log('container');
self.log(container); */
//if (params.html) { // new version
let itemsName = params.id || params.name;
//self.log('itemsArray');
//self.log(itemsArray);
/* if (params.reverse) {
var itemsReversed = {};
for (var key in Object(itemsArray).keys().reverse()) {
itemsReversed[key] = itemsArray[key];
}
itemsArray = itemsReversed;
} */
if (params.of) {
//var itemsArray = self.cloneObject(params.of); // value is the previous array id
//if (typeof itemsArray == 'string')
//itemsArray = self.compile(itemsArray, args); // compile includes functions and create bugs
//self.log('params.of');
//self.log(params.of);
var itemsArray = self.replaceProperties(params.of, args);
/* self.log('itemsArray');
self.log(itemsArray); */
/* if (typeof itemsArray == 'string') {
itemsArray = self.js(itemsArray); // TO DO: check
} */
if (itemsArray) {
/* if (typeof itemsArray == 'string') {
if (itemsArray.startsWith('js:')) itemsArray = self.js(itemsArray.substr(3));
//else itemsArray = self.replaceProperties(itemsArray, args);
} */
/* else {
itemsArray = self.actionResult(itemsArray, args);
itemsArray = self.replaceProperties(itemsArray, args);
} */
/* self.log('itemsArray replaced');
self.log(itemsArray); */
/* self.log('for'); */
/* self.log(itemsName); */
/* self.log(itemsArray); */
if (params.html) { // 1.0.6 html in for is deprecated
if (!params.do) params.do = [];
else if (!Array.isArray(params.do)) params.do = [params.do];
params.do.push({ html: params.html });
}
//delete params; // needed to avoid infinite loop
if (typeof itemsArray == 'object') {
let indexNum = 0;
for (var index in itemsArray) {
var item = itemsArray[index];
if (typeof item == 'object') {
item.key = index; // obsolete
item.index = index; // obsolete
}
if (typeof item.output == 'object') { // TO DO: obsolete
/* self.log('item.for.output');
self.log(item.for.output); */
for (let key in item.output) {
var output = item.output[key];
if (typeof output == 'string') {
output = self.js(output, args);
} else if (typeof output == 'object') {
//output = self.compile(output, args);
output = self.replaceProperties(output, args);
}
item = self.replaceItems(item, output, key); // replace
//item = self.replaceProperty(item, key, output);
}
}
if (params.do.length > 0) {
//alert(JSON.stringify(params.do));
//self.do(self.replaceProperty(params.do, itemsName, item), undefined, {selector: container});
//let objWithIndex = self.replaceStringInObject(params.do, '{' + params.index + '}', index);
let objWithIndex = params.do;
if (params.var) { // TO DO: obsolete (remove when used)
self.element({ path: params.var, value: item, root: self.json.var });
objWithIndex = self.replacePropertyWithPrefix(objWithIndex, 'index:' + params.var, index);
//objWithIndex = self.replaceStringInObject(objWithIndex, '{index:'+params.var+'}', index);
}
if (itemsName) {
//objWithIndex = self.replaceStringInObject(objWithIndex, '{index:'+itemsName+'}', index);
objWithIndex = self.replacePropertyWithPrefix(objWithIndex, 'index:' + itemsName, index);
objWithIndex = self.replacePropertyWithPrefix(objWithIndex, itemsName, item);
//objWithIndex = self.replaceProperty(objWithIndex, 'value:'+itemsName, item);
//objWithIndex = self.replaceProperty(objWithIndex, itemsName, item); // obsolete
}
if (params.delay) {
params.delay = self.replaceProperties(params.delay);
let forId = params.var || itemsName;
self.timer({
name: 't' + forId + index,
after: indexNum * params.delay,
do: objWithIndex
});
} else {
self.do(objWithIndex, { selector: container });
}
}
/* if (params.html) { // should be inside a do // commented from 1.0.6
let indexName = params.index || 'index';
let objWithIndex = self.replaceStringInObject(params.html, '{'+indexName+':'+itemsName+'}', index);
objWithIndex = self.replaceProperty(objWithIndex, itemsName, item);
self.do(objWithIndex, {selector: container});
} */
indexNum += 1;
}
}
}
} else if (params.from !== undefined && params.to !== undefined) {
/* var step = Number(params.step) || 1;
var from = Number(params.from) || 0;
var to = Number(params.to); */
var step = self.js(self.replaceProperties(params.step)) || 1;
var from = self.js(self.replaceProperties(params.from)) || 0;
var to = self.js(self.replaceProperties(params.to));
/* var step = Number(self.replaceProperties(params.step)) || 1;
var from = Number(self.replaceProperties(params.from)) || 0;
var to = Number(self.replaceProperties(params.to)); */
/* self.log('from');
self.log(from);
self.log('to');
self.log(to);
self.log('step');
self.log(step); */
if (to !== undefined) {
for (var index = Number(from); index <= Number(to); index += Number(step)) {
if (params.var)
self.element({ path: params.var, value: index, root: self.json.var });
// TO DO: find "if (params.html) { // 1.0.6" and modify also the following code
var item = self.replaceItems(params, String(index), itemsName); // obsolete: replaced with {index:itemsName}
//var item = self.replaceProperty(params, itemsName, String(index));
/* self.log('itemsName');
self.log(itemsName);
self.log('index');
self.log(index);
self.log('item');
self.log(item); */
if (item.output && typeof item.output == 'object') { //} !== undefined) {
/* self.log('item.for.output');
self.log(item.for.output); */
for (let key in item.output) {
var output = item.output[key];
if (typeof output == 'string') {
output = self.js(output, args);
} else if (typeof output == 'object') {
//output = self.compile(output, args);
output = self.replaceProperties(output, args);
}
item = self.replaceItems(item, output, key);
//item = self.replaceProperty(item, key, output);
}
}
// item = self.replaceItems(item, itemValue, itemsName); old version
//delete item.for; // needed to avoid infinite loop
if (item.do) {
params.do = self.replacePropertyWithPrefix(item.do, 'index:' + itemsName, index);
//params.do = self.replaceStringInObject(item.do, '{index:'+itemsName+'}', index);
self.do(item.do, selectorParams, args); // return?
//self.do(item.do, args, selectorParams); // return?
}
if (item.html) {
//params.html = self.replaceStringInObject(item.html, '{index:'+itemsName+'}', index);
params.html = self.replacePropertyWithPrefix(item.html, 'index:' + itemsName, index);
self.html(item.html, selectorParams);
}
}
}
} else {
self.log('"for" element requires "value" or "from" and "to" parameters'); // link to see the documentation
self.log(params);
}
//}
// }
};
this.htmlTag = function (params, selectorParams, tagParam, mainParam) {
/* self.log('htmlTag');
self.log(tagParam); */
if (Array.isArray(params)) {
for (var index in params)
self.htmlTag(params[index], selectorParams, tagParam, mainParam);
} else {
//----------------------------------
// attributes of the tag in the key
// example: "div id=btn btn"
// (classes are without identifier)
//----------------------------------
let htmlTagSplitter = tagParam.indexOf(' ');
if (htmlTagSplitter > 0) {
let tagClass = tagParam.substr(htmlTagSplitter + 1);
tagParam = tagParam.slice(0, htmlTagSplitter);
if (tagClass) {
if (typeof params !== 'object') params = { 'text': String(params) };
if (!params.attr) params.attr = {};
// attributes in key: attribute=value
let tagArr = tagClass.split(' ');
var attrClass = '';
for (let tagProp of tagArr) {
let tagAttr = new RegExp("([_a-zA-Z]+[_a-zA-Z0-9-]*)=(.+)"); // [_a-zA-Z0-9-/]
if (tagAttr.test(tagProp)) {
//console.log('attribute found '+tagProp);
let tagPropArr = tagProp.split('=');
params.attr[tagPropArr[0]] = tagPropArr[1];
} else {
attrClass += ' ' + tagProp;
}
}
// classes
if (params.attr.class)
params.attr.class = params.attr.class + attrClass;
else {
params.attr.class = attrClass;
}
//alert(tagParam + '/'+ tagClass+ '#');
}
}
let htmlTagObj = self.createTagParams(params, tagParam, mainParam);
self.do(htmlTagObj, selectorParams);
if (params.database) self.addFirebaseTag(self.extend({}, params, selectorParams));
}
};
this.createTagParams = function (params, tagParam, mainParam) {
if (!mainParam) {
switch (tagParam) {
case 'header':
case 'main':
case 'footer':
case 'div':
case 'p':
mainParam = 'html';
break;
case 'img':
mainParam = 'src';
break;
default:
mainParam = 'text'; // TO DO: -> html (to test with actual apps)
break;
}
}
var paramsObj = {};
if (typeof params == 'string') paramsObj[mainParam] = params; else paramsObj = params;
paramsObj.tag = tagParam;
return paramsObj;
};
this.onResize = [];
this.onHashChange = [];
this.onScroll = [];
//let swup;
this.notEmptyObject = function (obj) {
return (obj // null and undefined check
&& Object.keys(obj).length > 0);
// && Object.getPrototypeOf(obj) === Object.prototype
// https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object
};
this.run = function (params, selectorParams, args) {
/* self.log('run');
self.log(params); */
if (Array.isArray(params)) {
for (var index in params)
self.run(params[index], selectorParams, args);
} else {
var codeToRun;
if (typeof params == 'object')
codeToRun = self.cloneObject(params);
else if (typeof params == 'string')
codeToRun = self.replaceProperties(params);
else if (typeof params == 'function')
return params(args);
else
return params;
/* self.log('codeToRun');
self.log(codeToRun); */
if (typeof codeToRun == 'object') {
var selector = codeToRun.selector || codeToRun.container;
if (!selector) selector = selectorParams;
if (typeof selector == 'string') selector = { selector: selector };
var actions = {};
for (key in codeToRun) {
if (nodes.extend.indexOf(key) >= 0) {
var obj = {};
obj[key] = codeToRun[key];
self.extendJson(self.json, obj);
} else if (['setup', 'container', 'selector', 'resources', 'on', 'do'].indexOf(key) < 0)
actions[key] = codeToRun[key];
}
/* self.log('codeToRun.on');
self.log(codeToRun.on);
self.log('selector');
self.log(selector); */
// actions
//if (codeToRun.container) {self.empty(codeToRun.container);} // reset
// .in SIGNIFICA CONTENITORE (select)
if (codeToRun.on) { self.on(codeToRun.on, selector); }
if (codeToRun.do) { self.do(codeToRun.do, selector, args); }
if (self.notEmptyObject(actions)) {
/* self.log('notEmptyObject actions');
self.log(actions);
self.log('selector');
self.log(selector); */
return self.do(actions, selector, args);
//return self.do(actions, args, codeToRun.in);
}
}
}
//self.extendJsonFromElement(codeToRun); // style, actions, texts, data, var. no setup, on, do, blocks, container
};
/*
this.execute = function (params, selectorParams, args) { // obsolete
// should create a new jsonicApp instance and assign it to jsonic[id]
// jsonicApp should load the plugins required and not are already loaded
// jsonicApp should import the json not already imported
// jsonicApp should load the icons not already loaded
// jsonicApp should init the database if not already initialized
// otherwise should copy the db object from window.jsonic?
// to have app relative var and data these should be called as var:clock.... / var:calendar....
// or each app should have an ID (without id the ID is "app")
// to have exclusive setup, var, data/items, pages and to reset var on the second execution
// for example: window.jsonic['container'] = new jsonicObject(options);
self.log('execute');
if (params) {
if (params.do == 'init') {
self.log('init');
window.removeEventListener('hashchange');
window.removeEventListener('resize');
window.removeEventListener('beforeinstallprompt');
// PWA
if ('serviceWorker' in navigator) {
// Register a service worker hosted at the root of the
// site using the default scope.
navigator.serviceWorker.register('/app/assets/pwa/sw.js').then(function(registration) {
self.log('Service worker registration succeeded:', registration);
}, function(error) {
self.log('Service worker registration failed:', error);
});
} else {
self.log('Service workers are not supported.');
}
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
// Prevent Chrome 67 and earlier from automatically showing the prompt
e.preventDefault();
// Stash the event so it can be triggered later.
deferredPrompt = e;
});
self.json.setup.page.hash = window.location.hash.substr(1);
// we consider json.setup.modules instead of self.modules
// to be sure to follow the right order of execution
var modules = []; // we need it to keep the order of the modules given in the setup
for (key in json.setup.modules) {
var mod = self.replaceProperties(json.setup.modules[key]);
modules = modules.concat(self.cloneObject(mod));
}
//modules.push({name: 'ide', url: 'https://jsonic.io/app/modules/ide.json'}); // TO DO if admin
// or can execute global before all the rest
// modules can contain {libs and apps}
// ide module can be loaded only if required
for (var mod of modules) {
//self.log(mod.name);
var params = self.modules[mod.name];
//self.log(params);
if (params.html) {
var container = selectorParams || 'body';
//if (params.app.html) {
//var documentTitle = self.json.setup.title;
//if (documentTitle)
// document.title = documentTitle;
//if (document.querySelector('meta[name="description"]'))
// document.querySelector('meta[name="description"]').setAttribute("content", documentDescription);
self.html(params.html, {container: container});
// window events
//}
}
if (params.on) { // -> this.on
// hashchange
if (params.on.hashchange) {
self.onHashChange.push(params.on.hashchange);
window.addEventListener('hashchange', function() {
self.json.setup.page.hash = window.location.hash.substr(1); // potrebbe essere esplicitato sulla app
//var action = self.cloneObject(params.app.on.hashchange);
//self.replaceAll("{result}", window.location.hash);
self.do(self.onHashChange);
self.uiUpdate();
});
}
// resize
window.addEventListener('resize', self.resizeEvent);
if (params.on.resize) {
self.onResize.push(params.on.resize);
window.addEventListener('resize', function () {
self.do(self.onResize);
});
}
// receiveMessage
if (params.on.thunkable && params.on.thunkable.receiveMessage)
window.receiveMessage(function (message) {
//document.querySelector('#message').value = message;
jsonic.functions(params.on.thunkable.receiveMessage, message, undefined);
});
self.on(params.on, {container: container}); // init included
}
//else
//self.log('The node "app" requires "container" and "html" properties');
}
} else {
//if (params.setup) args = self.extend(args, params.setup); // or params.args?
if (params.blocks) self.extendJson(json, {blocks: params.blocks});
//if (params.library) self.extendJson(json, {library: params.library}); // obsolete
if (params.media) self.extendJson(json, {media: params.media}); // obsolete
if (params.functions) self.extendJson(json, {functions: params.functions}); // obsolete
if (params.actions) self.extendJson(json, {actions: params.actions});
if (params.css) self.extendJson(json, {css: params.css});
//if (params.styles) self.extendJson(json, {styles: params.styles});
//if (params.iconset) self.extendJson(json, {iconset: params.iconset});
if (params.data) self.extendJson(json, {data: params.data});
if (params.items) self.extendJson(json, {items: params.items});
if (params.var) self.extendJson(json, {var: params.var});
if (params.html) {
var container = selectorParams || 'body'; // is an object
if (typeof container == 'string')
container = {container: container};
//if (self.inputValue({id: 'module'}) == 'base') {
// icons will be obsolete
//} else {
//var setup = extendParams.setup || params.setup;
//if (container || html.container) {
//if (params.app.html) {
var code = self.cloneObject(params.html);
//self.log('code');
//self.log(code);
//self.log(JSON.stringify(code));
self.html(code, container);
//}
//} else {
// self.log('execute method requires container parameter');
//}
if (params.on && params.on.init) {
self.do(params.on.init, undefined, container);
}
// args can be params.setup
//}
} else if (params.module) {
var moduleId = self.replaceProperties(params.module);
return self.do(self.modules[moduleId]);
}
}
}
} */
/* this.createApp = function (data) {
self.log('createApp');
//self.log(self.modules);
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
// Prevent Chrome 67 and earlier from automatically showing the prompt
e.preventDefault();
// Stash the event so it can be triggered later.
deferredPrompt = e;
});
self.json.setup.page.hash = window.location.hash.substr(1);
for (var file in self.modules) {
var params = self.modules[file];
//if (params.on) self.extendJson(json, {media: params.media});
// if (params.icons) self.extendJson(json, {icons: params.icons});
//if (params.functions) self.extendJson(json, {functions: params.functions});
//if (params.styles) self.extendJson(json, {styles: params.styles});
//if (params.items) self.extendJson(json, {items: params.items});
//if (params.var) self.extendJson(json, {var: params.var});
//if (params.library) self.extendJson(json, {library: params.library});
if (params.app && params.app.container) {
//var documentTitle = self.json.setup.title;
//if (documentTitle)
// document.title = documentTitle;
//if (document.querySelector('meta[name="description"]'))
// document.querySelector('meta[name="description"]').setAttribute("content", documentDescription);
//alert(document.querySelector(params.app.container).isConnected);
self.html(params.app.html, {container: params.app.container});
// window events
if (params.app.on) { // -> this.on
// hashchange
if (params.app.on.hashchange) {
self.onHashChange.push(params.app.on.hashchange);
window.addEventListener('hashchange', function() {
self.json.setup.page.hash = window.location.hash.substr(1); // potrebbe essere esplicitato sulla app
//var action = self.cloneObject(params.app.on.hashchange);
//self.replaceAll("{result}", window.location.hash);
self.do(self.onHashChange);
self.uiUpdate();
});
}
// resize
window.addEventListener('resize', self.resizeEvent);
if (params.app.on.resize) {
self.onResize.push(params.app.on.resize);
window.addEventListener('resize', function () {
self.do(self.onResize);
});
}
// receiveMessage
if (params.app.on.thunkable && params.app.on.thunkable.receiveMessage)
window.receiveMessage(function (message) {
//document.querySelector('#message').value = message;
jsonic.functions(params.app.on.thunkable.receiveMessage, message, undefined);
});
// init
self.log('params.app.on');
self.log(params.app.on);
self.log('params.app.container');
self.log(params.app.container);
self.on(params.app.on, {container: params.app.container});
}
}
//else
//self.log('The node "app" requires the "container" property');
}
if (self.pluginsLoaded['swup'] && self.json.setup.swup) {
let swup = new Swup(self.json.setup.swup);
}
self.do(data);
} */
/* this.menuToggle = function () {
self.log('menuToggle');
//$('.offcanvas-collapse').toggleClass('open');
$('#header').toggleClass('headerMenuOpen');
var.menuOpen = (!var.menuOpen);
self.log(var.menuOpen);
}
this.menuOpen = function () {
self.log('menuOpen');
$('#menu').addClass('menuOpen');
var.menuOpen = true;
self.log(var.menuOpen);
}
this.menuClose = function () {
self.log('menuClose');
$('#menu').removeClass('menuOpen');
var.menuOpen = false;
self.log(var.menuOpen);
} */
/* this.createMenu = function (data) {
self.log('createMenu');
// self.userRole
var menuId = (typeof data.id == 'function') ? data.id() : data.id;
var container = data.container || '#header > ul';
$(container).empty();
for (var index in self.json.menu[menuId]) {
var selector = container + ' > li:eq(' + index + ')'; // > span';
var item = self.json.menu[menuId][index];
// action
//if (item.page && !item.action) item.action = {page: item.page};
if (!var.functions[container])
var.functions[container] = {};
var.functions[container][index] = item;
$(container).append('');
item.color = item.color || 'inherit';
item.background = item.background || 'transparent';
item.border = item.border || 'transparent';
self.tab(item, {container: selector});
}
self.do(data);
} */
/* this.changeMenu = function (menuId) {
}
*/
/* this.form = function (params, selectorParams) {
// replaceProperties può essere passato all'inizio di ogni costruttore
//params.container = params.container || self.selector(selectorParams);
//var selector = self.selector(params);
var container = params.container || self.selector(selectorParams);
//var elementContainer = self.query(container);
//var selector = self.selector(self.extend({}, params, selectorParams));
//var element = self.query(selector);
//params.tag = 'form';
//if (params.id === undefined) {params.id = '';}
//if (params.value === undefined) {params.value = ''};
//if (params.class === undefined) {params.class = ''};
//$(container).append('<'+params.tag+' id="'+params.id+'" class="'+params.class+'" data-value="'+params.value+'" data-selector="'+selector+'">'+params.tag+'>');
for (var itemKey in params.items) {
var item = params.items[itemKey];
self.html({
"form": {
"attr": {
"id": params.id,
"class": params.class,
"data-value": params.data-value || params.value
},
"div": [
{
"attr": {
"class": "form-group",
"data-value": itemKey
},
"html": [
{
"label": {
"attr": {
"for": itemKey,
"text": item.title
}
}
},
{
"input": {
"attr": {
"id": itemKey,
"class": "form-control",
"data-value": "formInput" + itemKey,
"value": item.inputValue,
"type": item.type,
"text": item.title,
"aria-describedby": "note"+itemKey,
"placeholder": "",
"disabled": disabled
}
}
},
{
"small": {
"attr": {
"class": "form-text text-muted",
"data-value": "formNote"+itemKey,
"text": item.note
}
}
},
]
}
]
}
}, {
container: container
});
}
} */
/* this.addList = function (params, selectorParams) {
var container = (selectorParams) ? self.selector(selectorParams) : params.container;
var selector = self.selector(self.extend({}, params, selectorParams));
if (params.id === undefined) {params.id = '';}
if (params.value === undefined) {params.value = ''};
if (params.class === undefined) {params.class = ''};
$(container).append('
');
self.list(params, {container: container});
} */
/*
this.addBlock = function (params, selectorParams) {
if (params.icons) self.icons(params.icons, selectorParams);
if (params.tab) self.tab(params.tab, selectorParams);
if (params.html) self.html(params.html, selectorParams);
if (params.div) self.div(params.div, selectorParams);
if (params.ul) self.ul(params.ul, selectorParams);
if (params.li) self.li(params.li, selectorParams);
if (params.span) self.span(params.span, selectorParams);
if (params.img) self.img(params.img, selectorParams);
if (params.form) self.form(params.form, selectorParams);
if (params.list) self.addList(params.list, selectorParams);
//if (params.img) alert(JSON.stringify(params.img.src));
}
*/
/* this.blocks = function (params, selectorParams, args) {
if (Array.isArray(params)) {
for (var index in params)
self.blocks(params[index], selectorParams, args);
} else {
if (typeof params == 'string') {
var blocksObj = self.get('self.json.library.'+params);
if (blocksObj)
self.blocks(blocksObj.blocks, selectorParams);
} else {
if (params.library) {
self.library(params.library, selectorParams, args); // {container: container}
} else {
self.addTag(params, selectorParams, args); // {container: container}
}
}
}
}
*/
this.inputValue = function (params) {
var selector = self.selector(params.selector || params.container);
var element = document.querySelector(selector); // self.query(p2);
return element.value;
};
/* this.layout = function (params, selectorParams, args) {
if (Array.isArray(params)) {
for (var index in params)
self.layout(params[index], selectorParams, args);
} else {
if (typeof params == 'string') {
var libraryObj = self.get('self.json.layouts.'+params); // todo: get?
//var libraryHtml = libraryObj.html || libraryObj.blocks;
if (libraryObj)
self.layout(libraryObj, selectorParams, args); // TODO warning potential infinite loop (if string)
else
self.log('"theme" not found: ' + params);
} else {
var libraryHtml = params.html;
// can a library component be an object?
if (params.setup) args = self.extend(args, params.setup); // or params.args?
if (params.functions) self.extendJson(json, {functions: params.functions});
if (params.css) self.extendJson(json, {css: params.css});
//if (params.styles) self.extendJson(json, {styles: params.styles});
if (params.items) self.extendJson(json, {items: params.items});
if (params.var) self.extendJson(json, {var: params.var});
self.html(libraryHtml, selectorParams, args); // {container: container}
//self.(params, selectorParams, args);
}
}
} */
this.part = this.block = function (params, selectorParams, args) {
let nested;
let part;
let partArguments;
if (typeof params.do == 'string' && self.json.parts) { // && par.match(/[.>]+/))
self.log('PART: ' + params.do, 'brown');
params.do = self.replaceProperties(params.do);
if (typeof params.do == 'object')
part = params.do;
else
part = self.element({ path: self.replaceAll(params.do, ':', '.'), root: self.json.parts }); // TO DO: . -> space?
/* if (par.indexOf(':')>0 && !part) {
self.firebaseGetPart({localPath:localPath, container: params.selector, arg:params.obj});
} */
} else if (typeof params.do == 'object')
part = params.do;
if (part) {
//if (!params.arguments) params.arguments = {};
// TO DO: Check this. seems a workaround for fantacards/ui:qrcode
if (params.arguments)
partArguments = self.replaceProperties(params.arguments);
if (typeof params.arguments == 'object') {
partArguments = (params.arguments.setup) ? params.arguments.setup : params.arguments; // compatibility
partArguments.selector = partArguments.selector || params.selector;
}
nested = self.replacePropertyWithPrefix(part, 'setup', partArguments); // {setup} -> {arguments}
nested = self.replacePropertyWithPrefix(nested, 'arguments', partArguments); // to tix
self.extendJsonFromElement(nested);
self.do(nested, params.selector, partArguments);
}
};
this.blocks = function (params, selectorParams, args) {
if (Array.isArray(params)) {
for (var index in params)
self.blocks(params[index], selectorParams, args);
} else {
//self.log('blocks');
//self.log(params);
if (typeof params == 'string') {
var blockName = self.replaceProperties(params, args); // self.compile(params, args);
//self.log('blockName');
//self.log(blockName);
var libraryObj = self.element({ path: 'self.json.blocks.' + blockName }); // todo: get?
//self.log('libraryObj');
//self.log(libraryObj);
//var libraryHtml = libraryObj.html || libraryObj.blocks;
if (libraryObj)
//self.html(libraryObj, selectorParams, args);
self.run(libraryObj, selectorParams, args);
//self.blocks(libraryObj, selectorParams, args); // TODO warning potential infinite loop (if string)
else
self.log('library component not found: ' + params);
} else {
self.run(params, selectorParams, args);
//self.run(params, selectorParams, args);
//var libraryHtml = params.html || params.app.html;
/* // can a library component be an object?
if (params.setup) args = self.extend(args, params.setup); // or params.args?
if (params.parts) self.extendJson(json, {parts: params.parts});
if (params.actions) self.extendJson(json, {actions: params.actions});
if (params.css) self.extendJson(json, {css: params.css});
if (params.data) self.extendJson(json, {data: params.data});
if (params.var) self.extendJson(json, {var: params.var});
if (params.texts) self.extendJson(json, {texts: params.texts});
self.html(params.html, selectorParams, args); // {container: container}
//self.do(params, selectorParams, args); */
}
}
};
this.uiUpdate = function (option) {
window.dispatchEvent(new Event('resize')); // workaround known ACE bug
//self.updateCodeEditors(); // workaround known ACE bug
};
this.resizeEvent = function (event) {
//self.log('resizeEvent');
for (var selector in self.resizeActions) {
var element = self.query(selector);
for (var property in self.resizeActions[selector]) {
if (property == 'action') {
self.do(self.resizeActions[element].action, { selector: selector });
//self.do(self.resizeActions[element].action, {selector: selector});
} else {
var value = self.resizeActions[selector][property];
var result = self.replaceProperties(value) || '';
//$(selector).css(property, result);
element.style[property] = result;
}
}
}
};
/* var pages = {};
var pagesSlider;
this.createPages = function (data) {
self.log('createPages');
//backLink = (self.json.setup && self.json.setup.home && self.json.setup.home[var.mode]) ? self.json.setup.home[var.mode] : '';
// class="container-fluid px-0" style="margin-top:'+self.json.setup.main.top+'"
var pageContainer = '#pages'; // 'main > div'
for (var pageKey in self.json.pages) {
params = self.json.pages[pageKey];
var pageRoles = (params.roles) ? String(params.roles).split(',') : undefined;
// se il ruolo dell'utente permette la vista della pagina e se non è stata già creata
if (!params.roles || (pageRoles.indexOf(self.userRole()) >= 0 && document.querySelectorAll('#'+pageKey).length == 0)) { // $('#'+pageKey).length == '#'+pageKey doesn't exist
//if (params.preload) {
params.tag = 'div';
//params.id = pageKey;
params.class = 'page';
params.value = pageKey;
// the previous definition should be in layout.page
self.addTag(params, {container: pageContainer});
//}
} else {
self.log('' + self.userRole() + ' users can\'t access to the page '+pageKey);
}
}
self.do(data);
} */
this.pageFullScreen = function (onOff) {
self.log('pageFullScreen');
if (onOff)
self.addClass(document.querySelector('body'), 'fullscreen');
else
self.removeClass(document.querySelector('body'), 'fullscreen');
};
//var backLink = 'stage';
/* this.pageBack = function () {
self.gotoPage(backLink);
//window.location.href = '?p='+backLink;
//$('body').removeClass('nav-open'); // chiude menu
} */
this.link = function (link, args) {
/* function link() {
[native code]
} */
//alert(link);
link = self.replaceProperties(link, args);
window.location.href = link;
};
this.reload = function () {
location.reload();
};
this.gotoHomePage = function () {
self.gotoPage(self.homePage());
};
this.homePage = function () {
//alert('homePage');
if (self.json.pages) {
if (Object.keys(self.json.pages).length > 0) {
//var homeKey = Object.keys(self.json.pages).find(key => self.json.pages[key] === 'home');
if (self.json.pages.home)
return 'home';
else
return Object.keys(self.json.pages)[0];
} else {
self.log('No pages in "pages" node');
}
} else {
self.log('Can\'t find the "pages" node');
}
};
/* this.activePage = function () { // to check if obsolete
return var.page;
} */
/* this.slideIndex = function (id) {
return $('#'+id).index()+1;
} */
/* this.slideTo = function (params) {
if (pagesSlider) pagesSlider.goTo(self.slideIndex(params.id));
$('#pages > .seq-canvas > .seq-in').addClass(params.transition);
} */
this.updateCodeEditors = function () {
// workaround known ACE bug:
// setValue doesn't work if editor is hidden
// http://jsfiddle.net/e4r7byLn/
var elements = document.querySelectorAll('.ace_editor');
if (elements) {
elements.forEach(function (element, index) {
var editor = ace.edit(element);
editor.renderer.updateFull(true);
//AceColorPicker.load(ace, editor);
//AceColorPicker.load(ace, editor); // works after some ms
});
}
};
this.gotoPage = function (pageId, fromHash) {
self.log('page'); // changePage
self.log('pageId');
self.log(pageId);
self.log('fromHash');
self.log(fromHash);
//self.log("var.page");
//self.log(var.page);
if (pageId) {
if (self.json.pages) {
if (self.json.pages[pageId]) {
var page = self.json.pages[pageId];
if (pageId !== self.json.setup.page.id || fromHash !== self.json.setup.page.hash) {
if (fromHash) {
//var.pagePath = fromHash; // obsolete
self.json.setup.page.hash = fromHash;
} else {
//delete var.pagePath;
delete self.json.setup.page.hash;
}
//var.page = pageId; // activePage
//var newHash = pageId;
//if (!fromHash) window.location.hash = newHash;
var fullScreen = self.json.pages[pageId].fullscreen || false;
//self.pageFullScreen(fullScreen);
var pageRoles = (page.roles) ? String(page.roles).split(',') : undefined;
if (self.params.d || !page.roles || pageRoles.indexOf(self.userRole()) >= 0) {
if (pageId !== self.json.setup.page.id) {
/* self.out({
"class": "page",
"data-value": self.json.setup.page.id,
"transition": "fadeOutLeft"
}); */
self.json.setup.page.id = pageId;
self.json.setup.page.title = page.title;
self.json.setup.page.roles = page.roles;
/* // TO DO: don't change document title and description
// window title
var documentTitle = self.json.setup.title;
if (page.title)
documentTitle += ' ' + self.text(page.title);
var documentDescription = self.json.setup.description || '';
if (documentTitle)
document.title = documentTitle;
if (document.querySelector('meta[name="description"]'))
document.querySelector('meta[name="description"]').setAttribute("content", documentDescription); */
//$('title').text(windowTitle);
// change page
self.hide({
"class": "page"
});
self.in({
"class": "page",
"data-value": pageId,
"transition": "fadeIn"
});
/* $('.page').hide();
$('.page[data-value='+pageId+']').fadeIn(); */
//self.resizeEvent();
self.uiUpdate(); // resize event trigger
/* // page back icon
if (page.back) {
backLink = page.back;
$('#headerLeftIcons').show((page.back));
} else {
$('#headerLeftIcons').hide();
} */
}
if (page.update) { // obsolete
self.do(page.update); //, {container: '.page[data-value='+pageId+']'});
//self.do(page.update); //, {container: '.page[data-value='+pageId+']'});
}
if (page.init) self.do(page.init);
self.log(page);
if (page.on)
self.on(page.on, { selector: '.page[data-value=' + pageId + ']' });
//$('body').removeClass('nav-open'); // chiude menu
//$('.offcanvas-collapse').removeClass('open');
} else {
if (self.userRole() == 'guest') {
/* self.do({
"login": {
"success": {
"reload": true
}
}
}); */
} else {
self.alert('Non hai i privilegi per accedere a questa pagina');
}
}
} else {
// pagina non trovata
}
} else {
self.log('Can\'t find the page "' + pageId + '"');
}
} else {
self.log('Can\'t find the main node "pages"');
}
} else {
return self.json.setup.page;
}
};
var alertInterval;
this.getTime = function (ms) {
var sec = parseInt(ms / 1000);
var min = parseInt(sec / 60);
sec = sec - min * 60;
if (min < 10) min = '0' + min;
if (sec < 10) sec = '0' + sec;
return min + ':' + sec;
};
this.sortablejs = function (params, selectorParams, args) {
let container = self.selector(params.selector || params.container, undefined, true) || self.selector(selectorParams, undefined, true);
let query = self.query(container);
self.log('container');
self.log(container);
self.log('query');
self.log(query);
var sortable = Sortable.create(query);
};
this.alert = function (params, args) {
/* self.log('alert');
self.log('params');
self.log(params);
self.log('args');
self.log(args); */
var paramsReplaced = self.cloneObject(params);
//paramsReplaced = self.replaceProperties(paramsReplaced, args);
//self.log('paramsReplaced');
//self.log(paramsReplaced);
if (paramsReplaced) {
if (paramsReplaced.do && paramsReplaced.do !== 'fire') {
return Swal[paramsReplaced.do](params);
// more info on https://sweetalert2.github.io/#methods
} else {
if (typeof paramsReplaced == 'string') paramsReplaced = self.text({ string: paramsReplaced, args: args }); // verify
//self.log('paramsReplaced string replaced');
//self.log(paramsReplaced);
if (typeof paramsReplaced == 'number') paramsReplaced = String(paramsReplaced); // avoid bug
if (paramsReplaced.title !== undefined) paramsReplaced.title = self.text({ string: paramsReplaced.title, args: args });
//self.log('paramsReplaced2');
//self.log(paramsReplaced);
if (paramsReplaced.html && typeof paramsReplaced.html == 'string') paramsReplaced.html = self.replaceProperties(paramsReplaced.html, args);
if (paramsReplaced.text !== undefined) paramsReplaced.text = self.text({ string: paramsReplaced.text, args: args });
//self.log('paramsReplaced string replaced 2');
if (paramsReplaced.inputValue) paramsReplaced.inputValue = self.text({ string: paramsReplaced.inputValue, args: args });
//if (paramsReplaced.html) paramsReplaced.html = self.text({string: paramsReplaced.html, args: args}); // verify
if (paramsReplaced.cancelButtonText) paramsReplaced.cancelButtonText = self.text({ string: paramsReplaced.cancelButtonText, args: args });
if (paramsReplaced.confirmButtonText) paramsReplaced.confirmButtonText = self.text({ string: paramsReplaced.confirmButtonText, args: args });
if (paramsReplaced.denyButtonText) paramsReplaced.denyButtonText = self.text({ string: paramsReplaced.denyButtonText, args: args });
//if (paramsReplaced.showConfirmButton) paramsReplaced.showConfirmButton = self.text({string: paramsReplaced.showConfirmButton, args: args});
if (paramsReplaced.inputPlaceholder) paramsReplaced.inputPlaceholder = self.text({ string: paramsReplaced.inputPlaceholder, args: args });
if (paramsReplaced.validationMessage) paramsReplaced.validationMessage = self.text({ string: paramsReplaced.validationMessage, args: args });
//if (paramsReplaced.inputOptions) paramsReplaced.inputOptions = self.text({string: paramsReplaced.inputOptions, args: args});
if (paramsReplaced.footer) {
paramsReplaced.footer = self.text({ string: paramsReplaced.footer, args: args });
}
//if (paramsReplaced.upload) alert('paramsReplaced.upload: '+paramsReplaced.upload);
if (paramsReplaced.upload) {
paramsReplaced.html = ' ';
//
//if (paramsReplaced.onUpload) var.onUpload = paramsReplaced.onUpload;
//var.uploadingTarget = paramsReplaced.uploadingTarget;
}
//self.log('paramsReplaced3');
//self.log(paramsReplaced);
alertObj.confirm = paramsReplaced.confirm; // deprecated
alertObj.cancel = paramsReplaced.cancel; // deprecated
alertObj.deny = paramsReplaced.deny; // deprecated
alertObj.on = paramsReplaced.on;
alertObj.id = paramsReplaced.id;
delete paramsReplaced.on;
var alertHtml = paramsReplaced.html || paramsReplaced.blocks;
if (alertHtml)
paramsReplaced.html = " ";
var swalParams = self.replaceProperties(paramsReplaced, args);
// animate
if (paramsReplaced.animate) {
var animationIn = paramsReplaced.animate.in || paramsReplaced.animate;
var animationOut = paramsReplaced.animate.out || paramsReplaced.animate;
if (paramsReplaced.animate.in)
animationIn = paramsReplaced.animate.in.transition || paramsReplaced.animate.in;
if (paramsReplaced.animate.out)
animationOut = paramsReplaced.animate.out.transition || paramsReplaced.animate.out;
swalParams.showClass = {
popup: 'animate__animated animate__faster animate__animated animate__' + animationIn
};
swalParams.hideClass = {
popup: 'animate__animated animate__faster animate__animated animate__' + animationOut
};
}
var customIcon;
if (swalParams.icon) {
//swalParams.icon = self.replaceProperties(swalParams.icon, args);
if (typeof swalParams.icon !== 'string') {
customIcon = self.cloneObject(swalParams.icon);
delete swalParams.icon;
}
/* var swalIcons = []; //"warning", "error", "success", "info", "question"];
if (swalIcons.indexOf(params.icon)<0) {
customIcon = params.icon;
//if (!params.customClass) params.customClass = {};
//params.customClass.icon = "customIcon";
} */
}
//if (swalParams.showConfirmButton) delete swalParams.showConfirmButton;
// swalParams.update = function() {
// self.log('swalParams.update');
// self.log(var.updateSwal);
// }
// onRender is obsolete
/* swalParams.onRender = function () {
startUploadListeners({
container: '.drop-zone',
onUpload: params.onUpload,
path: params.path
//uploadingTarget: var.uploadingTarget
//onError:
});
}
*/
delete swalParams.blocks;
delete swalParams.onUpload;
delete swalParams.upload;
if (swalParams.confirm) delete swalParams.confirm;
if (swalParams.cancel) delete swalParams.cancel;
if (swalParams.timerProgressBar) {
swalParams.onBeforeOpen = function () {
//Swal.showLoading(); // rimuove i bottoni
alertInterval = setInterval(() => {
const content = Swal.getContent();
if (content) {
const b = content.querySelector('b');
if (b) {
b.textContent = self.getTime(Swal.getTimerLeft());
}
}
}, 100);
};
swalParams.onClose = function () {
clearInterval(alertInterval);
};
}
//self.log('swalParams');
//self.log(swalParams);
Swal.fire(swalParams).then((result) => {
//self.log('alert result');
//self.log(result);
// TO DO: if (!result) result = {} to avoid errors
var alertResult = result.value;
if (alertObj.on) {
if (alertObj.on.value && result.value) {
//if (alertObj.id) alertObj.values[alertObj.id] = result.value;
if (alertObj.id) alertValues[alertObj.id] = result.value;
alertValues.value = result.value;
setTimeout(function () {
alertObj.on.value = self.replacePropertyWithPrefix(alertObj.on.value, 'alert', alertValues);
//alertObj.on.value = self.replaceProperty(alertObj.on.value, 'alert', result);
self.do(alertObj.on.value, undefined, result.value); // TO DO: remove result.value once removed all {result}
//self.do(alertObj.on.value, result.value); // TO DO: remove result.value once removed all {result}
}, 500);
}
if (alertObj.on.isConfirmed && result.isConfirmed) {
if (alertObj.id) alertValues[alertObj.id] = result.isConfirmed;
alertObj.on.isConfirmed = self.replacePropertyWithPrefix(alertObj.on.isConfirmed, 'alert', alertValues);
alertObj.on.isConfirmed = self.replacePropertyWithPrefix(alertObj.on.isConfirmed, 'alert', result);
self.do(alertObj.on.isConfirmed, undefined, result.value); // TO DO: remove result.value once removed all {result}
//self.do(alertObj.on.isConfirmed, result.value); // TO DO: remove result.value once removed all {result}
}
if (alertObj.on.isDenied && result.isDenied) {
alertObj.on.isDenied = self.replacePropertyWithPrefix(alertObj.on.isDenied, 'alert', result);
self.do(alertObj.on.isDenied, undefined, result.value); // TO DO: remove result.value once removed all {result}
//self.do(alertObj.on.isDenied, result.value); // TO DO: remove result.value once removed all {result}
}
if (alertObj.on.isDismissed && result.isDismissed) {
alertObj.on.isDismissed = self.replacePropertyWithPrefix(alertObj.on.isDismissed, 'alert', result);
self.do(alertObj.on.isDismissed, undefined, result.dismiss); // TO DO: remove result.value once removed all {result}
//self.do(alertObj.on.isDismissed, result.dismiss); // TO DO: remove result.value once removed all {result}
}
console.log('alertValues');
console.log(alertValues);
} else {
/* if (result.isConfirmed) {
self.do(alertObj.confirm, result.value);
} else if (result.isDenied) {
self.do(alertObj.deny, result.value);
} else if (result.dismiss === Swal.DismissReason.cancel) {
self.do(alertObj.cancel, result.value);
} else if (result.dismiss === Swal.DismissReason.timer) {
self.log('Alert closed by the timer');
} */
}
/*
Reason Description Related configuration
Swal.DismissReason.backdrop The user clicked the backdrop. allowOutsideClick
Swal.DismissReason.cancel The user clicked the cancel button. showCancelButton
Swal.DismissReason.close The user clicked the close button. showCloseButton
Swal.DismissReason.esc The user clicked the Esc key. allowEscapeKey
Swal.DismissReason.timer The timer ran out, and the alert closed automatically. timer
*/
});
if (alertHtml)
self.do(alertHtml, { selector: '#swal2-html-container' });
//self.log('customIcon');
//self.log(customIcon);
if (customIcon) {
/* self.icons({
"class": "icon",
"svg": customIcon
}, {container: '.swal2-icon'}); */
self.do(customIcon, { selector: '.swal2-icon' });
//self.addTag(customIcon, {container: '.swal2-icon'}); // check
self.css({
selector: '.swal2-icon',
style: {
'border': '0px solid transparent'
}
});
self.show({
selector: '.swal2-icon'
});
/* $('.swal2-icon').css({
'border': '0px solid transparent'
});
$('.swal2-icon').show(); */
}
if (swalParams.on && swalParams.on.init) // to be repeated in each function
self.do(swalParams.on.init);
//self.do(swalParams.on.init);
}
}
};
/* var startUploadListeners = function (params) { // da FIXO
self.log('startUploadListeners');
var.upload = params;
var obj = $(params.container);
self.log(params);
obj.on('dragenter', function (e) {
e.stopPropagation();
e.preventDefault();
$(this).css('border', '2px solid #0B85A1');
});
obj.on('dragover', function (e) {
e.stopPropagation();
e.preventDefault();
});
$(document).on('dragenter', function (e) {
e.stopPropagation();
e.preventDefault();
});
$(document).on('dragover', function (e) {
e.stopPropagation();
e.preventDefault();
obj.css('border', '2px dotted #0B85A1');
});
$(document).on('drop', function (e) {
e.stopPropagation();
e.preventDefault();
});
// automatically submit the form on file select
obj.on('drop', function (e) {
$(this).css('border', '2px dotted #0B85A1');
e.preventDefault();
var files = e.originalEvent.dataTransfer.files;
//We need to send dropped files to firebase
handleFileUpload(files);
});
$(params.container+'-file').on('change', function (e) {
var files = $(params.container+'-file')[0].files;
self.log(params.container+'-file');
self.log(files)
handleFileUpload(files);
});
} */
/* this.uploadFileNameAndType = function(params){
self.log('uploadFileNameAndType');
self.log(params);
var fileArr = params.fileName.split('.');
var.upload.fileName = params;
var.upload.fileType = fileArr[1].toLowerCase();
if (!$('.swal2-act').length) $('.swal2-modal').append('');
if (var.upload.fileType == 'ply') {
$('.swal2-act').css({'display':'none'});
} else {
$('.swal2-act').css({'display':'block'});
$('.swal2-act').append('');
}
} */
/* var handleFileUpload = function(files) {
self.log('handleFileUpload');
self.log(files);
self.log('var.upload');
self.log(var.upload);
//var auth0Id = fixo.getAuth0Id();
// Swal.close(); // chiusura popup
for (var i = 0; i < files.length; i++) {
var fd = new FormData();
fd.append('file', files[i]);
if (!files[i].name.endsWith('png')) var.upload.fileTimestamp = self.getTimestamp();
self.fireBaseUpload({
'file': files[i], //base64toBlob(files),
'timestamp': var.upload.fileTimestamp,
'path': var.user.uid+'/' || '' //auth0Id+'/files/images' //path_to_where_you_to_store_the_file
}, function (data) {
self.log('data');
self.log(data);
if (!data.error) {
//if (data.progress && data.progress == 0) $('.swal2-actions').append('');
if (data.progress >= 0 && data.progress <= 100) {
//progress update to view here
// self.log('Uploading file');
// self.log(var.uploadingTarget);
$('#msgFooter').html(''+data.progress+'%')
}
if (data.progress == 100) {
//$(var.uploadingTarget).removeClass('pulseFade');
// Swal.close();
if (data.fileExt !== 'png'){
self.log('diverso da png');
$('.drop-zone-file').attr('accept','.png');
var.upload.data = data;
}
if (var.upload.onUpload) self.do(var.upload.onUpload, data);
}
} else {
//$(var.uploadingTarget).removeClass('pulseFade');
self.log(data.error + ' Firebase image upload error');
}
});
}
}; */
/* var uploadDone = function (data) {
self.log('uploadDone');
// download URL here "data.downloadURL"
var auth0Id = fixo.getAuth0Id();
var storageRef = firebase.storage().ref();
var imageRef = storageRef.child(auth0Id+'/files/images/'+data.fileName);
// Get the download URL
imageRef.getDownloadURL().then(function(url) {
self.do(var.onUpload, url);
// Insert url into an tag to "download"
}).catch(function(error) {
self.log(error.code);
// A full list of error codes is available at
// https://firebase.google.com/docs/storage/web/handle-errors
switch (error.code) {
case 'storage/object_not_found':
// File doesn't exist
break;
case 'storage/unauthorized':
// User doesn't have permission to access the object
break;
case 'storage/canceled':
// User canceled the upload
break;
case 'storage/unknown':
// Unknown error occurred, inspect the server response
break;
}
});
} */
this.findKey = function (obj, key) {
return obj.filter(function (item) {
return Boolean(item[key]);
});
};
/* this.fireBaseUpload = function(parameters, callBackData) {
self.log('fireBaseUpload');
self.log('parameters');
self.log(parameters);
// Get a reference to the storage service, which is used to create references in your storage bucket
var storageRef = firebase.storage().ref();
var file = parameters.file;
var path = parameters.path;
var timestamp = parameters.timestamp;
//var path = var.user.uid; // non riesco a passare la path come parametro da olo.app.json così come l'errore funzione onUpload
self.log('file');
self.log(file);
self.log('timestamp');
self.log(timestamp);
self.log('path');
self.log(path);
//Riga originale pre-modifica nome file
// var fullPath = path + '/' + file.name;
// expected parameters to start storage upload
var metaData = {'contentType': file.type};
var fileSize = formatBytes(file.size); // get clean file size
var fileType = file.type;
var fileName = file.name;
var fileExt = fileName.split('.')[1];
self.log(metaData);
self.log(fileSize);
self.log(fileType);
self.log(fileName);
self.log(fileExt);
var modFileName = timestamp+'.'+fileExt;
//var fullFilePath = storageRef.child(path+timestamp+'-'+fileName);
var fullFilePath = storageRef.child(path+modFileName);
self.log('fullFilePath');
self.log(fullFilePath);
var nm = fileName.split('.');
var name = nm[0];
self.log('nm');
self.log(nm);
self.log('name');
self.log(name);
// Modifica file name generato
// var name = generateRandomString(16); //(location function below)
// var n = name+'.'+file.type.replace('image/','');
// var fullPath = path + '/' + n;
//Riga originale pre-modifica nome file
// var n = file.name;
// generate random string to identify each upload instance
//name = generateRandomString(12); //(location function below)
// var uploadFile = storageRef.child(parameters.path).put(file, metaData);
var uploadFile = fullFilePath.put(file, metaData);
// first instance identifier
//callBackData({id: name, fileSize: fileSize, fileType: fileType, fileName: n}); 20200724
callBackData({id: timestamp.toString(), fileSize: fileSize, fileType: fileType, fileName: modFileName, fileExt: fileExt}); // fileName: fileName //id: name
uploadFile.on('state_changed', function (snapshot) {
var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
progress = Math.floor(progress);
self.log('progress');
self.log(progress);
callBackData({
progress: progress,
element: timestamp.toString(),
//element: name,
fileSize: fileSize,
fileType: fileType,
fileName: modFileName,
fileExt: fileExt});
//fileName: fileName
}, function (error) {
callBackData({error: error});
}, function () {
var downloadURL = uploadFile.snapshot.downloadURL;
callBackData({
downloadURL: downloadURL,
element: timestamp.toString(),
//element: name,
fileSize: fileSize,
fileType: fileType,
fileName: modFileName,
fileExt: fileExt});
//fileName: fileName
});
} */
var formatBytes = function (bytes, decimals) {
if (bytes == 0) return '0 Byte';
var k = 1000;
var dm = decimals + 1 || 3;
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
var i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
};
this.userRole = function () {
switch (Boolean(self.user('uid'))) {
case true:
return 'user'; // user logged in
break;
case false:
return 'guest';
break;
}
};
this.userIn = function () {
//var user = firebase.auth().currentUser;
//if (user.emailVerified) {
return Boolean(self.user('uid'));
};
this.userOut = function () {
return (!self.user('uid'));
};
this.user = function (param) {
/* self.log('user');
self.log(auth); */
if (auth && auth.currentUser)
if (param == 'firstName')
return self.firstName(auth.currentUser['displayName']);
else if (auth.currentUser[param])
return auth.currentUser[param];
else if (!param)
return auth.currentUser;
else
return undefined;
else
return undefined;
};
this.firstName = function (nameParam) {
var firstNameStr = (nameParam) ? nameParam.split(' ')[0] : '';
return firstNameStr;
};
this.userUid = function () {
if (auth) return auth.currentUser.uid;
else return undefined;
};
this.userVerified = function () {
if (auth) return auth.currentUser.emailVerified;
else return undefined;
};
/* this.value = function (valueParams) {
if (valueParams.string)
return valueParams.string
else if (valueParams.function)
//return self.doFunctionByName(valueParams.function, window, '');
}
*/
this.thunkableMessage = function (message, callback) {
if (callback) callback(message);
};
this.onMessage = {
alert: "test"
};
this.processMessage = function (message) {
self.alert('processMessage');
self.do(self.onMessage, message);
//self.do(self.onMessage, undefined, message);
};
this.thunkable = function (params, args) {
if (params.postMessage) {
var message = self.replaceProperties(params.postMessage, args);
if (message) {
try {
ThunkableWebviewerExtension.postMessage(message);
} catch (error) {
}
}
else
self.log('in function "thunkable" "postMessage" parameter is wrong');
}
if (params.receiveMessage) {
self.onMessage = params.receiveMessage;
try {
ThunkableWebviewerExtension.receiveMessage(self.processMessage);
} catch (error) {
}
}
};
/* var ThunkableWebviewerExtension = (function () {
const postMessageToWebview = (message) => {
if (window.ReactNativeWebView) {
window.ReactNativeWebView.postMessage(message);
} else {
window.parent.postMessage(message, '*');
}
};
const getReceiveMessageCallback = (fxn, hasReturnValue) => (event) => {
if (typeof fxn === 'function') {
if (event.data) {
let dataObject;
try {
dataObject = JSON.parse(event.data);
} catch (e) {
// message is not valid json
}
if (dataObject && dataObject.type === 'ThunkablePostMessage' && hasReturnValue) {
fxn(dataObject.message, (returnValue) => {
const returnMessageObject = { type: 'ThunkablePostMessageReturnValue', uuid: dataObject.uuid, returnValue };
postMessageToWebview(JSON.stringify(returnMessageObject));
});
} else if (!hasReturnValue && (!dataObject || dataObject.type !== 'ThunkablePostMessage')) {
fxn(event.data);
}
}
}
};
return {
postMessage: postMessageToWebview,
receiveMessage: function (fxn) {
const callbackFunction = getReceiveMessageCallback(fxn, false);
document.addEventListener('message', callbackFunction, false);
window.addEventListener('message', callbackFunction, false);
},
receiveMessageWithReturnValue: function (fxn) {
const callbackFunction = getReceiveMessageCallback(fxn, true);
document.addEventListener('message', callbackFunction, false);
window.addEventListener('message', callbackFunction, false);
},
};
})(); */
this.extendFunctions = function (functions) {
// change it. don't call self.function
for (var name in functions) {
if (functions[name].js) {
try {
// create or override function
self.functions[name] = new Function(functions[name].js);
} catch (error) {
console.log('ERROR creating function %c' + name, 'color:orange;');
self.log(functions[name].js);
self.log(error.message);
// error.column is wrong
/* let col = error.column -17;
console.log(
functions[name].js.substring(0,col)
+ '%c' + functions[name].js.substring(col, col+1)
+ '%c' + functions[name].js.substring(col+1), 'color:orange; font-weight:bold', 'color:#ddd')
console.log('%c' + error.message, 'color:orange;'); */
// since the script is in one row, error.columns is the exact position of the error
}
} else {
self.log(name + ' function requires js property');
}
}
};
this.function = function (obj, args) {
/* console.log('function');
console.log(params);
console.log('args');
console.log(args); */
// TO DO: add "name" parameter to make the js function permanently available in self.methods[name]
// https://stackoverflow.com/questions/49125059/how-to-pass-parameters-to-an-eval-based-function-injavascript
//app[func].apply( this, args ); // or app[func]( ...args ); // ES6 (2015)
// https://stackoverflow.com/questions/1316371/converting-an-array-to-a-function-arguments-list
//args = self.replaceProperties(args); // needed?
//try {
if (obj.name && obj.js) {
// create or replace function
self.functions[obj.name] = new Function(obj.js);
} else if (obj.name && !obj.js) {
if (self.functions[obj.name]) {
// execute function
if (!obj.arguments || !Array.isArray(obj.arguments)) obj.arguments = [obj.arguments];
try {
return self.functions[obj.name](...obj.arguments);
//return self.functions[obj.name].apply(null, obj.arguments);
} catch (error) {
console.log('ERROR in function %c' + obj.name, 'color:orange;');
console.log('obj');
console.log(obj);
console.log('function');
console.log(self.json.functions[obj.name]);
console.log(error.message);
}
} else {
console.log('ERROR function undefined %c' + obj.name, 'color:orange;');
}
//return self.functions[obj.name](...obj.arguments); // also args?
} else if (obj.js) {
// execute js code as a function
if (obj.arguments && Array.isArray(obj.arguments)) {
return new Function(obj.js).call(null, obj.arguments);
//return new Function( obj.js ).apply(this, obj.arguments );
} else {
return new Function(obj.js).call(null, obj.arguments);
}
}
/* } catch (error) {
self.log('function ERROR');
self.log(error);
self.log(obj);
return false
} */
};
this.eval = this.js = function (code, args) {
/* self.log('js');
self.log(code);
self.log(args); */
/* if (Array.isArray(code)) {
let codeCombined = '';
for (var codePart of code) codeCombined += self.replaceProperties(codePart, args);
try {
return eval(code);
} catch (error) {
self.log('JS error');
self.log(error);
return code;
} */
/* if (typeof code == 'object') {
} else { */
code = self.replaceProperties(code, args);
/* self.log('args');
self.log(args); */
try {
//return new Function( code ).call(null, args);
return eval(code);
} catch (error) {
/* self.log('javascript catch on "'+ codeString + '"');
self.log('error');
self.log(error);
self.log('codeString');
self.log(codeString);
self.log('args');
self.log(args);
return false */
return code;
}
//}
};
/* this.compile = function (obj, args) {
// functions e addTag potrebbero essere eseguiti da una stessa funzione
// in reatà addTag è la funzione che andrebbe lanciata quando la chiave
// dell'azione è tra i tag html
if (obj !== undefined) {
var result;
if (typeof obj == 'object')
result = self.actionResult(obj, args);
result = self.replaceProperties(obj, args);
if (result == 'undefined')
return undefined;
else if (typeof result == 'object') // Array is also an object type
return self.do(result, args);
else if (typeof result == 'function')
return result(args);
else {
return result;
}
} else {
return undefined;
}
} */
this.if = function (params, selectorParams, args) {
// add array
if (typeof params == 'object') {
var conditionString = 'if';
var condition;
if (params.is !== undefined) {
if (typeof params.is == 'string') {
let isReplaced = self.replaceProperties(params.is, args, true);
self.log(isReplaced, 'grey');
try {
condition = Boolean(eval(isReplaced)); // remove undefined values
self.log(isReplaced + ' is ' + condition, 'grey');
} catch (error) {
self.log(isReplaced, 'red');
self.log('"if" condition wrong', 'red');
self.log(error, 'red');
}
conditionString += ' is ' + params.is;
} else if (Array.isArray(params.is)) {
let i = 0;
params.is[i];
switch (params.is[i + 1]) {
case '=': condition = Boolean(eval(params.is[i] + '===' + params.is[i + 2])); break;
}
}
} else if (params.not !== undefined) {
condition = (!Boolean(eval(self.replaceProperties(params.not, args, true)))); // remove undefined values
if (typeof params.not == 'string') conditionString += ' not ' + params.not;
} else if (params.regexp) {
const regex = new RegExp(params.regexp);
condition = Boolean(regex.test(params.string));
} else if (params.isArray) {
condition = self.isArray(params.isArray);
conditionString += 'isArray ' + params.isArray;
} else if (params.exist) {
let elementExist = self.element({ path: params.exist });
condition = (elementExist);
self.log('"if" exist ' + params.exist, 'grey');
} else if (params.value && params.in) {
//let arr = self.replaceProperties(params.in, args, true);
//condition = (arr.indexOf(self.replaceProperties(params.value)) >= 0);
condition = self.valueInJson(self.replaceProperties(params.in, args, true), self.replaceProperties(params.value));
self.log('"if" value ' + self.replaceProperties(params.value) + ' in array is ' + condition, 'grey');
} else if (params.key && params.in) {
condition = self.keyInJson(self.replaceProperties(params.in, args, true), self.replaceProperties(params.key));
self.log('"if" key ' + self.replaceProperties(params.key) + ' in object is ' + condition, 'grey');
} else {
let selector = self.selector(params.selector || params.container, undefined) || self.selector(selectorParams, undefined);
//var selector = self.selector(params.selector || params.container, selectorParams);
if (selector) {
if (params.exist) {
//var element = self.query(params.exist);
//condition = Boolean(self.query(selector));
condition = Boolean(self.exist(selector));
conditionString += ' ' + selector + ' exist ' + params.exist;
}
if (params.hasClass) { // to be reviewed (self.hasClass need 1 parameter)
var element = self.query(selector);
condition = Boolean(self.hasClass(element, params.hasClass));
conditionString += ' ' + selector + ' hasClass ' + params.hasClass;
}
if (params.isVisible) {
var element = self.query(selector);
condition = Boolean(self.isVisible(element, params.isVisible));
conditionString += ' ' + selector + ' isVisible';
}
if (params.isHidden) {
var element = self.query(selector);
condition = Boolean(self.isHidden(element, params.isHidden));
conditionString += ' ' + selector + ' isHidden';
}
if (params.inViewport) {
var element = self.query(selector);
condition = Boolean(self.inViewport(element, params.inViewport));
conditionString += ' ' + selector + ' inViewport';
}
if (params.outViewport) {
var element = self.query(selector);
condition = Boolean(self.outViewport(element, params.outViewport));
conditionString += ' ' + selector + ' outViewport';
}
if (params.isDisplay) {
var element = self.query(selector);
/* self.log('element');
self.log(element); */
condition = Boolean(self.isDisplay(element, params.isDisplay));
conditionString += ' ' + selector + ' isDisplay ' + params.isDisplay;
}
} else {
self.log('the "if" function requires "is" or "not" parameter');
}
}
/* conditionString += ': ' + condition;
self.log(condition, 'grey'); */
if (condition)
if (params.then) {
// self.console dovrebbe diventare così
if (typeof params.then == 'object') {
return self.do(params.then);
//return self.do(params.then);
} if (typeof params.then == 'string') {
return self.replaceProperties(params.then);
} else {
return params.then;
}
}
else
self.log('the "if" function requires "then" parameter');
else if (params.else) {
if (typeof params.else == 'object') {
return self.do(params.else);
//return self.do(params.else);
} if (typeof params.else == 'string') {
return self.replaceProperties(params.else);
} else {
return params.else;
}
}
} else {
//self.log(Boolean(params) && params !== 'false');
return Boolean(self.js(params, args)); // 0.9.7
//return Boolean(eval(self.replaceProperties(params, args))) // need try
}
};
this.switch = function (params, args) {
//self.log('switch');
//self.log(params);
var value;
var answer;
if (params.expression)
value = String(self.js(params.expression, args));
else
self.log('"switch" function requires "expression" parameter');
//self.log(value);
if (params.cases) {
//self.log('params.cases[value]');
//self.log(params.cases[value]);
if (value !== undefined && params.cases[value]) {
if (typeof params.cases[value] == 'object')
answer = self.do(params.cases[value], undefined, args);
//answer = self.do(params.cases[value], args);
else
answer = params.cases[value];
} else if (params.cases['default']) {
self.log('default');
self.log(params.cases['default']);
if (typeof params.cases['default'] == 'object')
answer = self.do(params.cases['default'], undefined, args);
//answer = self.do(params.cases['default'], args);
else
answer = params.cases['default'];
}
} else {
self.log('"switch" function requires "cases" parameter');
self.log('answer');
self.log(answer);
}
return answer;
};
/*
this.varAction = this.set = function (params, args) {
// {name, value, operator}
var value;
var operator = params.operator;
//self.log('operator');
//self.log(operator);
if (operator && args) operator = self.replaceProperties(operator, args);
//self.log('operator');
//self.log(operator);
if (params.value !== undefined) { // set
value = self.js(params.value, args);
if (params.var) {
self.docElement('self.json.var.'+params.var, value);
} else if (params.name) {
var actualValue = self.docElement('self.json.var.'+params.name);
if (actualValue == undefined && typeof value == 'string') actualValue = '';
if (actualValue == undefined && typeof value == 'number') actualValue = 0;
if (actualValue == undefined && typeof value == 'object') actualValue = {};
if (operator) {
if (operator == '+=') actualValue += value;
if (operator == '-=') actualValue -= value;
if (operator == '/=') actualValue /= value;
if (operator == '*=') actualValue *= value;
value = actualValue;
}
self.docElement('self.json.var.'+params.name, value);
//self.log('self.json.var[params.name]');
//self.log(self.json.var[params.name]);
} else {
self.log('set command requires "var" parameter');
}
} else { // get
if (params.var) {
return self.docElement('self.json.var.'+params.var);
} else if (params.name) {
return self.docElement('self.json.var.'+params.name);
} else {
self.log('set command requires "value" parameter');
}
}
//self.log('value');
//self.log(value);
self.log('var ' + params.name + ' = ' + value);
} */
this.delay = function (params, selector, args) {
self.log('delay');
self.log('selector');
self.log(selector);
var duration = params.duration || 1000;
duration = Number(self.replaceProperties(duration, args));
self.log(duration);
if (params.do) {
setTimeout(function () {
self.do(params.do, selector, args);
//self.do(params.do, args, container)
}, duration);
}
};
this.firebasePasswordReset = function (paramEmail, paramSuccess, paramError) {
//firebase.auth().languageCode = 'it';
firebase.auth().useDeviceLanguage();
auth.sendPasswordResetEmail(paramEmail).then(function () {
// Email sent.
if (paramSuccess) self.do(paramSuccess);
//if (paramSuccess) self.do(paramSuccess);
}).catch(function (error) {
// An error happened.
if (paramError) self.do(paramError, undefined, error.message);
//if (paramError) self.do(paramError, error.message);
});
};
this.firebaseUpdateProfile = function (params, paramSuccess, paramError) {
self.log('firebaseUpdateProfile');
self.log(params);
auth.currentUser.updateProfile(params).then(function () {
// Update successful.
self.log('User Profile Updated Successfully');
if (paramSuccess) self.do(paramSuccess);
//if (paramSuccess) self.do(paramSuccess);
}).catch(function (error) {
// An error happened.
if (paramError) self.do(paramError, undefined, error.message);
//if (paramError) self.do(paramError, error.message);
});
};
this.firebaseRegister = function (params, success, error) {
if (params.email && params.password) {
// log the user in
auth.createUserWithEmailAndPassword(params.email, params.password).then(cred => {
self.log(cred.user);
//var.auth.cred = cred;
var user = firebase.auth().currentUser;
/* if (user.emailVerified) {
} else {
self.sendEmailVerification(params);
} */
//if (params.success) self.do(params.success);
if (params.success) self.do(params.success);
}).catch(error => {
// Handle Errors here.
//if (params.error) self.do(params.error, error.message);
if (params.error) self.do(params.error, undefined, error.message);
});
}
};
this.firebaseLogin = function (params) {
self.log('firebaseLogin');
self.log(params);
if (auth) {
auth.signInWithEmailAndPassword(String(params.email), String(params.password)).then(cred => {
//var.auth.cred = cred;
var user = firebase.auth().currentUser;
//firebase.auth().languageCode = 'it';
if (user.emailVerified) {
if (params.success) self.do(self.replaceResult(params, undefined, cred));
//if (params.success) self.do(self.replaceResult(params, cred));
} else {
self.sendEmailVerification(params);
}
}).catch(error => {
self.log('error.code');
self.log(error.code);
if (params.error) self.do(self.replaceResult(params, undefined, error.message));
//if (params.error) self.do(self.replaceResult(params, error.message));
});
} else {
// firebase auth non inizializzato
}
};
this.firebaseLogout = function (params) {
self.log('firebaseLogout');
firebase.auth().signOut().then(function () {
self.log('firebaseLogout SUCCESS');
self.log(params.success);
if (params.success) {
//app.stopMeeting();
localStorage.clear();
//self.do(params.success);
self.do(params.success);
}
}).catch(function (error) {
self.log('firebaseLogout ERROR');
self.log(error);
//if (params.error) self.do(params.error);
if (params.error) self.do(params.error);
});
};
// this.firebaseUserVerify = function (params) {
// self.log('firebaseUserVerify');
// self.log(params);
// self.log(params.oobCode);
// if (params.oobCode) self.params.codeMail = params.oobCode
// self.log(self.params.codeMail);
// //self.do(data);
// // inviare mail di verifica
// }
this.sendEmailVerification = function (params) {
self.log('sendEmailVerification');
var user = firebase.auth().currentUser;
firebase.auth().languageCode = 'it';
var successAction = params.success || self.reload;
user.sendEmailVerification().then(function () {
firebase.auth().signOut();
self.alert({
//toast: true,
icon: "success",
title: "verifyingemail", // all\'indirizzo "+params.email+"
html: "msgverifyingemail",
//confirmButtonText: "Ok",
//showCancelButton: false,
showConfirmButton: false,
confirm: successAction
});
});
};
/* //self.log('function');
params = self.replaceProperties(params, args); // -> compile
if (typeof params == 'object') {
// jsonic function
//return self.do(params, args);
return self.do(params, args);
} else if (typeof params == 'function') {
// javascript function
return params(args);
} else if (typeof params == 'string') {
if (json.actions[params]) {
var functionCompiled = self.replaceResult(json.actions[params], args); // replace {result}
//functionCompiled = self.replaceProperties(functionCompiled, args);
// jsonic predefined function
//return self.do(functionCompiled);
return self.do(functionCompiled);
//return self.actionResult(json.actions[params], args);
} else {
// javascript function name
var functionName = self.docElement(params);
if (functionName)
if (typeof functionName == 'function') {
// javascript function
return functionName(args)
} else {
// javascript object
return functionName;
}
else
self.log('function undefined: '+ params);
}
} */
this.path = function (pathParams, args, separatorParam) {
var pathString = '';
var separator = separatorParam || '/';
/* self.log('this.path');
self.log(pathParams);
self.log(args); */
if (typeof pathParams == 'string') {
pathString = self.replaceProperties(pathParams, args);
} else {
for (var index in pathParams) {
pathObj = pathParams[index];
if (pathString !== '') pathString += separator;
if (pathObj.string)
pathString += String(pathObj.string);
else if (pathObj.number)
pathString += Number(pathObj.number);
else if (pathObj.function)
pathString += self.doFunctionByName(pathObj.function, window, '');
}
}
return pathString;
};
this.executeFunctionByName = function (functionName, context /*, arguments */) {
//self.log('executeFunctionByName');
//self.log(functionName);
if (functionName) {
var args = [].slice.call(arguments).splice(2);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for (var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
if (context[func] !== undefined) {
return context[func].apply(context, args);
} else {
//self.log('Error: executeFunctionByName');
//if (functionName !== undefined) {self.log('functionName:'+functionName);}
}
} else {
self.log('executeFunctionByName');
self.log('functionName undefined');
}
};
this.functions = {};
this.methods = {
// main methods
run: function (params, container, args) { self.run(params, container, args); },
delay: function (params, container, args) { self.delay(params, container, args); },
ajax: function (params, container, args) { self.ajax(params, container, args); },
do: function (params, container, args) { self.do(params, container, args); },
module: function (params, container, args) { self.module(params, args); },
js: function (params, container, args) { self.js(params, args); },
function: function (params, container, args) { self.function(params, args); },
dispatchEvent: function (params, container, args) { self.dispatchEvent(params, args); },
// TO DO: check
lang: function (params, container, args) { self.lang(params, args); },
find: function (params, container, args) { self.find(params, args); },
page: function (params, container, args) { self.page(params, args); },
// DA VERIFICARE
//dayjs: function (params, args) {self.dayjs(params, args)},
//moment: function (params, args) {self.moment(params, args)},
//data: function (params, args) {self.data(params, args)},
//var: function (params, args) {self.var(params, args)},
//javascript: function (params, args) {self.javascript(params, args)},
//color: function (params, args) {self.color(params, args)},
//select: function (params, args) {self.select(params, args)},
// LOGIC & DATA
for: function (params, container, args) { self.for(params, container, args); },
if: function (params, container, args) { self.if(params, container, args); },
switch: function (params, container, args) { self.switch(params, args); },
set: function (params, container, args) { self.set(params, args); },
// TO DO: check is needs to be renamed to avoid confusion with self.json.data
data: {
set: function (params, args) {
for (var param in params) {
var value = params[param];
if (value) value = self.replaceProperties(value, args);
if (value && args) value = self.replacePropertyWithPrefix(value, 'result', args); // backward compatibility TO DO: remove
self.element({ path: param, value: value });
}
},
get: function (params) {
return self.element(params);
},
delete: function (params, args) {
var path = self.replaceProperties(params, args);
alert(path);
self.objToDelete = self.element({ path: path });
delete self.objToDelete;
},
add: function (params, args) {
for (var param in params) {
var path = self.replaceProperties(param, args);
var value = self.replaceProperties(params[param], args);
if (value) {
var obj = self.element({ path: path }) || '';
obj += String(value);
self.element({ path: path, value: obj });
}
}
},
sum: function (params, args) {
console.log('%cdeprecated key "sum". Use set{x: "{x}+1"}', 'color:orange');
console.log(params);
console.log(args);
for (var param in params) {
var path = self.replaceProperties(param, args);
var value = self.replaceProperties(params[param], args);
if (value) {
var obj = self.element({ path: path }) || 0;
obj += Number(value);
self.element({ path: path, value: obj });
}
}
},
sub: function (params, args) {
console.log('%cdeprecated key "sub". Use set{x: "{x}+1"}', 'color:orange');
console.log(params);
console.log(args);
for (var param in params) {
var path = self.replaceProperties(param, args);
var value = self.replaceProperties(params[param], args);
if (value) {
var obj = self.element({ path: path }) || 0;
obj -= Number(value);
self.element({ path: path, value: obj });
}
}
},
push: function (params, args) {
for (var param in params) {
var path = self.replaceProperties(param, args);
var value = self.replaceProperties(params[param], args);
if (value) {
var obj = self.element({ path: path }) || [];
obj.push(value);
self.element({ path: path, value: obj });
}
}
}
},
// DOM
text: function (params, container, args) { self.text(params, container, args); }, // TO DO: -> html
html: function (params, container, args) { self.html(params, container, args); },
attr: function (params, container, args) { self.attr(params, container, args); },
empty: function (params, container, args) { self.empty(params, args); },
delete: function (params, args) {
var path = self.replaceProperties(params, args);
var obj = self.element({ path: path });
self.log(JSON.stringify(obj));
self.element({ path: path, delete: true });
// NOTE: obj = self.element non prende l'oggetto effettivo. quindi element deve contenere tutte le funzioni
//self.element({path: path, delete: true});
self.log(obj);
},
add: function (params, container, args) {
for (var param in params) {
var path = self.replaceProperties(param, args);
var value = self.replaceProperties(params[param], args);
/* self.log('value');
self.log(value); */
if (value) {
var obj = self.element({ path: path }) || '';
obj += String(value);
self.element({ path: path, value: obj });
}
}
},
sum: function (params, container, args) {
for (var param in params) {
var path = self.replaceProperties(param, args);
var value = self.replaceProperties(params[param], args);
if (value) {
var obj = self.element({ path: path }) || 0;
obj += Number(value);
self.element({ path: path, value: obj });
}
}
},
sub: function (params, container, args) {
for (var param in params) {
var path = self.replaceProperties(param, args);
var value = self.replaceProperties(params[param], args);
if (value) {
var obj = self.element({ path: path }) || 0;
obj -= Number(value);
self.element({ path: path, value: obj });
}
}
},
push: function (params, container, args) {
for (var param in params) {
var path = self.replaceProperties(param, args);
var value = self.replaceProperties(params[param], args);
if (value) {
var obj = self.element({ path: path }) || [];
obj.push(value);
self.element({ path: path, value: obj });
self.log('push obj');
self.log(obj);
}
}
},
// should go in utils.json
calendar: function (params, container, args) { self.calendar(params, args); }, // to check
array: function (params, container, args) { self.array(params, args); },
replace: function (params, container, args) { self.replace(params, args); },
shuffle: function (array) {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle.
while (currentIndex != 0) {
// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]
];
}
return array;
},
// should go in ui.json (or ux) module
alert: function (params, container, args) { self.alert(params, args); }, // change in swal2
offcanvas: function (params, container, args) { self.offcanvas(params, args); }, // bootstrap / obsolete
//in: function (params, container, args) {self.in(params, container, args)}, // bootstrap TO DO: replace in code with ui:in
out: function (params, container, args) { self.out(params, container, args); }, // bootstrap TO DO: replace in code with ui:out
qrcode: function (params, container, args) { self.qrcode(params, container, args); }, // obsolete TO DO: replace in code with ui:qrcode
hide: function (params, container, args) { self.hide(params, container, args); }, // TO DO: replace in code with ui:hide
show: function (params, container, args) { self.show(params, container, args); }, // TO DO: replace in code with ui:show
toggle: function (params, container, args) { self.toggle(params, container, args); }, // TO DO: replace in code with ui:toggle
sortablejs: function (params, container, args) { self.sortablejs(params, args); }, // TO DO: replace in code with ui:sortable
lottie: function (params, container, args) { self.lottie(params, container, args); }, // TO DO: replace in code with ui:lottie
chart: function (params, container, args) {
var selector = self.selector(container);
var element = self.query(selector);
element.innerHTML = '';
const ctx = element.querySelector('canvas');
const myChart = new Chart(ctx, self.replaceProperties(params));
},
animate: function (params, container, args) { self.animate(params, container, args); },
//editor: function (params, container, args) {self.editor(params, container, args)}, // quill
// window.dispatchEvent(new Event('resize')); // workaround known ACE bug
uiUpdate: function (params, container, args) { self.uiUpdate(params, args); },
swiper: {
data: {},
init: function (params, selector, args) {
//swiperConfig.on = {};
setTimeout(function () {
// waits the plugin... TO DO: add this function to a promise
console.log('swiper inited');
console.log(selector || params.selector);
console.log(params.options);
var swiperConfig = params.options;
self.methods.swiper.data[params.name] = new Swiper(self.selector(selector || params.selector), swiperConfig);
console.log(self.methods.swiper.data[params.name]);
}, 1000);
}
},
// should go in browser.json module
//export: function (params, container, args) {self.export(params, container, args)}, -> browser
//console: function (params, container, args) {self.console(params, args)}, // obsolete, changed in log
link: function (params, container, args) { self.link(params, args); },
scroll: function (params, container, args) { self.scroll(params, args); },
reload: function (params, container, args) { self.reload(params, args); },
timer: function (params, container, args) { self.timer(params, args); },
setInterval: function (params, container, args) { self.setInterval(params, args); },
clearInterval: function (params, container, args) { self.clearInterval(params, args); },
setTimeout: function (params, container, args) { self.setTimeout(params, args); },
clearTimeout: function (params, container, args) { self.clearTimeout(params, args); },
local: {
set: function (params) {
for (var param in params) {
var value = params[param];
if (value) value = self.replaceProperties(value);
if (typeof value == 'object') value = JSON.stringify(value);
localStorage.setItem(param, value);
}
},
get: function (key) {
var localValue = localStorage.getItem(key);
if (localValue && self.isJsonString(localValue))
localValue = JSON.parse(localValue);
return localValue;
},
remove: function (key) {
localStorage.removeItem(key);
},
clear: function () {
localStorage.clear();
}
},
storage: {
_storage: new WeakMap(),
set: function (element, key, obj) {
if (!self.methods.storage._storage.has(element)) {
self.methods.storage._storage.set(element, new Map());
}
self.methods.storage._storage.get(element).set(key, obj);
},
get: function (element, key) {
return self.methods.storage._storage.get(element).get(key);
},
has: function (element, key) {
return self.methods.storage._storage.has(element) && self.methods.storage._storage.get(element).has(key);
},
remove: function (element, key) {
var ret = self.methods.storage._storage.get(element).delete(key);
if (!self.methods.storage._storage.get(element).size === 0) {
self.methods.storage._storage.delete(element);
}
return ret;
}
},
choose: function (params, container, args) { self.choose(params, container, args); },
remove: function (params, container, args) { self.remove(params, container, args); },
part: function (params, container, args) { self.part(params, container, args); },
blocks: function (params, container, args) { self.part(params, container, args); }, // obsolete
block: function (params, container, args) { self.part(params, container, args); },
ace: function (params, container, args) { self.ace(params, container, args); },
code: function (params, container, args) { self.code(params, container, args); },
// should go in firebase.json module
database: function (params, container, args) { self.database(params, args); }, // obsolete (check)
firebase: function (params, container, args) { self.firebase(params, args); },
firebaseEvent: {
action: function (newObj) {
/* self.logdbRef('firebaseEvent.action');
self.log('newObj');
self.log(newObj); */
/* var path = newObj.path;
delete newObj.path;
var pathString = 'self.json.var.db.' + self.replaceAll(path, '/', '.');
self.log('pathString:'+pathString);
var dbObj = self.docElement(pathString);
dbObj = newObj; // update local db */
var path = newObj.path;
delete newObj.path;
//alert(path);
document.querySelectorAll('[data-firebase="' + path + '"]').forEach(function (element, index) {
//$('[data-firebase="'+path+'"]').each(function (index) {
// var element = this;
var pathString = 'self.json.var.db.' + self.replaceAll(element.getAttribute('data-firebase'), '/', '.'); // data('firebase')
var dbObj = self.docElement(pathString);
var firebaseValue = newObj[element.getAttribute('data-value')]; // TODO: not works for nested nodes
//var template = element.getAttribute('data-template');
var template = self.dataStorage.get(element, 'data-template');
//if ($(element).is('ul')) {
if (element.tagName == 'UL') { // se $(this) è un ul
//var dbObj = self.docElement(pathString);
// se il percorso ha più nodi e il dato non è presente nel db locale,
// va creato un oggetto vuoto per ogni nodo
//var context = element.getAttribute('data-firebase');
//self.var.db[context] = newObj; // update local db
var liTemplate = template.li || template.template; // template.li retro-compatibility
/* self.log('liTemplate');
self.log(liTemplate);
self.log('newObj');
self.log(newObj); */
//$(container).empty();
element.innerHTML = '';
var items = newObj;
for (itemKey in items) {
var item = items[itemKey];
item.key = itemKey;
/* if (params.li.class == "deviceItem d-flex flex-wrap align-items-center list-group-item list-group-item-action d-flex align-items-center justify-content-between") {
alert(JSON.stringify(params.li));
} */
//if (dbPath == 'lessons')
//prompt(JSON.stringify(liTemplate));
// TO DO: replace with replaceProperty
var dbParams = self.replaceItems(liTemplate, item, 'item') || '';
// var dbParams = self.replaceProperties(liTemplate, undefined, item) || '';
// -> TO DO container = self.elementToSelector(element);
var container = element.getAttribute('data-selector');
self.li(dbParams, { selector: container });
}
//} else if ( $(element).is('span') || $(element).is('p')) {
} else if (element.tagName == 'SPAN' || element.tagName == 'P') {
//$(element).text(firebaseValue);
element.textContent = firebaseValue;
} else if (element.tagName == 'SVG') {
// TODO without JQUERY
//$(element).children('text').text(firebaseValue);
} else { // se $(this) non è un ul
//var dbObj = self.docElement(pathString);
// se il percorso ha più nodi e il dato non è presente nel db locale,
// va creato un oggetto vuoto per ogni nodo
//var context = element.getAttribute('data-firebase');
//self.var.db[context] = newObj; // update local db
if (template.blocks || template.html) {
var blocksTemplate = template.html || template.blocks;
//$(container).empty();
element.innerHTML = '';
var items = newObj;
self.log('newObj');
self.log(newObj);
for (itemKey in items) {
var item = items[itemKey];
item.key = itemKey;
var dbParams = self.replaceProperties(blocksTemplate, undefined, item) || '';
/* self.log('container');
self.log(container);
self.log('dbParams');
self.log(dbParams); */
self.html(dbParams, { selector: container });
}
}
if (template.init) self.do(template.init); //self.do(template.init);
}
});
}
},
auth: {
init: function (params, container, args) {
self.log("auth init");
auth = firebase.auth();
auth.onAuthStateChanged(user => {
self.json.var.user = user;
if (!user) {
// No user logged in
self.log('authStateChanged: GUEST\n');
// non bisognerebbe chiedere sempre di fare login
} else {
// User logged in
self.log('authStateChanged: USER\n');
self.log('name: ' + self.user('displayName') + '\nemail: ' + user.email + '\nuid:' + user.uid);
//self.log('email verificata');
//self.log(self.userVerified());
}
/* self.log('params');
self.log(params); */
//self.do(params.onAuthStateChanged);
self.do(params.onAuthStateChanged);
//if (!firebaseInitialized) {
// firebaseInitialized = true;
//self.do(data);
//}
});
},
sendEmailVerification: function (params, container, args) {
self.sendEmailVerification(params);
},
login: function (params, container, args) {
self.log('params.auth');
self.log(params.auth); // QUESTO E' {var:auth} MA SEMBRA NON RIMPIAZZARLO
self.log(args); // QUI MI RIPORTA LA PWD, ma perché ultimo args
var fba = self.replaceProperties(params.auth, args);
self.log('fba');
self.log(fba);
var fbAuth = self.cloneObject(fba);
self.log('fbAuth');
self.log(fbAuth);
if (params.success) fbAuth.success = params.success;
if (params.error) fbAuth.error = params.error;
self.firebaseLogin(fbAuth, params.success, params.error);
},
register: function (params, container, args) {
//var fbAuth = self.replaceTags({text: params.auth, args: args});
//var fbAuth = self.replaceResult(params.auth, args);
var fbAuth = self.replaceProperties(params.auth, args);
fbAuth.success = params.success;
fbAuth.error = params.error;
//alert(JSON.stringify(fbAuth))
self.firebaseRegister(fbAuth, params.success, params.error);
},
updateProfile: function (params, container, args) {
//params.profile = self.replaceTags({text: params.profile, args: args});
//params.profile = self.replaceResult(params.profile, args);
params.profile = self.replaceProperties(params.profile, args);
self.firebaseUpdateProfile(params.profile, params.success, params.error);
},
passwordReset: function (params, container, args) {
//params.email = self.replaceTags({text: params.email, args: args});
//params.email = self.replaceResult(params.email, args);
params.email = self.replaceProperties(params.email, args);
self.firebasePasswordReset(params.email, params.success, params.error);
},
logout: function (params, container, args) {
self.firebaseLogout(params);
}
},
// should go in mobile.json module
thunkable: function (params, container, args) { self.thunkable(params, args); },
// should go in 3d.json module
modelViewer: {
events: {},
on: function (params) {
let container = self.selector(params.selector || params.container);
let element = self.query(container);
self.log('modelViewer on');
self.log('container');
self.log(container);
self.log('element');
self.log(element);
if (element) {
self.methods.modelViewer.events[container] = {}; // use self.element
//let events = ['load', 'preload'];
//for (var event in events) {
var event = 'load';
if (params[event]) {
//self.element({root: 'self.methods.modelViewer.events', path: container+'.'+event, value: params[event]})
self.methods.modelViewer.events[container][event] = params[event];
self.log('modelViewer element');
self.log(element);
element.addEventListener(event, (e) => {
self.log('modelViewer event');
self.log(e);
let container = e.path[0].getAttribute('data-selector');
self.log(container);
//self.do(self.methods.modelViewer.events[container][e.type]);
self.do(self.methods.modelViewer.events[container][e.type]);
});
}
}
},
set: function (params) {
let element = self.query(self.selector(params.selector || params.container));
if (element) {
if (params.color) {
let color = params.color.split(',').map(numberString => parseFloat(numberString));
self.log('Changing color to: ', color);
const [material] = element.model.materials;
material.pbrMetallicRoughness.setBaseColorFactor(color);
}
if (params.exposure) element.exposure = params.exposure;
if (params.shadow) element.shadowIntensity = params.shadow;
if (params.orientation) element.orientation = params.orientation;
}
}
}
};
this.googleSignInPopup = function () {
self.log('googleSignInPopup');
var provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().useDeviceLanguage(); // lingua del dispositivo
firebase.auth()
.signInWithPopup(provider)
.then((result) => {
// @type {firebase.auth.OAuthCredential}
var credential = result.credential;
// This gives you a Google Access Token. You can use it to access the Google API.
var token = credential.accessToken;
// The signed-in user info.
var user = result.user;
window.location.reload();
// ...
}).catch((error) => {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
});
};
/* this.googleSignInPopup = function () {
// [START auth_google_signin_popup]
self.log('googleSignInPopup');
var provider = new firebase.auth.GoogleAuthProvider();
//provider.addScope('https://www.googleapis.com/auth/contacts.readonly'); //check security
//provider.addScope('https://www.googleapis.com/auth/calendar');
//var languageApp = jsonic.var.language || 'en';
//firebase.auth().languageCode = 'it';//languageApp;
//self.log(provider);
//return;
firebase.auth()
.signInWithPopup(provider)
.then((result) => {
// @type {firebase.auth.OAuthCredential}
var credential = result.credential;
// This gives you a Google Access Token. You can use it to access the Google API.
var token = credential.accessToken;
// The signed-in user info.
var user = result.user;
//######### result ########//
self.log("credential");
self.log(credential);
self.log("token");
self.log(token);
self.log("user");
self.log(user);
window.location.reload();
// ...
}).catch((error) => {
// Handle Errors here.
var errorCode = error.code;
self.log('errorCode');
self.log(errorCode);
var errorMessage = error.message;
self.log('errorMessage');
self.log(errorMessage);
// The email of the user's account used.
var email = error.email;
self.log('email');
self.log(email);
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
self.log('credential');
self.log(credential);
// ...
});
// [END auth_google_signin_popup]
} */
/* this.auth = function (params, args) {
self.log('auth');
self.log(params);
if (params.do == 'init') {
auth = firebase.auth();
auth.onAuthStateChanged(user => {
self.json.var.user = user;
if (!user) {
// No user logged in
self.log('authStateChanged: GUEST\n');
// non bisognerebbe chiedere sempre di fare login
} else {
// User logged in
self.log('authStateChanged: USER\n');
self.log('name: '+self.user('displayName') + '\nemail: '+user.email + '\nuid:'+ user.uid);
//self.log('email verificata');
//self.log(self.userVerified());
}
//self.log('params.onAuthStateChanged');
//self.log(params.onAuthStateChanged);
self.do(params.onAuthStateChanged);
//if (!firebaseInitialized) {
// firebaseInitialized = true;
//self.do(data);
//}
});
} else if (params.do == 'sendEmailVerification') {
self.sendEmailVerification(params);
} else if (params.do == 'login') {
self.log('params.auth');
self.log(params.auth);
var fba = self.replaceProperties(params.auth, args);
self.log('fba');
self.log(fba);
var fbAuth = self.cloneObject(fba);
self.log('fbAuth');
self.log(fbAuth);
if (params.success) fbAuth.success = params.success;
if (params.error) fbAuth.error = params.error;
self.firebaseLogin(fbAuth, params.success, params.error);
} else if (params.do == 'register') {
//var fbAuth = self.replaceTags({text: params.auth, args: args});
//var fbAuth = self.replaceResult(params.auth, args);
var fbAuth = self.replaceProperties(params.auth, args);
fbAuth.success = params.success;
fbAuth.error = params.error;
//alert(JSON.stringify(fbAuth))
self.firebaseRegister(fbAuth, params.success, params.error);
} else if (params.do == 'updateProfile') {
//params.profile = self.replaceTags({text: params.profile, args: args});
//params.profile = self.replaceResult(params.profile, args);
params.profile = self.replaceProperties(params.profile, args);
self.firebaseUpdateProfile(params.profile, params.success, params.error);
} else if (params.do == 'passwordReset') {
//params.email = self.replaceTags({text: params.email, args: args});
//params.email = self.replaceResult(params.email, args);
params.email = self.replaceProperties(params.email, args);
self.firebasePasswordReset(params.email, params.success, params.error);
} else if (params.do == 'logout') {
self.firebaseLogout(params);
}
// else
//self.database(params, args);
}
*/
/* this.db = function (params, args) {
if (typeof params == 'string')
return self.db(params, args);
else
self.firebase(params, args);
} */
this.console = function (params, args) {
//value = self.replaceProperties(params);
//console.log('JSONIC: '+value, 'color:pink');
if (typeof params.log == 'string' && params.color) {
var color = params.color || 'white';
console.log('%c' + self.replaceProperties(params.log), 'color:' + color);
} else {
console.log(self.replaceProperties(params.log || params));
}
};
this.module = function (params, args) {
if (typeof params == 'string') {
var nameReplaced = self.replaceProperties(params, args);
return self.element({ root: self.modules, path: nameReplaced });
} else {
if (params.name) {
if (params.value) {
var name = self.replaceProperties(params.name, args);
//var value = self.actionResult(params.value, args);
var value = self.replaceProperties(value, args);
self.log('module');
self.log(name);
self.log('value');
self.log(value);
self.log(value.app.html.div.div[0].text.lang.en);
self.modules[name] = value;
} else if (params.url) {
self.addModule(params); // TO DO: return?
}
}
}
};
this.db = function (params, args) {
self.log('db');
if (typeof params == 'string') {
var paramsReplaced = self.replaceProperties(params, args);
self.log('paramsReplaced');
self.log(paramsReplaced);
self.log(self.var('db.' + paramsReplaced, args));
//var varValue = self.docElement('self.json.var.db.'+name);
return self.var('db.' + paramsReplaced, args); // to do: change with self.element({path: 'db.'+paramsReplaced}})
/*
// questa versione non funzionava. vuol dire che this.var ha un errore nel caso di oggetto
return self.var({
name: 'db.'+paramsReplaced
}, args);
*/
} /* else {
return self.actionResult(params, args);
} */
};
this.firebase = function (params, args) {
if (params.initializeApp) {
var firebaseConfig = self.replaceProperties(params.initializeApp);
firebase.initializeApp(firebaseConfig);
} else {
self.database(params, args);
}
};
this.database = function (params, args) {
//console.log('database');
if (params.do == 'init') {
database = firebase.database();
self.log('database');
self.log(database);
} else {
if (database) {
if (typeof params == 'string') {
return self.db(params, args); // local db
} else {
if (params) {
if (params.path) {
params.path = self.path(params.path, args);
}
/* console.log('params.path');
console.log(params.path); */
/* if (params.value)
params.value = params.value; */ //self.value({string: params.value});
if (params.value) {
/* self.log("params.value pre replace");
self.log(params.value); */
//params.value = self.replaceTags({text: params.value, args: args});
//params.value = self.replaceResult(params.value, args);
//params.value = self.replaceProperties(params.value, args);
//params.value = self.actionResult(params.value, args);
params.value = self.replaceProperties(params.value, args);
self.log("params.value post replace");
self.log(params.value);
}
/* self.log('params to FIREBASE');
self.log(params); */
// params.value = "${var.newDevice}"
//var newDevice = `${params.value}`;
//var newDevice = `${var.newDevice}`;
if (params.do == 'init') {
} else if (params.do == 'increase') {
self.firebaseIncrease(params);
} else if (params.do == 'get') {
self.firebaseGet(params.path, function (result) {
if (result.success) {
if (result.data) {
self.log('firebase get SUCCESS');
self.log(params.success);
if (params.on && params.on.success) self.do(params.on.success, undefined, result);
//if (params.on && params.on.success) self.do(params.on.success, result);
} else {
self.log('firebase get no result.data ERROR');
//if (params.on && params.on.error) self.do(params.on.error);
if (params.on && params.on.error) self.do(params.on.error);
}
} else {
self.log('firebase get ERROR');
//if (params.on && params.on.error) self.do(params.on.error, result);
if (params.on && params.on.error) self.do(params.on.error, undefined, result);
// alert errore di connessione. alert riprova
}
});
} else if (params.do == 'new' && params.value) {
var newKey = self.getKey(params.path);
self.firebaseSet(params.path + '/' + newKey, params.value, function (result) {
if (result.success) {
self.log('firebase set SUCCESS');
if (params.on && params.on.success) self.do(params.on.success, undefined, result);
//if (params.on && params.on.success) self.do(params.on.success, result);
} else {
self.log('firebase set ERROR');
if (params.on && params.on.error) self.do(params.on.error, undefined, result);
//if (params.on && params.on.error) self.do(params.on.error, result);
// alert errore di connessione. alert riprova
}
});
} else if (params.do == 'remove' && params.path) {
self.firebaseRemove(params.path, function (result) {
if (result.success) {
self.log('firebase set SUCCESS');
//if (params.on && params.on.success) self.do(params.on.success, result);
if (params.on && params.on.success) self.do(params.on.success, undefined, result);
} else {
self.log('firebase set ERROR');
if (params.on && params.on.error) self.do(params.on.error, undefined, result);
//if (params.on && params.on.success) self.do(params.on.success, result);
// alert errore di connessione. alert riprova
}
});
} else if (params.do == 'addListener') {
self.firebaseAddListener(params);
} else if (params.do == 'removeListener') {
self.firebaseRemoveListener(params);
} else if (params.do == 'update') {
if (params.value) { // 'set' is the default action with 'value' param
self.firebaseUpdate(params.path, params.value, function (result) {
if (result.success) {
self.log('firebase update SUCCESS');
if (params.on && params.on.success) self.do(params.on.success, undefined, result);
//if (params.on && params.on.success) self.do(params.on.success, result);
} else {
self.log('firebase update ERROR');
if (params.on && params.on.error) self.do(params.on.error, undefined, result);
//if (params.on && params.on.error) self.do(params.on.error, result);
// alert errore di connessione. alert riprova
}
});
} else {
self.log('data update requires value param');
}
} else if (params.do == 'push') {
if (params.value) { // 'set' is the default action with 'value' param
self.firebasePush(params.path, params.value, function (result) {
if (result.success) {
self.log('firebase push SUCCESS');
if (params.on && params.on.success) self.do(params.on.success, undefined, result);
//if (params.on && params.on.success) self.do(params.on.success,result);
} else {
self.log('firebase push ERROR');
if (params.on && params.on.error) self.do(params.on.error, undefined, result);
//if (params.on && params.on.error) self.do(params.on.error, result);
// alert errore di connessione. alert riprova
}
});
} else {
self.log('data push requires value param');
}
} else {
if (params.value) { // 'set' is the default action with 'value' param
self.firebaseSet(params.path, params.value, function (result) {
if (result.success) {
self.log('firebase set SUCCESS');
if (params.on && params.on.success) self.do(params.on.success, undefined, result);
//if (params.on && params.on.success) self.do(params.on.success,result);
} else {
self.log('firebase set ERROR');
if (params.on && params.on.error) self.do(params.on.error, undefined, result);
//if (params.on && params.on.error) self.do(params.on.error, result);
// alert errore di connessione. alert riprova
}
});
}
}
}
}
} else {
self.log('"database" function needs to be initialised');
}
}
};
this.ajax = function (params, selectorParams, args) {
/* self.log('ajax');
// TO DO: selectorParams
self.log('ajax');
self.log('params');
self.log(params);
self.log('args');
self.log(args); */
if (params.url) {
//var url = self.compile(params.url, args);
var url = self.replaceProperties(params.url, args);
var data;
if (params.data)
data = JSON.stringify(self.replaceProperties(params.data, args));
//data = JSON.stringify(self.compile(params.data, args));
/* self.log('data');
self.log(data); */
var type = params.type || 'POST';
var request = new XMLHttpRequest();
request.open(type, url, true);
//request.setRequestHeader("Accept", "application/json");
//request.setRequestHeader('Content-Type', 'application/json');
/* request.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) return;
alert("Success: " + r.responseText);
} */
request.onload = function () {
self.log('onload');
self.log(this);
if (this.status >= 200 && this.status < 400) {
// Success!
var result = {};
//try {
var response = this.response;
response = response.replace(/(\\\")/g, '"');
try {
response = decodeURI(response);
} catch (error) {
/* console.log('response');
console.log(response); */
console.log('decodeURI error');
console.log(error);
}
result.response = self.parse(response);
result.status = this.status;
result.header = this.getAllResponseHeaders().split('\r\n').reduce((resultHeader, current) => {
let [name, value] = current.split(': ');
resultHeader[name] = value;
return resultHeader;
}, {});
//} catch (e) {
//}
self.log('result');
self.log(result);
if (params.success)
self.do(params.success, undefined, result);
//self.do(params.success, result);
//self.do(self.replaceProperty(params.success, 'result', result), result);
} else {
// We reached our target server, but it returned an error
if (params.error)
self.do(params.error, undefined, 'Server error');
//self.do(params.error, 'Server error');
}
};
request.onerror = function (error) {
// There was a connection error of some sort
self.log('error');
self.log(error);
self.log('this');
self.log(this);
if (params.error)
self.do(params.error, undefined, 'Server unavailable');
//self.do(params.error, 'Server unavailable');
};
//request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
if (data)
request.send(data);
else
request.send();
} else {
self.log('ajax method requires url parameter');
}
/* $.ajax({
url: paramsReplaced.url,
type: params.type || 'post',
//dataType: 'json', // questo dovrebbe evitare JSON.parse
//dataType: 'text', // verificare se necessario
data: paramsReplaced.data || {},
success: function (result) {
self.log('ajax');
self.log('result');
self.log(result);
self.do(params.success, result);
//self.do(data); // in .params dovrebbe andare il resto
},
error: function (error) {
var errorText = error.responseText || error;
self.do(params.error, errorText);
//self.do(data); // in .params dovrebbe andare il resto
}
}); */
};
/* View in fullscreen */
this.openFullscreen = function (id) {
var element = document.getElementById(id);
if (screenfull.isEnabled) {
screenfull.request(element);
}
};
/* this.addListener = function(params) {
var selector = self.selector(params);
if (selector)
$(selector).on(params.event, self.do(params.action));
//event.stopPropagation();
} */
/* Close fullscreen */
this.closeFullscreen = function () {
//document.exitFullscreen();
screenfull.off('change'); // callback
};
/* this.list = function (params, selectorParams) {
var container = (selectorParams) ? self.selector(selectorParams) : params.container;
var selector = self.selector(self.extend({}, params, selectorParams));
if (selector) {
if (params.list) params.items = params.list; // retro-compatibilità
if (params.listAction) $(selector).data('listAction', params.listAction);
if (params.listClass) $(selector).data('listClass', params.listClass); // ul
if (params.items) {
$(selector).empty();
var index = 0;
//params.items = self.replaceTags({text:params.items, args:selectorParams});
//params.items = self.replaceResult(params.items, selectorParams);
params.items = self.replaceProperties(params.items, selectorParams);
for (var itemKey in params.items) {
// da rimuovere id="item'+itemKey+'" href=""
//self.log('PARAMETRI');
//self.log(itemKey);
//self.log(params.items);
$(selector).append('');
var item = params.items[itemKey];
//var itemSelector = selector + ' li:eq(' + index + ')';
var itemSelector = selector + ' li:eq(' + itemKey + ')';
// Item action
var itemAction;
if (item.action)
itemAction = item.action;
else if (params.action)
itemAction = params.action;
else if ($(selector).data('listAction'))
itemAction = $(selector).data('listAction');
item.action = itemAction;
if (item.action) {
$(itemSelector).addClass('list-group-item-action');
$(itemSelector).css('cursor', 'pointer');
}
if (item.color) $(itemSelector).css('color', item.color);
if (item.background) $(itemSelector).css('background', item.background);
//$(itemSelector).append('');
var itemFields = params.items[itemKey].fields || params.items[itemKey]; // retro-compatibilità
//self.log('itemFields');
//self.log(itemFields);
for (var itemField in itemFields) {
var field = itemFields[itemField];
//self.log(field);
if (itemField == 'icons') {
self.icons(field, {container: itemSelector});
} else if ((itemField != 'params') && (itemField != 'action')) { // retro-compatibilità
$(itemSelector).append(''+self.text(itemFields[itemField])+'');
}
}
// action
if (item.action) {
$(itemSelector).data('onData', item);
$(itemSelector).on(self.touch, function (event) {
event.stopPropagation();
self.onEvent(this, event);
});
}
// events
if (item.on) self.on(item.on, {container: selector});
index++;
}
} else if (params.append) {
// aggiunge una riga alla fine (calcolare path)
} else if (params.prepend) {
// aggiunge una riga all'inizio (calcolare path)
// sballa tutti i dati presenti in var.functions
// sarebbe meglio mem in data value tutto il json
// azione
}
// List classes
//if (params.id) $(selector).attr('id', params.id);
var listClass = $(selector).data('listClass');
if (listClass) {
var ulClass = listClass.ul || '';
var liClass = listClass.li || '';
$(selector).addClass(ulClass);
$(selector + ' > li').addClass(liClass);
var index = 0;
for (var field in listClass.fields) {
var fieldClass = listClass.fields[field] || '';
$(selector + ' > li > span[data-field='+field+']').addClass(fieldClass);
index++;
}
}
}
} */
this.scroll = function (params) {
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
// {id, class, value}
var selector = self.selector(params.selector || params.container);
var block = document.querySelector(selector);
//var offset = elem.dataset.offset ? parseInt(elem.dataset.offset) : 0;
if (block) {
var bodyOffset = document.body.getBoundingClientRect().top;
window.scrollTo({
top: block.getBoundingClientRect().top - bodyOffset, // + offset,
behavior: 'smooth'
});
} else {
self.log('scroll to unknown element: ' + selector);
}
};
/* this.scroll = function (params) {
// var selector = self.selector(params);
//var obj = $(selector).get(0);
var selector = "g."+params.class+".myLabelStyle."+params.value;
//var parent = $(selector).parent().get(0);
//document.querySelector(selector).scrollIntoView();
//self.resizeEvent(); // bug workaround
//$(selector).parent().scrollTop($(selector).position().top);
$(selector).parent().animate({
//scrollTop: $(selector).position().top
//scrollTop: $(selector).position().top,
transform: 'translate(0,-'+$(selector).position().top+'), scale(1)'
});
}
*/
//------------------------
/* this.do = function (data, args) {
if (data) {
if (typeof data == 'string' && self.json.actions[data]) {
self.do(self.json.actions[data], args);
} else {
if (!data.index) data.index = 0;
if (!data.tasks) {
if (Array.isArray(data)) {
if (data.index < data.length) {
self.do(data[data.index]);
data.index = data.index +1;
self.do(data);
} else {
delete data.index;
}
} else {
self.do(data);
}
//} else if (data.tasks.length > 0) {
} else {
if (data.index < data.tasks.length) {
var currentTask = data.tasks[data.index];
//var currentTask = data.tasks.shift();
if (currentTask.params == undefined) {currentTask.params = {}}
if (data.params == undefined) {data.params = {}}
if (currentTask.if == undefined) {currentTask.if = true}
var taskParams = currentTask.params; // parametri specifici del task
taskParams.params = data.params;
taskParams.index = data.index+1;
//for (var param in data.params) {taskParams[param] = data.params[param]; } // merge
taskParams.tasks = data.tasks;
var taskIf = (typeof currentTask.if == "function") ? currentTask.if() : currentTask.if;
if (taskIf) {
if (currentTask.delay !== undefined) {
setTimeout(function () {
self.do(currentTask.task, taskParams);
}, currentTask.delay);
} else if (currentTask.interval !== undefined) {
self.createTaskInterval(currentTask);
} else {
self.do(currentTask.task,taskParams);
}
} else {
self.do(taskParams);
}
}
}
}
}
} */
/* this.playTaskInterval = function (taskFunction) {
self.log('playTaskInterval');
var taskName = taskFunction.name;
if (tasksIntervals[taskName]) {
clearInterval(tasksIntervals[taskName].id);
tasksIntervals[taskName].id = setInterval(function () {
tasksIntervals[taskName].task(tasksIntervals[taskName].params);
}, tasksIntervals[taskName].interval);
} else {
self.log('taskName: '+taskName);
}
}
this.stopTaskInterval = function (taskFunction) {
self.log('stopTaskInterval');
var taskName = taskFunction.name;
if (tasksIntervals[taskFunction.name]) {
clearInterval(tasksIntervals[taskFunction.name].id);
} else {
self.log('taskName: '+taskName);
}
}
this.createTaskInterval = function (myTask) {
tasksIntervals[myTask.task.name] = {};
tasksIntervals[myTask.task.name].task = myTask.task;
tasksIntervals[myTask.task.name].params = myTask.params;
tasksIntervals[myTask.task.name].interval = myTask.interval;
self.playTaskInterval(myTask.task.name);
}
this.addTimedTask = function (data) {
self.log('addTimedTask');
if (data.frequence && data.task) {
if (!data.active) {data.active = true;}
if (!timedTasks[data.frequence]) {timedTasks[data.frequence] = {}}
timedTasks[data.frequence][data.task] = {active:data.active, params:{}};
if (data.params) {
timedTasks[data.frequence][id].params = data.params;
}
}
}
this.removeTimedTask = function (data) {
self.log('removeTimedTask');
if (data.frequence && data.task) {
delete timedTasks[data.frequence][data.task];
}
}
this.doTimedTask = function (data) {
self.log('doTimedTask');
self.log(data);
for (var task in timedTasks[data.frequence]) {
var taskObj = timedTasks[data.frequence][task];
if (taskObj.active) {
self.do(task, taskObj.params);
}
}
} */
//------------------------
// CSS METHODS
//------------------------
/* // SELETTORI
var previewPanel = '.appPanel[data-value="pnlPreview"]';
var toolsPanel = '.appPanel[data-value="pnlTools"]';
var stagePanel = '.framePanel[data-value="pnlStage"]';
var devicePanel = '.framePanel[data-value="pnlDevice"]';
this.closePanel = function(value) {
self.log(value);
switch (value) {
case 'closePanelTools':
$(toolsPanel).fadeOut();
$(previewPanel).fadeIn();
case 'closePanelFrame':
$(devicePanel).fadeOut();
$(stagePanel).fadeIn();
}
}
*/
//------------------------
// CSS METHODS
//------------------------
/* this.cssProp = function (propPar) {
var cssObj = {transform: ''};
if ((propPar.x) && (propPar.y)) {cssObj.transform += ' translate('+propPar.x+'px,'+propPar.y+'px)'; }
if (propPar.rotateY) {cssObj.transform += ' rotateY('+propPar.rotateY+'deg)'; }
if (propPar.rotateX) {cssObj.transform += ' rotateX('+propPar.rotateX+'deg)'; }
if (propPar.scale) {cssObj.transform += ' scale('+propPar.scale+','+propPar.scale+')'; }
if (propPar.deg) {cssObj.transform += ' rotate('+propPar.deg+'deg)'; }
if (propPar.opacity) {cssObj.opacity = propPar.opacity;}
return cssObj;
} */
/* this.getCSS = function (data) {
var $inspector = $("
").css('display', 'none').addClass(data.class);
$("body").append($inspector); // add to DOM, in order to read the CSS property
try {
var props = [];
for (i=0; i {
/* self.log('animate');
self.log('params');
self.log(params);
self.log('selectorParams');
self.log(selectorParams); */
/* selectorParams.container = (params.container) ? params.container : selectorParams.container;
selectorParams.id = (params.id) ? params.id : selectorParams.id ;
selectorParams.class = (params.class) ? params.class : selectorParams.class;
selectorParams.value = (params.value) ? params.value : selectorParams.value; */
const prefix = 'animate__';
//var selector = self.selector(self.extend({}, params, selectorParams), undefined, true); // selectAll
let selector = self.selector(params.selector || params.container, undefined, true) || self.selector(selectorParams, undefined, true);
//var selector = self.selector(params.selector || params.container, selectorParams, true); // selectAll
/* self.log('animate');
self.log('selector');
self.log(selector); */
var transition = params.transition || params;
transition = self.replaceProperties(transition, args);
const duration = params.duration || '0.5s';
const animationName = `${prefix}${transition}`;
if (!selector) {
self.log('animate function without selector');
self.log(params);
self.log(selectorParams);
} else {
var elements = self.queryAll(selector);
/* console.log('elements');
console.log(elements); */
//var elements = document.querySelectorAll(selector);
if (elements)
elements.forEach(function (element, index) {
if (element) {
//element.classList.add(`${prefix}animated`, animationName);
//console.log(element.classList);
element.classList.add('animate__animated', animationName);
element.style.setProperty('--animate-duration', duration);
} else {
console.log('element');
console.log(element);
}
});
if (params.on && params.on.start)
self.do(params.on.start, { selector: selector });
//self.do(params.on.start, undefined, {selector: selector});
if (params.style) self.css(params, selectorParams); // TO DO: deprecated / to be removed
//if (params.infinite)
// node.style.setProperty('--animate-infinite', 'infinite');
// When the animation ends, we clean the classes and resolve the Promise
function handleAnimationEnd(event) {
if (params.on && params.on.end) {
self.do(params.on.end, { selector: selector });
//self.do(params.on.end, undefined, {selector: selector});
/* self.log('handleAnimationEnd');
self.log('params.on.end');
self.log(params.on.end); */
}
event.stopPropagation();
if (elements)
elements.forEach(function (element, index) {
if (element)
element.classList.remove('animate__animated', animationName);
});
resolve('Animation ended');
}
if (elements)
elements.forEach(function (element, index) {
if (element)
element.addEventListener('animationend', handleAnimationEnd, { once: true });
});
}
});
};
/*
this.animation = function (data) { // deprecated
if (data.animation != undefined) {
if (data.animation == 'show') {
$(data.object).css({'display':'block', opacity:1});
} else if (data.animation == 'hide') {
$(data.object).css({'display':'none'});
} else {
//if (data.autoDisplay == undefined) {data.autoDisplay = true};
//var animationObject = self.cloneObject(animations[data.animation]);
var animationObject = jQuery.extend({}, animations[data.animation]);
//if (data.autoDisplay)
// if (data.animation == 'fadeIn') $(data.object).css({'display':'block'});
if (data.reverse) {animationObject.name += 'Reverse'}
if (data.duration !== undefined) {animationObject.duration = data.duration}
animationObject.complete = function () {
if (data.autoDisplay) {
if ((data.animation == 'fadeOut') || (data.animation == 'hide')) {
$('data.object').css({'display':'none'});
}
}
if (data.onComplete !== undefined) {
self.do(data.onComplete);
}
}
self.log('animationObject.name');
self.log(animationObject.name);
self.log('animationObject');
self.log(animationObject);
// playKeyframe va aggiornato con
// animate({from, to, ease, type, stiffness, dumping, mass, velocity, duration})
// https://popmotion.io/#quick-start-animation-animate-keyframes-options
//var obj = popmotion.styler($(data.object));
//popmotion.animate(animationObject).start(obj.set); // $(data.object).css
$(data.object).playKeyframe(animationObject);
}
} else {
$(data.object).resetKeyframe();
$(data.object).css({'opacity':1,'display':'block'});
self.log('ANIMATION UNDEFINED');
self.log(data);
}
}
this.move = function (data) { // deprecated
var targetPos = {x:0,y:0};
if (data.target != 'center') { targetPos = {x:384,y:384}; }
else if (data.target !== undefined) {targetPos = self.getTransform(data.target);}
else {self.log(data);}
if (data.move == 'toTarget') {
TweenMax.to(data.object, self.TweenMaxDuration(data.duration), { x: targetPos.x, y: targetPos.y});
} else if (data.move == 'fromTarget') {
TweenMax.from(this, self.TweenMaxDuration(data.duration), { x: targetPos.x, y: targetPos.y});
}
if (data.animation !== undefined) {
self.animation({object:data.object, animation:data.animation});
}
}
this.TweenMaxDuration = function (duration) {
if (duration != undefined) {return Number(duration)/1000} else {return 0.667;}
}
*/
// CSS CLASSES
this.addClassRule = function (ruleName, ruleParams) {
//self.log('addClassRule');
var ruleProperties = '{';
for (var property in ruleParams) {
if (typeof ruleParams[property] == 'object') {
self.addClassRule(ruleName + ' ' + property, ruleParams[property]);
} else {
ruleProperties += property + ':' + ruleParams[property] + ';';
}
}
ruleProperties += '}';
self.styleObj.sheet.insertRule(ruleName + ' ' + ruleProperties);
};
this.addApplyRule = function (ruleName, ruleParams) {
// Use @apply to inline any existing utility classes into your own custom CSS
// https://tailwindcss.com/docs/functions-and-directives#apply
self.styleObj.sheet.insertRule(ruleName + ' {@apply ' + ruleParams + '}');
};
this.findPlugin = function (name) {
if (self.json.plugins) {
for (var plugin of self.json.plugins) {
if (plugin.name == name) return plugin;
}
} else {
return false;
}
};
this.defineCss = function (cssObj) {
self.log('defineCss');
self.styleObj = document.createElement("style");
document.head.appendChild(self.styleObj);
self.styleObj.appendChild(document.createTextNode(""));
/* self.styleObj.sheet.insertRule('@tailwind base;');
self.styleObj.sheet.insertRule('@tailwind components;');
self.styleObj.sheet.insertRule('@tailwind utilities;'); */
// shortcuts (must be improved / can't be extended)
/* if (self.json.shortcuts && self.json.shortcuts.class)
shortcuts = self.json.shortcuts.class; */
if (cssObj) {
if (Array.isArray(cssObj)) {
for (var cssElement of cssObj) {
//console.log(cssElement);
for (var elementName in cssElement) {
//console.log(elementName);
let valueWithData = self.replaceProperties(cssElement[elementName]);
self.addClassRule(elementName, valueWithData);
}
}
} else {
for (var elementName in cssObj) {
let valueWithData = self.replaceProperties(cssObj[elementName]);
self.addClassRule(elementName, valueWithData);
}
}
}
if (self.pluginsLoaded.tailwindcss) {
var plugin = self.findPlugin('tailwindcss');
//var config = (plugin) ? plugin.config : {preflight: false};
var config = (self.json.setup.config.tailwindcss) ? self.json.setup.config.tailwindcss : { preflight: false };
//if (self.json.style.theme) setup.theme = self.json.style.theme;
//loadPlugin(undefined, 'tailwind-config', undefined, undefined, JSON.stringify(config)) // version 2.2.0
if (tailwind)
tailwind.config = config;
else
console.log('tailwind object is undefined');
}
/* // OBSOLETE
if (self.pluginsLoaded.twind && window.twind) {
var plugin = self.findPlugin('twind');
var config = (plugin) ? plugin.config : {preflight: false, mode:'silent'};
//if (self.json.setup.target) setup.target = self.query(self.json.setup.target);
//if (self.json.style.theme) setup.theme = self.json.style.theme;
window.twind.setup(config);
} */
/* if (self.pluginsLoaded.windicss && window.windicssRuntimeOptions) {
var config = self.json.style.windi || {
// enabled preflight
preflight: false,
// scan the entire dom tree to infer the classnames on page loaded
extractInitial: false,
// generate mock classes for browser to do the auto-completeion
mockClasses: false,
// the windi config you are used to put in `windi.setup.js`
setup: {},
theme: {extend: {}}
};
if (self.json.style.theme) setup.theme.extend = self.json.style.theme;
window.windicssRuntimeOptions = config;
} */
/* if (self.pluginsLoaded.unocss) {
var config = self.json.style.unocss || { // -> self.json.plugins[].setup
rules: [
// custom rules...
],
presets: [
// custom presets...
],
// ...
};
if (self.json.style.theme) setup.theme = self.json.style.theme;
if (self.json.shortcuts) setup.shortcuts = self.json.shortcuts;
window.__unocss = config;
//alert(JSON.stringify(config));
} */
//self.do(data);
};
/* this.createLoader = function (data) {
// !--
-->
if (self.json.loader) $('.preloader img').attr('src', self.json.loader);
self.do(data);
} */
/* this.preloadIcons = function (data) {
self.log('preloadIcons');
// to do: check for duplicated ids
if (self.json.icons) {
if (!data.icons && self.json.icons) data.icons = self.cloneObject(self.json.icons);
if (data.icons) {
var iconSet = Object.keys(data.icons)[0];
var icons = data.icons[iconSet];
delete data.icons[iconSet];
if (icons.preload) {
var ajax = new XMLHttpRequest();
ajax.open("GET", icons.src, true);
ajax.onload = function(e) {
if (this.status >= 200 && this.status < 400) {
self.log('Icon set loaded ' + iconSet);
var result = this.response; // responseText
//self.log(result);
var div = document.createElement("div");
//var iconsHtml = new XMLSerializer().serializeToString(result);
var iconsHtml = result;
iconsHtml = self.replaceAll(iconsHtml, 'id="', 'id="' + iconSet + '_');
div.innerHTML = iconsHtml;
div.setAttribute("style", "display: none");
//div.setAttribute("aria-hidden", "true");
//document.getElementbyId('preloadIcons').appendChild(element);
document.body.insertBefore(div, null);
if (Object.keys(data.icons).length > 0)
self.preloadIcons(data);
else
self.do(data);
}
}
ajax.send();
} else {
if (Object.keys(data.icons).length > 0)
self.preloadIcons(data);
else
self.do(data);
}
} else
self.do(data);
} else {
self.do(data);
}
} */
/* this.initApp = function (data) {
self.log('initApp');
self.defineCss();
window.addEventListener('resize', self.resizeEvent);
if (self.json) { // can be self.json.init
//if (self.json.on.init)
if (self.json.on)
self.on(self.json.on);
//else
// self.log('no on init functions');
}
//self.do(data);
}
*/
/* this.createUI = function (data) {
jsonic.do({
tasks:[
{task: self.firebaseInit},
{
task: self.firebaseVerifyUser,
params: {
code: self.params.oobCode
}
},
{task: self.getDevices, if: jsonic.userIn},
{task: self.defineCss},
{task: self.defineAnimations}, // animazioni css predefinite
{task: self.createHeader},
{task: self.createMenu, params: {
container: '#menu',
id: data.params.mode || 'guest'
}},
{task: jsonic.createPages}
]
});
} */
/* this.openPageFromUrl = function(data){
jsonic.log('openPageFromUrl');
jsonic.log('self.params');
jsonic.log(self.params);
var pageId = '';
//if (localStorage.getItem('scanning')) {
// self.hashopenTask({id:localStorage.getItem('scanningFile')});
//} else {
//self.disableFileIcons();
//var noDevices = (jsonic.userIn() && (!var.db.devices || Object.keys(var.db.devices).length == 0));
//if (noDevices && !self.params.d && !self.params.m) {
// jsonic.gotoPage('devices');
//} else {
if (window.location.hash && window.location.hash !== '') {
//pageId = window.location.hash.substr(1);
self.hash();
} else {
if (self.params.p) // retro-compatibilità
pageId = self.params.p;
else
pageId = self.homePage();
self.gotoPage(pageId);
}
//}
self.do(data);
}
*/
/*
// Load a script from given `url`
var loadPlugin = function(url) {
return new Promise(function(resolve, reject) {
const script = document.createElement('script');
script.src = url;
script.addEventListener('load', function() {
// The script is loaded completely
resolve(true);
});
document.head.appendChild(script);
});
};
// Perform all promises in the order
var waterfall = function(promises) {
return promises.reduce(
function(p, c) {
// Waiting for `p` completed
return p.then(function() {
// and then `c`
return c().then(function(result) {
return true;
});
});
},
// The initial value passed to the reduce method
Promise.resolve([])
);
};
// Load an array of scripts in order
var loadScriptsInOrder = function(arrayOfJs) {
self.log('loadScriptsInOrder');
self.log(arrayOfJs);
const promises = arrayOfJs.map(function(url) {
self.log(url);
return loadScript(url);
});
return waterfall(promises);
};
*/
this.hash = function (path, args) {
self.log('hash');
var path = self.replaceProperties(path, args);
self.log(path);
window.location.hash = path;
};
this.page = function (path, args) {
self.log('page');
var path = self.replaceProperties(path, args);
self.log(path);
if (path.startsWith('#'))
window.location.hash = path;
else
window.location.href = path;
//window.location.hash = path;
};
this.hashChangeEvent = function () {
self.log('hashChangeEvent');
self.log(window.location.hash);
/* if (window.location.hash && window.location.hash !== '') {
var hashParams = window.location.hash.substr(1).split('/');
self.gotoPage(hashParams[0], hashParams[1]);
} else {
//pageId = self.homePage();
if (self.json.setup && self.json.setup.wordpress && self.json.setup.wordpress.slug)
self.gotoPage(self.json.setup.wordpress.slug);
else
self.gotoPage(self.homePage());
}
if (json && json.app && json.app.on && json.app.on.page) { // page event
self.do(json.app.on.page);
}
if (json && json.actions && json.actions.init) { // obsolete
self.do(json.actions.init);
} */
};
/* this.addPageListeners = function (data) {
self.log('addPageListeners');
// Resize event
window.addEventListener('resize', self.resizeEvent);
// Location hash (url) event
window.addEventListener('hashchange', self.hashChangeEvent);
//$(window).on('hashchange', self.hashChangeEvent);
self.hashChangeEvent();
self.do(data);
} */
/* // testing
let findValues = function(obj, key, found) {
for (let localKey in obj) {
if (obj.hasOwnProperty(localKey)) {
let val = obj[localKey];
//self.log(localKey)
if (localKey === key) {
found.add(val)
} else {
if (typeof val === 'object') {
findValues(val, key, found)
}
}
}
}
}
function uniqueValue(obj, key, value) {
let found = new Set()
findValues(object, key, found)
return found.size === 1 && found.has(value);
} */
this.lookup = function (obj, k) {
for (var key in obj) {
var value = obj[key];
if (k == key) {
return [k, value];
}
if (typeof (value) === "object" && !Array.isArray(value)) {
var y = lookup(value, k);
if (y && y[0] == k) return y;
}
if (Array.isArray(value)) {
// for..in doesn't work the way you want on arrays in some browsers
//
for (var i = 0; i < value.length; ++i) {
var x = lookup(value[i], k);
if (x && x[0] == k) return x;
}
}
}
return null;
};
this.findValues = function (obj, key) {
//return Boolean(JSON.stringify(obj).indexOf('"' + string + '":') >= 0)
let matrix = [...JSON.stringify(obj).matchAll(new RegExp('\"?' + key + '\"?\:\s*\"([^,\"]+)', 'gi'))];
var results = [];
for (var element of matrix)
results.push(element[1]);
return results;
//return Boolean(JSON.stringify(obj).match(new RegExp('\"?' + key + '\"?\:\s+\"' + value + '\"'))) // JSON5 compatible
};
// testing
function findKey(obj, key) {
for ([k, v] of Object.entries(obj)) {
if (k == key) return v;
if (typeof v === 'object' && v !== null) {
let found = findKey(v, key);
if (found) return found;
}
}
}
// lookup in json
this.keyInJson = function (obj, string) {
//return Boolean(JSON.stringify(obj).indexOf('"' + string + '":') >= 0)
return Boolean(JSON.stringify(obj).match(new RegExp('\"?' + string + '\"?\:'))); // JSON5 compatible
};
// lookup in json
this.valueInJson = function (obj, string) {
//return Boolean(JSON.stringify(obj).indexOf('"' + string + '":') >= 0)
return Boolean(JSON.stringify(obj).match(new RegExp('\"?' + string + '\"?'))); // JSON5 compatible
};
/* this.keyInFiles = function (string) {
var found = self.keyInJson(self.options, string); // in main app options: jsonic = jsonicApp(options)
for (fileName in self.modules) {
if (fileName !== 'resources' && self.keyInJson(self.modules[fileName], string))
found = true;
}
return found;
} */
/* this.openPageFromUrl = function (data) {
self.log('openPageFromUrl');
self.hashChangeEvent();
self.do(data);
}; */
/* this.addEventListeners = function (data) {
self.log('addEventListeners');
// Resize event
window.addEventListener('resize', self.resizeEvent);
// Location hash (url) event
window.addEventListener('hashchange', self.hashChangeEvent);
$(window).on('hashchange', self.hashChangeEvent);
self.hashChangeEvent(); // add here on.hashchange
// Fullscreen event
if (screenfull && screenfull.isEnabled) {
screenfull.on('change', () => {
self.log('Am I fullscreen?', screenfull.isFullscreen ? 'Yes' : 'No');
if (screenfull.isFullscreen) {
var.fullscreen = true;
if (var.onFullScreenOpen) self.do(var.onFullScreenOpen);
} else {
var.fullscreen = false;
if (var.onFullScreenClose) self.do(var.onFullScreenClose);
}
});
}
if (json && json.app && json.app.on) {
if (json.app.on.thunkable && json.app.on.thunkable.receiveMessage)
window.receiveMessage(function (message) {
//document.querySelector('#message').value = message;
jsonic.functions(json.app.on.thunkable.receiveMessage, message, undefined);
});
var container = json.app.container || 'body';
self.on(json.app.on, {container: container});
self.do(data);
} else {
self.do(data);
}
} */
/* this.loadIconset = function (data) {
self.log('loadIconset');
if (self.json.iconset) {
if (!self.pluginsLoaded['iconify']) {
let plugin = self.json.resources.pluginsFunctions['iconify'];
self.pluginsLoader([plugin], self.loadIconset, [data]);
} else {
var iconset;
if (!self.json.iconset[0])
iconset = [self.json.iconset];
else
iconset = self.json.iconset;
for (var index in iconset) {
if (Iconify.addCollection(iconset[index]))
self.log('added iconset '+ iconset[index].prefix);
else
self.log('can\t add iconset '+ iconset[index].prefix);
//alert(x);
}
self.do(data);
}
} else {
self.do(data);
}
} */
// Si potrebbe creare una nuova istanza di jsonicApp
this.start = function () {
self.log('start');
//if (params.onFullScreenOpen) var.onFullScreenOpen = params.onFullScreenOpen;
//if (params.onFullScreenClose) var.onFullScreenClose = params.onFullScreenClose;
// PWA
/* if ('serviceWorker' in navigator) {
// Register a service worker hosted at the root of the
// site using the default scope.
navigator.serviceWorker.register('/app/assets/pwa/sw.js').then(function(registration) {
self.log('Service worker registration succeeded:', registration);
}, function(error) {
self.log('Service worker registration failed:', error);
});
} else {
self.log('Service workers are not supported.');
} */
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
// Prevent Chrome 67 and earlier from automatically showing the prompt
e.preventDefault();
// Stash the event so it can be triggered later.
deferredPrompt = e;
});
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
self.json.setup.darkMode = e.matches ? "dark" : false;
});
// DEFINE ICONSET (iconify)
if (self.json.iconset) {
if (!self.pluginsLoaded['iconify']) {
let plugin = self.json.resources.pluginsFunctions['iconify'];
self.pluginsLoader([plugin], self.start);
return false;
} else {
var iconset;
if (!self.json.iconset[0])
iconset = [self.json.iconset];
else
iconset = self.json.iconset;
for (var index in iconset) {
if (Iconify.addCollection(iconset[index]))
self.log('added iconset ' + iconset[index].prefix);
else
self.log('can\t add iconset ' + iconset[index].prefix);
//alert(x);
}
}
}
// DEFINE CSS
//self.defineCss(); // TO DO: only additional css (do it on load module success)
// ADD RESIZE LISTENER (for dynamic styles) TO DO: check it
window.addEventListener('resize', self.resizeEvent);
// PAGE
if (!self.json.setup.page) self.json.setup.page = {};
self.json.setup.page.hash = window.location.hash.substr(1);
// DO / ON
/* if (self.json) {
if (self.json.do)
self.do(self.json.do, undefined, self.json.container);
if (self.json.on)
self.on(self.json.on, self.json.container);
} */
var selector = self.json.selector || self.json.container;
/* if (self.json.do)
self.do(self.json.do, undefined, selector); */
// should go action/run
if (self.json.on)
self.on(self.json.on, selector);
};
this.extendJson = function (jsonBase, jsonExtension) {
// TO DO: should be renamed in extendApp (or executeModule) because extend self.json and add CSS style
if (jsonExtension.css) self.defineCss(jsonExtension.css);
if (jsonExtension.functions) self.extendFunctions(jsonExtension.functions);
for (var key in jsonExtension) {
// AGGIUNGERE ALL'ARRAY DELLE AZIONI ON.INIT...
if (key == 'on') {
for (var subKey in jsonExtension[key]) {
if (typeof jsonExtension[key][subKey] !== 'string') {
//jsonBase[key][subKey] = self.extend({}, jsonBase[key][subKey], jsonExtension[key][subKey]);
if (!jsonBase[key][subKey]) jsonBase[key][subKey] = [];
jsonBase[key][subKey].push(jsonExtension[key][subKey]);
} else {
jsonBase[key][subKey] = jsonExtension[key][subKey];
}
}
} else if (key == 'parts' || key == 'shortcuts') { // combine subelements
for (var subKey in jsonExtension[key]) {
if (typeof jsonExtension[key][subKey] !== 'string')
jsonBase[key][subKey] = self.extend({}, jsonBase[key][subKey], jsonExtension[key][subKey]);
else
jsonBase[key][subKey] = jsonExtension[key][subKey];
}
/* } else if (key == 'css') {
for (var subKey in jsonExtension[key]) {
if (typeof jsonExtension[key][subKey] !== 'string')
jsonBase[key][subKey] = self.extend({}, jsonBase[key][subKey], jsonExtension[key][subKey]);
else
jsonBase[key][subKey] = jsonExtension[key][subKey];
} */
/* } else if (key == 'app') { // to do: obsolete
for (var subKey in jsonExtension[key]) {
if (typeof jsonExtension[key][subKey] !== 'string')
jsonBase[key][subKey] = self.extend({}, jsonBase[key][subKey], jsonExtension[key][subKey]);
else
jsonBase[key][subKey] = jsonExtension[key][subKey];
} */
} else if (key == 'iconset' || key == 'plugins') { // combine arrays
if (!jsonBase[key]) jsonBase[key] = [];
jsonBase[key] = jsonBase[key].concat(jsonExtension[key]);
} else {
if (key == 'css') {
} else {
jsonBase[key] = self.extend({}, jsonBase[key], jsonExtension[key]);
}
}
}
return jsonBase;
};
this.loadModuleFromDb = function (data) {
self.log('loadModuleFromDb');
self.firebaseGet('jsonic', function (result) {
if (result.success) {
self.log('firebase get SUCCESS');
for (codeKey in result.data)
if (result.data[codeKey].code)
self.extendJson(json, result.data[codeKey].code);
//self.log('json');
//self.log(json);
//if (params.success) self.do(params.success,result.data);
} else {
self.log('firebase get ERROR');
//if (params.error) self.do(params.error, result.error);
// alert errore di connessione. alert riprova
}
self.do(data);
//self.do(data);
});
};
this.modules = {};
this.modulesLoading = {};
this.fileType = function (fileName) {
return /(?:\.([^.]+))?$/.exec(fileName)[1];
};
this.jsoncToJson = function (jsoncText) {
return jsoncText.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '$1').replace(/\r/, "\n").replace(/\n[\n]+/, "\n");
// https://stackoverflow.com/questions/244777/can-comments-be-used-in-json/24545329
};
//var json = jsoncToJson('https://fantacards.com/app/data.jsonc');
//console.log(json);
this.loadModule = function (mod) {
/* self.log('loadModule');
self.log(mod); */
// params: {files, onComplete}
// self.cloneObject(params.json) to avoid to remove from initial params
//if (typeof setup.modules == 'string') setup.modules = [setup.modules];
if (!self.modulesLoading[mod.name] && !self.modules[mod.name]) {
self.modulesLoading[mod.name] = true;
return new Promise(function (resolve, reject) {
//mod = self.replaceProperties(mod);
//self.log(mod);
const getAPIData = new XMLHttpRequest();
getAPIData.open("GET", mod.url);
getAPIData.onload = function () {
self.modulesLoading[mod.name] = false;
//console.log(getAPIData);
let responseText = getAPIData.responseText;
if (self.fileType(getAPIData.responseURL) == 'jsonc')
responseText = self.jsoncToJson(responseText);
// try
const result = JSON.parse(responseText);
// error self.log('Wrong JSON in module '+ mod.name);
if (self.isJson(result)) {
self.modules[mod.name] = result;
self.extendJson(self.json, result);
self.log('Loaded module ' + mod.name, 'grey');
} else {
self.log('Wrong JSON in module ' + mod.name, 'red');
}
resolve();
};
getAPIData.onerror = function () {
self.modulesLoading[mod.name] = false;
};
getAPIData.send();
});
} else {
self.log('Module ' + mod.name + ' already loaded', 'orange');
}
};
/* var loadPlugin = function (url) {
//self.log('loading ' + url);
return new Promise(function(resolve, reject) {
var type = 'script';
if (url.endsWith('.css')) type = 'link';
let obj = document.createElement(type);
// obj.src = url;
obj.async = false;
obj.onload = function() {
resolve(url);
};
obj.onerror = function() {
self.log('error loading: '+url);
reject(url);
};
if (type === 'script') {
if (url) obj.src = url;
//if (code) obj.text = code;
obj.location = document.body;
document.body.appendChild(obj);
} else {
obj.href = url;
obj.rel = 'stylesheet';
obj.type = 'text/css';
obj.location = document.head;
document.head.appendChild(obj);
}
//self.log('obj');
//self.log(obj);
});
} */
var loadPlugin = function (params) {
//self.log('loading ' + url);
return new Promise(function (resolve, reject) {
var tag = 'script', type = 'text/javascript';
if (params.type == 'script') { tag = 'script'; type = 'text/javascript'; }
else if (params.type == 'module') { tag = 'script'; type = 'module'; }
else if (params.type == 'tailwind-config') { tag = 'script'; type = 'tailwind-config'; }
else if (params.type == 'link') { tag = 'link'; type = 'text/css'; }
else if (params.type == 'font') { tag = 'link'; type = undefined; }
//if (!tag)
// tag = (url.endsWith('.js')) ? 'script' : 'link';
let obj = document.createElement(tag);
if (params.content)
obj.appendChild(document.createTextNode(params.content));
obj.async = false;
obj.onload = function () {
self.pluginsLoaded[params.name] = { version: "1.0.0" };
self.log('Loaded plugin ' + params.name, 'grey');
resolve(params.url);
};
obj.onerror = function () {
self.log('Error loading plugin ' + params.url, 'red');
reject(params.url);
};
if (tag === 'script') {
if (params.url) obj.src = params.url;
//if (code) obj.text = code;
obj.location = document.body;
obj.type = type || 'text/javascript';
/* if (type == 'tailwind-config') {
self.log('obj');
self.log(obj);
} */
document.body.appendChild(obj);
} else if (tag === 'link') {
obj.rel = params.rel || 'stylesheet';
obj.location = document.head;
if (params.url) obj.href = params.url;
if (type) obj.type = type;
if (params.as) obj.as = params.as;
document.head.appendChild(obj);
}
});
};
/* var loadPlugin = function (url, tag, rel, as) {
//self.log('loading ' + url);
//alert(url);
return new Promise(function(resolve, reject) {
if (tag == 'js') tag = 'script';
if (tag == 'css') tag = 'link';
if (!tag)
tag = (url.endsWith('.js')) ? 'script' : 'link';
let obj = document.createElement(tag);
obj.async = false;
obj.onload = function() {
self.log('loaded plugin: '+url);
resolve(url);
};
obj.onerror = function() {
self.log('error loading: '+url);
reject(url);
};
if (tag === 'script') {
if (url) obj.src = url;
//if (code) obj.text = code;
obj.location = document.body;
document.body.appendChild(obj);
} else {
obj.href = url;
obj.rel = rel || 'stylesheet';
if (obj.rel == 'stylesheet')
obj.type = 'text/css';
if (as)
obj.as = as;
obj.location = document.head;
document.head.appendChild(obj);
}
});
}
*/
this.uiLoaded = {};
this.pluginsLoaded = {};
//The Firebase Realtime Database lets you store and query user data, and makes it available between users in realtime
this.findUrl = function (array, url) {
for (var item of array) {
if (item.url == url)
return true;
}
};
/* this.export = function (params) {
// {name, data}
if (params && params.name && params.data) {
let element = document.createElement('a');
element.style.display = 'none';
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(params.data)));
element.setAttribute('download', params.name);
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
} else {
self.log('"export" requires name and data attributes');
}
} */
/* this.exportData = function (path) {
// data
const fileName = self.replaceAll(path, ' ', '.') + '.json';
const jsonData = self.element({path: path, root: params.root});
self.export({name: fileName, data: jsonData});
}
*/
this.loadPlugins = function () {
//self.log('loadPlugins');
//var setup = json.setup;
// TEMPORAL API
// https://cdn.jsdelivr.net/npm/@cogitatio/tc39-temporal@0.0.12-alpha.2/index.js
// https://cdn.jsdelivr.net/npm/cogitatio-tc39-temporal@1.0.2/index.js
/* */
var filesToLoad = [];
// plugins
if (self.json.plugins) {
for (var index in self.json.plugins) {
var plugin = self.json.plugins[index];
//self.log('loading ' + plugin.name + '...');
var version = plugin.version || '';
if (!plugin.ondemand) { // V. >= 1.0.2
if (plugin.url) { // directly loaded
// plugin.name and version are needed?
if (!self.findUrl(filesToLoad, plugin.url)) { // not included yet
filesToLoad.push({ name: plugin.name, url: plugin.url, type: plugin.type });
}
} else { // from resources (TO DO: remove)
var pluginsFiles = plugin.files || self.json.resources.pluginsFiles[plugin.name];
// moved in loadPlugin = ... onload
/* self.pluginsLoaded[plugin.name] = {
version: version
}; */
if (!Array.isArray(pluginsFiles))
pluginsFiles = [pluginsFiles];
for (item of pluginsFiles) {
var url = self.replaceAll(item.url, '{version}', version);
if (plugin.params) url += '?' + plugin.params;
let pluginName = plugin.name || item.name;
if (!url || !self.findUrl(filesToLoad, url)) // not included yet
filesToLoad.push({ name: pluginName, url: url, type: item.type, content: item.content });
}
}
}
}
}
// ui
/* for (var index in config.ui) {
var configUI = config.ui[index];
//self.log('loading ' + configUI.name + '...');
var version = configUI.version || '';
var uiFiles = self.json.resources.uiFiles[configUI.name];
if (!Array.isArray(uiFiles))
uiFiles = [uiFiles];
for (item of uiFiles) {
var url = self.replaceAll(item.url, '{version}', version);
if (!self.findUrl(filesToLoad, url)) // not included yet
filesToLoad.push({url: url, type: item.type, content: item.content});
}
} */
// Auto load Google Fonts
// TO DO: comment
for (fontName of self.findValues(self.json, 'font-family')) {
if (self.json.resources.googleFonts.indexOf(fontName) >= 0) {
//alert(fontName);
fontName = self.replaceAll(fontName, ' ', '+');
//filesToLoad.push({type: 'font', url:'https://fonts.googleapis.com/css2?family='+fontName+'&display=swap', rel:'preload', as:'font'});
filesToLoad.push({ type: 'link', url: 'https://fonts.googleapis.com/css2?family=' + fontName });
// +'&display=swap' // https://css-tricks.com/almanac/properties/f/font-display/
}
}
// Auto load plugins (firebase only)
/* if (config.plugins && config.plugins.autoload) {
self.log('plugins autoload');
//for (var index in self.json.resources.pluginsFunctions) {
var pluginFunctions = self.json.resources.pluginsFirebase; // pluginFunctions
for (var index in self.json.resources.pluginsFirebase) {
//self.log(index + ':' + self.keyInFiles(index));
if (self.keyInFiles(index)) {
if (pluginFunctions[index]) {
var plugins = [];
if (Array.isArray(pluginFunctions[index]))
plugins = pluginFunctions[index];
else
plugins = [pluginFunctions[index]];
for (plugin of plugins) {
self.log('loading ' + plugin.name + '...');
self.pluginsLoaded[plugin.name] = version;
var version = plugin.version || '';
var pluginsFiles = self.json.resources.pluginsFiles[plugin.name];
if (!Array.isArray(pluginsFiles))
pluginsFiles = [pluginsFiles];
for (item of pluginsFiles) {
var url = self.replaceAll(item.url, '{version}', version);
if (!self.findUrl(filesToLoad, url)) // not included yet
filesToLoad.push({url: url, type: item.type, content: item.content});
}
}
}
}
}
} */
// load multiple scripts in sequence
// https://bit.ly/3nT5Ky1
// one after another
// https://medium.com/@asimmittal/sequential-script-loading-in-javascript-a0b77ca9467c
// load multi js and css
// https://sphacks.io/load-multiple-js-scripts-dynamically-without-jquery/
// save all Promises as array
let promises = [];
//promises.push(loadPlugin("https://fonts.googleapis.com", 'link', 'preconnect'));
//promises.push(loadPlugin("https://fonts.gstatic.com", 'link', 'preconnect'));
filesToLoad.forEach(function (item) {
if (item.url)
promises.push(loadPlugin({ name: item.name, url: item.url, type: item.type, rel: item.rel, as: item.as, content: item.content }));
else
loadPlugin({ name: item.name, url: item.url, type: item.type, rel: item.rel, as: item.as, content: item.content });
//promises.push(loadPlugin(url));
});
//self.log(filesToLoad);
Promise.all(promises).then(function () {
self.start();
}).catch(function (script) {
self.log('Failed to load');
self.log(script);
});
};
this.modulesList = function (modulesObj) {
/* self.log('modulesList');
self.log('modulesObj');
self.log(modulesObj);
*/
var modulesList = [];
if (modulesObj) {
for (key in modulesObj) {
var mod = self.replaceProperties(modulesObj[key]);
modulesList = modulesList.concat(mod);
}
}
return self.replaceProperties(modulesObj);
};
this.loadModules = function () {
//self.log('loadModules');
if (self.json.setup.modules) {
var modules = self.replaceProperties(self.json.setup.modules); // replace {page:id}
/* self.log('modules');
self.log(modules); */
var promises = [];
modules.forEach(function (item) {
if (!self.modulesLoading[item.name] && !self.modules[item.name]) {
promises.push(self.loadModule(item));
}
});
Promise.all(promises).then(function () {
self.loadPlugins();
}).catch(function (file) {
self.log('Failed to load');
self.log(file);
});
} else {
self.loadPlugins();
}
};
this.moduleExecuted = {};
this.addModule = function (params) {
if (!self.modules[params.name]) {
var promises = [];
//var ideModule = {name: 'ide', url: 'https://jsonic.io/app/modules/ide.json'};
promises.push(self.loadModule(params));
Promise.all(promises).then(function () {
if (!self.moduleExecuted[params.name]) {
//self.log('all modules loaded');
var module = self.modules[params.name];
if (module.html) {
self.moduleExecuted[params.name] = true;
self.html(module.html);
// TO DO: add also on, funcions ...
}
}
if (params.success)
self.do(params.success);
//self.do(params.success);
}).catch(function (file) {
self.log('Failed to load');
self.log(file);
if (params.error)
self.do(params.error);
//self.do(params.error);
});
} else {
if (params.success)
self.do(params.success);
//self.do(params.success);
}
};
this.loadModuleGlobal = function () {
self.log('loadModuleGlobal');
var promises = [];
var modules = []; // we need it to keep the order of the modules given in the config
for (let key in self.json.setup.modules) {
var mod = self.replaceProperties(self.json.setup.modules[key]);
modules = modules.concat(self.cloneObject(mod));
}
/* self.log('modules');
self.log(modules); */
for (let mod of modules)
promises.push(self.loadModule(mod));
//var pageModule = {name: 'global', url: '/app/modules/global.json'};
//var ideModule = {name: 'ide', url: '/app/modules/ide.json'};
//promises.push(self.loadModule(ideModule)); // if admin
Promise.all(promises).then(function () {
//self.log('page module loaded');
//if (self.json.modules) {
//self.json.setup.modules = self.cloneObject(self.json.modules); // required modules
//self.json.setup.modules.app.push(pageModule); // page module
//self.json.setup.modules.app.push(ideModule); // ide module if admin
self.loadModules();
//}
}).catch(function (file) {
self.log('Failed to load');
self.log(file);
});
};
/* this.extendJsonFromModules = function () {
self.log('extendJsonFromModules');
for (var mod in self.modules) {
//self.extendJsonFromElement(self.modules[mod.name]);
self.extendJson(json, self.modules[mod]);
}
} */
/* DA SISTEMARE - TEMPORANEO */
this.code = function (params, selectorParams) {
/* self.log("params");
self.log(params);
self.log("selectorParams");
self.log(selectorParams); */
let container = self.selector(params.selector || params.container) || self.selector(selectorParams);
//var container = self.selector(params) || self.selector(selectorParams);
self.log("this.code");
self.log("container");
self.log(container);
var editorContainer = container.slice(1);
//if (editorContainer.startsWith('#')) {editorContainer.slice(1);} // remove #
var editor = ace.edit(editorContainer);
var value = params.value; // else value = params;
if (!params.do || (params.do == 'set')) {
//var langTools = ace.require('ace/ext/language_tools');
if (params.theme) editor.setTheme(params.theme); // "ace/theme/monokai"
var editorMode = params.mode || "ace/mode/json";
editor.getSession().setMode(editorMode);
var editorStyle = self.extend({
background: "rgba(255,255,255,0)"
}, params.style);
//$(container).css(editorStyle); //editor.container.style
/* self.css({
style: editorStyle
}, {
container: container
}); */ // Eventualmente
var codeOptions = self.extend({
fontSize: "11pt",
selectionStyle: "line",
highlightActiveLine: false,
wrap: true,
showLineNumbers: false,
showGutter: false,
fixedWidthGutter: false,
readOnly: true,
//enableBasicAutocompletion: false,
//enableSnippets: false,
//enableLiveAutocompletion: false,
}, params.options);
// https://github.com/ajaxorg/ace/wiki/Configuring-Ace
editor.setOptions(codeOptions);
var codeString;
if (typeof value == 'string')
if (editorMode == "ace/mode/json")
codeString = JSON.stringify(JSON.parse(value), null, '\t'); // json formatting
else
codeString = value;
else {
if (editorMode == "ace/mode/json")
codeString = JSON.stringify(value, null, '\t');
else {
var functionObj = self.docElement(value.function);
var functionParams = value.params;
codeString = functionObj(functionParams);
}
}
var codeRows = codeString.split(/\r\n|\r|\n/).length;
// $(container).css({
// height: Number(21 * codeRows) + 'px'
// });
/* self.css({
style: {
height: Number(21*codeRows)+"px"
}
}, {
container: container
}); */ // Eventualmente
editor.setValue(codeString, -1);
} else if (params.do == 'get') {
return editor.getValue();
} else {
self.log('"code" function requires value param');
}
};
this.init = function (appString, modulesString) {
console.log('init');
// app(String: app url) (Object = json app)
// modules(String): modules "ui,daisyui,svg"
/* json = { // the jsonic app tree
blocks: {},
parts: {},
css: {},
do: {},
on: {},
texts: {},
data: {},
var: {}
}; */
//self.app = self.getParams(); // from url
if (typeof appString == 'string') {
let modules = [{ "name": "app", "url": appString }];
let modulesNames = (modulesString) ? modulesString.split(",") : [];
for (let modName of modulesNames) {
modules.push({ "name": modName, "url": "jsonic/modules/" + modName + ".json" });
}
self.json.setup = { "modules": modules };
} else {
if (appString) self.extendJson(self.json, appString);
/* // TO DO: remove the requirement of resources.json
if (!self.json.setup || !self.json.setup.modules) {
self.json.setup = {
"modules": [
{
"name": "resources",
"url": "https://jsonic.io/app/modules/lib/resources.json"
}
]
}
} */
if (appString.css) self.defineCss(appString.css); // can be removed?
}
self.loadModuleGlobal();
};
function toJsonNode(xml) {
let obj = {};
if (xml.nodeType == 1) {
if (xml.attributes.length > 0) {
obj["attr"] = {};
for (let j = 0; j < xml.attributes.length; j++) {
let attribute = xml.attributes.item(j);
obj["attr"][attribute.nodeName] = attribute.nodeValue;
}
}
}
if (xml.hasChildNodes()) {
for (let i = 0; i < xml.childNodes.length; i++) {
let item = xml.childNodes.item(i);
let nodeName = item.nodeName;
if (item.nodeType == 3 && nodeName == "#text") {
if (/^\s+$/.test(item.nodeValue)) {
} else obj.text = item.nodeValue;
} else {
if (typeof obj[nodeName] == "undefined") {
obj[nodeName] = toJsonNode(item);
} else {
if (!Array.isArray(obj[nodeName]))
obj[nodeName] = [obj[nodeName]];
obj[nodeName].push(toJsonNode(item));
}
}
}
}
return obj;
}
this.htmlToJson = function (text) {
let xmlDoc = new DOMParser().parseFromString(text, "text/xml");
return JSON.stringify(toJsonNode(xmlDoc), null, "\t");
};
this.elementToJson = function (selector) {
let el = document.querySelector(selector);
return self.htmlToJson(el.getHTML());
};
function clearSelection() {
if (window.getSelection) { window.getSelection().removeAllRanges(); }
else if (document.selection) { document.selection.empty(); }
}
this.importHtml = function (htmlText) {
// use modal and monaco js
if (!htmlText)
htmlText = prompt("html/xml");
if (htmlText) {
let jsonDoc = self.htmlToJson(htmlText);
let textarea = document.createElement("textarea");
textarea.value = jsonDoc;
textarea.style = "position: absolute; z-index: 999999; background: white; width:100vw; height:100vh";
//document.body.innerHTML = '';
document.body.appendChild(textarea);
//document.execCommand("copy");
textarea.addEventListener('click', function () {
textarea.remove();
navigator.clipboard.writeText(textarea.value).then(() => console.log('copied!'));
});
//console.log(JSON.parse(jsonDoc));
}
};
// https://github.com/ktskts/html2json/blob/master/src/html2json.js
/*
var Util = {
div : null,
attrs: "id,name,style,class,value,src,href,width,height,title,type".split(","),
getJson: function(childNodes, attrs, length) {
var result = [];
for ( var i = 0, len = childNodes.length; i < len; i++) {
var item = childNodes[i];
if (item.nodeType == 3) { // textual content in an element or attribute
result.push({
text : item.nodeValue
})
} else if (item.nodeType == 1) { // element
var obj = {
//tag : item.nodeName.toLowerCase(),
attr : {}
};
var flag = false;
//for ie6
if (attrs) {
for (var j = 0; j < length; j++){
if (attrs[j] == 'style'){
var sStyle = item.getAttribute('style').cssText;
if(sStyle){
obj.attr["style"] = sStyle;
flag = true;
}
} else {
var attrNode = item.attributes[attrs[j]];
if(attrNode && attrNode.nodeType === 2){
var value = attrNode.value;
if(value && value != 'null'){
obj.attr[attrs[j]] = value;
flag = true;
}
}
}
}
} else {
if (item.attributes.length) {
for ( var n = 0, l = item.attributes.length; n < l; n++) {
var value = item.attributes[n].value;
if(value){
flag = true;
obj.attr[item.attributes[n].name] = value;
}
}
}
}
let nodeOut = {};
let nodeTag = item.nodeName.toLowerCase();
let nodeChild = Util.getJson(item.childNodes, attrs, length);
nodeOut[nodeTag] = {};
self.log( 'item.childNodes');
self.log( item.childNodes);
self.log( 'nodeChild');
self.log( nodeChild);
//self.log( item.textContent);
nodeOut[nodeTag].html = nodeChild;
if (flag) nodeOut[nodeTag].attr = obj.attr;
result.push(nodeOut);
} else {
// do nothing
}
}
if (result.length == 1) return result[0]
else if (result.length > 1) return result;
}
}
this.html2json = function(text) {
if (!Util.div) Util.div = document.createElement('div');
Util.div.innerHTML = text;
return {html: Util.getJson(Util.div.childNodes)};
};
*/
/* var jsonicOptions = self.extend({
}, options); */
if (typeof options == 'object') {
} else if (options)
self.init(arguments[0], arguments[1]);
} // of jsonicObject
//var jsonicApp = jsonApp;
var jsonApp = new jsonAppObj();
var js = jsonApp;
var jsonic = jsonApp;
//window.jsonic = new jsonicObject();
/* var receiveMessage = function (process) {
if (ThunkableWebviewerExtension)
ThunkableWebviewerExtension.receiveMessage(process);
}
var postMessage = function (message) {
if (ThunkableWebviewerExtension)
ThunkableWebviewerExtension.postMessage(message);
} */
/* "on": {
"init": [
{
"thunkable": {
"postMessage": "Hi Rick!"
}
},
{
"thunkable": {
"receiveMessage": {
"alert": "message: {result}"
}
}
}
]
}
*/