UNPKG

simplesvg

Version:

A very simple svg wrapper, inspired by original vivagraph

313 lines (245 loc) 8.43 kB
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ var svg = require('../../'); var circle = svg('circle', { r: 21, cx: 42, cy: 42, stroke: '#000', fill: 'deepskyblue' }); document.getElementById('scene').appendChild(circle); },{"../../":2}],2:[function(require,module,exports){ module.exports = svg; svg.compile = require('./lib/compile'); var compileTemplate = svg.compileTemplate = require('./lib/compileTemplate'); var domEvents = require('add-event-listener'); var svgns = "http://www.w3.org/2000/svg"; var xlinkns = "http://www.w3.org/1999/xlink"; function svg(element, attrBag) { var svgElement = augment(element); if (attrBag === undefined) { return svgElement; } var attributes = Object.keys(attrBag); for (var i = 0; i < attributes.length; ++i) { var attributeName = attributes[i]; var value = attrBag[attributeName]; if (attributeName === 'link') { svgElement.link(value); } else { svgElement.attr(attributeName, value); } } return svgElement; } function augment(element) { var svgElement = element; if (typeof element === "string") { svgElement = window.document.createElementNS(svgns, element); } else if (element.simplesvg) { return element; } var compiledTempalte; svgElement.simplesvg = true; // this is not good, since we are monkey patching svg svgElement.attr = attr; svgElement.append = append; svgElement.link = link; svgElement.text = text; // add easy eventing svgElement.on = on; svgElement.off = off; // data binding: svgElement.dataSource = dataSource; return svgElement; function dataSource(model) { if (!compiledTempalte) compiledTempalte = compileTemplate(svgElement); compiledTempalte.link(model); return svgElement; } function on(name, cb, useCapture) { domEvents.addEventListener(svgElement, name, cb, useCapture); return svgElement; } function off(name, cb, useCapture) { domEvents.removeEventListener(svgElement, name, cb, useCapture); return svgElement; } function append(content) { var child = svg(content); svgElement.appendChild(child); return child; } function attr(name, value) { if (arguments.length === 2) { if (value !== null) { svgElement.setAttributeNS(null, name, value); } else { svgElement.removeAttributeNS(null, name); } return svgElement; } return svgElement.getAttributeNS(null, name); } function link(target) { if (arguments.length) { svgElement.setAttributeNS(xlinkns, "xlink:href", target); return svgElement; } return svgElement.getAttributeNS(xlinkns, "xlink:href"); } function text(textContent) { if (textContent !== undefined) { svgElement.textContent = textContent; return svgElement; } return svgElement.textContent; } } },{"./lib/compile":3,"./lib/compileTemplate":4,"add-event-listener":6}],3:[function(require,module,exports){ var parser = require('./domparser.js'); var svg = require('../'); module.exports = compile; function compile(svgText) { try { svgText = addNamespaces(svgText); return svg(parser.parseFromString(svgText, "text/xml").documentElement); } catch (e) { throw e; } } function addNamespaces(text) { if (!text) return; var namespaces = 'xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"'; var match = text.match(/^<\w+/); if (match) { var tagLength = match[0].length; return text.substr(0, tagLength) + ' ' + namespaces + ' ' + text.substr(tagLength); } else { throw new Error('Cannot parse input text: invalid xml?'); } } },{"../":2,"./domparser.js":5}],4:[function(require,module,exports){ 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]; } } },{}],5:[function(require,module,exports){ module.exports = createDomparser(); function createDomparser() { if (typeof DOMParser === 'undefined') { return { parseFromString: fail }; } return new DOMParser(); } function fail() { throw new Error('DOMParser is not supported by this platform. Please open issue here https://github.com/anvaka/simplesvg'); } },{}],6:[function(require,module,exports){ addEventListener.removeEventListener = removeEventListener addEventListener.addEventListener = addEventListener module.exports = addEventListener var Events = null function addEventListener(el, eventName, listener, useCapture) { Events = Events || ( document.addEventListener ? {add: stdAttach, rm: stdDetach} : {add: oldIEAttach, rm: oldIEDetach} ) return Events.add(el, eventName, listener, useCapture) } function removeEventListener(el, eventName, listener, useCapture) { Events = Events || ( document.addEventListener ? {add: stdAttach, rm: stdDetach} : {add: oldIEAttach, rm: oldIEDetach} ) return Events.rm(el, eventName, listener, useCapture) } function stdAttach(el, eventName, listener, useCapture) { el.addEventListener(eventName, listener, useCapture) } function stdDetach(el, eventName, listener, useCapture) { el.removeEventListener(eventName, listener, useCapture) } function oldIEAttach(el, eventName, listener, useCapture) { if(useCapture) { throw new Error('cannot useCapture in oldIE') } el.attachEvent('on' + eventName, listener) } function oldIEDetach(el, eventName, listener, useCapture) { el.detachEvent('on' + eventName, listener) } },{}]},{},[1])