Skip to content

Instantly share code, notes, and snippets.

@jkutianski
Forked from JnBrymn/index.html
Last active December 27, 2015 12:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jkutianski/7328902 to your computer and use it in GitHub Desktop.
Save jkutianski/7328902 to your computer and use it in GitHub Desktop.
My attempt to add templating to d3.js
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);
});
};
(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={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},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))})()})();
<!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>
/**
* 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(/&/, '&amp;').replace(/</, '&lt;').replace('>', '&gt;'));
} 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