Skip to content

Commit

Permalink
Merge pull request #6 from syarul/rc
Browse files Browse the repository at this point in the history
fix toggle all, move hyperscript to ._hs file
  • Loading branch information
syarul authored Jan 29, 2024
2 parents 887ee1b + e0f1ba6 commit 8707a35
Show file tree
Hide file tree
Showing 18 changed files with 263 additions and 220 deletions.
19 changes: 19 additions & 0 deletions hs/behaviors/add-todo._hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
behavior AddTodo
on load send focus to me
on focus
if $focus === undefined
my.focus()
set $isFocus to 'true'
end
on blur set $isFocus to undefined
on keyup[keyCode==13]
if $todo
htmx.ajax('GET', `/add-todo?title=${my.value}`, {target:'.todo-list', swap:'beforeend'})
set my value to ''
else
htmx.ajax('GET', `/add-todo?title=${my.value}`, {target:'.header', swap:'beforeend'})
set my value to ''
end
send toggleMain to <section.todoapp/>
send toggleFooter to <section.todoapp/>
end
3 changes: 3 additions & 0 deletions hs/behaviors/clear-completed._hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
behavior ClearCompleted
on load set $clearCompleted to me
on click send destroy to <li.completed/>
7 changes: 7 additions & 0 deletions hs/behaviors/destroy._hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
behavior Destroy
on htmx:afterRequest debounced at 5ms
send toggleMain to <section.todoapp/>
send toggleFooter to <section.todoapp/>
send focus to <input.new-todo/>
if $todo
send toggleClearCompleted to <footer.footer/>
11 changes: 11 additions & 0 deletions hs/behaviors/footer._hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
behavior Footer
on load set $footerFooter to me
on toggleClearCompleted debounced at 20ms
if $clearCompleted === undefined
htmx.ajax("GET", "/completed", {target:".filters", swap: "afterend"})
else
-- need to first set to undefined in case the fetch may return empty which
-- will indiscriminately leave it in incorrect state
set $clearCompleted to undefined
htmx.ajax("GET", "/completed", {target:".clear-completed", swap: "outerHTML"})
send toggleFooter to <section.todoapp/>
11 changes: 11 additions & 0 deletions hs/behaviors/todo-check._hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
behavior TodoCheck
on htmx:afterRequest
send toggleAll to <input.toggle-all/>
send toggleClearCompleted to <footer.footer/>
send toggleFooter to <section.todoapp/>
on toggle
send toggleClearCompleted to <footer.footer/>
if $toggleAll.checked and my.checked === false
my.click()
else if $toggleAll.checked === false and my.checked
my.click()
4 changes: 4 additions & 0 deletions hs/behaviors/todo-count._hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
behavior TodoCount
on load send todoCount to me
on todoCount debounced at 100ms
fetch /update-counts then put the result into me
6 changes: 6 additions & 0 deletions hs/behaviors/todo-dblclick._hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
behavior TodoDblclick
on dblclick
add .editing to the closest <li/>
on htmx:afterRequest
set $el to my.parentNode.nextSibling
set $el.selectionStart to $el.value.length
19 changes: 19 additions & 0 deletions hs/behaviors/todo-edit._hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
behavior TodoEdit
on load
my.focus()
on keyup[keyCode==27]
set $keyup to "esc"
remove .editing from closest <li/>
on keyup[keyCode==13]
set $keyup to "enter"
htmx.ajax("GET", `/update-todo?id=${@todo-id}&title=${my.value}`, {target: closest <li/>, swap: "outerHTML"})
on blur debounced at 10ms
if $keyup === "enter"
set $keyup to "none"
else if $keyup === "esc"
set $keyup to "none"
else
htmx.ajax("GET", `/update-todo?id=${@todo-id}&title=${my.value}`, {target: closest <li/>, swap: "outerHTML"})
end
send toggleMain to <section.todoapp/>
send toggleFooter to <section.todoapp/>
14 changes: 14 additions & 0 deletions hs/behaviors/toggle-all._hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
behavior ToggleAll
on load set $toggleAll to me
on toggleAll debounced at 100ms
fetch /toggle-all then
if it === "true" and my.checked === false then
set my.checked to true
else
if my.checked === true and it === "false" then set my.checked to false
end
end
on click
fetch `/swap-json?all=${my.checked}` then
send show to <section.todoapp/>
send toggle to <input.toggle/>
24 changes: 24 additions & 0 deletions hs/behaviors/toggle-footer._hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
behavior ToggleFooter
on toggleFooter debounced at 20ms
-- log 'footer'
if $footerFooter
fetch /todo-json as json then
if $todo.hasChildNodes() === false and it.length === 0
remove $footerFooter
set $footerFooter to undefined
end
-- set-hash already update the hash on the server
-- this reassign the filter class selected base on user interaction
-- or location hash changes
for filter in $filter.children
if filter.textContent === 'All' and `${$initial}${$after}` === ''
add .selected to filter.firstChild
else if filter.textContent !== `${$initial}${$after}`
remove .selected from filter.firstChild
end
end
-- update counts
fetch /update-counts then put the result into <span.todo-count/>
else
htmx.ajax('GET', '/footer', {target:'.header', swap:'beforeend'})
end
9 changes: 9 additions & 0 deletions hs/behaviors/toggle-main._hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
behavior ToggleMain
on toggleMain debounced at 20ms
-- log 'main'
if $sectionMain
set $sectionMain to undefined
htmx.ajax("GET", "/toggle-main", {target: "section.main", swap: "outerHTML"})
else
htmx.ajax('GET', "/toggle-main", {target: ".todo-list", swap: "beforebegin"})
end
50 changes: 50 additions & 0 deletions hs/behaviors/toggle-show._hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
behavior ToggleShow
on show wait 20ms
-- log "show"
-- this is the DOM tree diffing of the todo-list, fetch only the needed
-- to render and remove accordingly base on route All/Active/Completed
fetch /todo-json as json then
if window.location.hash === "#/active"
for todo in it
if todo.done
document.getElementById(`todo-${todo.id}`) then if it remove it end
else
document.getElementById(`todo-${todo.id}`) then
if it === null
htmx.ajax("GET", `/todo-item?id=${todo.id}`, {target:".todo-list", swap: "beforeend"})
end
end
end
else if window.location.hash === "#/completed"
for todo in it
if todo.done
document.getElementById(`todo-${todo.id}`) then
if it === null
htmx.ajax("GET", `/todo-item?id=${todo.id}`, {target:".todo-list", swap: "beforeend"})
end
else
document.getElementById(`todo-${todo.id}`) then if it remove it end
end
end
else
-- loop through the JSON
for todo in it
-- check if the element exist in the current DOM, add if none
-- placement is decided according to order if there"s an element
-- with higher than the current todo swap as "beforebegin"
for el in $todo.children
if parseInt(el.id.slice(5)) > todo.id and document.getElementById(`todo-${todo.id}`) === null
htmx.ajax("GET", `/todo-item?id=${todo.id}`, {target: `#${el.id}`, swap: "beforebegin"})
end
end
-- do reverse lookup for lower than the current todo swap as "afterend"
for el in Array.from($todo.children).reverse()
if parseInt(el.id.slice(5)) < todo.id and document.getElementById(`todo-${todo.id}`) === null
htmx.ajax("GET", `/todo-item?id=${todo.id}`, {target: `#${el.id}`, swap: "afterend"})
end
end
-- if todo is empty initially recursively add all of it
if $todo.children.length === 0
htmx.ajax("GET", `/todo-item?id=${todo.id}`, {target:".todo-list", swap: "beforeend"})
end
end
15 changes: 15 additions & 0 deletions hs/main._hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
def hashCache()
-- this is done to get current location hash then update todo-list and footer
set $initial to window.location.hash.slice(2).charAt(0).toUpperCase()
set $after to window.location.hash.slice(3)
fetch `/set-hash?name=${$initial}${$after}` then
send show to <section.todoapp/>
send toggleFooter to <section.todoapp/>
end
-- this to handle popstate event such as back/forward button
-- where it will automatically calling hashCache _hyperscript function
js
window.addEventListener('popstate', function(){
hashCache();
});
end
19 changes: 19 additions & 0 deletions hs/start-me-up._hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
def startMeUp()
log "
ooooo ooooo ooooooooooooo ooo ooooo ooooooo ooooo
`888' `888' 8' 888 `8 `88. .888' `8888 d8'
888 888 888 888b d'888 Y888..8P
888ooooo888 888 8 Y88. .P 888 `8888'
888 888 888 8 `888' 888 .8PY888.
888 888 888 8 Y 888 d8' `888b
o888o o888o o888o o8o o888o o888o o88888o
===========================================================
Build with GO, TEMPL, HTMX & _HYPERSCRIPT
_ _ _ _ _
| |_| |__ ___ _ __(_) __ _| |__ | |_ __ ____ _ _ _
| __| '_ \\ / _ \\ | '__| |/ _\` | '_ \\| __| \\ \\ /\\ / / _\` | | | |
| |_| | | | __/ | | | | (_| | | | | |_ \\ V V / (_| | |_| |
\\__|_| |_|\\___| |_| |_|\\__, |_| |_|\\__| \\_/\\_/ \\__,_|\\__, |
|___/ |___/
by http://github.com/syarul/"
end
28 changes: 24 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,17 @@ func main() {
http.Handle("/toggle-footer", http.HandlerFunc(t.toggleFooterHandler))
http.Handle("/todo-list", http.HandlerFunc(t.todoListHandler))
http.Handle("/todo-json", http.HandlerFunc(t.getJSON))
http.Handle("/swap-json", http.HandlerFunc(t.swapJSON))
http.Handle("/todo-item", http.HandlerFunc(t.todoItemHandler))

// this is used to serve axe-core for the todomvc test
dir := "./cypress-example-todomvc/node_modules"

// Use the http.FileServer to create a handler for serving static files
fs := http.FileServer(http.Dir(dir))
// serve *._hs file
http.Handle("/hs/", http.StripPrefix("/hs/", http.FileServer(http.Dir("./hs"))))

// Use the http.Handle to register the file server handler for a specific route
http.Handle("/node_modules/", http.StripPrefix("/node_modules/", fs))
// use the http.Handle to register the file server handler for a specific route
http.Handle("/node_modules/", http.StripPrefix("/node_modules/", http.FileServer(http.Dir(dir))))

// start the server.
addr := os.Getenv("LISTEN_ADDRESS")
Expand Down Expand Up @@ -200,6 +201,25 @@ func (t *todos) getJSON(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(*t)
}

// swap json state if toggle is click
func (t *todos) swapJSON(w http.ResponseWriter, r *http.Request) {
all, err := strconv.ParseBool(r.FormValue("all"))
if err != nil {
fmt.Println("Error:", err)
return
}

for _, todo := range *t {
id := todo.Id
if all {
t.crudOps(Toggle, Todo{id, "", true, false})
} else {
t.crudOps(Toggle, Todo{id, "", false, false})
}
}
byteRenderer(w, r, "")
}

func selectedFilter(filters []Filter) string {
for _, filter := range filters {
if filter.selected {
Expand Down
Loading

0 comments on commit 8707a35

Please sign in to comment.