Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix blur event, improve _hs, dynamic nodes render without using display css #2

Merged
merged 1 commit into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading