diff --git a/karax.nim b/karax.nim index 587f2a7..888a2e9 100644 --- a/karax.nim +++ b/karax.nim @@ -26,6 +26,10 @@ type var document* {.importc.}: Document toFocus: Element + toFocusV: VNode + +proc setFocus*(n: VNode) = + toFocusV = n proc vnodeToDom(n: VNode): Element = if n.kind == VNodeKind.text: @@ -52,7 +56,7 @@ proc vnodeToDom(n: VNode): Element = assert myn != nil hh(ev, myn) result.addEventListener(toEventName[e], wrapper()) - if n.kind == VNodeKind.input and toFocus.isNil: + if n == toFocusV and toFocus.isNil: toFocus = result proc same(n: VNode, e: Element): bool = @@ -91,8 +95,8 @@ proc replaceById(id: cstring; newTree: Node) = proc equals(a, b: VNode): bool = if a.kind != b.kind: return false if a.id != b.id: return false - #if a.kind == VNodeKind.text: - if a.text != b.text: return false + if a.kind == VNodeKind.text: + if a.text != b.text: return false if not sameAttrs(a, b): return false if a.class != b.class: return false # 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 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) #if oldElem != nil: return oldElem #let newVal = if oldElem.isNil: val else: $oldElem.value var timer: Timeout proc onkeyup(ev: Event; n: VNode) = - proc wrapper() = - n.value = nativeValue(ev) - changed(ev, n) - setNativeValue(ev, n.value) - redraw() + proc wrapper() = keyeventBody() if timer != nil: clearTimeout(timer) timer = setTimeout(wrapper, 400) @@ -334,29 +340,21 @@ proc realtimeInput*(val: cstring; changed: EventHandler): VNode = result.value = val 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) #if oldElem != nil: return oldElem #let newVal = if oldElem.isNil: val else: $oldElem.value proc onkeyup(ev: Event; n: VNode) = - if ev.keyCode == 13: - n.value = nativeValue(ev) - onenter(ev, n) - setNativeValue(ev, n.value) - redraw() + if ev.keyCode == 13: keyeventBody() result = tree(VNodeKind.input, [(cstring"type", cstring"text")]) result.id = id result.value = val result.addEventListener(EventKind.onkeyup, onkeyup) -proc setOnEnter*(n: VNode; onenter: EventHandler) = +proc setOnEnter*(n: VNode; action: EventHandler) = proc onkeyup(ev: Event; n: VNode) = - if ev.keyCode == 13: - n.value = nativeValue(ev) - onenter(ev, n) - setNativeValue(ev, n.value) - redraw() + if ev.keyCode == 13: keyeventBody() n.addEventListener(EventKind.onkeyup, onkeyup) proc ajax(meth, url: cstring; headers: openarray[(cstring, cstring)]; diff --git a/karaxdsl.nim b/karaxdsl.nim index e90a9b3..a96c70a 100644 --- a/karaxdsl.nim +++ b/karaxdsl.nim @@ -3,7 +3,7 @@ import macros, karax, vdom from strutils import startsWith, toLowerAscii const - StmtContext = ["kout", "inc", "echo", "dec"] + StmtContext = ["kout", "inc", "echo", "dec", "!"] proc getName(n: NimNode): string = case n.kind @@ -76,16 +76,18 @@ proc tcall2(n, tmpContext: NimNode): NimNode = result.add newDotAsgn(tmp, key, x[1]) else: result.add newCall(bindSym"setAttr", tmp, newLit(key), x[1]) + elif x.kind == nnkIdent: + result.add newCall(x, tmp) else: result.add tcall2(x, tmp) - #if tag == "link": - # result.add newCall(bindSym"setAttr", tmp, newLit"href", newLit"#") if tmpContext == nil: result.add tmp else: result.add newCall(bindSym"add", tmpContext, tmp) elif tmpContext != nil and op notin StmtContext: result = newCall(bindSym"add", tmpContext, n) + elif op == "!" and n.len == 2: + result = n[1] else: result = n else: diff --git a/todoapp.nim b/todoapp.nim index 40bc4bb..63875a6 100644 --- a/todoapp.nim +++ b/todoapp.nim @@ -63,7 +63,7 @@ proc createEntry(id: int; d: cstring; completed, selected: bool): VNode = else: input(class = "edit", name = "title", id = "todo-edit:" & &id, onfocusLost = focusLost, - onenter = editEntry, value = d) + onenter = editEntry, value = d, setFocus) proc createDom(): VNode = result = buildHtml(tdiv(class="todomvc-wrapper")): @@ -72,7 +72,7 @@ proc createDom(): VNode = h1: text "todos" input(class = "new-todo", placeholder="What needs to be done?", name = "newTodo", - onenter = onTodoEnter) + onenter = onTodoEnter, setFocus) section(class = "main"): input(class = "toggle-all", `type` = "checkbox", name = "toggle") label(`for` = "toggle-all", onclick = onAllDone):