Skip to main content

max / makenotwork

Say the browser's own verbs in the dispatcher, not in a global print, back, open, nav-to-value, submit-form, remove-parent and noop are the user agent's verbs: no description will ever own them, and nav was already spelled as a builtin. Seven wrappers leave actions-pages.js, actions-partials.js and actions-tabs.js; the seal drops 131 to 124.
Author: Max Johnson <me@maxj.phd> · 2026-09-01 16:18 UTC
Signed with PGP, not checked
Commit: b154427475234a4c65d79bc5ce6f070064a512eb
Parent: 1edf304
11 files changed, +33 insertions, -37 deletions
@@ -44,13 +44,3 @@
44 44 window.onAddToCartLink = function () {
45 45 fetch('/api/cart/' + this.getAttribute('data-arg'), {method:'POST',headers:csrfHeaders()}).then(function(r){if(!r.ok)throw new Error('Failed');return r.json()}).then(function(){window.location.href='/cart'}).catch(function(){alert('Could not add to cart. Please try again.')});
46 46 };
47 -
48 - // purchase.html: onclick="window.history.back()"
49 - window.historyBack = function () {
50 - window.history.back();
51 - };
52 -
53 - // receipt.html: onclick="window.print()"
54 - window.printPage = function () {
55 - window.print();
56 - };
@@ -10,19 +10,12 @@
10 10 * Each function preserves the original inline behavior verbatim.
11 11 */
12 12
13 - // No-op verb: lets an element use data-stop/data-prevent modifiers without
14 - // running any action (former onclick="event.stopPropagation();").
15 - window.noop = function () {};
16 -
17 13 // link_row.html
18 14 window.onMoveLink = function (dir) { moveLink(this, parseInt(dir, 10)); };
19 15 window.onEditLink = function () { editLink(this); };
20 16 window.onSaveLink = function () { saveLink(this); };
21 17 window.onCancelLink = function () { cancelLink(this); };
22 18
23 - // git_nav.html
24 - window.navToValue = function () { if (this.value) window.location.href = this.value; };
25 -
26 19 // insertion_list.html
27 20 window.insertionsStartUpload = function () { MNW.insertions.startUpload(); };
28 21 window.onInsertionFileSelected = function () { MNW.insertions.handleFileSelected(this); };
@@ -47,9 +40,6 @@
47 40 window.onPlacementPositionChange = function () { MNW.insertions.toggleOffsetInput(this.value); };
48 41 window.onAddPlacement = function (id) { MNW.insertions.addPlacement(id); };
49 42
50 - // toast.html
51 - window.dismissToast = function () { this.parentElement.remove(); };
52 -
53 43 // slug_status.html
54 44 window.applySlugSuggestion = function () {
55 45 var i = this.closest('.form-group').querySelector('input[name=slug]');
@@ -6,10 +6,6 @@
6 6 // verbatim former inline handlers, adjusted only to read args from the element.
7 7
8 8 // --- item_overview.html ---
9 - window.openInNewTab = function (url) {
10 - window.open(url, '_blank');
11 - };
12 -
13 9 window.copyItemLink = function (path) {
14 10 navigator.clipboard.writeText(window.location.origin + path).then(() => this.textContent = 'Copied!').catch(() => this.textContent = 'Failed');
15 11 };
@@ -63,11 +59,6 @@
63 59 document.getElementById('pc-trial-days').value = this.value;
64 60 };
65 61
66 - // --- user_payments.html ---
67 - window.submitOwnForm = function () {
68 - this.form.requestSubmit();
69 - };
70 -
71 62 // --- library_collections.html ---
72 63 window.slugifyCollName = function () {
73 64 document.getElementById('new-coll-slug').value = this.value.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
@@ -42,7 +42,7 @@
42 42 /// A ratchet that only refuses to grow lets removals go unrecorded, so this
43 43 /// number is a ceiling rather than a progress figure: measure before trusting
44 44 /// it as one.
45 - const HIGH_WATER: usize = 131;
45 + const HIGH_WATER: usize = 124;
46 46
47 47 /// Every file whose global assignments count: the legacy scripts and the typed
48 48 /// modules that replaced them.
@@ -161,7 +161,7 @@
161 161 <div id="page-purchase-cfg" hidden data-item-id="{{ item.id }}" data-pwyw-enabled="{% if pwyw_enabled %}true{% else %}false{% endif %}"></div>
162 162 <script src="/static/page-purchase.js?v=0623" defer></script>
163 163 {% endif %}
164 - <button class="btn-secondary" data-action="historyBack">Cancel</button>
164 + <button class="btn-secondary" data-action="back">Cancel</button>
165 165 </div>
166 166
167 167 <div class="security-note">
@@ -68,7 +68,7 @@
68 68
69 69 <div class="receipt-footer">
70 70 <p>Sold by {{ seller_username }} via Makenotwork. Makenotwork charges 0% platform fee. Payment processing by Stripe (~3%).</p>
71 - <button class="btn-secondary print-btn" data-action="printPage">Print Receipt</button>
71 + <button class="btn-secondary print-btn" data-action="print">Print Receipt</button>
72 72 </div>
73 73 </div>
74 74 </div>
@@ -1,5 +1,5 @@
1 1 <div class="git-ref-bar">
2 - <select class="git-ref-select" data-change="navToValue">
2 + <select class="git-ref-select" data-change="nav-to-value">
3 3 {% for r in refs %}
4 4 <option value="/git/{{ owner }}/{{ repo_name }}/tree/{{ r.name }}"
5 5 {% if r.name == current_ref %}selected{% endif %}>
@@ -1,4 +1,4 @@
1 1 <div class="toast toast-{{ toast_type }}" role="alert">
2 2 <span>{{ message }}</span>
3 - <button class="toast-dismiss" data-action="dismissToast" aria-label="Dismiss">&times;</button>
3 + <button class="toast-dismiss" data-action="remove-parent" aria-label="Dismiss">&times;</button>
4 4 </div>
@@ -39,7 +39,15 @@
39 39
40 40 type BuiltinFn = (el: Element) => void;
41 41
42 - /** Built-in verbs operating on `data-target` element ids. */
42 + /** Built-in verbs: the ones that operate on `data-target` element ids, and the
43 + * ones that ask the browser for something.
44 + *
45 + * The second group is here rather than in `static/actions-*.js` because no
46 + * description will ever own it. Printing, going back, opening a second tab and
47 + * submitting the form an input sits in are the user agent's own verbs: quasi
48 + * describes what a screen says, and none of these say anything about this
49 + * server. `nav` was already spelled this way; these read their argument off the
50 + * same `data-href`, or off the element itself. */
43 51 const BUILTINS: Record<string, BuiltinFn> = {
44 52 show: (el) => targets(el).forEach((t) => t.classList.remove('hidden')),
45 53 hide: (el) => targets(el).forEach((t) => t.classList.add('hidden')),
@@ -47,6 +55,23 @@
47 55 click: (el) => targets(el).forEach((t) => t.click()),
48 56 remove: (el) => targets(el).forEach((t) => t.remove()),
49 57 'remove-self': (el) => el.remove(),
58 + 'remove-parent': (el) => el.parentElement?.remove(),
59 + // Runs nothing on purpose. It is what lets an element carry `data-stop` or
60 + // `data-prevent` without also naming an action, and both modifiers are
61 + // applied by `run` before any verb is looked up.
62 + noop: () => {},
63 + print: () => window.print(),
64 + back: () => window.history.back(),
65 + open: (el) => {
66 + const href = el.getAttribute('data-href');
67 + if (href) window.open(href, '_blank');
68 + },
69 + // A select whose own value is the address to go to.
70 + 'nav-to-value': (el) => {
71 + const { value } = el as HTMLSelectElement;
72 + if (value) window.location.href = value;
73 + },
74 + 'submit-form': (el) => (el as HTMLInputElement).form?.requestSubmit(),
50 75 };
51 76
52 77 /** Collect positional args from `data-arg` / `data-arg2`. Exported for tests. */
@@ -2,7 +2,7 @@
2 2 <div class="section-header">
3 3 <h2 class="subsection-title">Overview</h2>
4 4 <div class="action-buttons">
5 - <button class="btn-secondary" data-action="openInNewTab" data-arg="/i/{{ item.id }}">View Public Page</button>
5 + <button class="btn-secondary" data-action="open" data-href="/i/{{ item.id }}">View Public Page</button>
6 6 <button class="btn-secondary" data-action="copyItemLink" data-arg="/i/{{ item.id }}">Copy Link</button>
7 7 <button class="btn-secondary" data-action="openEmbedSection">Embed &amp; Share</button>
8 8 <button class="btn-secondary"