if (typeof selector === "string") {
return Array.from(document.querySelectorAll(selector));
}
+ // A single Element node — including <select>/<form>, which expose a
+ // numeric .length — must not be mistaken for a collection.
+ if (selector.nodeType === 1) return [selector];
if (typeof selector.length === "number") {
return Array.from(selector).filter(Boolean);
}
}
// jQuery fires statusCode handlers once per request for the final
- // status, in addition to success/error.
+ // status, in addition to success/error. Unlike jQuery, which passed
+ // (jqXHR, textStatus, errorThrown), the handler here is invoked as
+ // (responseText, statusText, xhr).
function runStatusCode() {
if (o.statusCode && typeof o.statusCode[xhr.status] === "function") {
o.statusCode[xhr.status](xhr.responseText, xhr.statusText, xhr);
queryServer(neighbours_status, 0, "neighbours", {
success: function (json) {
const [{data}] = json;
- if (Object.keys(data).length === 0) {
+ if (!data || Object.keys(data).length === 0) {
ui.neighbours = {
local: {
host: window.location.host,
if (anim) {
const height = el.offsetHeight;
el.style.overflow = "hidden";
- el.animate(
+ const fx = el.animate(
[{height: height + "px"}, {height: 0}],
{duration: 400, easing: "ease", fill: "forwards"}
- ).onfinish = () => {
+ );
+ fx.onfinish = () => {
el.classList.add("d-none");
el.style.height = "";
el.style.overflow = "";
+ fx.cancel();
};
} else {
el.classList.add("d-none");
const height = el.offsetHeight; // measure natural height now visible
el.style.overflow = "hidden";
el.style.height = "0";
- el.animate(
+ const fx = el.animate(
[{height: 0}, {height: height + "px"}],
{duration: 400, easing: "ease", fill: "forwards"}
- ).onfinish = () => {
+ );
+ fx.onfinish = () => {
el.style.height = "";
el.style.overflow = "";
+ fx.cancel();
};
} else {
el.classList.remove("d-none");
stopTimers();
if (id === "#refresh" || id === "#autoRefresh") {
- tab_id = "#" + document.querySelector(".nav-link.active").id;
+ const active = document.querySelector(".nav-link.active");
+ if (active) tab_id = "#" + active.id;
}
document.getElementById("autoRefresh").classList.add("invisible");
} else {
document.getElementById("learnServers").classList.add("invisible");
}
- tabClick("#" + document.querySelector("#tablist > .nav-item > .nav-link.active").id);
+ const active = document.querySelector("#tablist > .nav-item > .nav-link.active");
+ if (active) tabClick("#" + active.id);
});
// Radio buttons
function addFuzzyStorage(server, storages) {
let i = 0;
const fuzzyTbody = document.querySelector("#fuzzyTable tbody");
- Object.entries(storages).forEach(([storage, hashes]) => {
+ Object.entries(storages || {}).forEach(([storage, hashes]) => {
const serverCell = (i === 0)
- ? '<td rowspan="' + Object.keys(storages).length + '">' + common.escapeHTML(server) + "</td>"
+ ? '<td rowspan="' + Object.keys(storages || {}).length + '">' + common.escapeHTML(server) + "</td>"
: "";
fuzzyTbody.insertAdjacentHTML("beforeend", "<tr>" + serverCell +
"<td>" + common.escapeHTML(storage) + "</td>" +
common.query(url, {
data: data,
- params: {
- processData: false,
- },
method: method,
headers: headers,
success: function (json, jqXHR) {
enable_disable_scan_btn(true);
common.query("checkv2", {
data: data,
- params: {
- processData: false,
- },
method: "POST",
headers: scanTextHeaders,
success: function (neighbours_status) {
common.query("plugins/fuzzy/hashes?flag=" + document.getElementById("fuzzy-flag").value, {
data: data,
- params: {
- processData: false,
- },
method: "POST",
success: function (neighbours_status) {
const json = neighbours_status[0].data;