| index 994fcdd..1bff4c6 100644 |
| --- a/apps/rust/static/app.js |
| +++ b/apps/rust/static/app.js |
| @@ -23,13 +23,41 @@ function send(action, body) { |
| } |
| |
| // Replaces section.main and footer.footer with the server's fresh copies. |
| +// An edit still in progress (not yet sent) survives: its li stays in the |
| +// page, focus and draft included, and the fresh items go around it. |
| function swap(html) { |
| const tpl = document.createElement('template'); |
| tpl.innerHTML = html; |
| - for (const sel of ['section.main', 'footer.footer']) { |
| - const fresh = tpl.content.querySelector(sel); |
| - const old = document.querySelector(`.todoapp ${sel}`); |
| - if (fresh && old) old.replaceWith(fresh); |
| + const freshMain = tpl.content.querySelector('section.main'); |
| + const freshFooter = tpl.content.querySelector('footer.footer'); |
| + const main = document.querySelector('.todoapp section.main'); |
| + const footer = document.querySelector('.todoapp footer.footer'); |
| + if (!freshMain || !freshFooter || !main || !footer) return; |
| + footer.replaceWith(freshFooter); |
| + |
| + const editing = [...main.querySelectorAll('.todo-list li.editing')] |
| + .find((li) => !li.querySelector('.edit').dataset.done); |
| + const keep = editing && freshMain.querySelector(`.todo-list li[data-id="${editing.dataset.id}"]`); |
| + if (!keep) { |
| + // Gone from this view: drop the edit without the blur saving it. |
| + if (editing) editing.querySelector('.edit').dataset.done = '1'; |
| + main.replaceWith(freshMain); |
| + return; |
| + } |
| + |
| + // Patch main in place so the editing li is never detached. |
| + main.hidden = freshMain.hidden; |
| + const list = main.querySelector('.todo-list'); |
| + for (const el of [...main.children]) if (el !== list) el.remove(); |
| + for (const el of [...freshMain.children]) if (!el.matches('.todo-list')) list.before(el); |
| + for (const li of [...list.children]) if (li !== editing) li.remove(); |
| + editing.querySelector('.view').replaceWith(keep.querySelector('.view')); |
| + editing.classList.toggle('completed', keep.classList.contains('completed')); |
| + let before = true; |
| + for (const li of [...freshMain.querySelector('.todo-list').children]) { |
| + if (li === keep) before = false; |
| + else if (before) editing.before(li); |
| + else list.append(li); |
| } |
| } |
| |