carlos / todomvc-bakeoff Public

Clone
git clone https://amadan.net/carlos/todomvc-bakeoff

Plain git — no account needed to clone.

Download

Download this file

1// Progressive enhancement for the reference fixture: every form in the app
2// is submitted with fetch, and the server's re-rendered .todoapp replaces
3// the current one. Editing in place is client-side until it saves.
4const FETCH = { 'X-Requested-With': 'fetch' };
5
6async function send(form) {
7 const res = await fetch(form.action, {
8 method: 'POST',
9 headers: FETCH,
10 body: new URLSearchParams(new FormData(form)),
11 });
12 const doc = new DOMParser().parseFromString(await res.text(), 'text/html');
13 document.querySelector('.todoapp').replaceWith(doc.querySelector('.todoapp'));
14}
15
16document.addEventListener('submit', async (e) => {
17 const form = e.target;
18 if (!form.closest('.todoapp')) return;
19 e.preventDefault();
20 // Leave editing mode first, so the focusout that follows doesn't save twice.
21 form.closest('li')?.classList.remove('editing');
22 const adding = form.querySelector('.new-todo');
23 await send(form);
24 if (adding) document.querySelector('.new-todo').focus();
25});
26
27document.addEventListener('change', (e) => {
28 if (e.target.matches('.toggle, .toggle-all')) e.target.form.requestSubmit();
29});
30
31document.addEventListener('dblclick', (e) => {
32 const label = e.target.closest('.todo-list label');
33 if (!label) return;
34 const li = label.closest('li');
35 li.classList.add('editing');
36 const input = li.querySelector('.edit');
37 input.focus();
38 input.setSelectionRange(input.value.length, input.value.length);
39});
40
41document.addEventListener('keydown', (e) => {
42 if (!e.target.matches('.edit')) return;
43 const li = e.target.closest('li');
44 if (e.key === 'Escape') {
45 e.target.value = li.querySelector('label').textContent;
46 li.classList.remove('editing');
47 }
48});
49
50document.addEventListener('focusout', (e) => {
51 if (!e.target.matches('.edit')) return;
52 const li = e.target.closest('li');
53 if (li.classList.contains('editing')) {
54 li.classList.remove('editing');
55 e.target.form.requestSubmit();
56 }
57});
58