From a3009324217f49a8431aab6400a3a3ad76741349 Mon Sep 17 00:00:00 2001 From: solocla Date: Wed, 22 Jul 2026 14:04:50 +0200 Subject: [PATCH] fixed field object search ranking --- public/userarea/gridRenderer.js | 66 ++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/public/userarea/gridRenderer.js b/public/userarea/gridRenderer.js index 4dc6b97..d35b92e 100644 --- a/public/userarea/gridRenderer.js +++ b/public/userarea/gridRenderer.js @@ -143,7 +143,54 @@ }), ); } + // Ranking inizio/centro/fine per select con dati già in memoria. + // Restituisce { matcher, sorter } da passare a select2(). + function rankedLocalSelect2() { + return { + matcher: function (params, data) { + const term = $.trim(params.term || "").toLowerCase(); + if (term === "") return data; + if (typeof data.text === "undefined") return null; + // AND multi-termine, posizione indipendente + const text = data.text.toLowerCase(); + const terms = term.split(/\s+/).filter(Boolean); + const all = terms.every((t) => text.indexOf(t) !== -1); + return all ? data : null; + }, + sorter: function (results) { + const term = $( + ".select2-container--open .select2-search__field", + ).val(); + const search = (term || "").toLowerCase().trim(); + if (!search) return results; + + const first = search.split(/\s+/)[0]; + + function score(text) { + const t = (text || "").toLowerCase(); + if (t === search) return 0; // match esatto + if (t.indexOf(first) === 0) return 1; // inizia col termine + if (new RegExp("(^|\\s)" + escapeRegExp(first)).test(t)) + return 2; // inizio parola + return 3; // in mezzo + } + + return results.slice().sort(function (a, b) { + const sa = score(a.text); + const sb = score(b.text); + if (sa !== sb) return sa - sb; + return (a.text || "").localeCompare(b.text || "", "it", { + sensitivity: "base", + }); + }); + }, + }; + } + + function escapeRegExp(s) { + return String(s).replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + } function sortSelect2ResultsByStart(data) { const term = $(".select2-container--open .select2-search__field").val(); @@ -683,7 +730,7 @@ const reqCls = col.isRequired ? " required-input" : ""; const req = col.isRequired ? " required" : ""; - return ``; + return ``; } function buildDropdownOptionsHTML(fieldId, selectedValue) { @@ -1203,6 +1250,12 @@ items.forEach((item) => sel.add(new Option(item.text, item.id)), ); + $(sel).select2({ + placeholder: "Seleziona...", + allowClear: true, + width: "100%", + ...rankedLocalSelect2(), + }); } }); @@ -1705,9 +1758,18 @@ const fieldId = this.dataset.fieldId; if (fieldId) $(this).select2(sceltaSelect2Config(fieldId)); }); + $(this) + .find(".searchable-fixed:not(.select2-hidden-accessible)") + .each(function () { + $(this).select2({ + placeholder: "Seleziona...", + allowClear: true, + width: "100%", + ...rankedLocalSelect2(), + }); + }); }); } - // ── Column resize ────────────────────────────────────────────────────── function initColumnResizers() {