Skip to content

Commit

Permalink
fix blur event, improve _hs, dynamic nodes render without using displ…
Browse files Browse the repository at this point in the history
…ay css
  • Loading branch information
shahrul committed Jan 4, 2024
1 parent 7f2049a commit 5ab9d7e
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 55 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
- install templ `go install github.com/a-h/templ/cmd/templ@latest`
- run `templ generate`
- finally run `go run .`
- visit `http://localhost:8888`
- alternatively you can compile into executable with `go build .`

### HTMX
Expand Down
49 changes: 28 additions & 21 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ const (
)

var filters = []Filter{
{url: "#/", name: "all", selected: true},
{url: "#/active", name: "active", selected: false},
{url: "#/completed", name: "completed", selected: false},
{url: "#/", name: "All", selected: true},
{url: "#/active", name: "Active", selected: false},
{url: "#/completed", name: "Completed", selected: false},
}

func (t *todos) crudOps(action Action, todo Todo) Todo {
Expand Down Expand Up @@ -118,7 +118,7 @@ func main() {
// start the server.
addr := os.Getenv("LISTEN_ADDRESS")
if addr == "" {
addr = "localhost:8080"
addr = "localhost:8888"
}

fmt.Printf("Listening on %s\n", addr)
Expand Down Expand Up @@ -204,7 +204,7 @@ func (t *todos) getHash(w http.ResponseWriter, r *http.Request) {
if len(hash) != 0 {
name = hash
} else {
name = "all"
name = "All"
}
}
// loop through filters and update the selected field
Expand All @@ -222,6 +222,8 @@ func (t *todos) getHash(w http.ResponseWriter, r *http.Request) {

func (t *todos) pageHandler(w http.ResponseWriter, r *http.Request) {
// start with new todo data when refresh
// *t = make([]Todo, 0)
// idCounter = 0
templRenderer(w, r, Page(*t, filters, defChecked(*t), hasCompleteTask(*t)))
}

Expand All @@ -248,7 +250,12 @@ func (t *todos) addTodoHandler(w http.ResponseWriter, r *http.Request) {

todo := t.crudOps(Create, Todo{id, title, false, false})

templRenderer(w, r, todoItem(todo))
if len(*t) == 1 {
templRenderer(w, r, todoList(*t))
} else {
templRenderer(w, r, todoItem(todo))
}

}

func (t *todos) clearCompleted(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -324,26 +331,26 @@ func (t *todos) updateTodo(w http.ResponseWriter, r *http.Request) {
return
}

esc, err := strconv.ParseBool(r.FormValue("esc"))
if err != nil {
fmt.Println("Error:", err)
return
}
// esc, err := strconv.ParseBool(r.FormValue("esc"))
// if err != nil {
// fmt.Println("Error:", err)
// return
// }

title := r.FormValue("title")

// esc will not do update instead will send the original unmodified title
if esc {
todo := t.crudOps(Edit, Todo{id, "", false, false})
templRenderer(w, r, todoItem(todo))
} else {
todo := t.crudOps(Update, Todo{id, title, false, false})
if len(todo.title) == 0 {
byteRenderer(w, r, "")
return
}
templRenderer(w, r, todoItem(todo))
// if esc {
// todo := t.crudOps(Edit, Todo{id, "", false, false})
// templRenderer(w, r, todoItem(todo))
// } else {
todo := t.crudOps(Update, Todo{id, title, false, false})
if len(todo.title) == 0 {
byteRenderer(w, r, "")
return
}
templRenderer(w, r, todoItem(todo))
// }
}

func (t *todos) removeTodo(w http.ResponseWriter, r *http.Request) {
Expand Down
92 changes: 58 additions & 34 deletions todomvc.templ
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ templ todoCheck(todo Todo) {

// blur event handle both keyup ESC and blur
// where only blur should trigger update call while ESC is not
// to solve this I write a htmx extension 'esc-blur-polyfill' that check the
// specific event where ESC produce 'triggeringEvent.sourceCapabilities' as null
// where the query send to server added one more parameter &esc=true or false
// according to user event
templ editTodo(todo Todo) {
Expand All @@ -80,14 +78,23 @@ templ editTodo(todo Todo) {
} else {
value=""
}
hx-trigger="keyup[keyCode==13], blur"
hx-get={ fmt.Sprintf(`/update-todo?id=%s`, strconv.FormatUint(todo.id, 10)) }
hx-target="closest <li/>"
hx-swap="outerHTML"
hx-ext="esc-blur-polyfill"
todo-id={ strconv.FormatUint(todo.id, 10) }
autofocus
_="
on keyup[keyCode==27] remove .editing from closest <li/>
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
on htmx:afterRequest
send toggleMain to <section.todoapp/>
send toggleFooter to <section.todoapp/>
Expand All @@ -98,6 +105,7 @@ templ editTodo(todo Todo) {

templ todoItem(todo Todo) {
<li
id={ strconv.FormatUint(todo.id, 10) }
class={ "todo", templ.KV("completed", todo.done), templ.KV("editing", todo.editing) }
_="
on destroy my.querySelector('button').click()
Expand Down Expand Up @@ -155,14 +163,14 @@ templ toggleMain(todos []Todo, checked bool) {
</section>
}
}
// toggleDisplayClearCompleted

templ clearCompleted (hasCompleted bool) {
if hasCompleted {
<button class="clear-completed"
_="
on load set $clearCompleted to me
on click send destroy to <li.completed/>"
>Clear Complete</button>
>Clear completed</button>
}
}

Expand Down Expand Up @@ -195,6 +203,26 @@ templ footer(todos []Todo, filters []Filter, hasCompleted bool) {
}
}

templ todoList(todos []Todo) {
if len(todos) != 0 {
<ul
class="todo-list"
_="
on load debounced at 10ms
set $todo to me
send todoCount to <span.todo-count/>
send toggleAll to <input.toggle-all/>
send show to <li.todo/>
send toggleMain to <section.todoapp/>
send toggleFooter to <section.todoapp/>"
>
for _, todo := range todos {
@todoItem(todo)
}
</ul>
}
}

templ Page(todos []Todo, filters []Filter, checked bool, hasCompleted bool) {
<html lang="en" data-framework="htmx">
<head>
Expand All @@ -209,7 +237,7 @@ templ Page(todos []Todo, filters []Filter, checked bool, hasCompleted bool) {
_="
on toggleMain
if $sectionMain === undefined and $todo.hasChildNodes()
fetch /toggle-main then put the result after <header.header/>
htmx.ajax('GET', '/toggle-main', {target:'.todo-list', swap:'beforebegin'})
else if $sectionMain and $todo.hasChildNodes() === false
remove $sectionMain
set $sectionMain to undefined
Expand All @@ -220,44 +248,39 @@ templ Page(todos []Todo, filters []Filter, checked bool, hasCompleted bool) {
htmx.ajax('GET', `/get-hash?hash=${window.location.hash.slice(2)}`, {target:'.filters', swap:'outerHTML'})
else if $footerFooter and $todo.hasChildNodes() === false
remove $footerFooter
remove $todo
set $todo to undefined
set $clearCompleted to undefined
set $footerFooter to undefined
else if $clearCompleted
fetch /completed then if it === ''
remove $clearCompleted
set $clearCompleted to undefined
end"
>
<header class="header">
<ul class="phdr"></ul>
<h1>todos</h1>
<input
id="add-todo"
name="title"
class="new-todo"
placeholder="What needs to be done?"
hx-get="/add-todo"
hx-trigger="keyup[keyCode==13]"
hx-target=".todo-list"
hx-swap="beforeend"
_="
on load my.focus()
on htmx:afterRequest set my value to ''
on focus my.focus()"
on focus my.focus()
on keyup[keyCode==13]
if $todo
htmx.ajax('GET', `/add-todo?title=${my.value}`, {target:'.todo-list', swap:'beforeend'})
set my value to ''
my.focus()
else
htmx.ajax('GET', `/add-todo?title=${my.value}`, {target:'.header', swap:'beforeend'})
set my value to ''
my.focus()"
autofocus />
</header>
@toggleMain(todos, checked)
<ul
class="todo-list"
_="
on load debounced at 10ms
set $todo to me
send todoCount to <span.todo-count/>
send toggleAll to <input.toggle-all/>
send show to <li.todo/>
send toggleMain to <section.todoapp/>
send toggleFooter to <section.todoapp/>"
>
for _, todo := range todos {
@todoItem(todo)
}
</ul>
@todoList(todos)
@footer(todos, filters, hasCompleted)
</section>
<footer class="info" _="on load debounced at 100ms call startMeUp()">
Expand All @@ -269,7 +292,8 @@ templ Page(todos []Todo, filters []Filter, checked bool, hasCompleted bool) {
</body>
<script src="https://unpkg.com/[email protected]/base.js" />
<script src="https://unpkg.com/[email protected]" />
<script src="https://cdn.jsdelivr.net/npm/[email protected]/esc-blur-polyfill.js" />
<!--script src="https://cdn.jsdelivr.net/npm/[email protected]/esc-blur-polyfill.js" /-->
<script src="/assets/js/esc-blur-polyfill.js" />
<script src="https://unpkg.com/hyperscript.org/dist/_hyperscript.js" />
<script type="text/hyperscript">
def startMeUp()
Expand Down

0 comments on commit 5ab9d7e

Please sign in to comment.