394 lines
14 KiB
JavaScript
394 lines
14 KiB
JavaScript
"use strict";
|
|
|
|
import {Utils} from "../Utils/Utils.ecma.js";
|
|
import {Check} from "../Utils/Check.ecma.js";
|
|
import {Attributes} from "./Attributes.ecma.js";
|
|
import {LicensesComponent} from "../Components/LicensesComponent.ecma.js";
|
|
import {FormsComponent} from "../Components/FormsComponent.ecma.js";
|
|
import {BaseComponent} from "../Components/BaseComponent.ecma.js";
|
|
|
|
/**
|
|
* @typedef {import("./AnP.ecma.js").AnP} AnP
|
|
* @typedef {import("../Models/ThreadModel.ecma.js").ThreadModel} ThreadModel
|
|
*/
|
|
|
|
/**
|
|
* @callback anp_event_callback
|
|
* @param {!Event} event
|
|
* @returns {any|null|void}
|
|
*/
|
|
|
|
/**
|
|
* @class
|
|
* @constructor
|
|
* @param {!AnP} anp
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
export const Components = (function(){
|
|
|
|
/**
|
|
* @constructs Components
|
|
* @param {!AnP} anp
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const Components = function(anp){
|
|
|
|
/** @type {Components} */
|
|
const self = this;
|
|
/** @type {boolean} */
|
|
let started = false,
|
|
/** @type {ThreadModel|null} */
|
|
thread = null;
|
|
|
|
/**
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const constructor = () => {
|
|
|
|
[
|
|
["licenses", LicensesComponent],
|
|
["base", BaseComponent],
|
|
["forms", FormsComponent]
|
|
].forEach(([name, Class]) => {
|
|
if(Class){
|
|
self[name + "_component"] = new Class(anp);
|
|
Check.is_function(self[name + "_component"].build) &&
|
|
(self[name] = self[name + "_component"].build);
|
|
};
|
|
});
|
|
|
|
};
|
|
|
|
/**
|
|
* @param {!ThreadModel} thread
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const analyzer = thread => {
|
|
if(anp.item_self == document)
|
|
return;
|
|
|
|
anp.item_self.querySelectorAll(".image[data-status=unloaded]").forEach(image => {
|
|
image.setAttribute("data-status", "loading");
|
|
image.querySelector("img").setAttribute("src", Utils.variables_decode(image.getAttribute("data-sources"))[0]);
|
|
});
|
|
|
|
};
|
|
|
|
/**
|
|
* @param {?anp_start_callback} callback
|
|
* @returns {boolean}
|
|
* @access public
|
|
*/
|
|
this.start = (callback = null) => {
|
|
|
|
/** @type {!anp_start_callback} */
|
|
const end = ok => {
|
|
Utils.execute(callback, ok);
|
|
return ok;
|
|
};
|
|
|
|
if(started)
|
|
return end(false);
|
|
started = true;
|
|
|
|
thread = anp.threads.add(analyzer, {
|
|
bucle : true,
|
|
timer : 100
|
|
});
|
|
|
|
Utils.execute_items([
|
|
"licenses", "base", "forms"
|
|
], (key, next) => {
|
|
self[key + "_component"].start(ok => {
|
|
next();
|
|
});
|
|
}, () => {
|
|
end(true);
|
|
});
|
|
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* @param {!(Array.<any|null>)} childs
|
|
* @returns {Array.<Array.<string, Object.<string, any|null>|Array.<any|null>|null>, Array.<Array.<any|null>>|null>>}
|
|
* @access private
|
|
*/
|
|
const set_childs = childs => Check.is_string(childs[0]) ? [childs] : childs;
|
|
|
|
/**
|
|
* @param {...Array.<string, Object.<string, any|null>|Array.<any|null>|null>, Array.<Array.<any|null>>|null} items
|
|
* @returns {string}
|
|
* @access public
|
|
*/
|
|
this.set = (...items) => items.reduce((html, [tag, attributes, childs]) => {
|
|
|
|
const subitem = (
|
|
self[tag] && (!attributes || !attributes.built) ? self[tag](...Utils.get_array(attributes)) :
|
|
`<` + tag + anp.attributes.create(attributes, null, "built") + `>` + (
|
|
Check.is_array(childs) && childs.length ? self.set(...set_childs(childs)) :
|
|
Check.is_null_or_undefined(childs) ? "" :
|
|
"" + childs) + `</` + tag + `>`);
|
|
|
|
return html + (Check.is_array(subitem) ? self.set(...[subitem]) : subitem);
|
|
}, ``);
|
|
|
|
/**
|
|
* @param {!(string|HTMLElement)} item
|
|
* @param {...Array.<string, Object.<string, any|null>|Array.<any|null>|null>, Array.<Array.<any|null>>|null>} items
|
|
* @returns {string}
|
|
* @access public
|
|
*/
|
|
this.set_to = (item, ...items) => {
|
|
anp.preload(item, (item, asynchronous, ok) => {
|
|
ok && items.forEach(([tag, attributes, childs]) => {
|
|
if(self[tag] && (!attributes || !attributes.built)){
|
|
|
|
/** @type {string|Array.<any|null>|HTMLElement|NodeList} */
|
|
const subitem = self[tag](...Utils.get_array(attributes));
|
|
|
|
if(Check.is_string(subitem))
|
|
item.innerHTML += subitem;
|
|
else if(Check.is_array(subitem))
|
|
self.set_to(item, subitem);
|
|
else if(Check.is_html_items(subitem))
|
|
subitem.forEach(subnode => item.appendChild(subnode));
|
|
else if(Check.is_html_item(subitem))
|
|
item.appendChild(subitem);
|
|
|
|
}else{
|
|
|
|
/** @type {HTMLElement} */
|
|
const subitem = item.appendChild(document.createElement(tag));
|
|
|
|
anp.attributes.set(subitem, attributes, null, ["built"]);
|
|
Check.is_array(childs) && childs.length && self.set_to(subitem, ...set_childs(childs));
|
|
|
|
};
|
|
});
|
|
});
|
|
};
|
|
|
|
/**
|
|
* @param {!(Object.<string, any|null>|Array.<any|null>)} inputs
|
|
* @returns {Array.<any|null>}
|
|
* @access public
|
|
*/
|
|
this.image = inputs => {
|
|
|
|
/** @type {Object.<string, any|null>} */
|
|
const attributes = Utils.get_dictionary(Check.is_array_string(inputs) ? {sources : inputs} : inputs),
|
|
/** @type {Array.<string>} */
|
|
source_keys = ["images", "sources", "image", "source", "src"],
|
|
/** @type {Array.<string>} */
|
|
images = Utils.get_strings(Utils.get_value(source_keys, attributes));
|
|
|
|
Attributes.remove(attributes, source_keys.concat([
|
|
"class", "classes", "status", "data_status", "data_i", "data_sources"
|
|
]));
|
|
|
|
return ["span", {
|
|
...attributes,
|
|
class : Attributes.join_classes("image", Utils.get_value(["class", "classes"], attributes)),
|
|
data_status : "unloaded",
|
|
data_sources : images,
|
|
data_i : 0
|
|
}, [
|
|
["img", {
|
|
// on_load_execute : item => {
|
|
// item.setAttribute("src", images[0]);
|
|
// },
|
|
onload : (item, event) => {
|
|
item.parentNode.setAttribute("data-status", "loaded");
|
|
item.parentNode.querySelector("span").style.backgroundImage = "url('" + item.src + "')";
|
|
},
|
|
onerror : (item, event) => {
|
|
|
|
/** @type {Array.<string>} */
|
|
const images = Utils.variables_decode(item.parentNode.getAttribute("data-sources")),
|
|
/** @type {number} */
|
|
i = Number(item.parentNode.getAttribute("data-i")) + 1;
|
|
|
|
if(i < images.length){
|
|
item.parentNode.setAttribute("data-i", i);
|
|
item.setAttribute("src", images[i]);
|
|
}else
|
|
item.parentNode.setAttribute("data-status", "error");
|
|
|
|
},
|
|
...(attributes.title ? {alt : attributes.title} : {})
|
|
}],
|
|
["span"]
|
|
]];
|
|
};
|
|
|
|
/**
|
|
* @param {!string} name
|
|
* @param {!string} [tag = "span"]
|
|
* @param {?(Object.<string, any|null>|Array.<any|null>)} [attributes = null]
|
|
* @returns {Array.<any|null>}
|
|
* @access public
|
|
*/
|
|
this.icon = (name, tag = "span", attributes = null) => {
|
|
|
|
/** @type {Array.<any|null>|string|null} */
|
|
const childs = Utils.get_value(["content", "child", "childs"], attributes, null);
|
|
|
|
Attributes.remove(attributes = Utils.get_dictionary(attributes), [
|
|
["content", "child", "childs"]
|
|
]);
|
|
attributes.data_icon = name;
|
|
|
|
return [tag, attributes, childs];
|
|
};
|
|
|
|
/**
|
|
* @param {?string} base
|
|
* @param {?(Object.<string, any|null>|Array.<any|null>)} attributes
|
|
* @returns {Array.<any|null>}
|
|
* @access private
|
|
*/
|
|
const process_title = (base, attributes) => [
|
|
anp.i18n.get([base].concat(Utils.get_strings(Utils.get_value([
|
|
"title", "text", "texts", "default_text", "default_texts"
|
|
], attributes, []))), attributes),
|
|
(
|
|
!Check.is_null_or_undefined(Utils.get_dictionary(attributes).title) ||
|
|
Utils.get_value(["with_title", "has_title"], attributes, false)
|
|
)
|
|
];
|
|
|
|
/**
|
|
* @param {!string} name
|
|
* @param {!string} [tag = "span"]
|
|
* @param {?(Object.<string, any|null>|Array.<any|null>)} [attributes = null]
|
|
* @returns {Array.<any|null>}
|
|
* @access public
|
|
*/
|
|
this.i18n = (name, tag = "span", attributes = null) => {
|
|
|
|
/** @type {[string, boolean]} */
|
|
const [text, has_title] = process_title(name, attributes);
|
|
|
|
Attributes.remove(attributes = Utils.get_dictionary(attributes), [
|
|
"text", "texts", "default_text", "default_texts", "with_title", "has_title"
|
|
]);
|
|
attributes.data_i18n = name;
|
|
has_title && (attributes.title = text);
|
|
|
|
return [tag, attributes, text];
|
|
};
|
|
|
|
/**
|
|
* @param {!string} name
|
|
* @param {?(anp_event_callback|Object.<string, any|null>|Array.<any|null>)} [attributes = null]
|
|
* @returns {Array.<any|null>}
|
|
*/
|
|
this.button = (name, attributes = null) => {
|
|
|
|
/** @type {[string, boolean]} */
|
|
const [text, has_title] = process_title(name, {with_title : true, ...(
|
|
Check.is_function(attributes) ? attributes = {onclick : attributes} :
|
|
attributes)}),
|
|
/** @type {Array.<Array.<any|null>|string>} */
|
|
childs = [
|
|
self.icon(Utils.get_value(["icon", "data_icon"], attributes, name)),
|
|
self.i18n(name)
|
|
],
|
|
/** @type {Array.<any|null>|string|null} */
|
|
content = Utils.get_value(["child", "childs", "content"], attributes, null);
|
|
|
|
content && childs.push(content);
|
|
|
|
Attributes.remove(attributes = Utils.get_dictionary(attributes), [
|
|
"text", "texts", "default_text", "default_texts", "with_title", "has_title",
|
|
"icon", "data_icon", "child", "childs", "content"
|
|
]);
|
|
attributes.built = true;
|
|
attributes.type || (attributes.type = "button");
|
|
|
|
if(has_title){
|
|
attributes.title = text;
|
|
attributes.data_i18n = name;
|
|
attributes.data_i18n_without = true;
|
|
};
|
|
|
|
return ["button", {
|
|
...attributes,
|
|
}, childs];
|
|
};
|
|
|
|
/**
|
|
* @param {!Array.<Array.<any|null>|string>} items
|
|
* @param {?(Object.<string, any|null>|Array.<any|null>)} [attributes = null]
|
|
* @param {!string} [tag = "div"]
|
|
* @returns {Array.<any|null>}
|
|
* @access public
|
|
*/
|
|
this.group = (items, attributes = null, tag = "div") => {
|
|
|
|
/** @type {string} */
|
|
const classes = Attributes.join_classes("group", Utils.get_value(["class", "classes"], attributes));
|
|
|
|
Attributes.remove(attributes = Utils.get_dictionary(attributes), [
|
|
"class", "classes"
|
|
]);
|
|
attributes.class = classes;
|
|
|
|
return [tag, attributes, items];
|
|
};
|
|
|
|
/**
|
|
* @param {!Array.<Array.<any|null>|string>} buttons
|
|
* @param {?(Object.<string, any|null>|Array.<any|null>)} [attributes = null]
|
|
* @param {!string} [tag = "div"]
|
|
* @returns {Array.<any|null>}
|
|
* @access public
|
|
*/
|
|
this.buttons = (buttons, attributes = null, tag = "div") => self.group(buttons, Utils.get_dictionary([attributes, {
|
|
class : Attributes.join_classes("buttons", Utils.get_value(["class", "classes"], attributes))
|
|
}]), tag);
|
|
|
|
/**
|
|
* @param {?(Object.<string, any|null|Array.<any|null>)} [attributes = null]
|
|
* @param {?(Object.<string, any|null|Array.<any|null>)} [own_attributes = null]
|
|
* @returns {Array.<any|null>}
|
|
* @access public
|
|
*/
|
|
this.input = (attributes = null, own_attributes = null) => ["input", {
|
|
...Utils.get_dictionary(attributes),
|
|
...Utils.get_dictionary(own_attributes),
|
|
built : true
|
|
}];
|
|
|
|
/**
|
|
* @param {?(Object.<string, any|null|Array.<any|null>)} [attributes = null]
|
|
* @returns {Array.<any|null>}
|
|
* @access public
|
|
* @returns
|
|
*/
|
|
this.number = (attributes = null) => {
|
|
|
|
/** @type {string} */
|
|
const classes = Attributes.join_classes("input-field input-number", Utils.get_value(["class", "classes"], attributes));
|
|
|
|
Attributes.remove(attributes = Utils.get_dictionary(attributes), ["class", "classes"]);
|
|
|
|
return ["span", {class : classes}, [
|
|
["input", {
|
|
...attributes,
|
|
type : "number"
|
|
}]
|
|
]];
|
|
};
|
|
|
|
constructor();
|
|
|
|
};
|
|
|
|
return Components;
|
|
})(); |