]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] WebUI: address jQuery-removal review comments
authorAlexander Moisseev <moiseev@mezonplus.ru>
Fri, 10 Jul 2026 14:03:25 +0000 (17:03 +0300)
committerAlexander Moisseev <moiseev@mezonplus.ru>
Fri, 10 Jul 2026 14:03:25 +0000 (17:03 +0300)
- stats.js: guard the optional fuzzy_hashes key in addFuzzyStorage
  (Object.entries/keys of undefined threw on every Status refresh when
  fuzzy_check was disabled or a neighbour was down), matching the guard
  addStatfiles already had.
- common.js: cancel the hide/show slide animations once the final state
  is committed, so the fill:"forwards" no longer pins height:0 — a later
  re-show was measuring the pinned height and animating 0→0.
- common.js: treat a single Element (incl. <select>/<form>, which expose
  a numeric .length) as one node in toElements, not a collection.
- common.js: tolerate a null neighbours body before Object.keys.
- rspamd.js: null-guard the active-tab lookup in two spots, where a
  missing active tab used to throw.
- upload.js: drop the dead params:{processData:false} (queryServer no
  longer form-encodes).
- common.js: document the statusCode handler signature.

interface/js/app/common.js
interface/js/app/rspamd.js
interface/js/app/stats.js
interface/js/app/upload.js

index 87ea0a78a7bd197def2cee6b20b6b2e3b6b4168e..a7bea8e4a76c81dbdaec19ee3f629a1be65075fe 100644 (file)
@@ -94,6 +94,9 @@ define(["nprogress"],
             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);
             }
@@ -454,7 +457,9 @@ define(["nprogress"],
             }
 
             // 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);
@@ -638,7 +643,7 @@ define(["nprogress"],
                 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,
@@ -696,13 +701,15 @@ define(["nprogress"],
                 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");
@@ -722,12 +729,14 @@ define(["nprogress"],
                     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");
index 955655bd2732250ee1b498d00bee02d7b667f7ee..c41cd288e5f0d56b45fbfd3ebf505398bec2dc1f 100644 (file)
@@ -119,7 +119,8 @@ define(["app/common", "bootstrap", "visibility",
         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");
@@ -604,7 +605,8 @@ define(["app/common", "bootstrap", "visibility",
         } 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
index 2c2d5d4bb653dae4513499789cd9c366a5d0f278..0d60f52dac667fcb9d8548b55eb6d5e3e9453b30 100644 (file)
@@ -338,9 +338,9 @@ define(["app/common", "d3pie", "d3"],
             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>" +
index 8f1de314a1a30a44ab563aaa945f9de881f898a1..3450e92da0f1d756a6803c5f4f64b21346ae5e7f 100644 (file)
@@ -28,9 +28,6 @@ define(["app/common", "app/libft"],
 
                 common.query(url, {
                     data: data,
-                    params: {
-                        processData: false,
-                    },
                     method: method,
                     headers: headers,
                     success: function (json, jqXHR) {
@@ -56,9 +53,6 @@ define(["app/common", "app/libft"],
             enable_disable_scan_btn(true);
             common.query("checkv2", {
                 data: data,
-                params: {
-                    processData: false,
-                },
                 method: "POST",
                 headers: scanTextHeaders,
                 success: function (neighbours_status) {
@@ -153,9 +147,6 @@ define(["app/common", "app/libft"],
 
             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;