improved focus handling for todoapp example

This commit is contained in:
Andreas Rumpf 2017-04-05 10:04:02 +02:00
commit 11e4f355e7
3 changed files with 26 additions and 26 deletions

View file

@ -26,6 +26,10 @@ type
var var
document* {.importc.}: Document document* {.importc.}: Document
toFocus: Element toFocus: Element
toFocusV: VNode
proc setFocus*(n: VNode) =
toFocusV = n
proc vnodeToDom(n: VNode): Element = proc vnodeToDom(n: VNode): Element =
if n.kind == VNodeKind.text: if n.kind == VNodeKind.text:
@ -52,7 +56,7 @@ proc vnodeToDom(n: VNode): Element =
assert myn != nil assert myn != nil
hh(ev, myn) hh(ev, myn)
result.addEventListener(toEventName[e], wrapper()) result.addEventListener(toEventName[e], wrapper())
if n.kind == VNodeKind.input and toFocus.isNil: if n == toFocusV and toFocus.isNil:
toFocus = result toFocus = result
proc same(n: VNode, e: Element): bool = proc same(n: VNode, e: Element): bool =
@ -91,8 +95,8 @@ proc replaceById(id: cstring; newTree: Node) =
proc equals(a, b: VNode): bool = proc equals(a, b: VNode): bool =
if a.kind != b.kind: return false if a.kind != b.kind: return false
if a.id != b.id: return false if a.id != b.id: return false
#if a.kind == VNodeKind.text: if a.kind == VNodeKind.text:
if a.text != b.text: return false if a.text != b.text: return false
if not sameAttrs(a, b): return false if not sameAttrs(a, b): return false
if a.class != b.class: return false if a.class != b.class: return false
# XXX test event listeners here? # XXX test event listeners here?
@ -316,17 +320,19 @@ proc getAttr(e: Element; key: cstring): cstring {.
template nativeValue(ev): cstring = cast[Element](ev.target).value template nativeValue(ev): cstring = cast[Element](ev.target).value
template setNativeValue(ev, val) = cast[Element](ev.target).value = val template setNativeValue(ev, val) = cast[Element](ev.target).value = val
proc realtimeInput*(val: cstring; changed: EventHandler): VNode = template keyeventBody() =
n.value = nativeValue(ev)
action(ev, n)
setNativeValue(ev, n.value)
redraw()
proc realtimeInput*(val: cstring; action: EventHandler): VNode =
#let oldElem = getElementById(id) #let oldElem = getElementById(id)
#if oldElem != nil: return oldElem #if oldElem != nil: return oldElem
#let newVal = if oldElem.isNil: val else: $oldElem.value #let newVal = if oldElem.isNil: val else: $oldElem.value
var timer: Timeout var timer: Timeout
proc onkeyup(ev: Event; n: VNode) = proc onkeyup(ev: Event; n: VNode) =
proc wrapper() = proc wrapper() = keyeventBody()
n.value = nativeValue(ev)
changed(ev, n)
setNativeValue(ev, n.value)
redraw()
if timer != nil: clearTimeout(timer) if timer != nil: clearTimeout(timer)
timer = setTimeout(wrapper, 400) timer = setTimeout(wrapper, 400)
@ -334,29 +340,21 @@ proc realtimeInput*(val: cstring; changed: EventHandler): VNode =
result.value = val result.value = val
result.addEventListener(EventKind.onkeyup, onkeyup) result.addEventListener(EventKind.onkeyup, onkeyup)
proc enterInput*(id, val: cstring; onenter: EventHandler): VNode = proc enterInput*(id, val: cstring; action: EventHandler): VNode =
#let oldElem = getElementById(id) #let oldElem = getElementById(id)
#if oldElem != nil: return oldElem #if oldElem != nil: return oldElem
#let newVal = if oldElem.isNil: val else: $oldElem.value #let newVal = if oldElem.isNil: val else: $oldElem.value
proc onkeyup(ev: Event; n: VNode) = proc onkeyup(ev: Event; n: VNode) =
if ev.keyCode == 13: if ev.keyCode == 13: keyeventBody()
n.value = nativeValue(ev)
onenter(ev, n)
setNativeValue(ev, n.value)
redraw()
result = tree(VNodeKind.input, [(cstring"type", cstring"text")]) result = tree(VNodeKind.input, [(cstring"type", cstring"text")])
result.id = id result.id = id
result.value = val result.value = val
result.addEventListener(EventKind.onkeyup, onkeyup) result.addEventListener(EventKind.onkeyup, onkeyup)
proc setOnEnter*(n: VNode; onenter: EventHandler) = proc setOnEnter*(n: VNode; action: EventHandler) =
proc onkeyup(ev: Event; n: VNode) = proc onkeyup(ev: Event; n: VNode) =
if ev.keyCode == 13: if ev.keyCode == 13: keyeventBody()
n.value = nativeValue(ev)
onenter(ev, n)
setNativeValue(ev, n.value)
redraw()
n.addEventListener(EventKind.onkeyup, onkeyup) n.addEventListener(EventKind.onkeyup, onkeyup)
proc ajax(meth, url: cstring; headers: openarray[(cstring, cstring)]; proc ajax(meth, url: cstring; headers: openarray[(cstring, cstring)];

View file

@ -3,7 +3,7 @@ import macros, karax, vdom
from strutils import startsWith, toLowerAscii from strutils import startsWith, toLowerAscii
const const
StmtContext = ["kout", "inc", "echo", "dec"] StmtContext = ["kout", "inc", "echo", "dec", "!"]
proc getName(n: NimNode): string = proc getName(n: NimNode): string =
case n.kind case n.kind
@ -76,16 +76,18 @@ proc tcall2(n, tmpContext: NimNode): NimNode =
result.add newDotAsgn(tmp, key, x[1]) result.add newDotAsgn(tmp, key, x[1])
else: else:
result.add newCall(bindSym"setAttr", tmp, newLit(key), x[1]) result.add newCall(bindSym"setAttr", tmp, newLit(key), x[1])
elif x.kind == nnkIdent:
result.add newCall(x, tmp)
else: else:
result.add tcall2(x, tmp) result.add tcall2(x, tmp)
#if tag == "link":
# result.add newCall(bindSym"setAttr", tmp, newLit"href", newLit"#")
if tmpContext == nil: if tmpContext == nil:
result.add tmp result.add tmp
else: else:
result.add newCall(bindSym"add", tmpContext, tmp) result.add newCall(bindSym"add", tmpContext, tmp)
elif tmpContext != nil and op notin StmtContext: elif tmpContext != nil and op notin StmtContext:
result = newCall(bindSym"add", tmpContext, n) result = newCall(bindSym"add", tmpContext, n)
elif op == "!" and n.len == 2:
result = n[1]
else: else:
result = n result = n
else: else:

View file

@ -63,7 +63,7 @@ proc createEntry(id: int; d: cstring; completed, selected: bool): VNode =
else: else:
input(class = "edit", name = "title", id = "todo-edit:" & &id, input(class = "edit", name = "title", id = "todo-edit:" & &id,
onfocusLost = focusLost, onfocusLost = focusLost,
onenter = editEntry, value = d) onenter = editEntry, value = d, setFocus)
proc createDom(): VNode = proc createDom(): VNode =
result = buildHtml(tdiv(class="todomvc-wrapper")): result = buildHtml(tdiv(class="todomvc-wrapper")):
@ -72,7 +72,7 @@ proc createDom(): VNode =
h1: h1:
text "todos" text "todos"
input(class = "new-todo", placeholder="What needs to be done?", name = "newTodo", input(class = "new-todo", placeholder="What needs to be done?", name = "newTodo",
onenter = onTodoEnter) onenter = onTodoEnter, setFocus)
section(class = "main"): section(class = "main"):
input(class = "toggle-all", `type` = "checkbox", name = "toggle") input(class = "toggle-all", `type` = "checkbox", name = "toggle")
label(`for` = "toggle-all", onclick = onAllDone): label(`for` = "toggle-all", onclick = onAllDone):