260 lines
8.5 KiB
JavaScript
260 lines
8.5 KiB
JavaScript
"use strict";
|
|
|
|
import {Check} from "../Utils/Check.ecma.js";
|
|
import {Utils} from "../Utils/Utils.ecma.js";
|
|
import {Patterns} from "../Utils/Patterns.ecma.js";
|
|
import {EventsManager} from "../Managers/EventsManager.ecma.js";
|
|
|
|
/**
|
|
* @typedef {import("./AnP.ecma.js").AnP} AnP
|
|
*/
|
|
|
|
/**
|
|
* @callback anp_attributes_name_callback
|
|
* @param {!string} name
|
|
* @param {?string} value
|
|
* @returns {void}
|
|
*/
|
|
|
|
/**
|
|
* @callback anp_attributes_remove_callback
|
|
* @param {!string} name
|
|
* @returns {void}
|
|
*/
|
|
|
|
/**
|
|
* @callback anp_attributes_load_callback
|
|
* @param {!HTMLElement} item
|
|
* @returns {void}
|
|
*/
|
|
|
|
/**
|
|
* @class
|
|
* @constructor
|
|
* @param {!AnP} anp
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
export const Attributes = (function(){
|
|
|
|
/**
|
|
* @constructs Attributes
|
|
* @param {!AnP} anp
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const Attributes = function(anp){
|
|
|
|
/** @type {Attributes} */
|
|
const self = this,
|
|
/** @type {Array.<string>} */
|
|
without_values = [
|
|
"disabled", "readonly"
|
|
],
|
|
/** @type {Array.<string>} */
|
|
normals = [
|
|
"src", "class", "title", "id", "alt", "target", "href", "style", "lang",
|
|
"type", "name", "placeholder", "min", "max", "value", "step", "disabled",
|
|
"readonly"
|
|
];
|
|
/** @type {boolean} */
|
|
let started = false;
|
|
|
|
/**
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const constructor = () => {};
|
|
|
|
/**
|
|
* @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;
|
|
};
|
|
|
|
return end(started ? false : started = true);
|
|
};
|
|
|
|
/**
|
|
* @param {!(Object.<string, any|null>|Array.<any|null>)} attributes
|
|
* @param {!Array.<string>} included
|
|
* @param {!Array.<string>} excluded
|
|
* @param {!anp_attributes_name_callback} callback
|
|
* @param {!Object.<string, any|null>} parameters
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const process_fixed = (attributes, included, excluded, callback, parameters) => {
|
|
if(Check.is_dictionary(attributes)){
|
|
|
|
/** @type {boolean} */
|
|
const has_events_loader = !!parameters.on_load_for_events;
|
|
|
|
for(let name in attributes){
|
|
|
|
/** @type {any|null} */
|
|
const value = attributes[name],
|
|
/** @type {string} */
|
|
pascal = name.replace(Patterns.RE_ATTRIBUTE_BAD_SET_CHARACTERS, "-").toLowerCase();
|
|
|
|
if(
|
|
(!included.length || included.includes(pascal)) &&
|
|
(!excluded.length || !excluded.includes(pascal))
|
|
){
|
|
if(pascal.slice(0, 2) == "on" && Check.is_function(value)){
|
|
parameters.on_load_for_events || (parameters.on_load_for_events = new EventsManager());
|
|
if(name == "on_load_execute")
|
|
parameters.on_load_execute = value;
|
|
else
|
|
parameters.on_load_for_events.add(item => {
|
|
item.addEventListener(pascal.replace(Patterns.RE_CLEAN_EVENT_NAME, ""), event => value(item, event));
|
|
});
|
|
continue;
|
|
};
|
|
callback(
|
|
((
|
|
normals.includes(pascal) ||
|
|
["data-", "aria-"].includes(pascal.slice(0, 5))
|
|
) ? "" : "data-") + pascal,
|
|
(
|
|
without_values.includes(pascal) ? null :
|
|
Check.is_bool(value) ? value ? "true" : "false" :
|
|
Check.is_json_object(value) ? Utils.variables_encode(value) :
|
|
"" + value)
|
|
);
|
|
};
|
|
|
|
};
|
|
|
|
if(!has_events_loader && parameters.on_load_for_events){
|
|
|
|
/** @type {string} */
|
|
const chain = anp.random_chain();
|
|
|
|
callback("data-anp-events-loader", chain);
|
|
anp.preload("[data-anp-events-loader=" + chain + "]", (item, asynchronous, ok) => {
|
|
anp.remove_random_chain(chain);
|
|
if(ok){
|
|
item.removeAttribute("data-anp-events-loader");
|
|
parameters.on_load_for_events.execute(item);
|
|
parameters.on_load_execute && parameters.on_load_execute(item);
|
|
};
|
|
});
|
|
|
|
};
|
|
|
|
}else if(Check.is_array(attributes))
|
|
attributes.forEach(group => {
|
|
process_fixed(group, included, excluded, callback, parameters);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* @param {!(Object.<string, any|null>|Array.<any|null>)} attributes
|
|
* @param {?(string|Array.<string>)} included
|
|
* @param {?(string|Array.<string>)} excluded
|
|
* @param {!anp_attributes_name_callback} callback
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const process = (attributes, included, excluded, callback) => {
|
|
process_fixed(attributes, Utils.get_pascal_keys(included), Utils.get_pascal_keys(excluded), callback, {});
|
|
};
|
|
|
|
/**
|
|
* @param {!(Object.<string, any|null>|Array.<any|null>)} attributes
|
|
* @param {?(string|Array.<string>)} [included = null]
|
|
* @param {?(string|Array.<string>)} [excluded = null]
|
|
* @returns {string}
|
|
* @access public
|
|
*/
|
|
this.create = (attributes, included = null, excluded = null) => {
|
|
|
|
/** @type {string} */
|
|
let html = ``;
|
|
|
|
process(attributes, included, excluded, (name, value) => {
|
|
html += ` ` + name + (value === null ? `` : `="` + value + `"`)
|
|
});
|
|
|
|
return html;
|
|
};
|
|
|
|
/**
|
|
* @param {!(string|HTMLElement)} item
|
|
* @param {!(Object.<string, any|null>|Array.<any|null>)} attributes
|
|
* @param {?(string|Array.<string>)} [included = null]
|
|
* @param {?(string|Array.<string>)} [excluded = null]
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
this.set = (item, attributes, included, excluded) => {
|
|
anp.preload(item, (item, asynchronous, ok) => {
|
|
ok && process(attributes, included, excluded, (name, value) => {
|
|
item.setAttribute(name, value);
|
|
});
|
|
});
|
|
};
|
|
|
|
constructor();
|
|
|
|
};
|
|
|
|
/**
|
|
* @param {!(string|Array.<string>)} classes
|
|
* @returns {Array.<string>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Attributes.get_classes = classes => Utils.get_pascal_keys(
|
|
Check.is_array(classes) ? classes :
|
|
Check.is_string(classes) ? classes.split(Patterns.RE_SPACES) :
|
|
[]);
|
|
|
|
/**
|
|
* @param {!(string|Array.<string>)} classes
|
|
* @param {?(Object.<string, any|null>|Array.<any|null>)} attributes
|
|
* @returns {Array.<string>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Attributes.join_classes = (...sets) => Utils.get_pascal_keys(
|
|
sets.reduce((set, new_classes) => set.concat(Attributes.get_classes(new_classes)), [])
|
|
).join(" ");
|
|
|
|
/**
|
|
* @param {!(Object.<string, any|null>|HTMLElement)} item
|
|
* @param {!(string|Array.<string>)} names
|
|
* @returns {Object.<string, any|null>|void}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Attributes.remove = (item, names) => {
|
|
|
|
/** @type {anp_attributes_remove_callback|null} */
|
|
var action = (
|
|
Check.is_dictionary(item) ? name => {
|
|
if(item[name] !== undefined)
|
|
delete item[name];
|
|
} :
|
|
Check.is_html_item(item) ? name => {
|
|
item.hasAttribute(name) &&
|
|
item.removeAttribute(name)
|
|
} :
|
|
null);
|
|
|
|
action && Utils.get_pascal_keys(names).forEach(action);
|
|
|
|
if(Check.is_dictionary(item))
|
|
return item;
|
|
};
|
|
|
|
return Attributes;
|
|
})(); |