From 14660f9d685d1b14cdead9cb09421f0f8ff7512e Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Thu, 15 Jun 2017 13:53:53 +0200 Subject: [PATCH] implemented refs draft --- experiments/refs/demo.html | 13 +++++++++++++ experiments/refs/demo.nim | 39 ++++++++++++++++++++++++++++++++++++++ experiments/refs/demo.nims | 1 + src/karax.nim | 10 ++++++++-- src/karaxdsl.nim | 2 +- src/vdom.nim | 4 ++++ 6 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 experiments/refs/demo.html create mode 100644 experiments/refs/demo.nim create mode 100644 experiments/refs/demo.nims diff --git a/experiments/refs/demo.html b/experiments/refs/demo.html new file mode 100644 index 0000000..e1fe419 --- /dev/null +++ b/experiments/refs/demo.html @@ -0,0 +1,13 @@ + + + + + + Refs + + + +
+ + + diff --git a/experiments/refs/demo.nim b/experiments/refs/demo.nim new file mode 100644 index 0000000..dffb1e9 --- /dev/null +++ b/experiments/refs/demo.nim @@ -0,0 +1,39 @@ +include karaxprelude +import random + +var + modelData = @[5, 2, 4] + + refA = VNodeRef() + refB = VNodeRef() + refSeq = newSeq[VNodeRef]() + +proc onClick(ev: Event, n: VNode) = + kout(refA) + kout(refB) + kout(refSeq) + +proc secureRefSlot(i: int): VNodeRef = + while refSeq.len <= i: + refSeq.add(VNodeRef()) + result = refSeq[i] + +proc view(): VNode = + result = buildHtml(): + tdiv: + button(onclick=onClick): + text "click me" + # storing refs to single elements is straightforward now + tdiv(nref=refA): + text "A" + tdiv(nref=refB): + text "B" + # It's a bit more tricky when containers are involved: + for i, x in modelData.pairs: + tdiv(nref=secureRefSlot(i)): + text "List item: " & $x + +proc renderer(): VNode = + view() + +setRenderer renderer diff --git a/experiments/refs/demo.nims b/experiments/refs/demo.nims new file mode 100644 index 0000000..9028ff1 --- /dev/null +++ b/experiments/refs/demo.nims @@ -0,0 +1 @@ +--path: "../../src" diff --git a/src/karax.nim b/src/karax.nim index cc52e2f..d8a4cb1 100644 --- a/src/karax.nim +++ b/src/karax.nim @@ -65,8 +65,14 @@ proc wrapEvent(d: Node; n: VNode; k: EventKind; action: EventHandler) = # --------------------- DOM diff ----------------------------------------- -template detach(n: VNode) = n.dom = nil -template attach(n: Vnode) = n.dom = result +template detach(n: VNode) = + if not n.nref.isNil(): + n.nref.vnode = nil + n.dom = nil +template attach(n: VNode) = + if not n.nref.isNil(): + n.nref.vnode = n + n.dom = result proc vnodeToDom(n: VNode): Node = if n.kind == VNodeKind.text: diff --git a/src/karaxdsl.nim b/src/karaxdsl.nim index 190545c..8693f5b 100644 --- a/src/karaxdsl.nim +++ b/src/karaxdsl.nim @@ -4,7 +4,7 @@ from strutils import startsWith, toLowerAscii const StmtContext = ["kout", "inc", "echo", "dec", "!"] - SpecialAttrs = ["id", "class", "value", "key", "style"] + SpecialAttrs = ["id", "class", "value", "key", "style", "nref"] proc getName(n: NimNode): string = case n.kind diff --git a/src/vdom.nim b/src/vdom.nim index d55e7b4..f4ccff8 100644 --- a/src/vdom.nim +++ b/src/vdom.nim @@ -101,6 +101,9 @@ macro buildLookupTables(): untyped = buildLookupTables() type + VNodeRef* = ref object + vnode*: VNode + EventHandler* = proc (ev: Event; target: VNode) {.closure.} VKey* = int @@ -108,6 +111,7 @@ type kind*: VNodeKind key*: VKey id*, class*, text*: cstring + nref*: VNodeRef kids: seq[VNode] # even index: key, odd index: value; done this way for memory efficiency: attrs: seq[cstring]