Last active
August 29, 2015 14:07
-
-
Save jinjor/5dd47b5b82ea3acd3104 to your computer and use it in GitHub Desktop.
荒削りテンプレート
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
<template id="target"> | |
<div> | |
<span foo="{{ bar }}">{{foo}}</span> | |
<template repeat="{{ bar , i in list }}"> | |
<div><span>{{i}}: </span><span>{{foo}}</span><span>{{bar}}</span></div> | |
</template> | |
<div><a>{{bar}} dayo{{foo}}</a></div> | |
</div> | |
</template> | |
<script> | |
var template = {}; | |
template.splitBracketOnce = function(text) { | |
var index1 = text.indexOf('{{'); | |
if (index1 < 0) { | |
return [text]; | |
} | |
var left = text.substring(0, index1); | |
var rest = text.substring(index1 + 2); | |
var index2 = rest.indexOf('}}'); | |
if (index2 < 0) { | |
return [left, rest]; | |
} | |
var center = rest.substring(0, index2).trim(); | |
var right = rest.substring(index2 + 2); | |
return [left, center, right]; | |
}; | |
template.parse = function(text) { | |
var parts = []; | |
while (true) { | |
var splitted = template.splitBracketOnce(text); | |
splitted[0] && parts.push(splitted[0]); | |
if (splitted.length >= 2) { | |
if (splitted.length === 3) { | |
var inner = splitted[1]; | |
parts.push({ | |
value: inner | |
}); | |
text = splitted[2]; | |
} else { | |
parts.push(splitted[1]); | |
break; | |
} | |
} else { | |
break; | |
} | |
} | |
return parts; | |
}; | |
template.traverse = function(nodes, variables) { | |
var len_i = nodes.length; | |
for (var i = 0; i < len_i; i++) { | |
var node = nodes[i]; | |
if (node.tagName === 'TEMPLATE') { | |
var rep = node.getAttribute('repeat') | |
if (rep) { | |
var parsed = template.parseRepeat(rep); | |
var render = template.compile(node); | |
node.forLoop = { | |
one: parsed[0], | |
index: parsed[1], | |
list: parsed[2], | |
render: render | |
}; | |
} | |
} else { | |
if (node.attributes) { | |
var len_j = node.attributes.length; | |
for (var j = 0; j < len_j; j++) { | |
var attribute = node.attributes[j]; | |
var parts = template.parse(attribute.value); | |
if (parts.length > 1 || typeof parts[0] === 'object') { | |
node.attrParts = node.attrParts || {}; | |
node.attrParts[attribute.name] = parts; | |
} | |
} | |
} | |
if (node.nodeValue) { | |
var text = node.nodeValue; | |
var parts = template.parse(text); | |
if (parts.length > 1 || typeof parts[0] === 'object') { | |
node.parts = parts; | |
} | |
} | |
} | |
if (node.attrParts || node.parts || node.forLoop) { | |
variables.push(node); | |
} | |
if (node.tagName !== 'TEMPLATE') { | |
template.traverse(node.childNodes, variables); | |
} | |
} | |
}; | |
template.parseRepeat = function(text) { | |
var splitted = template.splitBracketOnce(text); | |
var inner = splitted[1]; | |
if (!inner) { | |
throw new Error(); | |
} | |
var innerSplitted = inner.split(' in '); | |
var _one = innerSplitted[0].trim(); | |
var _oneSplitted = _one.split(','); | |
var one = _oneSplitted[0].trim(); | |
var index = _oneSplitted[1].trim(); | |
var list = innerSplitted[1].trim(); | |
return [one, index, list]; | |
}; | |
template.traverseAndRender = function(variables, object) { | |
var len_i = variables.length; | |
for (var i = 0; i < len_i; i++) { | |
var node = variables[i]; | |
if (node.forLoop) { | |
var newObject = Object.create(object); | |
var list = object[node.forLoop.list]; | |
var len_j = list.length; | |
for(var j = 0; j < len_j; j++){ | |
newObject[node.forLoop.one] = list[j]; | |
newObject[node.forLoop.index] = j; | |
var childNode = node.forLoop.render(newObject); | |
node.parentNode.insertBefore(childNode, node); | |
} | |
continue; | |
} | |
if (node.attrParts) { | |
var names = Object.keys(node.attrParts); | |
var len_j = names.length; | |
for (var j = 0; j < len_j; j++) { | |
var name = names[j]; | |
var parts = node.attrParts[name]; | |
var text = template.makeText(parts, object); | |
node.setAttribute(name, text); | |
} | |
} | |
if (node.parts) { | |
var text = template.makeText(node.parts, object); | |
node.nodeValue = text; | |
} | |
} | |
}; | |
template.makeText = function(parts, object) { | |
var text = '' | |
var len_j = parts.length; | |
for (var j = 0; j < len_j; j++) { | |
var part = parts[j]; | |
if (typeof part === 'object') { | |
text += object[part.value]; | |
} else { | |
text += part; | |
} | |
} | |
return text; | |
}; | |
template.compile = function(templateElement) { | |
var variables = []; | |
template.traverse(templateElement.content.childNodes, variables); | |
return function(object) { | |
template.traverseAndRender(variables, object); | |
var clone = document.importNode(templateElement.content, true); | |
return clone; | |
}; | |
}; | |
window.onload = function() { | |
var render = template.compile(document.getElementById('target')); | |
var node = render({ | |
foo: 'FOO', | |
bar: 'BAR', | |
list: ['a', 'b', '<b>c</b>'] | |
}); | |
document.body.appendChild(node); | |
}; | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment