314 lines
10 KiB
JavaScript
314 lines
10 KiB
JavaScript
GamUsino = function(custom){
|
|
|
|
const self = this,
|
|
default_settings = {
|
|
nulls : false,
|
|
default_value : null,
|
|
autostart : true,
|
|
timeout : 2000,
|
|
frames_per_second : 24
|
|
},
|
|
settings = {},
|
|
fragments = {},
|
|
filter_cache = {};
|
|
let started = false,
|
|
my_ip = null,
|
|
frames_per_second = 24,
|
|
ajax_timeout = 2000,
|
|
preload_timeout = 2000,
|
|
thread_filter = null;
|
|
|
|
const constructor = () => {
|
|
|
|
self.settings("autostart") && self.start();
|
|
|
|
};
|
|
|
|
this.start = callback => {
|
|
|
|
const end = status => typeof callback == "function" && callback(status);
|
|
|
|
if(started){
|
|
end(false);
|
|
return false;
|
|
};
|
|
started = true;
|
|
|
|
ajax_timeout = self.settings(["ajax_timeout", "timeout"]);
|
|
preload_timeout = self.settings(["preload_timeout", "timeout"]);
|
|
frames_per_second = self.settings(["frames_per_second", "fps"]);
|
|
|
|
self.send({action : "load_polls"}, data => {
|
|
my_ip = data.content.ip;
|
|
self.preload(".polls-box>.polls", () => {
|
|
|
|
let html = document.querySelector(".html-structure-fragments").innerHTML,
|
|
matches;
|
|
|
|
while(matches = html.match(/<\!\-{2}\s*\[{2}([^\[\]]+)\]{2}\s*\-{2}>/)){
|
|
|
|
const key = matches[1];
|
|
let l;
|
|
|
|
html = html.substring(matches.index + matches[0].length);
|
|
|
|
if((l = html.indexOf(matches[0])) == -1)
|
|
continue;
|
|
|
|
fragments[key] = html.substring(0, l);
|
|
|
|
html = html.substring(l + matches[0].length);
|
|
|
|
};
|
|
|
|
build_polls(data.content.polls);
|
|
|
|
setTimeout(() => thread_filter = setInterval(thread_filter_method, 1000 / frames_per_second), 1000);
|
|
|
|
});
|
|
end(true);
|
|
});
|
|
|
|
return true;
|
|
};
|
|
|
|
this.nulls = nulls => typeof nulls == "boolean" ? nulls : self.settings("nulls", null, false, false);
|
|
|
|
this.default_value = (_default, nulls) => _default !== undefined && (self.nulls(nulls) || _default !== null) ? _default : self.settings("default_value", null, null, true);
|
|
|
|
this.settings = (keys, inputs, _default, nulls) => {
|
|
|
|
const m = (keys = (typeof keys == "object" && keys instanceof Array ? keys : [keys]).filter(key => key && typeof key == "string")).length;
|
|
|
|
if(m){
|
|
|
|
const l = (inputs = (typeof inputs == "object" ? inputs instanceof Array ? inputs : [inputs] : []).concat(custom, settings, default_settings)).length;
|
|
|
|
nulls = self.nulls(nulls);
|
|
|
|
for(let i = 0; i < l; i ++)
|
|
if(inputs[i] && typeof inputs[i] == "object")
|
|
for(let j = 0; j < m; j ++)
|
|
if(inputs[i][keys[j]] !== undefined && (nulls || inputs[i][keys[j]] !== null))
|
|
return inputs[i][keys[j]];
|
|
};
|
|
return self.default_value(_default, nulls);
|
|
};
|
|
|
|
this.send = (data, callback) => {
|
|
|
|
let ended = false;
|
|
const ajax = new XMLHttpRequest(),
|
|
date = Date.now(),
|
|
end = error => {
|
|
if(ended)
|
|
return;
|
|
ended = true;
|
|
if(typeof callback != "function")
|
|
return;
|
|
|
|
let data = ajax.responseText;
|
|
|
|
try{
|
|
data = JSON.parse(data);
|
|
}catch(exception){
|
|
data = ajax.responseText;
|
|
};
|
|
|
|
callback(data, ajax.status, ajax.readyState, error == "OK", error);
|
|
|
|
};
|
|
|
|
ajax.open("post", "/api.php", true);
|
|
ajax.timeout = ajax_timeout;
|
|
ajax.setRequestHeader("content-type", "application/x-www-form-urlencoded,charset=utf-8");
|
|
ajax.onreadystatechange = () => {
|
|
if(ended)
|
|
return;
|
|
if(ajax.readyState == 4)
|
|
end([301, 302, 304].includes(ajax.stauts) || (ajax.status >= 200 && ajax.status < 300) ? "OK" : "HTTP_ERROR");
|
|
else if(Date.now() - date > ajax_timeout)
|
|
end("FORCED_TIMEOUT");
|
|
};
|
|
ajax.send("GamUsino=" + btoa(JSON.stringify(data)));
|
|
|
|
ajax.onabort = () => end("ABORTED");
|
|
ajax.ontimeout = () => end("TIMEOUT");
|
|
ajax.onerror = () => end("ERROR");
|
|
|
|
return ajax;
|
|
};
|
|
|
|
this.confirm = (message, ok_action, no_action) => {
|
|
|
|
const action = confirm(message) ? ok_action : no_action;
|
|
|
|
typeof action == "function" && action();
|
|
|
|
};
|
|
|
|
this.preload = (selector, callback) => {
|
|
if(!selector){
|
|
callback(null, false);
|
|
return;
|
|
};
|
|
if(selector.nodeName || selector.tagName){
|
|
callback(selector, false);
|
|
return;
|
|
};
|
|
if(typeof selector != "string"){
|
|
callback(false, false);
|
|
return;
|
|
};
|
|
|
|
let item;
|
|
|
|
try{
|
|
if(item = document.querySelector(selector)){
|
|
callback(item, false);
|
|
return;
|
|
};
|
|
}catch(exception){
|
|
callback(null, false);
|
|
return;
|
|
};
|
|
|
|
const date = Date.now();
|
|
let preload = setInterval(() => {
|
|
if(item = document.querySelector(selector)){
|
|
clearInterval(preload);
|
|
callback(item, true);
|
|
return;
|
|
}else if(Date.now() - date > preload_timeout){
|
|
clearInterval(preload);
|
|
callback(null, true);
|
|
return;
|
|
};
|
|
}, 1000 / frames_per_second);
|
|
|
|
};
|
|
|
|
this.string_variables = (string, variables, _default) => {
|
|
|
|
const l = (variables = (
|
|
typeof variables == "object" ? variables instanceof Array ? variables : [variables] : []
|
|
).filter(subset => subset && typeof subset == "object")).length;
|
|
|
|
return string.replace(/\{([^\{\}]+)\}/g, (all, key) => {
|
|
for(let i = 0; i < l; i ++)
|
|
if(variables[i][key] !== undefined)
|
|
return variables[i][key];
|
|
return _default !== undefined ? _default : all;
|
|
});
|
|
};
|
|
|
|
const build_polls = polls => {
|
|
|
|
const text = document.querySelector(".polls-box [type=text]").value.trim();
|
|
|
|
document.querySelector(".polls-box>.polls>ul").innerHTML = polls.map((poll, i) => self.string_variables(fragments.poll_menu_fragment, {
|
|
...poll,
|
|
i : i,
|
|
visible : !text || poll.name.includes(text)
|
|
})).join("");
|
|
|
|
};
|
|
|
|
this.add_poll = (item, event) => {
|
|
|
|
const poll_name = item.parentNode.parentNode.querySelector("input").value;
|
|
|
|
poll_name && self.confirm("add_poll_sure", () => {
|
|
self.send({
|
|
action : "add_poll",
|
|
name : poll_name
|
|
}, data => data.content.message ? alert(data.content.message) : build_polls(data.content));
|
|
});
|
|
|
|
};
|
|
|
|
const get_maximum_points = options => options.length ? Math.max(...options.map(option => option.points.filter(point => point.selected).length)) : 0;
|
|
|
|
this.show_poll = (item, event) => {
|
|
|
|
const i = Number(item.getAttribute("data-i"));
|
|
|
|
document.querySelectorAll(".polls-box>.polls [data-seleted=true]").forEach(item => item.setAttribute("data-selected", false));
|
|
item.setAttribute("data-selected", true);
|
|
document.querySelector(".poll-box textarea").value = "";
|
|
|
|
self.send({
|
|
action : "get_poll",
|
|
i : i
|
|
}, data => document.querySelector(".poll-box>.poll").innerHTML = self.string_variables(fragments.poll_box, {
|
|
...data.content,
|
|
i : i,
|
|
maximum_points : get_maximum_points(data.content.options),
|
|
options : create_options_html(data.content.options)
|
|
}));
|
|
|
|
};
|
|
|
|
this.add_option = (item, event) => {
|
|
|
|
const poll_selected = document.querySelector(".polls-box>.polls [data-selected=true]");
|
|
|
|
if(!poll_selected){
|
|
alert("poll_no_selected");
|
|
return;
|
|
};
|
|
|
|
const text = item.parentNode.parentNode.querySelector("textarea").value,
|
|
i = Number(poll_selected.getAttribute("data-i"));
|
|
|
|
!isNaN(i) && text && self.confirm("add_option_sure", () => {
|
|
self.send({
|
|
action : "add_option",
|
|
i : i,
|
|
text : text
|
|
}, data => data.content.message ? alert(data.content.message) : build_options(data.content));
|
|
});
|
|
};
|
|
|
|
const create_options_html = options => {
|
|
|
|
const text = document.querySelector(".poll-box textarea").value.trim();
|
|
|
|
return options.map((option, k) => self.string_variables(fragments.option_item, {
|
|
...option,
|
|
points : option.points.filter(point => point.selected).length,
|
|
i : k,
|
|
visible : !text || option.text.includes(text),
|
|
selected : option.points.some(point => my_ip == point.ip && point.selected) ? " checked" : ""
|
|
})).join("");
|
|
};
|
|
|
|
const build_options = options => {
|
|
document.querySelector(".poll-box>.poll>form").setAttribute("data-maximum-points", get_maximum_points(options));
|
|
document.querySelector(".poll-box>.poll .options>ul").innerHTML = create_options_html(options);
|
|
};
|
|
|
|
this.select_option = (item, event) => self.send({
|
|
action : "set_option",
|
|
i : Number(document.querySelector(".polls-box>.polls [data-selected=true]").getAttribute("data-i")),
|
|
j : Number(item.parentNode.parentNode.getAttribute("data-i")),
|
|
selected : item.checked
|
|
}, data => build_options(data.content));
|
|
|
|
const thread_filter_method = () => [
|
|
["polls", ".polls-box [type=text]", ".polls-box>.polls li"],
|
|
["poll", ".poll-box textarea", ".poll-box>.poll li"]
|
|
].forEach(([key, box, items]) => {
|
|
|
|
const text = document.querySelector(box).value.trim();
|
|
|
|
if(filter_cache[key] != text){
|
|
filter_cache[key] = text;
|
|
document.querySelectorAll(items).forEach(item => item.setAttribute("data-visible", !text || item.getAttribute("title").includes(text)));
|
|
};
|
|
|
|
});
|
|
|
|
constructor();
|
|
|
|
}; |