Skip to content

Instantly share code, notes, and snippets.

@Buslowicz
Last active May 17, 2016 23:59
Show Gist options
  • Save Buslowicz/408053572eecfa97f25bfc71cda5f671 to your computer and use it in GitHub Desktop.
Save Buslowicz/408053572eecfa97f25bfc71cda5f671 to your computer and use it in GitHub Desktop.
Google Polymer behavior allowing to use simple javascript expressions inside of the templates
(function (global) {
var dynamicFunctionsNames = {};
var cached = {};
function expressBinding(match, p) {
var fun;
var attrs = p
.replace(/&/g, "&") // decode &
.replace(/&lt;/g, "<") // decode <
.replace(/&gt;/g, ">") // decode >
.replace(/&quot;/g, "\"") // decode "
.replace(/&apos;/g, "'") // decode '
.replace(/'[^']+'/, "") // remove single quote strings
.replace(/"[^"]+"/, "") // remove double quote strings
.match(/([a-z_$\.][\w_$]*)/ig) // get all words starting from a letter, _, $ or a dot
.filter(function (el) {
return el[0] !== "."
}); // now exclude the words starting with a dot
if (!(fun = cached[p])) {
fun = cached[p] = new (Function.prototype.bind.apply(Function, [null].concat(attrs).concat("return " + p)));
}
var camelCasedName = this.is.replace(/\-([\w])/g, function (match, p) {
return p.toUpperCase()
});
var dynamicFunctionNameIndex = ++dynamicFunctionsNames[camelCasedName];
if (!dynamicFunctionNameIndex) {
dynamicFunctionNameIndex = dynamicFunctionsNames[camelCasedName] = 1;
}
var functionName = camelCasedName + "_" + dynamicFunctionNameIndex;
this.prototype[functionName] = fun;
return "[[" + functionName + "(" + attrs.join(",") + ")]]";
}
function expressBindingBehavior(id) {
var module = Polymer.DomModule.import(id);
var template = module.querySelector("template");
template.innerHTML = template.innerHTML.replace(/\{\{\{(.*)}}}/g, expressBinding.bind({
is: id,
prototype: this
}))
}
if (global.Polymer) {
global.Polymer.expressBindingBehavior = expressBindingBehavior;
} else {
global.addEventListener('HTMLImportsLoaded', function () {
global.Polymer.expressBindingBehavior = expressBindingBehavior;
});
}
}(this));
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/0.7.22/webcomponents-lite.min.js"></script>
<script>
// window.Polymer = {dom: 'shadow'};
</script>
<link href="http://polygit.org/polymer+:master/components/polymer/polymer.html" rel="import">
<script src="polymer-expression-binding-behavior.js"></script>
<dom-module id="test-module">
<template>
<p>Born in {{birthYear}} currently are {{{currentYear - birthYear}}} years old</p>
</template>
</dom-module>
</head>
<body>
<script>
window.addEventListener('HTMLImportsLoaded', function () {
var currentYear = new Date().getFullYear();
Polymer({
is: "test-module",
behaviors: [new Polymer.expressBindingBehavior("test-module")],
properties: {
currentYear: {
type: Number,
value: currentYear
},
birthYear: Number
}
});
function testBinding(year) {
var node = document.createElement("test-module");
node.birthYear = year;
var actual = Polymer.dom(node.root).textContent.trim();
var expected = "Born in " + year + " currently are " + (currentYear - year) + " years old";
document.writeln("Test <strong>" + (actual === expected ? "passed" : "failed") + "</strong> for `birthYear` equal to " + year + "<br>");
}
testBinding(1989);
testBinding(1969);
testBinding(1995);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment