added support for all HTML5 tags and drag&drop events
This commit is contained in:
parent
21bb6a0311
commit
be0f9c9e08
3 changed files with 85 additions and 32 deletions
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
92
src/vdom.nim
92
src/vdom.nim
|
|
@ -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.
|
||||||
|
|
||||||
|
macro buildLookupTables(): untyped =
|
||||||
|
var a = newTree(nnkBracket)
|
||||||
|
for i in low(VNodeKind)..high(VNodeKind):
|
||||||
|
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
|
const
|
||||||
toEventName*: array[EventKind, cstring] = [
|
toTag*: array[VNodeKind, cstring] = a
|
||||||
cstring"click", "dblclick", "keyup", "keydown", "keypressed", "blur",
|
toEventName*: array[EventKind, cstring] = e
|
||||||
"change", "scroll"
|
|
||||||
]
|
result = getAst tmpl(a, e)
|
||||||
|
|
||||||
|
buildLookupTables()
|
||||||
|
|
||||||
type
|
type
|
||||||
EventHandler* = proc (ev: Event; target: VNode) {.closure.}
|
EventHandler* = proc (ev: Event; target: VNode) {.closure.}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue