291 lines
10 KiB
JavaScript
291 lines
10 KiB
JavaScript
"use strict";
|
|
|
|
import {SettingsManager} from "../Managers/SettingsManager.ecma.js";
|
|
import {I18NManager} from "../Managers/I18NManager.ecma.js";
|
|
import {URLPathDriver} from "../Drivers/URLPathDriver.ecma.js";
|
|
import {ThreadsManager} from "../Managers/ThreadsManager.ecma.js";
|
|
import {Attributes} from "./Attributes.ecma.js";
|
|
import {Components} from "./Components.ecma.js";
|
|
import {Check} from "../Utils/Check.ecma.js";
|
|
import {Utils} from "../Utils/Utils.ecma.js";
|
|
import {Patterns} from "../Utils/Patterns.ecma.js";
|
|
|
|
/**
|
|
* @callback anp_preload_callback
|
|
* @param {?HTMLElement} item
|
|
* @param {!boolean} asynchronous
|
|
* @param {!boolean} ok
|
|
* @returns {void}
|
|
*/
|
|
|
|
/**
|
|
* @callback anp_settings_get_callback
|
|
* @param {!(string|Array.<string>)} keys
|
|
* @param {?(Object.<string, any|null>|Array.<any|null>)} [inputs = null]
|
|
* @param {?any} [_default = null]
|
|
* @returns {any|null}
|
|
*/
|
|
|
|
/**
|
|
* @callback anp_start_callback
|
|
* @param {!boolean} ok
|
|
* @returns {boolean}
|
|
*/
|
|
|
|
/**
|
|
* @callback anp_autostart_callback
|
|
* @param {!AnP} anp
|
|
* @returns {void}
|
|
*/
|
|
|
|
/**
|
|
* @class
|
|
* @constructor
|
|
* @param {?(Object.<string, any|null>|Array.<any|null>)} inputs
|
|
* @param {?anp_autostart_callback} [autostart_callback = null]
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
export const AnP = (function(){
|
|
|
|
/**
|
|
* @constructs AnP
|
|
* @param {?(Object.<string, any|null>|Array.<any|null>)} [inputs = null]
|
|
* @param {?anp_autostart_callback} [autostart_callback = null]
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const AnP = function(inputs = null, autostart_callback = null){
|
|
|
|
/** @type {AnP} */
|
|
const self = this,
|
|
/** @type {Array.<string>} */
|
|
random_chains = [],
|
|
// http://detectmobilebrowsers.com/
|
|
/** @type {boolean} */
|
|
is_mobile = ((a) => (
|
|
/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) ||
|
|
/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))
|
|
))(navigator.userAgent || navigator.vendor || window.opera),
|
|
// https://stackoverflow.com/questions/56393880/how-do-i-detect-dark-mode-using-javascript#answer-57795495
|
|
/** @type {boolean} */
|
|
is_dark_mode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
/** @type {boolean} */
|
|
let started = false,
|
|
/** @type {number} */
|
|
preload_timeout = 2000,
|
|
/** @type {string} */
|
|
chain_alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",
|
|
/** @type {number} */
|
|
chain_length = 11;
|
|
|
|
/** @type {SettingsManager} */
|
|
this.settings = null;
|
|
/** @type {I18NManager} */
|
|
this.i18n = null;
|
|
/** @type {URLPathDriver} */
|
|
this.request = null;
|
|
/** @type {ThreadsManager} */
|
|
this.threads = null;
|
|
/** @type {Attributes} */
|
|
this.attributes = this.attr = null;
|
|
/** @type {Components} */
|
|
this.components = this.comp = null;
|
|
|
|
/** @type {string|null} */
|
|
this.object_name = null;
|
|
/** @type {HTMLElement|Document} */
|
|
this.item_self = document;
|
|
/** @type {string|null} */
|
|
this.hash_self = null;
|
|
|
|
/**
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const set_basics = () => {
|
|
|
|
/** @type {anp_settings_get_callback} */
|
|
const get = self.settings ? self.settings.get : Utils.get_value;
|
|
|
|
preload_timeout = get(["preload_timeout", "timeout"], inputs, preload_timeout);
|
|
chain_alphabet = get(["random_chain_alphabet", "chain_alphabet", "alphabet"], inputs, chain_alphabet);
|
|
chain_length = get(["random_chain_length", "chain_length", "length"], inputs, chain_length);
|
|
|
|
};
|
|
|
|
/**
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const execute_constructor = () => {
|
|
|
|
set_basics();
|
|
|
|
self.settings = new SettingsManager(self, inputs);
|
|
self.object_name = self.settings.get("object_name");
|
|
set_basics();
|
|
self.i18n = new I18NManager(self);
|
|
self.request = new URLPathDriver(self);
|
|
self.threads = new ThreadsManager(self);
|
|
self.attributes = self.attr = new Attributes(self);
|
|
self.components = self.comp = new Components(self);
|
|
|
|
set_basics();
|
|
|
|
self.settings.get("autostart") && self.start();
|
|
|
|
}
|
|
|
|
/**
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const constructor = () => {
|
|
if(Utils.get_value("debug_mode")){
|
|
try{
|
|
execute_constructor();
|
|
}catch(exception){
|
|
console.error(exception);
|
|
};
|
|
}else
|
|
execute_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);
|
|
ok && Utils.execute(autostart_callback, self);
|
|
return ok;
|
|
};
|
|
|
|
if(started)
|
|
return end(false);
|
|
started = true;
|
|
|
|
Utils.execute_items([
|
|
"settings", "i18n", "request", "threads", "attributes", "components"
|
|
], (key, next) => {
|
|
self[key].start(ok => {
|
|
next();
|
|
});
|
|
}, () => {
|
|
end(true);
|
|
});
|
|
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* @param {!(string|HTMLElement)} selector
|
|
* @param {!anp_preload_callback} callback
|
|
* @param {?(Object.<string, any|null>|Array.<any|null>)} [inputs = null]
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
this.preload = (selector, callback, inputs = null) => {
|
|
if(!Check.is_function(callback))
|
|
return;
|
|
|
|
if(Check.is_html_item(selector)){
|
|
callback(selector, false, true);
|
|
return;
|
|
};
|
|
|
|
if(Check.is_string(selector)){
|
|
|
|
/** @type {HTMLElement|null} */
|
|
let item;
|
|
|
|
try{
|
|
if(item = self.item_self.querySelector(selector)){
|
|
callback(item, false, true);
|
|
return;
|
|
};
|
|
}catch(exception){
|
|
callback(null, false, false);
|
|
return;
|
|
};
|
|
|
|
/** @type {number} */
|
|
const date = Date.now(),
|
|
/** @type {number} */
|
|
timeout = Utils.get_value(["preload_timeout", "timeout"], inputs, preload_timeout);
|
|
|
|
self.threads.add(thread => {
|
|
if(item = self.item_self.querySelector(selector)){
|
|
self.threads.remove(thread);
|
|
callback(item, true, true);
|
|
}else if(Date.now() - date > timeout){
|
|
self.threads.remove(thread);
|
|
callback(null, true, false);
|
|
};
|
|
}, {
|
|
/** @type {boolean} */
|
|
bucle : true
|
|
});
|
|
|
|
}else
|
|
callback(null, false, false);
|
|
|
|
};
|
|
|
|
/**
|
|
* @returns {string}
|
|
* @access public
|
|
*/
|
|
this.random_chain = () => {
|
|
|
|
/** @type {string} */
|
|
let chain;
|
|
/** @type {number} */
|
|
const l = chain_alphabet.length;
|
|
|
|
do{
|
|
chain = "";
|
|
while((chain += chain_alphabet[Math.random() * l >> 0]).length < chain_length);
|
|
}while(
|
|
random_chains.includes(chain) ||
|
|
!Patterns.RE_RIGHT_RANDOM_CHAIN.test(chain) ||
|
|
document.querySelector("." + chain + ",#" + chain + ",[name=" + chain + "]")
|
|
);
|
|
random_chains.push(chain);
|
|
|
|
return chain;
|
|
};
|
|
|
|
/**
|
|
* @param {!string} chain
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
this.remove_random_chain = chain => {
|
|
random_chains.includes(chain) &&
|
|
random_chains.splice(random_chains.indexOf(chain), 1);
|
|
};
|
|
|
|
/**
|
|
* @returns {boolean}
|
|
* @access public
|
|
*/
|
|
this.is_mobile = () => is_mobile;
|
|
|
|
/**
|
|
* @returns {boolean}
|
|
* @access public
|
|
*/
|
|
this.is_dark_mode = () => is_dark_mode;
|
|
|
|
constructor();
|
|
|
|
};
|
|
|
|
return AnP
|
|
})(); |