From: Alexander Moisseev Date: Sat, 4 Jul 2026 15:38:58 +0000 (+0300) Subject: [Rework] WebUI: migrate BS5 off jQuery bridge X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=48203be3de6dfd1d16910cdfe3fad1a4e67b330d;p=thirdparty%2Frspamd.git [Rework] WebUI: migrate BS5 off jQuery bridge 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. --- diff --git a/interface/js/app/config.js b/interface/js/app/config.js index 3cba6a7ab3..3dacf3a636 100644 --- a/interface/js/app/config.js +++ b/interface/js/app/config.js @@ -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", diff --git a/interface/js/app/libft.js b/interface/js/app/libft.js index 5cad98974b..0a0135dcc6 100644 --- a/interface/js/app/libft.js +++ b/interface/js/app/libft.js @@ -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(); diff --git a/interface/js/app/rspamd.js b/interface/js/app/rspamd.js index 01339cd1f7..dd2b8e4f53 100644 --- a/interface/js/app/rspamd.js +++ b/interface/js/app/rspamd.js @@ -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(); }); }); }());