UNPKG

simplesvg

Version:

A very simple svg wrapper, inspired by original vivagraph

93 lines (74 loc) 2.63 kB
module.exports = template; var BINDING_EXPR = /{{(.+?)}}/; function template(domNode) { var allBindings = Object.create(null); extractAllBindings(domNode, allBindings); return { link: function(model) { Object.keys(allBindings).forEach(function(key) { var setter = allBindings[key]; setter.forEach(changeModel); }); function changeModel(setter) { setter(model); } } }; } function extractAllBindings(domNode, allBindings) { var nodeType = domNode.nodeType; var typeSupported = (nodeType === 1) || (nodeType === 3); if (!typeSupported) return; var i; if (domNode.hasChildNodes()) { var domChildren = domNode.childNodes; for (i = 0; i < domChildren.length; ++i) { extractAllBindings(domChildren[i], allBindings); } } if (nodeType === 3) { // text: bindTextContent(domNode, allBindings); } if (!domNode.attributes) return; // this might be a text. Need to figure out what to do in that case var attrs = domNode.attributes; for (i = 0; i < attrs.length; ++i) { bindDomAttribute(attrs[i], domNode, allBindings); } } function bindDomAttribute(domAttribute, element, allBindings) { var value = domAttribute.value; if (!value) return; // unary attribute? var modelNameMatch = value.match(BINDING_EXPR); if (!modelNameMatch) return; // does not look like a binding var attrName = domAttribute.localName; var modelPropertyName = modelNameMatch[1]; var isSimpleValue = modelPropertyName.indexOf('.') < 0; if (!isSimpleValue) throw new Error('simplesvg currently does not support nested bindings'); var propertyBindings = allBindings[modelPropertyName]; if (!propertyBindings) { propertyBindings = allBindings[modelPropertyName] = [attributeSetter]; } else { propertyBindings.push(attributeSetter); } function attributeSetter(model) { element.setAttributeNS(null, attrName, model[modelPropertyName]); } } function bindTextContent(element, allBindings) { // todo reduce duplication var value = element.nodeValue; if (!value) return; // unary attribute? var modelNameMatch = value.match(BINDING_EXPR); if (!modelNameMatch) return; // does not look like a binding var modelPropertyName = modelNameMatch[1]; var isSimpleValue = modelPropertyName.indexOf('.') < 0; var propertyBindings = allBindings[modelPropertyName]; if (!propertyBindings) { propertyBindings = allBindings[modelPropertyName] = [textSetter]; } else { propertyBindings.push(textSetter); } function textSetter(model) { element.nodeValue = model[modelPropertyName]; } }