-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
1,336 additions
and
74 deletions.
There are no files selected for viewing
19 changes: 19 additions & 0 deletions
19
public/blog/articles/2024-09-28-unreasonable-effectiveness-of-vanilla-js/complete/AddTask.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
customElements.define('task-add', class extends HTMLElement { | ||
connectedCallback() { | ||
this.innerHTML = ` | ||
<input type="text" placeholder="Add task" /> | ||
<button>Add</button> | ||
`; | ||
this.querySelector('button').onclick = () => { | ||
const input = this.querySelector('input'); | ||
this.closest('tasks-context').dispatch({ | ||
type: 'added', | ||
id: nextId++, | ||
text: input.value | ||
}); | ||
input.value = ''; | ||
}; | ||
} | ||
}) | ||
|
||
let nextId = 3; |
11 changes: 11 additions & 0 deletions
11
public/blog/articles/2024-09-28-unreasonable-effectiveness-of-vanilla-js/complete/App.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
customElements.define('tasks-app', class extends HTMLElement { | ||
connectedCallback() { | ||
this.innerHTML = ` | ||
<tasks-context> | ||
<h1>Day off in Kyoto</h1> | ||
<task-add></task-add> | ||
<task-list></task-list> | ||
</tasks-context> | ||
`; | ||
} | ||
}); |
101 changes: 101 additions & 0 deletions
101
...ic/blog/articles/2024-09-28-unreasonable-effectiveness-of-vanilla-js/complete/TaskList.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
customElements.define('task-list', class extends HTMLElement { | ||
get context() { return this.closest('tasks-context'); } | ||
|
||
connectedCallback() { | ||
this.context.addEventListener('change', () => this.update()); | ||
this.append(document.createElement('ul')); | ||
this.update(); | ||
} | ||
|
||
update() { | ||
const ul = this.querySelector('ul'); | ||
let before = ul.firstChild; | ||
this.context.tasks.forEach(task => { | ||
let li = ul.querySelector(`:scope > [data-key="${task.id}"]`); | ||
if (!li) { | ||
li = document.createElement('li'); | ||
li.dataset.key = task.id; | ||
li.append(document.createElement('task-item')); | ||
} | ||
li.firstChild.task = task; | ||
// move to the right position in the list if not there yet | ||
if (li !== before) ul.insertBefore(li, before); | ||
before = li.nextSibling; | ||
}); | ||
// remove unknown nodes | ||
while (before) { | ||
const remove = before; | ||
before = before.nextSibling; | ||
ul.removeChild(remove); | ||
} | ||
} | ||
}); | ||
|
||
customElements.define('task-item', class extends HTMLElement { | ||
#isEditing = false; | ||
#task; | ||
set task(task) { this.#task = task; this.update(); } | ||
get context() { return this.closest('tasks-context'); } | ||
|
||
connectedCallback() { | ||
if (this.querySelector('label')) return; | ||
this.innerHTML = ` | ||
<label> | ||
<input type="checkbox" /> | ||
<input type="text" /> | ||
<span></span> | ||
<button id="edit">Edit</button> | ||
<button id="save">Save</button> | ||
<button id="delete">Delete</button> | ||
</label> | ||
`; | ||
this.querySelector('input[type=checkbox]').onchange = e => { | ||
this.context.dispatch({ | ||
type: 'changed', | ||
task: { | ||
...this.#task, | ||
done: e.target.checked | ||
} | ||
}); | ||
}; | ||
this.querySelector('input[type=text]').onchange = e => { | ||
this.context.dispatch({ | ||
type: 'changed', | ||
task: { | ||
...this.#task, | ||
text: e.target.value | ||
} | ||
}); | ||
}; | ||
this.querySelector('button#edit').onclick = () => { | ||
this.#isEditing = true; | ||
this.update(); | ||
}; | ||
this.querySelector('button#save').onclick = () => { | ||
this.#isEditing = false; | ||
this.update(); | ||
}; | ||
this.querySelector('button#delete').onclick = () => { | ||
this.context.dispatch({ | ||
type: 'deleted', | ||
id: this.#task.id | ||
}); | ||
}; | ||
this.context.addEventListener('change', () => this.update()); | ||
this.update(); | ||
} | ||
|
||
update() { | ||
if (this.isConnected && this.#task) { | ||
this.querySelector('input[type=checkbox]').checked = this.#task.done; | ||
const inputEdit = this.querySelector('input[type=text]'); | ||
inputEdit.style.display = this.#isEditing ? 'inline' : 'none'; | ||
inputEdit.value = this.#task.text; | ||
const span = this.querySelector('span'); | ||
span.style.display = this.#isEditing ? 'none' : 'inline'; | ||
span.textContent = this.#task.text; | ||
this.querySelector('button#edit').style.display = this.#isEditing ? 'none' : 'inline'; | ||
this.querySelector('button#save').style.display = this.#isEditing ? 'inline' : 'none'; | ||
} | ||
} | ||
}); |
49 changes: 49 additions & 0 deletions
49
...log/articles/2024-09-28-unreasonable-effectiveness-of-vanilla-js/complete/TasksContext.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
customElements.define('tasks-context', class extends HTMLElement { | ||
#tasks = structuredClone(initialTasks); | ||
get tasks() { return this.#tasks; } | ||
set tasks(tasks) { | ||
this.#tasks = tasks; | ||
this.dispatchEvent(new Event('change')); | ||
} | ||
|
||
dispatch(action) { | ||
this.tasks = tasksReducer(this.tasks, action); | ||
} | ||
|
||
connectedCallback() { | ||
this.style.display = 'content'; | ||
} | ||
}); | ||
|
||
function tasksReducer(tasks, action) { | ||
switch (action.type) { | ||
case 'added': { | ||
return [...tasks, { | ||
id: action.id, | ||
text: action.text, | ||
done: false | ||
}]; | ||
} | ||
case 'changed': { | ||
return tasks.map(t => { | ||
if (t.id === action.task.id) { | ||
return action.task; | ||
} else { | ||
return t; | ||
} | ||
}); | ||
} | ||
case 'deleted': { | ||
return tasks.filter(t => t.id !== action.id); | ||
} | ||
default: { | ||
throw Error('Unknown action: ' + action.type); | ||
} | ||
} | ||
} | ||
|
||
const initialTasks = [ | ||
{ id: 0, text: 'Philosopher’s Path', done: true }, | ||
{ id: 1, text: 'Visit the temple', done: false }, | ||
{ id: 2, text: 'Drink matcha', done: false } | ||
]; |
13 changes: 13 additions & 0 deletions
13
public/blog/articles/2024-09-28-unreasonable-effectiveness-of-vanilla-js/complete/index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Document</title> | ||
<link rel="stylesheet" href="styles.css"> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
<script type="module" src="index.js"></script> | ||
</body> | ||
</html> |
11 changes: 11 additions & 0 deletions
11
public/blog/articles/2024-09-28-unreasonable-effectiveness-of-vanilla-js/complete/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import './App.js'; | ||
import './AddTask.js'; | ||
import './TaskList.js'; | ||
import './TasksContext.js'; | ||
|
||
const render = () => { | ||
const root = document.getElementById('root'); | ||
root.append(document.createElement('tasks-app')); | ||
} | ||
|
||
document.addEventListener('DOMContentLoaded', render); |
51 changes: 51 additions & 0 deletions
51
public/blog/articles/2024-09-28-unreasonable-effectiveness-of-vanilla-js/complete/styles.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
* { | ||
box-sizing: border-box; | ||
} | ||
|
||
body { | ||
font-family: sans-serif; | ||
margin: 20px; | ||
padding: 0; | ||
} | ||
|
||
h1 { | ||
margin-top: 0; | ||
font-size: 22px; | ||
} | ||
|
||
h2 { | ||
margin-top: 0; | ||
font-size: 20px; | ||
} | ||
|
||
h3 { | ||
margin-top: 0; | ||
font-size: 18px; | ||
} | ||
|
||
h4 { | ||
margin-top: 0; | ||
font-size: 16px; | ||
} | ||
|
||
h5 { | ||
margin-top: 0; | ||
font-size: 14px; | ||
} | ||
|
||
h6 { | ||
margin-top: 0; | ||
font-size: 12px; | ||
} | ||
|
||
code { | ||
font-size: 1.2em; | ||
} | ||
|
||
ul { | ||
padding-inline-start: 20px; | ||
} | ||
|
||
button { margin: 5px; } | ||
li { list-style-type: none; } | ||
ul, li { margin: 0; padding: 0; } |
Binary file added
BIN
+118 KB
public/blog/articles/2024-09-28-unreasonable-effectiveness-of-vanilla-js/image.webp
Binary file not shown.
Oops, something went wrong.