bipp-sneltoetsen: Zoeken, Reset, Nieuw, Opslaan, Indienen, Terug (1.1.0)
Ctrl+Z/R/N/S/I/T next to Ctrl+B, one table of label, letter, key. Hints for all buttons while Ctrl is held. BIPP's own title kept, shortcut on a line below. AGENTS.md: Claude installs the dev-stub itself, only the Install click is left, pick the UA Chrome profile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
6d9ae45a2f
commit
3b2528d72a
@@ -21,9 +21,19 @@ De grootte in het dashboard zegt dus in welk spoor een rij zit.
|
|||||||
bin/dev-stub bipp-budgetcode
|
bin/dev-stub bipp-budgetcode
|
||||||
```
|
```
|
||||||
|
|
||||||
De stub gaat meteen naar het klembord. In Tampermonkey neem je het potlood van de bestaande
|
Claude installeert de stub zelf, Glenn plakt niets. Serveer de stub (`--no-copy`) als
|
||||||
rij, dan Cmd+A, Cmd+V, Cmd+S. Via de `+`-tab krijg je een tweede rij in plaats van een
|
`<map>.user.js` vanuit de scratchpad op een vrije poort, open die URL in de Claude-in-Chrome-tab
|
||||||
bijgewerkte, want Tampermonkey herkent een script aan `@namespace` plus `@name`.
|
en Tampermonkey opent zijn installatiepagina. Die pagina (`chrome-extension://`) is voor de
|
||||||
|
browsertools onbereikbaar, dus de enige stap voor Glenn is daar op **Install** klikken. Stop de
|
||||||
|
server daarna.
|
||||||
|
|
||||||
|
- **Juiste Chrome-profiel.** BIPP en de Tampermonkey-scripts zitten in het profiel **UA**
|
||||||
|
(Profile 1). Met de Claude-extensie in twee profielen verbindt `list_connected_browsers` met
|
||||||
|
het profiel dat eerst antwoordt; kies UA met `select_browser`. Of je goed zit, zie je aan de
|
||||||
|
`History` van het profiel na een bezoek vanuit de tool.
|
||||||
|
- Een bestaande rij met dezelfde `@namespace` plus `@name` wordt bijgewerkt. Een andere `@name`
|
||||||
|
geeft een tweede rij die dezelfde file nog eens laadt, dus elke sneltoets dubbel: verwijder
|
||||||
|
dan eerst de oude rij.
|
||||||
|
|
||||||
`bin/dev-stub --list` toont de scriptmappen, `--no-copy` slaat het klembord over.
|
`bin/dev-stub --list` toont de scriptmappen, `--no-copy` slaat het klembord over.
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
| **BIPP** | budgetcode kiezen en zien in het winkelmandje | [installeren](https://raw.githubusercontent.com/glgoose/ua-userscripts/main/scripts/bipp-budgetcode/bipp-budgetcode.user.js) |
|
| **BIPP** | budgetcode kiezen en zien in het winkelmandje | [installeren](https://raw.githubusercontent.com/glgoose/ua-userscripts/main/scripts/bipp-budgetcode/bipp-budgetcode.user.js) |
|
||||||
| **BIPP** | "Inclusief niet-raamcontractartikelen" standaard aan | [installeren](https://raw.githubusercontent.com/glgoose/ua-userscripts/main/scripts/bipp-raamcontract/bipp-raamcontract.user.js) |
|
| **BIPP** | "Inclusief niet-raamcontractartikelen" standaard aan | [installeren](https://raw.githubusercontent.com/glgoose/ua-userscripts/main/scripts/bipp-raamcontract/bipp-raamcontract.user.js) |
|
||||||
| **BIPP** | budgetverantwoordelijke en aanvrager standaard op jezelf | [installeren](https://raw.githubusercontent.com/glgoose/ua-userscripts/main/scripts/bipp-budgetverantwoordelijke/bipp-budgetverantwoordelijke.user.js) |
|
| **BIPP** | budgetverantwoordelijke en aanvrager standaard op jezelf | [installeren](https://raw.githubusercontent.com/glgoose/ua-userscripts/main/scripts/bipp-budgetverantwoordelijke/bipp-budgetverantwoordelijke.user.js) |
|
||||||
| **BIPP** | Ctrl+B voor Bevestigen, met zichtbare hint | [installeren](https://raw.githubusercontent.com/glgoose/ua-userscripts/main/scripts/bipp-sneltoetsen/bipp-sneltoetsen.user.js) |
|
| **BIPP** | Ctrl+letter voor Bevestigen, Zoeken, Opslaan en meer | [installeren](https://raw.githubusercontent.com/glgoose/ua-userscripts/main/scripts/bipp-sneltoetsen/bipp-sneltoetsen.user.js) |
|
||||||
| **iExpense** | alle onkostenrapporten in één doorzoekbare tabel | [installeren](https://raw.githubusercontent.com/glgoose/ua-userscripts/main/scripts/iexpense-search/iexpense-search.user.js) |
|
| **iExpense** | alle onkostenrapporten in één doorzoekbare tabel | [installeren](https://raw.githubusercontent.com/glgoose/ua-userscripts/main/scripts/iexpense-search/iexpense-search.user.js) |
|
||||||
| **PeopleSoft** | werkende knop "Downloaden naar Excel" | [installeren](https://raw.githubusercontent.com/glgoose/ua-userscripts/main/scripts/peoplesoft-excel-download/peoplesoft-excel-download.user.js) |
|
| **PeopleSoft** | werkende knop "Downloaden naar Excel" | [installeren](https://raw.githubusercontent.com/glgoose/ua-userscripts/main/scripts/peoplesoft-excel-download/peoplesoft-excel-download.user.js) |
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,28 @@
|
|||||||
# bipp-sneltoetsen
|
# bipp-sneltoetsen
|
||||||
|
|
||||||
Ctrl+B drukt in BIPP op *Bevestigen*. Op de knop is de B onderstreept, de tooltip toont *Ctrl+B*, en zolang je Ctrl ingedrukt houdt verschijnt *Ctrl+B* boven de knop.
|
Ctrl+letter drukt in BIPP op een knop. De letter is onderstreept, de tooltip toont de sneltoets, en zolang je Ctrl ingedrukt houdt verschijnt de sneltoets boven elke knop die er een heeft.
|
||||||
|
|
||||||
|
| toets | knop | waar |
|
||||||
|
| ------ | ---------- | ------------------------------------------------- |
|
||||||
|
| Ctrl+B | Bevestigen | Aanvraag evalueren, bestelbon detail |
|
||||||
|
| Ctrl+Z | Zoeken | Artikelen, Favorietenlijsten, Aanvragen, Bestelbonnen, Ontvangstregistratie |
|
||||||
|
| Ctrl+R | Reset | idem |
|
||||||
|
| Ctrl+N | Nieuw | Artikelen, Favorietenlijsten |
|
||||||
|
| Ctrl+S | Opslaan | Winkelmandje, bestelbon detail |
|
||||||
|
| Ctrl+I | Indienen | Winkelmandje |
|
||||||
|
| Ctrl+T | Terug | detailpagina's |
|
||||||
|
|
||||||
|
Verwijderen, Annuleren en In wachtstand krijgen bewust geen sneltoets: die zijn niet terug te draaien of komen zelden voor.
|
||||||
|
|
||||||
[**Installeren**](https://raw.githubusercontent.com/glgoose/ua-userscripts/main/scripts/bipp-sneltoetsen/bipp-sneltoetsen.user.js)
|
[**Installeren**](https://raw.githubusercontent.com/glgoose/ua-userscripts/main/scripts/bipp-sneltoetsen/bipp-sneltoetsen.user.js)
|
||||||
· gebeurt er niets, zie de [installatie-uitleg](../../README.md).
|
· gebeurt er niets, zie de [installatie-uitleg](../../README.md).
|
||||||
|
|
||||||
## Hoe het werkt
|
## Hoe het werkt
|
||||||
|
|
||||||
- Het script zoekt op elke pagina onder `/web/` de eerste zichtbare, actieve knop met het label *Bevestigen*. Is er geen, dan doet Ctrl+B niets.
|
- Het script zoekt op elke pagina onder `/web/` per sneltoets de eerste zichtbare, actieve knop met dat label. Is er geen, dan doet de toets niets en gaat hij gewoon door naar de browser.
|
||||||
- Ctrl+B werkt ook in tekstvelden. Op macOS betekent het daar normaal "cursor één teken terug" (Emacs-binding), die je dan niet meer hebt.
|
- Op macOS gebruikt Chrome Cmd voor zijn eigen sneltoetsen, dus Ctrl+letter is vrij. In tekstvelden zijn sommige Ctrl-letters Emacs-bindings (Ctrl+B één teken terug, Ctrl+N volgende regel, Ctrl+T letters wisselen): die heb je in BIPP niet meer.
|
||||||
- De onderstreping en de hint verschuiven niets: ze staan `position:absolute` buiten de flow. Bij een `<input>` kan de letter niet onderstreept worden met HTML, dus komt er een lijntje over, berekend uit de lettermaat.
|
- Zet BIPP zelf al een tooltip op de knop (Bevestigen, Indienen), dan komt de sneltoets op een eigen regel eronder.
|
||||||
|
- De onderstreping en de hints verschuiven niets: ze staan `position:absolute` buiten de flow. Bij een `<input>` kan de letter niet onderstreept worden met HTML, dus komt er een lijntje onder, berekend uit de lettermaat.
|
||||||
- Pagina's die hun knoppen later opbouwen krijgen tot 15 seconden de tijd.
|
- Pagina's die hun knoppen later opbouwen krijgen tot 15 seconden de tijd.
|
||||||
|
|
||||||
## Licentie
|
## Licentie
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name BIPP: sneltoets Ctrl+B voor Bevestigen
|
// @name BIPP: sneltoetsen voor knoppen
|
||||||
// @namespace https://github.com/glgoose/ua-userscripts
|
// @namespace https://github.com/glgoose/ua-userscripts
|
||||||
// @version 1.0.0
|
// @version 1.1.0
|
||||||
// @description Ctrl+B drukt op Bevestigen. De B in de knop is onderstreept en bij ingedrukte Ctrl verschijnt Ctrl+B boven de knop.
|
// @description Ctrl+letter drukt op Bevestigen (B), Zoeken (Z), Reset (R), Nieuw (N), Opslaan (S), Indienen (I) en Terug (T). De letter is onderstreept en bij ingedrukte Ctrl verschijnt de sneltoets boven de knop.
|
||||||
// @author glgoose
|
// @author glgoose
|
||||||
// @license GPL-3.0-or-later
|
// @license GPL-3.0-or-later
|
||||||
// @homepageURL https://github.com/glgoose/ua-userscripts/tree/main/scripts/bipp-sneltoetsen
|
// @homepageURL https://github.com/glgoose/ua-userscripts/tree/main/scripts/bipp-sneltoetsen
|
||||||
@@ -16,32 +16,43 @@
|
|||||||
(function () {
|
(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var LABEL = 'bevestigen';
|
// Knoplabel (kleine letters), de letter die onderstreept wordt, en de toets.
|
||||||
var HINT = 'Ctrl+B';
|
var KEYS = [
|
||||||
|
{ label: 'bevestigen', letter: 'b', code: 'KeyB' },
|
||||||
|
{ label: 'zoeken', letter: 'z', code: 'KeyZ' },
|
||||||
|
{ label: 'reset', letter: 'r', code: 'KeyR' },
|
||||||
|
{ label: 'nieuw', letter: 'n', code: 'KeyN' },
|
||||||
|
{ label: 'opslaan', letter: 's', code: 'KeyS' },
|
||||||
|
{ label: 'indienen', letter: 'i', code: 'KeyI' },
|
||||||
|
{ label: 'terug', letter: 't', code: 'KeyT' }
|
||||||
|
];
|
||||||
var MARK = 'data-bipp-sneltoets';
|
var MARK = 'data-bipp-sneltoets';
|
||||||
|
|
||||||
|
function hint(k) { return 'Ctrl+' + k.letter.toUpperCase(); }
|
||||||
|
|
||||||
function norm(s) { return (s || '').replace(/\s+/g, ' ').trim().toLowerCase(); }
|
function norm(s) { return (s || '').replace(/\s+/g, ' ').trim().toLowerCase(); }
|
||||||
|
|
||||||
function visible(el) { return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length); }
|
function visible(el) { return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length); }
|
||||||
|
|
||||||
// Eerste zichtbare, actieve knop met dit label. Een postback-pagina kan er verborgen kopieën van hebben.
|
// Eerste zichtbare, actieve knop met dit label. Een postback-pagina kan er verborgen kopieën van hebben.
|
||||||
function findButton() {
|
function findButton(k) {
|
||||||
var btns = document.querySelectorAll('input[type="submit"], input[type="button"], button');
|
var btns = document.querySelectorAll('input[type="submit"], input[type="button"], button');
|
||||||
for (var i = 0; i < btns.length; i++) {
|
for (var i = 0; i < btns.length; i++) {
|
||||||
var b = btns[i];
|
var b = btns[i];
|
||||||
if (norm(b.value || b.textContent) === LABEL && !b.disabled && visible(b)) return b;
|
if (norm(b.value || b.textContent) === k.label && !b.disabled && visible(b)) return b;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <button>: de B in een <u>. <input> kan geen HTML bevatten, dus daar komt een lijntje over de letter.
|
// <button>: de letter in een <u>. <input> kan geen HTML bevatten, dus daar komt een lijntje onder de letter.
|
||||||
function underline(btn) {
|
function underline(btn, k) {
|
||||||
if (btn.getAttribute(MARK)) return;
|
if (btn.getAttribute(MARK)) return;
|
||||||
btn.setAttribute(MARK, '1');
|
btn.setAttribute(MARK, k.letter);
|
||||||
if (!btn.title) btn.title = HINT;
|
// BIPP zet soms zelf een title (Bevestigen): dan komt de sneltoets op een eigen regel eronder.
|
||||||
|
btn.title = btn.title ? btn.title + '\n' + hint(k) : hint(k);
|
||||||
if (btn.tagName === 'BUTTON' && btn.children.length === 0) {
|
if (btn.tagName === 'BUTTON' && btn.children.length === 0) {
|
||||||
var t = btn.textContent;
|
var t = btn.textContent;
|
||||||
var i = t.toLowerCase().indexOf('b');
|
var i = t.toLowerCase().indexOf(k.letter);
|
||||||
btn.textContent = '';
|
btn.textContent = '';
|
||||||
btn.appendChild(document.createTextNode(t.slice(0, i)));
|
btn.appendChild(document.createTextNode(t.slice(0, i)));
|
||||||
var u = document.createElement('u');
|
var u = document.createElement('u');
|
||||||
@@ -50,18 +61,18 @@
|
|||||||
btn.appendChild(document.createTextNode(t.slice(i + 1)));
|
btn.appendChild(document.createTextNode(t.slice(i + 1)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
drawLine(btn);
|
drawLine(btn, k);
|
||||||
window.addEventListener('resize', function () { drawLine(btn); });
|
window.addEventListener('resize', function () { drawLine(btn, k); });
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawLine(btn) {
|
function drawLine(btn, k) {
|
||||||
var old = btn.nextSibling && btn.nextSibling.getAttribute && btn.nextSibling.getAttribute(MARK + '-line');
|
var old = btn.nextSibling && btn.nextSibling.getAttribute && btn.nextSibling.getAttribute(MARK + '-line');
|
||||||
if (old) btn.parentNode.removeChild(btn.nextSibling);
|
if (old) btn.parentNode.removeChild(btn.nextSibling);
|
||||||
var cs = getComputedStyle(btn);
|
var cs = getComputedStyle(btn);
|
||||||
var ctx = document.createElement('canvas').getContext('2d');
|
var ctx = document.createElement('canvas').getContext('2d');
|
||||||
ctx.font = cs.fontStyle + ' ' + cs.fontWeight + ' ' + cs.fontSize + ' ' + cs.fontFamily;
|
ctx.font = cs.fontStyle + ' ' + cs.fontWeight + ' ' + cs.fontSize + ' ' + cs.fontFamily;
|
||||||
var text = btn.value || btn.textContent;
|
var text = btn.value || btn.textContent;
|
||||||
var i = text.toLowerCase().indexOf('b');
|
var i = text.toLowerCase().indexOf(k.letter);
|
||||||
var before = ctx.measureText(text.slice(0, i)).width;
|
var before = ctx.measureText(text.slice(0, i)).width;
|
||||||
var letter = ctx.measureText(text.charAt(i)).width;
|
var letter = ctx.measureText(text.charAt(i)).width;
|
||||||
var total = ctx.measureText(text).width;
|
var total = ctx.measureText(text).width;
|
||||||
@@ -77,39 +88,51 @@
|
|||||||
btn.parentNode.insertBefore(line, btn.nextSibling);
|
btn.parentNode.insertBefore(line, btn.nextSibling);
|
||||||
}
|
}
|
||||||
|
|
||||||
var tip = null;
|
var tips = [];
|
||||||
function showTip() {
|
function showTips() {
|
||||||
var btn = findButton();
|
hideTips();
|
||||||
if (!btn) return;
|
KEYS.forEach(function (k) {
|
||||||
hideTip();
|
var btn = findButton(k);
|
||||||
var r = btn.getBoundingClientRect();
|
if (!btn) return;
|
||||||
tip = document.createElement('span');
|
var r = btn.getBoundingClientRect();
|
||||||
tip.textContent = HINT;
|
var tip = document.createElement('span');
|
||||||
tip.style.cssText = 'position:absolute;z-index:99999;pointer-events:none;white-space:nowrap;' +
|
tip.textContent = hint(k);
|
||||||
'font:11px ui-monospace,Menlo,Consolas,monospace;background:#1f2937;color:#fff;border-radius:4px;padding:1px 6px;' +
|
tip.style.cssText = 'position:absolute;z-index:99999;pointer-events:none;white-space:nowrap;' +
|
||||||
'left:' + (r.left + window.scrollX + r.width / 2) + 'px;top:' + (r.top + window.scrollY - 22) + 'px;transform:translateX(-50%)';
|
'font:11px ui-monospace,Menlo,Consolas,monospace;background:#1f2937;color:#fff;border-radius:4px;padding:1px 6px;' +
|
||||||
document.body.appendChild(tip);
|
'left:' + (r.left + window.scrollX + r.width / 2) + 'px;top:' + (r.top + window.scrollY - 22) + 'px;transform:translateX(-50%)';
|
||||||
|
document.body.appendChild(tip);
|
||||||
|
tips.push(tip);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function hideTips() {
|
||||||
|
tips.forEach(function (t) { if (t.parentNode) t.parentNode.removeChild(t); });
|
||||||
|
tips = [];
|
||||||
}
|
}
|
||||||
function hideTip() { if (tip && tip.parentNode) tip.parentNode.removeChild(tip); tip = null; }
|
|
||||||
|
|
||||||
document.addEventListener('keydown', function (e) {
|
document.addEventListener('keydown', function (e) {
|
||||||
if (e.key === 'Control') { if (!e.repeat) showTip(); return; }
|
if (e.key === 'Control') { if (!e.repeat) showTips(); return; }
|
||||||
if (e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey && e.code === 'KeyB') {
|
if (!e.ctrlKey || e.metaKey || e.altKey || e.shiftKey) return;
|
||||||
var btn = findButton();
|
for (var i = 0; i < KEYS.length; i++) {
|
||||||
|
if (e.code !== KEYS[i].code) continue;
|
||||||
|
var btn = findButton(KEYS[i]);
|
||||||
if (!btn) return;
|
if (!btn) return;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
hideTip();
|
hideTips();
|
||||||
btn.click();
|
btn.click();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
document.addEventListener('keyup', function (e) { if (e.key === 'Control') hideTip(); }, true);
|
document.addEventListener('keyup', function (e) { if (e.key === 'Control') hideTips(); }, true);
|
||||||
window.addEventListener('blur', hideTip);
|
window.addEventListener('blur', hideTips);
|
||||||
|
|
||||||
// De pagina bouwt de knoppen soms pas na een postback op: probeer het een paar keer.
|
// De pagina bouwt de knoppen soms pas na een postback op: probeer het een paar keer.
|
||||||
var tries = 0;
|
var tries = 0;
|
||||||
(function init() {
|
(function init() {
|
||||||
var btn = findButton();
|
var left = 0;
|
||||||
if (btn) { underline(btn); return; }
|
KEYS.forEach(function (k) {
|
||||||
if (++tries < 30) setTimeout(init, 500);
|
var btn = findButton(k);
|
||||||
|
if (btn) underline(btn, k); else left++;
|
||||||
|
});
|
||||||
|
if (left && ++tries < 30) setTimeout(init, 500);
|
||||||
})();
|
})();
|
||||||
})();
|
})();
|
||||||
|
|||||||
Reference in New Issue
Block a user