2024-03-20 18:39:48 +00:00
|
|
|
Sizerboard = function(inputs){
|
|
|
|
|
|
|
|
const self = this,
|
2024-03-31 19:20:12 +00:00
|
|
|
default_settings = {
|
|
|
|
nulls : false,
|
|
|
|
default_value : null,
|
|
|
|
default_text : "",
|
|
|
|
autostart : true,
|
|
|
|
default_language : "english",
|
2024-04-14 13:32:18 +00:00
|
|
|
timeout : 2000,
|
|
|
|
print_format : "[{type}] {yyyy}{mm}{dd} {hh}{ii}{ss} [{line}]{file}({method}): {message}",
|
|
|
|
gui_mode : "light",
|
|
|
|
frames_per_second : 24,
|
|
|
|
position : "body",
|
|
|
|
default_settings_files : [
|
|
|
|
"/json/Sizerboard.settings.json",
|
|
|
|
"/json/Sizerboard.settings.secrets.json"
|
|
|
|
],
|
|
|
|
object_name : "sizerboard"
|
2024-03-31 19:20:12 +00:00
|
|
|
},
|
|
|
|
settings = {},
|
2024-04-14 13:32:18 +00:00
|
|
|
sentences = {},
|
|
|
|
print_types = [
|
|
|
|
["unkn", "unknown"],
|
|
|
|
["info", "information"],
|
|
|
|
[" ok ", "ok", "yes", "y"],
|
|
|
|
["erro", "error", "wrong"],
|
|
|
|
["warn", "warning"],
|
|
|
|
["exce", "except", "exception"],
|
|
|
|
["note", "test", "tests", "notes", "data"]
|
|
|
|
],
|
|
|
|
print_styles = {
|
|
|
|
unkn : {
|
|
|
|
dark : "color : #AAA;",
|
|
|
|
light : "color : #666;"
|
|
|
|
},
|
|
|
|
info : {
|
|
|
|
dark : "color : #99F;",
|
|
|
|
light : "color : #009;"
|
|
|
|
},
|
|
|
|
ok : {
|
|
|
|
dark : "color : #9F9;",
|
|
|
|
light : "color : #090;"
|
|
|
|
},
|
|
|
|
note : {
|
|
|
|
dark : "color : #222;",
|
|
|
|
light : "color : #EFEFEF;"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
threads = [],
|
|
|
|
hashes = [];
|
2024-03-31 19:20:12 +00:00
|
|
|
let started = false,
|
|
|
|
language, default_language,
|
|
|
|
allow_settings_nulls, default_text, default_value,
|
2024-04-14 13:32:18 +00:00
|
|
|
ajax_timeout,
|
|
|
|
print_format = "[{type}] {yyyy}{mm}{dd} {hh}{ii}{ss} [{line}]{file}({method}): {message}",
|
|
|
|
gui_mode = "light",
|
|
|
|
threads_interval,
|
|
|
|
frames_per_second = 24,
|
|
|
|
preload_timeout = 2000,
|
|
|
|
hashes_alphabet, hashes_length;
|
|
|
|
|
|
|
|
const re_trace_block = new RegExp("^(" + [
|
|
|
|
/\s*at\s+(([^\s]+)\s+\()?(([^\(\)\:]+\:)?[^\(\)\:]+)(\:([0-9]+)\:[0-9]+)?\)?/.source, // Webkit
|
|
|
|
/([^\@]+)\@([^:]+\:[^\:]+)\:([0-9]+)\:[0-9]+/.source, // Gecko
|
|
|
|
].join("|") + ")$");
|
|
|
|
|
|
|
|
let object_name = this.object_name;
|
|
|
|
let item_self = this.item_self = document;
|
|
|
|
let hash_self = this.hash_self;
|
|
|
|
|
|
|
|
let base = this.base;
|
|
|
|
let views = this.views;
|
|
|
|
let projects = this.projects;
|
|
|
|
let draw_box = this.draw_box;
|
2024-03-20 18:39:48 +00:00
|
|
|
|
2024-03-31 19:20:12 +00:00
|
|
|
const construct = () => {
|
|
|
|
|
|
|
|
basic_values();
|
|
|
|
|
2024-04-14 13:32:18 +00:00
|
|
|
self.print("info", "sizerboard_building");
|
|
|
|
|
|
|
|
object_name = self.object_name = self.settings("object_name");
|
|
|
|
|
|
|
|
base = self.base = new Sizerboard.Base(self, inputs);
|
|
|
|
views = self.views = new Sizerboard.Views(self, inputs);
|
|
|
|
projects = self.projects = new Sizerboard.Projects(self, inputs);
|
|
|
|
draw_box = self.draw_box = new Sizerboard.DrawBox(self, inputs);
|
|
|
|
|
|
|
|
self.print("ok", "sizerboard_built");
|
|
|
|
|
2024-03-31 19:20:12 +00:00
|
|
|
self.settings("autostart") && self.start();
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
const basic_values = () => {
|
|
|
|
|
|
|
|
default_value = self.settings("default_value", null, null, true);
|
|
|
|
default_text = self.settings("default_text");
|
|
|
|
allow_settings_nulls = self.settings("nulls", null, false, false);
|
|
|
|
language = self.settings(["language", "default_language"]);
|
|
|
|
default_language = self.settings(["default_language", "language"]);
|
|
|
|
ajax_timeout = self.settings(["ajax_timeout", "timeout"]);
|
2024-04-14 13:32:18 +00:00
|
|
|
print_format = self.settings("print_format");
|
|
|
|
gui_mode = self.settings("gui_mode");
|
2024-03-31 19:20:12 +00:00
|
|
|
|
|
|
|
};
|
2024-03-20 18:39:48 +00:00
|
|
|
|
|
|
|
this.start = callback => {
|
|
|
|
|
|
|
|
const end = status => typeof callback == "function" && callback(status);
|
2024-04-14 13:32:18 +00:00
|
|
|
|
|
|
|
self.print("info", "sizerboard_starting");
|
2024-03-20 18:39:48 +00:00
|
|
|
|
|
|
|
if(started){
|
2024-04-14 13:32:18 +00:00
|
|
|
self.print("warn", "sizerboard_already_started");
|
2024-03-20 18:39:48 +00:00
|
|
|
end(false);
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
started = true;
|
2024-03-31 19:20:12 +00:00
|
|
|
|
2024-04-14 13:32:18 +00:00
|
|
|
basic_values();
|
|
|
|
|
|
|
|
self.print("info", "settings_loading");
|
2024-03-31 19:20:12 +00:00
|
|
|
self.execute_array_items(["default_settings_files", "settings_files"], (key, callback) => {
|
|
|
|
self.settings_add(self.settings(key), true, callback);
|
2024-04-14 13:32:18 +00:00
|
|
|
basic_values();
|
2024-03-31 19:20:12 +00:00
|
|
|
}, () => {
|
2024-04-14 13:32:18 +00:00
|
|
|
self.print("ok", "settings_loaded");
|
|
|
|
|
|
|
|
frames_per_second = self.settings("frames_per_second");
|
|
|
|
preload_timeout = self.settings(["preload_timeout", "timeout"]);
|
|
|
|
hashes_alphabet = self.settings(["hashes_alphabet", "alphabet"]);
|
|
|
|
hashes_length = self.settings(["hashes_length", "length"]);
|
|
|
|
|
|
|
|
threads_interval = setInterval(threads_method, 1000 / frames_per_second);
|
|
|
|
|
|
|
|
self.print("info", "i18n_loading");
|
2024-03-31 19:20:12 +00:00
|
|
|
self.execute_array_items(["default_i18n_files", "i18n_files"], (key, callback) => {
|
|
|
|
self.i18n_add(self.settings(key), true, callback);
|
|
|
|
}, () => {
|
2024-04-14 13:32:18 +00:00
|
|
|
self.print("ok", "i18n_loaded");
|
|
|
|
|
|
|
|
self.execute_array_items([views, base, projects, draw_box], (item, callback) => {
|
|
|
|
item.start(callback);
|
|
|
|
}, () => {
|
|
|
|
self.print("ok", "sizerboard_started");
|
|
|
|
end(true);
|
|
|
|
});
|
2024-03-31 19:20:12 +00:00
|
|
|
});
|
|
|
|
});
|
2024-03-20 18:39:48 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
2024-03-31 19:20:12 +00:00
|
|
|
this.nulls = nulls => typeof nulls == "boolean" ? nulls : allow_settings_nulls;
|
2024-03-20 18:39:48 +00:00
|
|
|
|
2024-03-31 19:20:12 +00:00
|
|
|
this.default_value = (_default, nulls) => _default !== undefined && (_default !== null || self.nulls(nulls)) ? _default : default_value;
|
2024-04-14 13:32:18 +00:00
|
|
|
|
|
|
|
this.set_keys = keys => (typeof keys == "object" && keys instanceof Array ? keys : [keys]).filter(key => typeof key == "string" && key.trim()).map(key => key.trim());
|
2024-03-20 18:39:48 +00:00
|
|
|
|
2024-04-14 13:32:18 +00:00
|
|
|
this.settings = (keys, own_inputs, _default, nulls) => {
|
2024-03-20 18:39:48 +00:00
|
|
|
|
2024-04-14 13:32:18 +00:00
|
|
|
const m = (keys = self.set_keys(keys)).length;
|
2024-03-20 18:39:48 +00:00
|
|
|
|
|
|
|
if(m){
|
|
|
|
|
2024-04-14 13:32:18 +00:00
|
|
|
const l = (own_inputs = (
|
|
|
|
own_inputs == "object" ? own_inputs instanceof Array ? own_inputs : [own_inputs] : []
|
2024-03-20 18:39:48 +00:00
|
|
|
).concat(
|
|
|
|
[inputs, settings, default_settings]
|
|
|
|
)).length;
|
|
|
|
|
|
|
|
nulls = self.nulls(nulls);
|
|
|
|
|
|
|
|
for(let i = 0; i < l; i ++)
|
2024-04-14 13:32:18 +00:00
|
|
|
if(own_inputs[i] && typeof own_inputs[i] == "object")
|
2024-03-20 18:39:48 +00:00
|
|
|
for(let j = 0; j < m; j ++)
|
2024-04-14 13:32:18 +00:00
|
|
|
if(own_inputs[i][keys[j]] !== undefined && (nulls || own_inputs[i][keys[j]] !== null))
|
|
|
|
return own_inputs[i][keys[j]];
|
2024-03-20 18:39:48 +00:00
|
|
|
};
|
|
|
|
return self.default_value(_default, nulls);
|
|
|
|
};
|
|
|
|
|
|
|
|
this.load_file = (url, callback) => {
|
|
|
|
|
|
|
|
let ended = false;
|
|
|
|
const ajax = new XMLHttpRequest(),
|
|
|
|
end = message => !ended && (ended = true) && typeof callback == "function" && callback(ajax.responseText, ajax.status, ajax.readyState, message, message == "OK");
|
2024-03-31 19:20:12 +00:00
|
|
|
timeout = ajax_timeout,
|
2024-03-20 18:39:48 +00:00
|
|
|
date = Date.now();
|
|
|
|
|
2024-04-14 13:32:18 +00:00
|
|
|
ajax.open("get", url, true);
|
2024-03-20 18:39:48 +00:00
|
|
|
ajax.timeout = timeout;
|
|
|
|
ajax.onreadystatechange = () => {
|
|
|
|
if(ended)
|
|
|
|
return;
|
|
|
|
if(ajax.readyState == 4)
|
|
|
|
end((ajax.status >= 200 && ajax.status < 300) || [301, 302, 304].includes(ajax.status) ? "OK" : "HTTP_ERROR");
|
|
|
|
else if(Date.now() - date > timeout)
|
|
|
|
end("FORCED_TIMEOUT");
|
|
|
|
};
|
|
|
|
ajax.send(null);
|
|
|
|
|
|
|
|
ajax.onabort = () => end("ABORTED");
|
|
|
|
ajax.onerror = () => end("ERROR");
|
|
|
|
ajax.ontimeout = () => end("TIMEOUT");
|
|
|
|
|
|
|
|
return ajax;
|
|
|
|
};
|
2024-04-14 13:32:18 +00:00
|
|
|
|
|
|
|
this.execute_json = (data, yes, no) => {
|
|
|
|
|
|
|
|
let json;
|
|
|
|
|
|
|
|
try{
|
|
|
|
json = JSON.parse(data);
|
|
|
|
}catch(exception){};
|
|
|
|
|
|
|
|
if(json)
|
|
|
|
typeof yes == "function" && yes(json);
|
|
|
|
else
|
|
|
|
typeof no == "function" && no();
|
|
|
|
|
|
|
|
};
|
2024-03-20 18:39:48 +00:00
|
|
|
|
|
|
|
this.execute_array_dictionaries = (inputs, partial_callback, full_callback, i) => {
|
|
|
|
|
2024-04-14 13:32:18 +00:00
|
|
|
if(!inputs || typeof inputs != "object" || !(inputs instanceof Array) || (i || (i = 0)) >= inputs.length){
|
2024-03-20 18:39:48 +00:00
|
|
|
typeof full_callback == "function" && full_callback();
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
|
|
|
|
const end = () => {
|
2024-04-14 13:32:18 +00:00
|
|
|
inputs[i] && typeof inputs[i] == "object" && typeof partial_callback == "function" && partial_callback(inputs[i]);
|
|
|
|
self.execute_array_dictionaries(inputs, partial_callback, full_callback, i + 1);
|
2024-03-20 18:39:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if(!inputs[i]){
|
|
|
|
end();
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
|
|
|
|
if(typeof inputs[i] == "object"){
|
2024-04-14 13:32:18 +00:00
|
|
|
if(inputs[i] instanceof Array)
|
2024-03-20 18:39:48 +00:00
|
|
|
self.execute_array_dictionaries(inputs[i], partial_callback, end, 0);
|
2024-04-14 13:32:18 +00:00
|
|
|
else
|
|
|
|
end();
|
2024-03-20 18:39:48 +00:00
|
|
|
}else if(typeof inputs[i] == "string"){
|
2024-04-14 13:32:18 +00:00
|
|
|
if(/^(\{(.|[\r\n])*\}|\[(.|[\r\n])*\])$/.test(inputs[i].trim()))
|
|
|
|
self.execute_json(inputs[i], json => self.execute_array_dictionaries(json instanceof Array ? json : [json], partial_callback, end, 0), end);
|
|
|
|
else
|
2024-03-20 18:39:48 +00:00
|
|
|
self.load_file(inputs[i], data => {
|
2024-04-14 13:32:18 +00:00
|
|
|
self.execute_json(data, json => self.execute_array_dictionaries(json instanceof Array ? json : [json], partial_callback, end, 0), end);
|
2024-03-20 18:39:48 +00:00
|
|
|
});
|
|
|
|
}else
|
|
|
|
end();
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2024-03-31 19:20:12 +00:00
|
|
|
this.execute_array_items = (items, action, callback, i) => {
|
|
|
|
(typeof items != "object" || !(items instanceof Array)) && (items = [items]);
|
|
|
|
|
2024-04-14 13:32:18 +00:00
|
|
|
if(!items || (i || (i = 0)) >= items.length){
|
2024-03-31 19:20:12 +00:00
|
|
|
typeof callback == "function" && callback();
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
|
2024-04-14 13:32:18 +00:00
|
|
|
const end = () => self.execute_array_items(items, action, callback, i + 1);
|
2024-03-31 19:20:12 +00:00
|
|
|
|
|
|
|
if(typeof action == "function")
|
|
|
|
action(items[i], end);
|
|
|
|
else
|
|
|
|
end();
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2024-03-20 18:39:48 +00:00
|
|
|
this.settings_add = (inputs, overwrite, callback) => {
|
|
|
|
typeof overwrite != "boolean" && (overwrite = settings_overwrite);
|
|
|
|
self.execute_array_dictionaries(inputs, data => {
|
|
|
|
for(const key in data)
|
2024-04-14 13:32:18 +00:00
|
|
|
(overwrite || settings[key] === undefined) &&
|
|
|
|
!/^Sizerboard.*_(start|end)$/.test(key) &&
|
|
|
|
(settings[key] = data[key]);
|
2024-03-20 18:39:48 +00:00
|
|
|
}, callback);
|
|
|
|
};
|
2024-03-31 19:20:12 +00:00
|
|
|
|
|
|
|
this.i18n_add = (inputs, overwrite, callback) => {
|
|
|
|
typeof overwrite != "boolean" && (overwrite = i18n_overwrite);
|
|
|
|
self.execute_array_dictionaries(inputs, data => {
|
|
|
|
for(const language in data){
|
|
|
|
!sentences[language] && (sentences[language] = {});
|
|
|
|
if(typeof data[language] == "object")
|
|
|
|
for(const key in data[language])
|
|
|
|
(overwrite || sentences[language][key] === undefined) &&
|
2024-04-14 13:32:18 +00:00
|
|
|
!/^Sizerboard.*_(start|end)$/.test(key) &&
|
2024-03-31 19:20:12 +00:00
|
|
|
(sentences[language][key] = data[language][key]);
|
|
|
|
};
|
|
|
|
}, callback);
|
|
|
|
};
|
|
|
|
|
|
|
|
this.string_variables = (string, variables, _default) => {
|
|
|
|
|
|
|
|
const l = (variables = (
|
|
|
|
typeof variables == "object" && variables instanceof Array ? variables : [variables]
|
|
|
|
).filter(variables => typeof variables == "object")).length;
|
|
|
|
|
2024-04-14 13:32:18 +00:00
|
|
|
return ("" + string).replace(/\{([^\{\}]+)\}/g, (all, key) => {
|
2024-03-31 19:20:12 +00:00
|
|
|
for(let i = 0; i < l; i ++)
|
|
|
|
if(variables[i][key] !== undefined)
|
|
|
|
return variables[i][key];
|
|
|
|
return _default !== undefined ? _default : all;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
this.default_text = _default => _default !== undefined ? _default : default_text;
|
|
|
|
|
|
|
|
const i18n = (keys, _default) => {
|
|
|
|
|
2024-04-14 13:32:18 +00:00
|
|
|
const m = (keys = self.set_keys(keys)).length;
|
2024-03-31 19:20:12 +00:00
|
|
|
|
2024-04-14 13:32:18 +00:00
|
|
|
if(m){
|
2024-03-31 19:20:12 +00:00
|
|
|
|
2024-04-14 13:32:18 +00:00
|
|
|
const languages = [language, default_language].concat(Object.keys(sentences)).filter((language, i, array) => array.indexOf(language) == i),
|
2024-03-31 19:20:12 +00:00
|
|
|
l = languages.length;
|
|
|
|
|
|
|
|
for(let i = 0; i < l; i ++)
|
2024-04-14 13:32:18 +00:00
|
|
|
if(sentences[languages[i]])
|
|
|
|
for(let j = 0; j < m; j ++)
|
|
|
|
if(sentences[languages[i]][keys[j]] !== undefined)
|
|
|
|
return sentences[languages[i]][keys[j]];
|
2024-03-31 19:20:12 +00:00
|
|
|
return keys[0];
|
|
|
|
};
|
|
|
|
return self.default_text(_default);
|
|
|
|
};
|
|
|
|
|
2024-04-14 13:32:18 +00:00
|
|
|
this.i18n = (keys, variables, _default) => {
|
|
|
|
|
|
|
|
const text = i18n(keys, _default);
|
|
|
|
|
|
|
|
return self.string_variables(typeof text == "object" ? text.join("") : text, variables, _default);
|
|
|
|
};
|
|
|
|
|
|
|
|
this.get_print_type = type => {
|
|
|
|
|
|
|
|
const l = print_types.length;
|
|
|
|
|
|
|
|
type = type.toLowerCase();
|
|
|
|
|
|
|
|
for(let i = 0; i < l; i ++)
|
|
|
|
if(print_types[i].includes(type))
|
|
|
|
return print_types[i][0].toUpperCase();
|
|
|
|
return print_types[0][0];
|
|
|
|
};
|
|
|
|
|
|
|
|
this.get_trace = i => (new Error()).stack.replace(/^Error\s*?[\r\n]+/, "").trim().split(/[\r\n]+/).slice(1 + (i || 0)).map(line => {
|
|
|
|
|
|
|
|
const matches = line.match(re_trace_block);
|
|
|
|
|
|
|
|
return matches ? {
|
|
|
|
file : matches[4] || matches[9],
|
|
|
|
method : matches[3] || matches[8] || "",
|
|
|
|
line : Number(matches[7] || matches[10])
|
|
|
|
} : null;
|
|
|
|
}).filter(line => line);
|
|
|
|
|
|
|
|
this.print = (type, message, variables, i) => {
|
|
|
|
|
|
|
|
const date = new Date(),
|
|
|
|
own = {
|
|
|
|
...((
|
|
|
|
variables ? typeof variables == "object" ? [variables] : variables instanceof Array ? variables : [] : []
|
|
|
|
).reduce((results, set) => typeof set == "object" ? {...results, ...set} : results, {})),
|
|
|
|
...self.get_trace(i || 1)[0],
|
|
|
|
raw_type : type,
|
|
|
|
type : self.get_print_type(type)
|
|
|
|
};
|
|
|
|
|
|
|
|
["year", "month", "day", "hours", "minutes", "seconds"].forEach(key => {
|
|
|
|
|
|
|
|
const k = key != "minutes" ? key[0] : "i";
|
|
|
|
|
|
|
|
own[k + k] = ("00" + (own[k] = (own[key] = date["get" + (
|
|
|
|
key == "year" ? "FullYear" :
|
|
|
|
key == "day" ? "Date" :
|
|
|
|
key[0].toUpperCase() + key.substring(1)
|
|
|
|
)]()) % 100)).slice(-2);
|
|
|
|
|
|
|
|
});
|
|
|
|
own.yyyy = own.year;
|
|
|
|
|
|
|
|
const final_message = self.string_variables(print_format, {
|
|
|
|
...own,
|
|
|
|
message : self.i18n(message, own)
|
|
|
|
});
|
|
|
|
|
|
|
|
switch(own.type){
|
|
|
|
case "INFO":
|
|
|
|
console.log("%c" + final_message, print_styles.info[gui_mode]);
|
|
|
|
break;
|
|
|
|
case " OK ":
|
|
|
|
console.log("%c" + final_message, print_styles.ok[gui_mode]);
|
|
|
|
break;
|
|
|
|
case "ERRO":
|
|
|
|
case "EXCE":
|
|
|
|
console.error(final_message);
|
|
|
|
break;
|
|
|
|
case "WARN":
|
|
|
|
console.warn(final_message);
|
|
|
|
break;
|
|
|
|
case "NOTE":
|
|
|
|
console.log("%c" + final_message, print_styles.note[gui_mode]);
|
|
|
|
break;
|
|
|
|
case "UNKN":
|
|
|
|
default:
|
|
|
|
console.log("%c" + final_message, print_styles.unkn[gui_mode]);
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
const threads_method = () => threads.forEach(thread => {
|
|
|
|
if(thread)
|
|
|
|
try{
|
|
|
|
thread();
|
|
|
|
}catch(exception){};
|
|
|
|
});
|
|
|
|
|
|
|
|
this.thread_add = callback => {
|
|
|
|
|
|
|
|
let error = (
|
|
|
|
callback === undefined ? 1 << 0 :
|
|
|
|
callback === null ? 1 << 1 :
|
|
|
|
typeof callback != "function" ? 1 << 2 :
|
|
|
|
0) << 1,
|
|
|
|
i = null;
|
|
|
|
|
|
|
|
if(!error){
|
|
|
|
|
|
|
|
const l = threads.length;
|
|
|
|
|
|
|
|
for(i = 0; i < l; i ++)
|
|
|
|
if(!threads[i])
|
|
|
|
break;
|
|
|
|
|
|
|
|
threads[i] = callback;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
return [i, error];
|
|
|
|
};
|
|
|
|
|
|
|
|
this.thread_remove = i => {
|
|
|
|
|
|
|
|
let error = (
|
|
|
|
i === undefined ? 1 << 0 :
|
|
|
|
i === null ? 1 << 1 :
|
|
|
|
isNaN(i) ? 1 << 2 :
|
|
|
|
i != i >> 0 ? 1 << 3 :
|
|
|
|
i < 0 ? 1 << 4 :
|
|
|
|
i >= threads.length ? 1 << 5 :
|
|
|
|
0) << 1;
|
|
|
|
|
|
|
|
!i && (threads[i] = null);
|
|
|
|
|
|
|
|
return error;
|
|
|
|
};
|
|
|
|
|
|
|
|
this.preload = (selector, callback) => {
|
|
|
|
|
|
|
|
let callback_is_function = typeof callback == "function",
|
|
|
|
error = (
|
|
|
|
((
|
|
|
|
selector === undefined ? 1 << 0 :
|
|
|
|
selector === null ? 1 << 1 :
|
|
|
|
0) << 0) |
|
|
|
|
((
|
|
|
|
callback === undefined ? 1 << 0 :
|
|
|
|
callback === null ? 1 << 1 :
|
|
|
|
!callback_is_function ? 1 << 2 :
|
|
|
|
0) << 10) |
|
|
|
|
0) << 1,
|
|
|
|
item = null,
|
|
|
|
asynchronous = false;
|
|
|
|
const end = () => callback_is_function && callback(item, error, asynchronous);
|
|
|
|
|
|
|
|
if(!error){
|
|
|
|
switch(typeof selector){
|
|
|
|
case "string":
|
|
|
|
if(!(error |= (
|
|
|
|
!selector ? 1 << 5 :
|
|
|
|
!(selector = selector.trim()) ? 1 << 6 :
|
|
|
|
0) << 5)){
|
|
|
|
|
|
|
|
try{
|
|
|
|
(item = item_self.querySelector(selector)) && end();
|
|
|
|
}catch(exception){
|
|
|
|
error |= 1 << 7;
|
|
|
|
end();
|
|
|
|
};
|
|
|
|
|
|
|
|
if(!item && !error){
|
|
|
|
|
|
|
|
const date = Date.now(),
|
|
|
|
[thread, suberror] = self.thread_add(() => {
|
|
|
|
if(item = item_self.querySelector(selector)){
|
|
|
|
self.thread_remove(thread);
|
|
|
|
end();
|
|
|
|
}else if(Date.now() - date > preload_timeout){
|
|
|
|
self.thread_remove(thread);
|
|
|
|
error |= 1 << 8;
|
|
|
|
end();
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
};
|
|
|
|
break;
|
|
|
|
case "object":
|
|
|
|
if(selector.tagName || selector.nodeName)
|
|
|
|
item = selector;
|
|
|
|
else
|
|
|
|
error |= 1 << 4;
|
|
|
|
end();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error |= 1 << 3;
|
|
|
|
end();
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
return error;
|
|
|
|
};
|
|
|
|
|
|
|
|
this.hash = () => {
|
|
|
|
|
|
|
|
let hash;
|
|
|
|
const l = hashes_alphabet.length;
|
|
|
|
|
|
|
|
do{
|
|
|
|
hash = "";
|
|
|
|
while((hash += hashes_alphabet[Math.random() * l >> 0]).length < hashes_length);
|
|
|
|
}while(
|
|
|
|
hashes.includes(hash) ||
|
|
|
|
/^[0-9]/.test(hash) ||
|
|
|
|
document.querySelector("#" + hash + ",." + hash + ",[name=" + hash + "]")
|
|
|
|
);
|
|
|
|
hashes.push(hash);
|
|
|
|
|
|
|
|
return hash;
|
|
|
|
};
|
|
|
|
|
|
|
|
this.build_preloader = callback => {
|
|
|
|
|
|
|
|
const hash = self.hash();
|
|
|
|
|
|
|
|
self.preload("[data-preloader=" + hash + "]", (preloader, error, asynchronous) => {
|
|
|
|
typeof callback == "function" && callback(error ? null : preloader.parentNode, error, asynchronous);
|
|
|
|
preloader.remove();
|
|
|
|
});
|
|
|
|
|
|
|
|
return `<div data-preloader="` + hash + `"></div>`;
|
|
|
|
};
|
|
|
|
|
|
|
|
this.set_self = (item, hash) => {
|
|
|
|
|
|
|
|
let error = ((
|
|
|
|
((item_self.tagName || item_self.nodeName) != "#document" ? 1 << 0 : 0) |
|
|
|
|
(hash_self ? 1 << 1 : 0) |
|
|
|
|
0) || (
|
|
|
|
((
|
|
|
|
item === undefined ? 1 << 0 :
|
|
|
|
item === null ? 1 << 1 :
|
|
|
|
typeof item != "object" ? 1 << 2 :
|
|
|
|
!item.tagName && !item.nodeName ? 1 << 3 :
|
|
|
|
(item.tagName || item.nodeName) == "#document" ? 1 << 4 :
|
|
|
|
0) << 2) |
|
|
|
|
((
|
|
|
|
hash === undefined ? 1 << 0 :
|
|
|
|
hash === null ? 1 << 1 :
|
|
|
|
typeof hash != "string" ? 1 << 2 :
|
|
|
|
!hash ? 1 << 3 :
|
|
|
|
!hash.trim() ? 1 << 4 :
|
|
|
|
hash != hash.trim() ? 1 << 5 :
|
|
|
|
hash.split("").some(character => !hashes_alphabet.includes(character)) ? 1 << 6 :
|
|
|
|
hash.length < hashes_length ? 1 << 7 :
|
|
|
|
0) << 7) |
|
|
|
|
0)) << 1;
|
|
|
|
|
|
|
|
if(!error){
|
|
|
|
item_self = self.item_self = item;
|
|
|
|
hash_self = self.hash_self = hash;
|
|
|
|
};
|
|
|
|
|
|
|
|
return error;
|
|
|
|
};
|
2024-03-20 18:39:48 +00:00
|
|
|
|
|
|
|
construct();
|
|
|
|
|
|
|
|
};
|