added support for all HTML5 tags and drag&drop events

This commit is contained in:
Andreas Rumpf 2017-04-14 19:36:16 +02:00
commit be0f9c9e08
3 changed files with 85 additions and 32 deletions

View file

@ -9,6 +9,7 @@ var
type type
ComponentKind* {.pure.} = enum ComponentKind* {.pure.} = enum
None, None,
Tag,
VNode, VNode,
Node Node
@ -18,6 +19,17 @@ var
proc isComponent*(x: string): ComponentKind {.compileTime.} = proc isComponent*(x: string): ComponentKind {.compileTime.} =
allcomponents.getOrDefault(x) allcomponents.getOrDefault(x)
proc addTags() {.compileTime.} =
let x = (bindSym"VNodeKind").getTypeImpl
expectKind(x, nnkEnumTy)
for i in ord(VNodeKind.html)..ord(VNodeKind.high):
# +1 because of empty node at the start of the enum AST:
let tag = $x[i+1]
allcomponents[tag] = ComponentKind.Tag
static:
addTags()
proc unpack(symbolicType: NimNode; index: int): NimNode {.compileTime.} = proc unpack(symbolicType: NimNode; index: int): NimNode {.compileTime.} =
#let t = symbolicType.getTypeImpl #let t = symbolicType.getTypeImpl
let t = repr(symbolicType) let t = repr(symbolicType)

View file

@ -111,7 +111,6 @@ proc same(n: VNode, e: Node): bool =
var var
dorender: proc (): VNode {.closure.} dorender: proc (): VNode {.closure.}
drawTimeout: Timeout
currentTree: VNode currentTree: VNode
proc setRenderer*(renderer: proc (): VNode) = proc setRenderer*(renderer: proc (): VNode) =
@ -125,9 +124,8 @@ proc getElementById*(id: cstring): Element {.importc: "document.getElementById",
#proc getElementsByClassName*(cls: cstring): seq[Element] {.importc: #proc getElementsByClassName*(cls: cstring): seq[Element] {.importc:
# "document.getElementsByClassName", nodecl.} # "document.getElementsByClassName", nodecl.}
#proc textContent(e: Node): cstring {.
proc textContent(e: Node): cstring {. # importcpp: "#.textContent", nodecl.}
importcpp: "#.textContent", nodecl.}
proc replaceById(id: cstring; newTree: Node) = proc replaceById(id: cstring; newTree: Node) =
let x = document.getElementById(id) let x = document.getElementById(id)
@ -215,6 +213,8 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
for i in 0..oldPos-pos: for i in 0..oldPos-pos:
current.removeChild(current.childNodes[pos]) current.removeChild(current.childNodes[pos])
when false:
var drawTimeout: Timeout
proc dodraw() = proc dodraw() =
let newtree = dorender() let newtree = dorender()
@ -316,9 +316,6 @@ proc setOnHashChange*(action: proc (hashPart: cstring)) =
redraw() redraw()
onhashchange = wrapper onhashchange = wrapper
proc getAttr(e: Node; key: cstring): cstring {.
importcpp: "#.getAttribute(#)", nodecl.}
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

View file

@ -1,37 +1,81 @@
# Virtual DOM implementation ## Virtual DOM implementation for Karax.
from dom import Event from dom import Event
import shash import shash, macros
from strutils import toUpperAscii
type type
VNodeKind* {.pure.} = enum VNodeKind* {.pure.} = enum
text, int, bool, vthunk, dthunk, text = "#text", int = "#int", bool = "#bool",
anchor, vthunk = "#vthunk", dthunk = "#dthunk",
tdiv,
table, tr, td, th, thead, tbody,
link, span, label, br, select, option,
fieldset, input, button, ul, li, section, header, footer,
h1, h2, h3, h4, h5, strong
const html, head, title, base, link, meta, style,
toTag*: array[VNodeKind, cstring] = [ script, noscript,
cstring"#text", "#int", "#bool", "#vthunk", "#dthunk", body, section, nav, article, aside,
"A", "DIV", "TABLE", "TR", "TD", h1, h2, h3, h4, h5, h6,
"TH", "THEAD", header, footer, address, main
"TBODY", "LINK",
"SPAN", "LABEL", "BR", "SELECT", "OPTION", "FIELDSET", "INPUT", "BUTTON", "UL", p, hr, pre, blockquote, ol, ul, li,
"LI", "SECTION", "HEADER", "FOOTER", "H1", "H2", "H3", "H4", "H5", "STRONG" dl, dt, dd,
] figure, figcaption,
tdiv = "div",
anchor, em, strong, small,
strikethrough = "s", cite, quote,
dfn, abbr, data, time, code, `var` = "var", samp,
kdb, sub, sup, italic = "i", bold = "b", underlined = "u",
mark, ruby, rt, rp, bdi, dbo, span, br, wbr,
ins, del, img, iframe, embed, `object` = "object",
param, video, audio, source, track, canvas, map,
area, svg, math,
table, caption, colgroup, col, tbody, thead,
tfoot, tr, td, th,
form, fieldset, legend, label, input, button,
select, datalist, optgroup, option, textarea,
keygen, output, progress, meter,
details, summary, command, menu
type type
EventKind* {.pure.} = enum EventKind* {.pure.} = enum ## The events supported by the virtual DOM.
onclick, ondblclick, onkeyup, onkeydown, onkeypressed, onblur, onchange, onscroll onclick, ## An element is clicked.
ondblclick, ## An element is double clicked.
onkeyup, ## A key was released.
onkeydown, ## A key is pressed.
onkeypressed, # A key was pressed.
onblur, ## An element lost the focus.
onchange, ## The selected value of an element was changed.
onscroll, ## The user scrolled within an element.
ondrag, ## An element or text selection is being dragged (every 350ms).
ondragend, ## A drag operation is being ended (by releasing a mouse button
## or hitting the escape key).
ondragenter, ## A dragged element or text selection enters a valid drop target.
ondragleave, ## A dragged element or text selection leaves a valid drop target.
ondragover, ## An element or text selection is being dragged over a valid
## drop target (every 350ms).
ondragstart, ## The user starts dragging an element or text selection.
ondrop ## An element is dropped on a valid drop target.
const macro buildLookupTables(): untyped =
toEventName*: array[EventKind, cstring] = [ var a = newTree(nnkBracket)
cstring"click", "dblclick", "keyup", "keydown", "keypressed", "blur", for i in low(VNodeKind)..high(VNodeKind):
"change", "scroll" let x = $i
] let y = if x[0] == '#': x else: toUpperAscii(x)
a.add(newCall("cstring", newLit(y)))
var e = newTree(nnkBracket)
for i in low(EventKind)..high(EventKind):
e.add(newCall("cstring", newLit(substr($i, 2))))
template tmpl(a, e) {.dirty.} =
const
toTag*: array[VNodeKind, cstring] = a
toEventName*: array[EventKind, cstring] = e
result = getAst tmpl(a, e)
buildLookupTables()
type type
EventHandler* = proc (ev: Event; target: VNode) {.closure.} EventHandler* = proc (ev: Event; target: VNode) {.closure.}