AnP/Public/ecma/Application/Components.ecma.js

392 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 {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]
].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"
], (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;
})();