]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Rework] WebUI: migrate BS5 off jQuery bridge
authorAlexander Moisseev <moiseev@mezonplus.ru>
Sat, 4 Jul 2026 15:38:58 +0000 (18:38 +0300)
committerAlexander Moisseev <moiseev@mezonplus.ru>
Sun, 5 Jul 2026 17:21:16 +0000 (20:21 +0300)
Replace the Bootstrap 5 jQuery bridge (.modal/.popover/.trigger
"click.bs.dropdown") with the vanilla constructor API
(bootstrap.{Modal,Popover,Dropdown}.getOrCreateInstance) in
rspamd.js, config.js and libft.js, capturing the bootstrap module
where needed.

Prerequisite for removing jQuery: the bridge only activates when
jQuery is loaded, while the vanilla API works regardless. With jQuery
still present the existing $(el).on("*.bs.*") subscriptions keep
firing, so those stay jQuery for now and move to addEventListener
together with the rest of the jQuery removal. The main.js shim
deps:["jquery"] becomes redundant and is dropped in the final stage.

interface/js/app/config.js
interface/js/app/libft.js
interface/js/app/rspamd.js

index 3cba6a7ab3589ed8074713b28949aacf9e569b09..3dacf3a636957fa687857997fdd217c83a4c6c0b 100644 (file)
@@ -4,8 +4,8 @@
 
 /* global require */
 
-define(["jquery", "app/common"],
-    ($, common) => {
+define(["jquery", "app/common", "bootstrap"],
+    ($, common, bootstrap) => {
         "use strict";
         const ui = {};
 
@@ -178,7 +178,7 @@ define(["jquery", "app/common"],
                     $("#modalDialog .modal-header").find("[data-fa-i2svg]").addClass(icon);
                     $("#modalTitle").html(item.uri);
 
-                    $("#modalDialog").modal("show");
+                    bootstrap.Modal.getOrCreateInstance(document.getElementById("modalDialog")).show();
                 },
                 errorMessage: "Cannot receive maps data",
                 server: common.getServer()
@@ -204,7 +204,7 @@ define(["jquery", "app/common"],
             common.query("savemap", {
                 success: function () {
                     common.alertMessage("alert-success", "Map data successfully saved");
-                    $("#modalDialog").modal("hide");
+                    bootstrap.Modal.getOrCreateInstance(document.getElementById("modalDialog")).hide();
                 },
                 errorMessage: "Save map error",
                 method: "POST",
index 5cad98974b36beb70a1421a72efecfd6115fb46c..0a0135dcc65d3fefced885cd26fdc9a03d89f64b 100644 (file)
@@ -1,5 +1,5 @@
-define(["jquery", "app/common", "app/tab-utils", "tabulator"],
-    ($, common, tabUtils, Tabulator) => {
+define(["jquery", "app/common", "bootstrap", "app/tab-utils", "tabulator"],
+    ($, common, bootstrap, tabUtils, Tabulator) => {
         "use strict";
         const ui = {};
         const columnsCustom = JSON.parse(localStorage.getItem("columns")) || {};
@@ -456,7 +456,10 @@ define(["jquery", "app/common", "app/tab-utils", "tabulator"],
         };
 
         ui.destroyTable = function (table) {
-            $("#" + table + " .tab-columns-btn.show").trigger("click.bs.dropdown");
+            const openColumnsBtn = document.querySelector("#" + table + " .tab-columns-btn.show");
+            if (openColumnsBtn) {
+                bootstrap.Dropdown.getOrCreateInstance(openColumnsBtn).hide();
+            }
             $("#" + table + " .tab-columns-btn").attr("disabled", true);
             if (common.tables[table]) {
                 common.tables[table].destroy();
index 01339cd1f7428be579ca6ed5da2e5d99f2a032ac..dd2b8e4f53f9a1f2be77f03f5aa32f6d241d1511 100644 (file)
@@ -308,8 +308,8 @@ define(["jquery", "app/common", "bootstrap", "visibility",
                     .on("shown.bs.modal", () => {
                         $("#connectDialog").off("shown.bs.modal");
                         $("#connectPassword").focus();
-                    })
-                    .modal("show");
+                    });
+                bootstrap.Modal.getOrCreateInstance(document.getElementById("connectDialog")).show();
 
                 $("#connectForm").off("submit").on("submit", (e) => {
                     e.preventDefault();
@@ -339,7 +339,7 @@ define(["jquery", "app/common", "bootstrap", "visibility",
                                 sessionStorage.setItem("read_only", data.read_only);
                                 saveCredentials(password);
                                 $("#connectForm").off("submit");
-                                $("#connectDialog").modal("hide");
+                                bootstrap.Modal.getOrCreateInstance(document.getElementById("connectDialog")).hide();
                                 displayUI();
                             }
                         },
@@ -409,7 +409,7 @@ define(["jquery", "app/common", "bootstrap", "visibility",
             );
         }
 
-        $("#settings").popover({
+        bootstrap.Popover.getOrCreateInstance(document.getElementById("settings"), {
             container: "body",
             placement: "bottom",
             html: true,
@@ -418,8 +418,9 @@ define(["jquery", "app/common", "bootstrap", "visibility",
                 // Using .clone() has the side-effect of producing elements with duplicate id attributes.
                 return $("#settings-popover").clone();
             }
+        });
         // Restore the tooltip of the element that the popover is attached to.
-        }).attr("title", function () {
+        $("#settings").attr("title", function () {
             return $(this).attr("data-original-title");
         });
         $("#settings").on("click", (e) => {
@@ -489,7 +490,7 @@ define(["jquery", "app/common", "bootstrap", "visibility",
                     // Button (or icon within a button) that triggers the popover.
                     $(e.target).closest("button").attr("aria-describedby") === this.id
                 ) return;
-                $("#settings").popover("hide");
+                bootstrap.Popover.getOrCreateInstance(document.getElementById("settings")).hide();
             });
         });
     }());