select-search: recent-blok voor elke dropdown, bipp-budgetcode levert het niet meer zelf

Elke grote dropdown houdt nu zijn eigen vijf laatst gekozen waarden bij,
bovenaan de lijst onder de kopregel recent. Alles zit onder een
localStorage-sleutel, per veld, met een sleutel die uit name of id volgt
zodat rij 3 en rij 4 van hetzelfde veld één lijst delen. Delete haalt een
regel uit recent, en data-ss-recent="manual" plus window.selectSearch.remember()
is er voor wie pas mag onthouden nadat de server bevestigd heeft.

bipp-budgetcode gebruikt die weg en bouwt zijn eigen recent-optgroup dus
niet langer zelf.

Een optie zonder leesbare tekst telt voortaan als "niets gekozen", ook als
ze een waarde draagt, zoals de <option value="0">&nbsp;</option> van een
OAF-scherm. Zo'n regel stond eerst gewoon in de lijst; wie ze koos kreeg
haar daarna permanent als lege blauwe balk onder recent te zien.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Glenn Goossens
2026-09-01 16:59:22 +02:00
co-authored by Claude Opus 5
parent 4a9ea34649
commit b831ab9f1f
8 changed files with 437 additions and 79 deletions
+4 -2
View File
@@ -17,8 +17,10 @@ gekozen waarde zit wel al in de pagina, maar alleen als tooltip op die link.
staat.
- Zoeken in die lijst van ruim vijfduizend codes gaat via
[select-search](../select-search/README.md), dat op dezelfde pagina meeloopt.
- Bovenaan de lijst staan onder *recent* de codes die je het laatst gebruikt hebt. Die
staan verderop niet nog een keer: elke code komt maar één keer in de lijst voor.
- Bovenaan de lijst staan onder *recent* de vijf codes die je het laatst gebruikt hebt. Dat blok
komt van [select-search](../select-search/README.md#recent) en werkt intussen op elke grote
dropdown op BIPP, niet enkel op de budgetcode. Hier telt een code pas als de server ze
aanvaard heeft: mislukt het opslaan, dan blijft recent ongemoeid.
- Is de grootboekrekening ook gekozen, dan komt de code in **Interne commentaar** te staan.
Stond daar al iets, dan komt ze op een nieuwe regel eronder. Kies je daarna een andere code,
dan wordt die regel vervangen in plaats van dat er een bijkomt.
+12 -49
View File
@@ -1,7 +1,7 @@
// ==UserScript==
// @name BIPP: budgetcode in het winkelmandje
// @namespace https://github.com/glgoose/ua-userscripts
// @version 1.4.0
// @version 1.5.0
// @description Zet de budgetcode als dropdown in de winkelmandjerij zelf, onder de grootboekrekening, zodat je niet meer via de aparte pagina Selectie analytische velden moet en de gekozen code ook gewoon ziet staan. Slaat op via een achtergrond-postback en vult de code aan in Interne commentaar.
// @author Glenn Goossens
// @license GPL-3.0-or-later
@@ -30,9 +30,7 @@
var SELECTOR_URL = 'AnalyticalFieldSelector.aspx';
var CACHE_KEY = 'bippBudgetcodeOptions';
var MRU_KEY = 'bippBudgetcodeRecent';
var TTL_MS = 7 * 24 * 60 * 60 * 1000;
var MRU_MAX = 8;
var EMPTY_LABEL = 'budgetcode';
// ---------- kleine hulpjes ----------
@@ -117,24 +115,6 @@
return loading;
}
// ---------- recent gebruikte codes ----------
function readMru() {
try { return JSON.parse(localStorage.getItem(MRU_KEY)) || []; } catch (e) { return []; }
}
function pushMru(value, label) {
if (!value) return;
var list = readMru().filter(function (e) { return e[0] !== value; });
list.unshift([value, label]);
try { localStorage.setItem(MRU_KEY, JSON.stringify(list.slice(0, MRU_MAX))); } catch (e) { /* stil */ }
}
// De lijst kon alleen groeien. Dit is de weg terug: de code verdwijnt uit recent en staat
// daarna weer gewoon tussen alle budgetcodes.
function removeMru(value) {
var list = readMru().filter(function (e) { return e[0] !== value; });
try { localStorage.setItem(MRU_KEY, JSON.stringify(list)); } catch (e) { /* stil */ }
}
// ---------- formulier posten ----------
function serialize(form, extra) {
@@ -401,27 +381,12 @@
// dubbel in. De select zelf blijft dezelfde node, dus dit verschuift niets.
while (select.children.length > 1) select.removeChild(select.lastChild);
var mru = readMru();
var inRecent = {};
if (mru.length) {
var recent = document.createElement('optgroup');
recent.label = 'recent';
// Hiermee weet select-search dat deze regels weg mogen met Delete. Alle budgetcodes krijgt
// die vlag niet, daar valt niets te verwijderen.
recent.dataset.removable = '1';
mru.forEach(function (e) {
inRecent[e[0]] = true;
recent.appendChild(new Option(e[1], e[0]));
});
select.appendChild(recent);
}
// Het recent-blok komt van select-search, dat het bovenaan de lijst zet en de dubbels er
// hier uit haalt. Wij leveren enkel de volledige lijst.
var all = document.createElement('optgroup');
all.label = 'alle budgetcodes';
data.options.forEach(function (e) {
// Wat al onder recent staat komt hier niet nog eens: twee keer dezelfde regel in de
// zoekresultaten is verwarrend, ook al staat er een groepslabel bij.
if (e[0] && !inRecent[e[0]]) all.appendChild(new Option(e[1], e[0]));
if (e[0]) all.appendChild(new Option(e[1], e[0]));
});
select.appendChild(all);
@@ -437,7 +402,11 @@
var select = document.createElement('select');
select.className = 'TextBox';
// Geen name-attribuut: dan serialiseert FormData ons veld niet mee.
// Geen name-attribuut: dan serialiseert FormData ons veld niet mee. select-search leidt zijn
// veldsleutel normaal uit name of id af, dus die krijgt hij hier expliciet mee. Manueel, want
// een code hoort pas in recent te staan als de server ze aanvaard heeft, zie onPick.
select.dataset.ssRecent = 'manual';
select.dataset.ssRecentKey = 'budgetcode';
select.appendChild(new Option(EMPTY_LABEL, ''));
var code = currentCode(row);
@@ -498,7 +467,9 @@
row.pending = null;
// De guard kan de zichtbare waarde ondertussen teruggezet hebben.
setValue(row, code);
if (code) pushMru(code, label);
if (code && window.selectSearch && window.selectSearch.remember) {
window.selectSearch.remember(select, code, label);
}
// Geen vinkje. De zandloper verdwijnt en de dropdowntekst wordt weer zwart, en dat is
// de bevestiging al. Een tick die een seconde later toch weer weggaat voegt niets toe
// en vraagt aandacht voor iets wat al gelukt is.
@@ -543,14 +514,6 @@
return;
}
fillOptions(u.select, data, row.savedCode);
// select-search meldt dat een regel uit recent weg mag, wij weten pas wat dat betekent.
// Opnieuw opbouwen zet de code vanzelf terug onder alle budgetcodes. Er wordt niets
// opgeslagen: fillOptions vuurt geen change, dus onPick en de POST-keten blijven erbuiten.
u.select.addEventListener('select-search:remove', function (e) {
if (!e.detail || !e.detail.value) return;
removeMru(e.detail.value);
fillOptions(u.select, data, u.select.value);
});
if (typeof window.__selectSearchScan === 'function') window.__selectSearchScan();
});
})['catch'](function (err) {