Skip to content

Instantly share code, notes, and snippets.

@shawndumas
Last active August 29, 2015 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shawndumas/cbc1e37210165e3e9fb1 to your computer and use it in GitHub Desktop.
Save shawndumas/cbc1e37210165e3e9fb1 to your computer and use it in GitHub Desktop.
jsbin.com/mewixa
<html>
<head>
<style>
b {
font-weight: normal;
}
</style>
<script src="http://cdn.jsdelivr.net/handlebarsjs/2.0.0/handlebars.js"></script>
</head>
<body>
<div/>
<script id="template" type="text/x-handlebars-template">
message:&nbsp;{{bound message}}<br />
{{bound-input-text message}}<br />
{{#button "showMessage"}}alert{{/button}}
</script>
<script>
var elementAddedObserver = function (binding, elmId, event, handler) {
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
if (mutation.type === 'childList' && mutation.addedNodes) {
[].slice.call(mutation.addedNodes).forEach(function (node) {
if (node.id === elmId) {
node.addEventListener(event, handler.bind(binding));
observer.disconnect();
}
}, binding);
}
}, binding);
}, binding);
return observer.observe(
document.querySelector('body'),
{ childList: true, subtree: true }
);
},
objectElementHook = function (obj, elmId, name) {
Object.observe(obj, function (changes) {
var elm = document.getElementById(elmId);
elm[(elm.nodeName === 'B' ? 'innerText' : 'value')] = changes
.filter(function (change) {
return change.name === name;
})
.shift()
.object[name];
});
},
whichName = function (o, value) {
var name = [],
keys = Object.keys(o),
rec = function (key) {
if (({}).toString.call(this[key]) === '[object Object]') {
var keys = Object.keys(this[key]);
name.push(key)
keys.forEach(rec.bind(this[key]));
} else {
if (this[key] === value) {
name.push(key);
} else {
name.pop();
}
}
};
keys.forEach(rec.bind(o));
return name.join('.');
};
Handlebars.registerHelper({
'button': (function () {
var uniq = 0;
return function (value, options) {
var id = '__button__' + (++uniq);
elementAddedObserver(this, id, 'click', function (evt) {
this.events[value].bind(this)();
});
return new Handlebars.SafeString(
'<input ' +
'type="button" ' +
'id="' + id + '" ' +
'value="' + options.fn() + '"' +
'>'
);
};
}()),
'bound-input-text': (function () {
var uniq = 0;
return function (value) {
var id = '__bound-input-text__' + (++uniq),
name = whichName(this, value);
objectElementHook(this, id, name);
elementAddedObserver(this, id, 'change', function (evt) {
this[name] = evt.target.value;
});
return new Handlebars.SafeString(
' <input' +
' type="text"' +
' id="' + id + '"' +
' value="' + value + '"' +
' />'
);
};
}()),
'bound': (function () {
var uniq = 0;
return function (value) {
var id = '__bound__' + (++uniq),
name = whichName(this, value);
objectElementHook(this, id, name);
return new Handlebars.SafeString(
'<b id="' + id + '">' +
value +
'</b>'
);
};
}())
});
var o = {
message: 'inital',
events: {
showMessage: function () {
alert(this.message);
}
}
},
t = Handlebars.compile(document.getElementById('template').innerHTML);
document.querySelector('div').innerHTML = t(o);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment