Modified and working version of John Berryman's attempt to add templating to d3.js using ICanHaz.js and innersvg polyfill. Solved based on this stackoverflow.com answers
My attempt to add templating to d3.js
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
d3.selection.prototype.ich = d3.selection.enter.prototype.ich = function(id,d) { | |
var thisSelection = (d) ? this.datum(d) : this; | |
thisSelection.html(function (d) { | |
return ich[id](d); | |
}); | |
}; |
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
(function(){var r,v=Object.prototype.toString;Array.isArray=Array.isArray||function(a){return"[object Array]"==v.call(a)};var s=String.prototype.trim,l;if(s)l=function(a){return null==a?"":s.call(a)};else{var n,p;/\S/.test("\u00a0")?(n=/^[\s\xA0]+/,p=/[\s\xA0]+$/):(n=/^\s+/,p=/\s+$/);l=function(a){return null==a?"":a.toString().replace(n,"").replace(p,"")}}var w={"&":"&","<":"<",">":">",'"':""","'":"'"},t={},u=function(){};u.prototype={otag:"{{",ctag:"}}",pragmas:{},buffer:[],pragmas_implemented:{"IMPLICIT-ITERATOR":!0}, | |
context:{},render:function(a,c,b,d){d||(this.context=c,this.buffer=[]);if(this.includes("",a)){a=this.render_pragmas(a);var e=this.render_section(a,c,b);!1===e&&(e=this.render_tags(a,c,b,d));if(d)return e;this.sendLines(e)}else{if(d)return a;this.send(a)}},send:function(a){""!==a&&this.buffer.push(a)},sendLines:function(a){if(a){a=a.split("\n");for(var c=0;c<a.length;c++)this.send(a[c])}},render_pragmas:function(a){if(!this.includes("%",a))return a;var c=this,b=this.getCachedRegex("render_pragmas", | |
function(a,b){return RegExp(a+"%([\\w-]+) ?([\\w]+=[\\w]+)?"+b,"g")});return a.replace(b,function(a,b,g){if(!c.pragmas_implemented[b])throw{message:"This implementation of mustache doesn't understand the '"+b+"' pragma"};c.pragmas[b]={};g&&(a=g.split("="),c.pragmas[b][a[0]]=a[1]);return""})},render_partial:function(a,c,b){a=l(a);if(!b||void 0===b[a])throw{message:"unknown_partial '"+a+"'"};return!c||"object"!=typeof c[a]?this.render(b[a],c,b,!0):this.render(b[a],c[a],b,!0)},render_section:function(a, | |
c,b){if(!this.includes("#",a)&&!this.includes("^",a))return!1;var d=this,e=this.getCachedRegex("render_section",function(a,b){return RegExp("^([\\s\\S]*?)"+a+"(\\^|\\#)\\s*(.+)\\s*"+b+"\n*([\\s\\S]*?)"+a+"\\/\\s*\\3\\s*"+b+"\\s*([\\s\\S]*)$","g")});return a.replace(e,function(a,e,j,f,k,m){a=e?d.render_tags(e,c,b,!0):"";m=m?d.render(m,c,b,!0):"";var q;f=d.find(f,c);"^"===j?q=!f||Array.isArray(f)&&0===f.length?d.render(k,c,b,!0):"":"#"===j&&(q=Array.isArray(f)?d.map(f,function(a){return d.render(k, | |
d.create_context(a),b,!0)}).join(""):d.is_object(f)?d.render(k,d.create_context(f),b,!0):"function"==typeof f?f.call(c,k,function(a){return d.render(a,c,b,!0)}):f?d.render(k,c,b,!0):"");return a+q+m})},render_tags:function(a,c,b,d){var e=this,g=function(){return e.getCachedRegex("render_tags",function(a,b){return RegExp(a+"(=|!|>|&|\\{|%)?([^#\\^]+?)\\1?"+b+"+","g")})},h=g(),j=function(a,d,f){switch(d){case "!":return"";case "=":return e.set_delimiters(f),h=g(),"";case ">":return e.render_partial(f, | |
c,b);case "{":case "&":return e.find(f,c);default:return a=e.find(f,c),String(a).replace(/&(?!\w+;)|[<>"']/g,function(a){return w[a]||a})}};a=a.split("\n");for(var f=0;f<a.length;f++)a[f]=a[f].replace(h,j,this),d||this.send(a[f]);if(d)return a.join("\n")},set_delimiters:function(a){a=a.split(" ");this.otag=this.escape_regex(a[0]);this.ctag=this.escape_regex(a[1])},escape_regex:function(a){arguments.callee.sRE||(arguments.callee.sRE=RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\)","g")); | |
return a.replace(arguments.callee.sRE,"\\$1")},find:function(a,c){a=l(a);var b;if(a.match(/([a-z_]+)\./ig)){var d=this.walk_context(a,c);(!1===d||0===d||d)&&(b=d)}else!1===c[a]||0===c[a]||c[a]?b=c[a]:(!1===this.context[a]||0===this.context[a]||this.context[a])&&(b=this.context[a]);return"function"==typeof b?b.apply(c):void 0!==b?b:""},walk_context:function(a,c){for(var b=a.split("."),d=void 0!=c[b[0]]?c:this.context,e=d[b.shift()];void 0!=e&&0<b.length;)d=e,e=e[b.shift()];return"function"==typeof e? | |
e.apply(d):e},includes:function(a,c){return-1!=c.indexOf(this.otag+a)},create_context:function(a){if(this.is_object(a))return a;var c=".";this.pragmas["IMPLICIT-ITERATOR"]&&(c=this.pragmas["IMPLICIT-ITERATOR"].iterator);var b={};b[c]=a;return b},is_object:function(a){return a&&"object"==typeof a},map:function(a,c){if("function"==typeof a.map)return a.map(c);for(var b=[],d=a.length,e=0;e<d;e++)b.push(c(a[e]));return b},getCachedRegex:function(a,c){var b=t[this.otag];b||(b=t[this.otag]={});var d=b[this.ctag]; | |
d||(d=b[this.ctag]={});(b=d[a])||(b=d[a]=c(this.otag,this.ctag));return b}};r={name:"mustache.js",version:"0.4.0",to_html:function(a,c,b,d){var e=new u;d&&(e.send=d);e.render(a,c||{},b);if(!d)return e.buffer.join("\n")}};(function(){function a(a){return"".trim?a.trim():a.replace(/^\s+/,"").replace(/\s+$/,"")}var c={VERSION:"0.10.2",templates:{},$:"undefined"!==typeof window?window.jQuery||window.Zepto||null:null,addTemplate:function(b,d){if("object"===typeof b)for(var e in b)this.addTemplate(e,b[e]); | |
else c[b]?console.error("Invalid name: "+b+"."):c.templates[b]?console.error('Template "'+b+' " exists'):(c.templates[b]=d,c[b]=function(d,e){d=d||{};var j=r.to_html(c.templates[b],d,c.templates);return c.$&&!e?c.$(a(j)):j})},clearAll:function(){for(var a in c.templates)delete c[a];c.templates={}},refresh:function(){c.clearAll();c.grabTemplates()},grabTemplates:function(){var b,d,e=document.getElementsByTagName("script"),g,h=[];b=0;for(d=e.length;b<d;b++)if((g=e[b])&&g.innerHTML&&g.id&&("text/html"=== | |
g.type||"text/x-icanhaz"===g.type))c.addTemplate(g.id,a(g.innerHTML)),h.unshift(g);b=0;for(d=h.length;b<d;b++)h[b].parentNode.removeChild(h[b])}};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=c),exports.ich=c):this.ich=c;"undefined"!==typeof document&&(c.$?c.$(function(){c.grabTemplates()}):document.addEventListener("DOMContentLoaded",function(){c.grabTemplates()},!0))})()})(); |
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
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>appendNodeFace</title> | |
<script src="http://mbostock.github.com/d3/d3.v2.js" type="text/javascript"></script> | |
<script src="icanhaz.min.js" type="text/javascript"></script> | |
<script src="innersvg.js" type="text/javascript"></script> | |
<script src="d3.selection.ich.template.js" type="text/javascript"></script> | |
<script type="text/javascript"> | |
</script> | |
<script id="head" type="text/html"> | |
<path | |
d="M 28.471261,-5.0558794 C 32.671841,22.243131 19.834631,49.162831 0.60952108,49.162831 -18.615599,49.162831 -27.684919,24.667631 -27.053699,-3.0332694 -26.458119,-29.170189 -25.961069,-47.588419 0.21246108,-48.936829 19.417701,-49.926249 24.103691,-33.440159 28.471261,-5.0558794 z" | |
id="face" | |
transform="scale({{head.width}} 1)" | |
style="color:#000000;fill:#ffccaa;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> | |
<path | |
d="m 15,0 c 0,3.7959 -4.91374,13.7461 -12.8383199,13.7461 -7.92458,0 -17.6233801,-10.3065 -15.8591001,-13.7461 1.0069201,-1.9631 7.9345201,0 15.8591001,0 7.9245799,0 12.8383199,-3.7959 12.8383199,0 z" | |
id="mouth" | |
transform="translate(0, {{mouth.drop}}) translate(0,17) scale({{mouth.width}} {{mouth.height}})" | |
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> | |
<path | |
d="m -18.009869,-17.276949 c 3.23815,-9.62232 14.5716901,-8.70591 14.5716901,-8.70591" | |
id="rightbrow" | |
transform="translate(0, -{{brow.lift}})" | |
style="color:#000000;fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> | |
<path | |
d="m 20.443211,-18.868939 c -3.23815,-9.62232 -14.5716899,-8.70591 -14.5716899,-8.70591" | |
id="leftbrow" | |
transform="translate(0, -{{brow.lift}})" | |
style="color:#000000;fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> | |
<path | |
d="m 2.3,0 c 0.90841,1.59522 -1.53169,3.13263 -4.07974,3.51899 -2.5480401,0.38635 -5.4168801,-0.16412 -5.1475501,-2.11987 0.25826,-1.87529 1.62394,-2.35301 4.1719801,-2.73937 2.54805,-0.38636 4.17038,-0.21373 5.05531,1.34025 z" | |
id="righteye" | |
transform="translate(-5,-18) scale({{eye.width}} {{eye.height}})" | |
style="color:#000000;fill:#000000;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> | |
<path | |
d="m 5.5,0 c 0.90841,1.59522 -1.53169,3.13263 -4.07974,3.51899 -2.5480399,0.38635 -5.4168799,-0.16412 -5.1475499,-2.11987 0.25826,-1.87529 1.62394,-2.35301 4.17198,-2.73937 2.5480499,-0.38636 4.1703899,-0.21373 5.0553099,1.34025 z" | |
id="lefteye" | |
transform="translate(10,-18) scale({{eye.width}} {{eye.height}})" | |
style="color:#000000;fill:#000000;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> | |
<path | |
d="M -8.1253309,-1.8487371 C -3.740886,13.80696 10.948853,19.556588 10.177223,-2.5578614" | |
id="nose" | |
transform="translate(0, {{nose.drop}}) scale({{nose.width}} {{nose.height}})" | |
style="color:#000000;fill:#ffccaa;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> | |
</script> | |
</head> | |
<body> | |
</body> | |
<script type="text/javascript"> | |
window.onload = function () { | |
var count = 0, | |
w = 960, | |
h = 520, | |
vis = d3.select('body') | |
.append('svg') | |
.attr('width', w) | |
.attr('height', h), | |
nextData = function() { | |
count += 1; | |
return { | |
head: { | |
width: .7*Math.random()+.8 //.8 - 1.5 | |
}, | |
mouth: { | |
width: .8*Math.random()+.5, //.5 - 1.3 | |
height: Math.random()+.5, //.5 - 1.5 | |
drop: 15*Math.random()-5 //-5 - 10 | |
}, | |
nose: { | |
width: Math.random()+.5, //.5 - 1.5 | |
height: Math.random()+.5, // .5 - 1.5 | |
drop: 15*Math.random()-5 // -5 - 10 | |
}, | |
eye: { | |
width: .8*Math.random()+.5, //.5 - 1.3 | |
height: 1.1*Math.random()+.4//.4 - 1.5 | |
}, | |
brow: { | |
lift: 10*Math.random() //0 - 10 | |
}, | |
x: w*(count%5+1)/5 - 85 , | |
y: h*.95*Math.ceil(count/5)/4.9 - 51 | |
}; | |
}, | |
data = d3.range(25).map(function() { | |
return nextData(); | |
}); | |
vis.selectAll('.head') | |
.data(data) | |
.enter() | |
.append('g') | |
.attr('class', 'head') | |
.attr('transform',function(d) { | |
return 'translate('+ d.x +' '+ d.y +')' | |
}) | |
.ich('head'); | |
}; | |
</script> | |
</html> |
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
/** | |
* innerHTML property for SVGElement | |
* Copyright(c) 2010, Jeff Schiller | |
* | |
* Licensed under the Apache License, Version 2 | |
* | |
* Works in a SVG document in Chrome 6+, Safari 5+, Firefox 4+ and IE9+. | |
* Works in a HTML5 document in Chrome 7+, Firefox 4+ and IE9+. | |
* Does not work in Opera since it doesn't support the SVGElement interface yet. | |
* | |
* I haven't decided on the best name for this property - thus the duplication. | |
*/ | |
(function() { | |
var serializeXML = function(node, output) { | |
var nodeType = node.nodeType; | |
if (nodeType == 3) { // TEXT nodes. | |
// Replace special XML characters with their entities. | |
output.push(node.textContent.replace(/&/, '&').replace(/</, '<').replace('>', '>')); | |
} else if (nodeType == 1) { // ELEMENT nodes. | |
// Serialize Element nodes. | |
output.push('<', node.tagName); | |
if (node.hasAttributes()) { | |
var attrMap = node.attributes; | |
for (var i = 0, len = attrMap.length; i < len; ++i) { | |
var attrNode = attrMap.item(i); | |
output.push(' ', attrNode.name, '=\'', attrNode.value, '\''); | |
} | |
} | |
if (node.hasChildNodes()) { | |
output.push('>'); | |
var childNodes = node.childNodes; | |
for (var i = 0, len = childNodes.length; i < len; ++i) { | |
serializeXML(childNodes.item(i), output); | |
} | |
output.push('</', node.tagName, '>'); | |
} else { | |
output.push('/>'); | |
} | |
} else if (nodeType == 8) { | |
// TODO(codedread): Replace special characters with XML entities? | |
output.push('<!--', node.nodeValue, '-->'); | |
} else { | |
// TODO: Handle CDATA nodes. | |
// TODO: Handle ENTITY nodes. | |
// TODO: Handle DOCUMENT nodes. | |
throw 'Error serializing XML. Unhandled node of type: ' + nodeType; | |
} | |
} | |
// The innerHTML DOM property for SVGElement. | |
Object.defineProperty(SVGElement.prototype, 'innerHTML', { | |
get: function() { | |
var output = []; | |
var childNode = this.firstChild; | |
while (childNode) { | |
serializeXML(childNode, output); | |
childNode = childNode.nextSibling; | |
} | |
return output.join(''); | |
}, | |
set: function(markupText) { | |
// Wipe out the current contents of the element. | |
while (this.firstChild) { | |
this.removeChild(this.firstChild); | |
} | |
try { | |
// Parse the markup into valid nodes. | |
var dXML = new DOMParser(); | |
dXML.async = false; | |
// Wrap the markup into a SVG node to ensure parsing works. | |
sXML = '<svg xmlns=\'http://www.w3.org/2000/svg\'>' + markupText + '</svg>'; | |
var svgDocElement = dXML.parseFromString(sXML, 'text/xml').documentElement; | |
// Now take each node, import it and append to this element. | |
var childNode = svgDocElement.firstChild; | |
while(childNode) { | |
this.appendChild(this.ownerDocument.importNode(childNode, true)); | |
childNode = childNode.nextSibling; | |
} | |
} catch(e) { | |
throw new Error('Error parsing XML string'); | |
}; | |
} | |
}); | |
// The innerSVG DOM property for SVGElement. | |
Object.defineProperty(SVGElement.prototype, 'innerSVG', { | |
get: function() { | |
return this.innerHTML; | |
}, | |
set: function(markupText) { | |
this.innerHTML = markupText; | |
} | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment