mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 08:09:18 +02:00
feat: render actual elements in markdown cheatsheet instead of labels
Replace text labels (h1, bold, italic) with rendered HTML in the Rendu column: headings, strong, em, del, code, links, blockquote, lists, hr, sup, small
This commit is contained in:
@@ -236,6 +236,156 @@ Possible causes:
|
||||
updates `hidden.value` programmatically. If someone adds custom JS that updates
|
||||
form values without firing events, autosave won't detect those changes.
|
||||
|
||||
## HTMX v2 Migration Plan
|
||||
|
||||
### The Core Pattern
|
||||
|
||||
HTMX v2 replaces the entire `autosave.js` fetch/debounce/CSRF-update loop. The key pieces:
|
||||
|
||||
- `hx-trigger` handles debouncing
|
||||
- `hx-on::after-request` handles CSRF token rotation
|
||||
- `hx-swap="none"` since you only need the JSON response side-effect
|
||||
- A response header (`HX-Trigger`) can drive the status indicator
|
||||
|
||||
### 1. Native Input Forms (Contacts & Sidebar Links) — Full Replacement
|
||||
|
||||
These are straightforward since all inputs fire native DOM events.
|
||||
|
||||
```html
|
||||
<form
|
||||
hx-post="/admin/actions/apropos.php"
|
||||
hx-trigger="change delay:1500ms, input delay:1500ms"
|
||||
hx-swap="none"
|
||||
hx-on::after-request="handleAutosaveResponse(event)"
|
||||
>
|
||||
<input type="hidden" name="csrf_token" value="...">
|
||||
<input type="hidden" name="apropos_key" value="contacts">
|
||||
|
||||
<!-- your inputs -->
|
||||
|
||||
<span data-autosave-status></span>
|
||||
</form>
|
||||
```
|
||||
|
||||
One subtlety: HTMX v2 fires the trigger on the **element with `hx-trigger`**, which
|
||||
here is the `<form>` — so `change` and `input` events bubbling up from child inputs
|
||||
will correctly trigger it.
|
||||
|
||||
### 2. OverType Forms (Static Pages & Form Help) — Partial Replacement
|
||||
|
||||
OverType updates the hidden input programmatically without firing DOM events, so you
|
||||
need to dispatch a custom event from its `onChange` hook:
|
||||
|
||||
```js
|
||||
// In your OverType init
|
||||
onChange: function(value) {
|
||||
hiddenInput.value = value;
|
||||
// Dispatch a custom event that HTMX can listen for
|
||||
hiddenInput.dispatchEvent(
|
||||
new CustomEvent('overtype:change', { bubbles: true })
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Then on the form:
|
||||
|
||||
```html
|
||||
<form
|
||||
hx-post="/admin/actions/page.php"
|
||||
hx-trigger="overtype:change delay:1500ms"
|
||||
hx-swap="none"
|
||||
hx-on::after-request="handleAutosaveResponse(event)"
|
||||
>
|
||||
<input type="hidden" name="csrf_token" value="...">
|
||||
<input type="hidden" name="slug" value="charte">
|
||||
<input type="hidden" id="content" name="content" value="">
|
||||
|
||||
<span data-autosave-status></span>
|
||||
</form>
|
||||
```
|
||||
|
||||
### 3. CSRF Rotation + Status Indicator
|
||||
|
||||
Replace `autosave.js`'s `.json().then()` pattern with a single shared handler. The
|
||||
silent-parse-error risk disappears because you're explicitly handling the response:
|
||||
|
||||
```js
|
||||
function handleAutosaveResponse(event) {
|
||||
const status = event.target.closest('form')
|
||||
.querySelector('[data-autosave-status]');
|
||||
|
||||
if (!event.detail.successful) {
|
||||
if (status) status.textContent = 'Erreur !';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = JSON.parse(event.detail.xhr.responseText);
|
||||
|
||||
// Rotate CSRF token in both the form and the meta tag
|
||||
if (data.csrf_token) {
|
||||
event.target.closest('form')
|
||||
.querySelector('input[name="csrf_token"]').value = data.csrf_token;
|
||||
const meta = document.querySelector('meta[name="csrf-token"]');
|
||||
if (meta) meta.content = data.csrf_token;
|
||||
}
|
||||
|
||||
if (status) status.textContent = data.success ? 'Enregistré ✓' : 'Erreur !';
|
||||
|
||||
} catch {
|
||||
// JSON parse failed (e.g. PHP warning in output) — surface it rather than silently swallowing
|
||||
if (status) status.textContent = 'Erreur !';
|
||||
console.warn('Autosave: could not parse response', event.detail.xhr.responseText);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This is a direct improvement over the current `autosave.js` `.catch(() => {})`
|
||||
silent swallow — you now see the PHP warning in the console instead of just
|
||||
getting a mystery 403 on the next save.
|
||||
|
||||
### 4. "Loading" State During Save
|
||||
|
||||
If you want a saving indicator (the current `"Enregistrement…"` state), use
|
||||
`htmx:beforeRequest` on the form — or use HTMX's built-in `htmx-request` class
|
||||
which is added to the element automatically while a request is in flight:
|
||||
|
||||
```css
|
||||
/* Target the class HTMX adds */
|
||||
form.htmx-request [data-autosave-status]::after {
|
||||
content: 'Enregistrement…';
|
||||
}
|
||||
```
|
||||
|
||||
Or explicitly with an event listener:
|
||||
|
||||
```js
|
||||
document.body.addEventListener('htmx:beforeRequest', e => {
|
||||
const status = e.target.querySelector('[data-autosave-status]');
|
||||
if (status) status.textContent = 'Enregistrement…';
|
||||
});
|
||||
```
|
||||
|
||||
### 5. The Add/Remove Group JS Still Works Unchanged
|
||||
|
||||
The reindex logic (updating `name` attributes after add/remove) is inline
|
||||
`<script>` independent of `autosave.js`. This continues to work — HTMX reads
|
||||
`FormData` at request time, so newly added/reindexed inputs are automatically
|
||||
included in the next triggered save.
|
||||
|
||||
### Migration Checklist
|
||||
|
||||
| Form | Change required |
|
||||
|---|---|
|
||||
| `contenus-edit.php` (pages) | Add `hx-*` attrs, add `overtype:change` dispatch in OverType `onChange` |
|
||||
| `contenus-edit.php` (form_help) | Same as above |
|
||||
| `apropos-groups-form.php` (contacts) | Add `hx-*` attrs only |
|
||||
| `contenus-edit.php` (sidebar_links) | Add `hx-*` attrs only |
|
||||
| `autosave.js` | **Delete** once all four forms are migrated |
|
||||
| Backend handlers | **No changes needed** — they already return `{success, csrf_token}` |
|
||||
|
||||
The backend is untouched throughout, which is the cleanest part of this migration.
|
||||
|
||||
## HTMX Migration Feasibility
|
||||
|
||||
The settings toggles already use HTMX successfully for similar patterns
|
||||
|
||||
Reference in New Issue
Block a user