This commit is contained in:
Andreas Rumpf 2017-06-28 11:26:09 +02:00
commit 0ad9d68c81
3 changed files with 34 additions and 11 deletions

View file

@ -48,8 +48,9 @@ template keyeventBody() =
# Do not call redraw() here! That is already done # Do not call redraw() here! That is already done
# by ``karax.addEventHandler``. # by ``karax.addEventHandler``.
proc wrapEvent(d: Node; n: VNode; k: EventKind; action: EventHandler) = proc wrapEvent(d: Node; n: VNode; k: EventKind;
proc stdWrapper(): (proc (ev: Event)) = action: EventHandler): NativeEventHandler =
proc stdWrapper(): NativeEventHandler =
let action = action let action = action
let n = n let n = n
result = proc (ev: Event) = result = proc (ev: Event) =
@ -57,13 +58,13 @@ proc wrapEvent(d: Node; n: VNode; k: EventKind; action: EventHandler) =
keyeventBody() keyeventBody()
else: action(ev, n) else: action(ev, n)
proc enterWrapper(): (proc (ev: Event)) = proc enterWrapper(): NativeEventHandler =
let action = action let action = action
let n = n let n = n
result = proc (ev: Event) = result = proc (ev: Event) =
if ev.keyCode == 13: keyeventBody() if ev.keyCode == 13: keyeventBody()
proc laterWrapper(): (proc (ev: Event)) = proc laterWrapper(): NativeEventHandler =
let action = action let action = action
let n = n let n = n
var timer: Timeout var timer: Timeout
@ -74,11 +75,14 @@ proc wrapEvent(d: Node; n: VNode; k: EventKind; action: EventHandler) =
case k case k
of EventKind.onkeyuplater: of EventKind.onkeyuplater:
d.addEventListener("keyup", laterWrapper()) result = laterWrapper()
d.addEventListener("keyup", result)
of EventKind.onkeyupenter: of EventKind.onkeyupenter:
d.addEventListener("keyup", enterWrapper()) result = enterWrapper()
d.addEventListener("keyup", result)
else: else:
d.addEventListener(toEventName[k], stdWrapper()) result = stdWrapper()
d.addEventListener(toEventName[k], result)
# --------------------- DOM diff ----------------------------------------- # --------------------- DOM diff -----------------------------------------
@ -90,6 +94,11 @@ template detach(n: VNode) =
template attach(n: VNode) = template attach(n: VNode) =
n.dom = result n.dom = result
proc applyEvents(n: VNode; kxi: KaraxInstance) =
let dest = n.dom
for i in 0..<len(n.events):
n.events[i][2] = wrapEvent(dest, n, n.events[i][0], n.events[i][1])
proc vnodeToDom(n: VNode; kxi: KaraxInstance): Node = proc vnodeToDom(n: VNode; kxi: KaraxInstance): Node =
if n.kind == VNodeKind.text: if n.kind == VNodeKind.text:
result = document.createTextNode(n.text) result = document.createTextNode(n.text)
@ -132,8 +141,7 @@ proc vnodeToDom(n: VNode; kxi: KaraxInstance): Node =
for k, v in attrs(n): for k, v in attrs(n):
if v != nil: if v != nil:
result.setAttr(k, v) result.setAttr(k, v)
for e, h in items(n.events): applyEvents(n, kxi)
wrapEvent(result, n, e, h)
if n == kxi.toFocusV and kxi.toFocus.isNil: if n == kxi.toFocusV and kxi.toFocus.isNil:
kxi.toFocus = result kxi.toFocus = result
if not n.style.isNil: applyStyle(result, n.style) if not n.style.isNil: applyStyle(result, n.style)
@ -191,6 +199,17 @@ proc updateStyles(newNode, oldNode: VNode) =
else: oldNode.dom.style = Style() else: oldNode.dom.style = Style()
oldNode.style = newNode.style oldNode.style = newNode.style
proc mergeEvents(newNode, oldNode: VNode) =
let d = oldNode.dom
for i in 0..<oldNode.events.len:
let k = oldNode.events[i][0]
let name = case k
of EventKind.onkeyuplater, EventKind.onkeyupenter: cstring"keyup"
else: toEventName[k]
d.removeEventListener(name, oldNode.events[i][2])
shallowCopy(oldNode.events, newNode.events)
applyEvents(oldNode, kxi)
proc printV(n: VNode; depth: cstring = "") = proc printV(n: VNode; depth: cstring = "") =
kout depth, cstring($n.kind), cstring"key ", n.key kout depth, cstring($n.kind), cstring"key ", n.key
#for k, v in pairs(n.style): #for k, v in pairs(n.style):
@ -240,6 +259,8 @@ proc diff(newNode, oldNode: VNode;parent, current: Node; patches: JSeq[Patch]):
of identical, similar: of identical, similar:
newNode.dom = oldNode.dom newNode.dom = oldNode.dom
if result == similar: updateStyles(newNode, oldNode) if result == similar: updateStyles(newNode, oldNode)
if newNode.events.len != 0 or oldNode.events.len != 0:
mergeEvents(newNode, oldNode)
let newLength = newNode.len let newLength = newNode.len
var oldLength = oldNode.len var oldLength = oldNode.len

View file

@ -483,6 +483,7 @@ proc clearTimeout*(t: Timeout) {.importc, nodecl.}
# EventTarget "methods" # EventTarget "methods"
proc addEventListener*(et: EventTarget, ev: cstring, cb: proc(ev: Event), useCapture: bool = false) proc addEventListener*(et: EventTarget, ev: cstring, cb: proc(ev: Event), useCapture: bool = false)
proc removeEventListener*(et: EventTarget; ev: cstring; cb: proc(ev: Event))
# Window "methods" # Window "methods"
proc alert*(w: Window, msg: cstring) proc alert*(w: Window, msg: cstring)

View file

@ -104,6 +104,7 @@ buildLookupTables()
type type
EventHandler* = proc (ev: Event; target: VNode) {.closure.} EventHandler* = proc (ev: Event; target: VNode) {.closure.}
NativeEventHandler* = proc (ev: Event) {.closure.}
VKey* = int VKey* = int
VNode* = ref object of RootObj VNode* = ref object of RootObj
@ -113,7 +114,7 @@ type
kids: seq[VNode] kids: seq[VNode]
# even index: key, odd index: value; done this way for memory efficiency: # even index: key, odd index: value; done this way for memory efficiency:
attrs: seq[cstring] attrs: seq[cstring]
events*: seq[(EventKind, EventHandler)] events*: seq[(EventKind, EventHandler, NativeEventHandler)]
when false: when false:
hash*: Hash hash*: Hash
validHash*: bool validHash*: bool
@ -222,7 +223,7 @@ proc sameAttrs*(a, b: VNode): bool =
if a.attrs[i] != b.attrs[i]: return false if a.attrs[i] != b.attrs[i]: return false
proc addEventListener*(n: VNode; event: EventKind; handler: EventHandler) = proc addEventListener*(n: VNode; event: EventKind; handler: EventHandler) =
n.events.add((event, handler)) n.events.add((event, handler, nil))
template toStringAttr(field) = template toStringAttr(field) =
if n.field != nil: if n.field != nil: