329 lines
9.5 KiB
JavaScript
329 lines
9.5 KiB
JavaScript
"use strict";
|
|
|
|
import {Check} from "./Check.ecma.js";
|
|
|
|
/**
|
|
* @class Utils
|
|
* @constructor
|
|
* @returns {void}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
export const Utils = (function(){
|
|
|
|
/**
|
|
* @callback utils_execute_callback
|
|
* @param {...(any|null)} inputs
|
|
* @returns {any|null}
|
|
*/
|
|
|
|
/**
|
|
* @callback utils_default_callback
|
|
* @returns {void}
|
|
*/
|
|
|
|
/**
|
|
* @callback utils_execute_array_each_callback
|
|
* @param {?any} item
|
|
* @param {!utils_default_callback} callback
|
|
* @returns {void}
|
|
*/
|
|
|
|
/**
|
|
* @constructs Utils
|
|
* @returns {void}
|
|
* @access private
|
|
* @static
|
|
*/
|
|
const Utils = function(){};
|
|
|
|
/** @type {string} */
|
|
Utils.BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
|
/** @type {string} */
|
|
Utils.RANDOM_ALPHABET = "bHMnuamw/RUBk+xNvCXghsPdlSFG12rLoT0O3VZ=5QeWyI8pADqjcEfJ9Kt64i7Yz";
|
|
|
|
/**
|
|
* @param {...(any|null)} items
|
|
* @returns {Array<string>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.get_keys = (...items) => items.reduce((keys, item) => {
|
|
|
|
if(Check.is_key(item))
|
|
keys.push(item);
|
|
else if(Check.is_array(item))
|
|
keys.push(...Utils.get_keys(...item));
|
|
|
|
return keys;
|
|
}, []);
|
|
|
|
/**
|
|
* @param {...(any|null)} items
|
|
* @returns {Array.<Object.<string, any|null>>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.get_dictionaries = (...items) => items.reduce((dictionaries, item) => {
|
|
|
|
if(Check.is_dictionary(item))
|
|
dictionaries.push(item);
|
|
else if(Check.is_array(item))
|
|
dictionaries.push(...Utils.get_dictionaries(...item));
|
|
|
|
return dictionaries;
|
|
}, []);
|
|
|
|
/**
|
|
* @param {?any} items
|
|
* @param {!boolean} [overwrite = false]
|
|
* @returns {Object.<string, any|null>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.get_dictionary = (items, overwrite = false) => (
|
|
Check.is_dictionary ? items :
|
|
Check.is_array(items) ? items.reduce((dictionary, item) => {
|
|
|
|
if(Check.is_dictionary(item))
|
|
dictionary = overwrite ? {...dictionary, ...item} : {...item, ...dictionary};
|
|
else if(Check.is_array(item))
|
|
dictionary = {...dictionary, ...Utils.get_dictionary(item, overwrite)};
|
|
|
|
return dictionary;
|
|
}) :
|
|
{});
|
|
|
|
/**
|
|
* @param {!(string|Array.<string>)} keys
|
|
* @param {!(Object.<string, any|null>|Array.<any|null>)} inputs
|
|
* @param {?any} [_default = null]
|
|
* @returns {any|null}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.get_value = (keys, inputs, _default = null) => {
|
|
|
|
/** @type {number} */
|
|
const l = (keys = Utils.get_keys(keys)).length;
|
|
|
|
if(l){
|
|
|
|
/** @type {number} */
|
|
const m = (inputs = Utils.get_dictionaries(inputs)).length;
|
|
|
|
for(let i = 0; i < l; i++)
|
|
for(let j = 0; j < m; j++)
|
|
if(keys[i] in inputs[j])
|
|
return inputs[j][keys[i]];
|
|
};
|
|
return _default;
|
|
};
|
|
|
|
/**
|
|
* @param {!string} string
|
|
* @param {!(Object.<string, any|null>|Array.<any|null>)} variables
|
|
* @param {?any} _default
|
|
* @returns {string}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.string_variables = (string, variables, _default = null) => {
|
|
|
|
variables = Utils.get_dictionary(variables);
|
|
|
|
return ("" + string).replace(/\{([a-z_][a-z0-9_]*)\}/gi, (all, key) => (
|
|
key in variables ? variables[key] :
|
|
_default === null ? all :
|
|
_default));
|
|
};
|
|
|
|
/**
|
|
* @param {!string} string
|
|
* @returns {string}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.to_kebab_case = string => ("" + string).replace(/([A-Z]+)|[^a-z0-9]+/g, (_, upper) => (
|
|
upper ? "-" + upper.toLowerCase() :
|
|
"-"));
|
|
|
|
/**
|
|
* @param {!HTMLElement} item
|
|
* @param {...Object.<string, any|null>} attributes
|
|
* @returns {void}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.attributes = (item, attributes) => {
|
|
for(const [key, value] of Object.entries(attributes)){
|
|
if(/^on[_\-]?/i.test(key) && Check.is_function(value))
|
|
item.addEventListener(key.toLowerCase().replace(/^on[_\-]?/, ""), event => {
|
|
Utils.execute(value, item, event);
|
|
});
|
|
else
|
|
item.setAttribute(Utils.to_kebab_case(key), value);
|
|
};
|
|
};
|
|
|
|
/**
|
|
* @param {!HTMLElement} item
|
|
* @param {...(string|HTMLElement|[string, Object.<string, any|null>|null, string|Array.<string>|null]|null)} structure
|
|
* @returns {Array.<HTMLElement>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.html = (item, ...structure) => {
|
|
|
|
/** @type {Array.<HTMLElement>} */
|
|
const items = [];
|
|
|
|
item || (item = document.createDocumentFragment());
|
|
|
|
for(const node of structure)
|
|
if(Check.is_string(node))
|
|
item.innerHTML += node;
|
|
else if(Check.is_html_item(node))
|
|
items.push(item.appendChild(node));
|
|
else if(Check.is_array(node)){
|
|
|
|
/** @type {[string, Object.<string, any|null>|null, Array.<any|null>|null]} */
|
|
const [tag, attributes, children] = node.concat(null, null).slice(0, 3),
|
|
/** @type {HTMLElement} */
|
|
element = document.createElement(tag);
|
|
|
|
attributes && Utils.attributes(element, attributes);
|
|
if(children && children.length){
|
|
if(Check.is_string(children))
|
|
element.innerHTML += children;
|
|
else
|
|
Utils.html(element, ...children);
|
|
};
|
|
items.push(item.appendChild(element));
|
|
|
|
};
|
|
|
|
return items;
|
|
};
|
|
|
|
/**
|
|
* @param {?any} item
|
|
* @returns {any|null}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.unique = item => (
|
|
Check.is_array(item) ? item.filter((item, i, array) => array.indexOf(item) == i) :
|
|
Check.is_string(item) ? item.split("").filter((char, i, array) => array.indexOf(char) == i).join("") :
|
|
item);
|
|
|
|
/**
|
|
* @param {?(number|Array.<any|null>|string)} [from = null]
|
|
* @param {?number} [to = null]
|
|
* @returns {any|null}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.get_random = (from = null, to = null) => (
|
|
Check.is_array(from) || Check.is_string(from) ? from.length ? from[Math.random() * from.length >> 0] : null :
|
|
Check.is_integer(from) ? (
|
|
to === null ? Math.random() * from >> 0 :
|
|
Check.is_integer(to) ? from + (Math.random() * (to - from + 1) >> 0) :
|
|
Check.is_number(to) ? from + Math.random() * (to - from) :
|
|
null) :
|
|
Check.is_number(from) ? (
|
|
to === null ? Math.random() * from :
|
|
Check.is_number(to) ? from + Math.random() * (to - from) :
|
|
null) :
|
|
from === null ? Math.random() :
|
|
null);
|
|
|
|
/**
|
|
* @param {?any} data
|
|
* @returns {string}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.encode_data = data => btoa(encodeURIComponent(JSON.stringify(data)).replace(/%([0-9A-F]{2})/g, (_, p1) => String.fromCharCode("0x" + p1)));
|
|
|
|
/**
|
|
* @param {!string} code
|
|
* @returns {any|null}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.decode_data = code => {
|
|
|
|
/** @type {string} */
|
|
const data = decodeURIComponent(atob(code).split("").map(c => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2)).join(""));
|
|
|
|
try{
|
|
return JSON.parse(data) || data;
|
|
}catch(exception){};
|
|
|
|
return data;
|
|
};
|
|
|
|
/**
|
|
* @param {!utils_execute_callback} callback
|
|
* @param {...(any|null)} inputs
|
|
* @returns {any|null}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.execute = (callback, ...inputs) => (
|
|
Check.is_function(callback) ? callback(...inputs) :
|
|
null);
|
|
|
|
/**
|
|
* @param {!Array.<any|null>} array
|
|
* @param {!utils_execute_array_each_callback} each_callback
|
|
* @param {?utils_default_callback} [end_callback = null]
|
|
* @param {!number} [i = 0]
|
|
* @returns {void}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.execute_array = (array, each_callback, end_callback = null, i = 0) => {
|
|
if(i < array.length)
|
|
Utils.execute(each_callback, array[i], () => {
|
|
Utils.execute_array(array, each_callback, end_callback, i + 1);
|
|
});
|
|
else
|
|
Utils.execute(end_callback);
|
|
};
|
|
|
|
/**
|
|
* @param {?any} item
|
|
* @returns {Array.<any|null>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.get_array = item => Check.is_array(item) ? item : [item];
|
|
|
|
/**
|
|
* @param {!string} string
|
|
* @returns {string}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.randomize_string = string => string.split("").sort(() => Utils.get_random() - 0.5).join("");
|
|
|
|
/**
|
|
* @param {?any} data
|
|
* @returns {string}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.encrypt_data = data => Utils.encode_data(data).split("").map(character => Utils.RANDOM_ALPHABET[Utils.BASE64_ALPHABET.indexOf(character)]).join("");
|
|
|
|
/**
|
|
* @param {string} data
|
|
* @returns {any|null}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
Utils.decrypt_data = data => Utils.decode_data(data.split("").map(character => Utils.BASE64_ALPHABET[Utils.RANDOM_ALPHABET.indexOf(character)]).join(""));
|
|
|
|
return Utils;
|
|
})(); |