-
-
Save eizenberg/6620722 to your computer and use it in GitHub Desktop.
A reactive svg implementation, based on reactive-coffee by @yang
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bind = rx.bind | |
ObsCell = rx.ObsCell | |
ObsArray = rx.ObsArray | |
@rxv = {} | |
events = ["click", "mousedown", "mouseup"] | |
specialAttrs = rxv.specialAttrs = { | |
init: (elt, fn) -> fn.call(elt) | |
} | |
for ev in events | |
do (ev) -> | |
specialAttrs[ev] = (elt, fn) -> elt.addEventListener ev, fn | |
setProp = (elt, prop, val) -> | |
elt.setAttribute prop, val | |
rxv.mktag = mktag = (tag) -> | |
(arg1, arg2) -> | |
# arguments are either (), (attrs: Object), (contents: non-Object), or | |
# (attrs: Object, contents: non-Object) | |
[attrs, contents] = | |
if not arg1? and not arg2? | |
[{}, null] | |
else if arg2? | |
[arg1, arg2] | |
else if _.isString(arg1) or arg1 instanceof SVGElement or _.isArray(arg1) or arg1 instanceof ObsCell or arg1 instanceof ObsArray | |
[{}, arg1] | |
else | |
[arg1, null] | |
elt = document.createElementNS('http://www.w3.org/2000/svg', tag) | |
for name, value of _.omit(attrs, _.keys(specialAttrs)) | |
if value instanceof ObsCell | |
do (name) -> | |
value.onSet.sub ([old, val]) -> setProp(elt, name, val) | |
else | |
setProp(elt, name, value) | |
if contents? | |
toNodes = (contents) -> | |
for child in contents | |
if _.isString(child) | |
document.createTextNode(child) | |
else if child instanceof SVGElement | |
child | |
else | |
throw 'Unknown element type in array: ' + child.constructor.name | |
updateContents = (contents) -> | |
(elt.removeChild elt.firstChild) while elt.firstChild | |
if _.isArray(contents) | |
(elt.appendChild node) for node in toNodes(contents) | |
else if _.isString(contents) | |
updateContents([contents]) | |
else | |
throw 'Unknown type for contents: ' + contents.constructor.name | |
if contents instanceof ObsArray | |
contents.onChange.sub ([index, removed, added]) -> | |
(elt.removeChild elt.childNodes[index]) for i in [0...removed.length] | |
toAdd = toNodes(added) | |
if index == elt.childNodes.length | |
(elt.appendChild node) for node in toAdd | |
else | |
(elt.childNodes[index].insertBefore node) for node in toAdd | |
else if contents instanceof ObsCell | |
contents.onSet.sub(([old, val]) -> updateContents(val)) | |
else | |
updateContents(contents) | |
for key of attrs when key of specialAttrs | |
specialAttrs[key](elt, attrs[key], attrs, contents) | |
elt | |
tags = ['svg', 'rect', 'text', 'g'] | |
rxv.tags = _.object([tag, rxv.mktag(tag)] for tag in tags) | |
rxv.importTags = (x) => _(x ? this).extend(rxv.tags) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment