/**
* Element rendering engine.
*/
var tmpl = {
/**
* Renders element by specification.
*
* @param spec
* elements specification
* @return DOM element
*/
render : function(spec) {
var elem = document.createElement(spec[0]);
if (spec.length == 1) {
return elem;
}
var maybeAttrs = spec[1];
var n = 2;
if (this._isHash(maybeAttrs)) {
this._applyAttrs(elem, maybeAttrs);
} else {
n = 1;
}
while (n < spec.length) {
this._makeElem(elem, spec[n++]);
}
return elem;
},
/**
* Sets element attributes.
*
* @param e
* element to set attributes
* @param attrs
* attributes object
*/
_applyAttrs : function(e, attrs) {
for (attr in attrs) {
if (attrs.hasOwnProperty(attr)) {
e.setAttribute(attr, attrs[attr]);
}
}
},
/**
* Creates nested node.
*
* @param elem
* element insert node to
* @param x
* value to create node from
* @return DOM node
*/
_makeElem : function(elem, x) {
var type = typeof (x);
var i = 0;
if (type == "string") {
elem.appendChild(document.createTextNode(x));
} else if (x instanceof Array) {
// flatten array of nested elements
if (x[0] instanceof Array) {
while (i < x.length) {
this._makeElem(elem, x[i++]);
}
} else {
elem.appendChild(this.render(x));
}
} else if (x instanceof Function) {
this._makeElem(elem, x.apply(null));
}
},
/**
* Checks whether it's argument a hash or not.
*
* @param x
* value to test
* @return true if object is a hash, false otherwise
*/
_isHash : function(x) {
return typeof (x) == "object" && !(x instanceof Array);
}
};
ICAgICAgICAvKioKICAgICAgICAgKiBFbGVtZW50IHJlbmRlcmluZyBlbmdpbmUuCiAgICAgICAgICovCiAgICAgICAgdmFyIHRtcGwgPSB7CiAgICAgICAgICAgIC8qKgogICAgICAgICAgICAgKiBSZW5kZXJzIGVsZW1lbnQgYnkgc3BlY2lmaWNhdGlvbi4KICAgICAgICAgICAgICogCiAgICAgICAgICAgICAqIEBwYXJhbSBzcGVjCiAgICAgICAgICAgICAqICAgICAgICAgIGVsZW1lbnRzIHNwZWNpZmljYXRpb24KICAgICAgICAgICAgICogQHJldHVybiBET00gZWxlbWVudAogICAgICAgICAgICAgKi8KICAgICAgICAgICAgcmVuZGVyIDogZnVuY3Rpb24oc3BlYykgewogICAgICAgICAgICAgICAgdmFyIGVsZW0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KHNwZWNbMF0pOwogICAgICAgICAgICAgICAgaWYgKHNwZWMubGVuZ3RoID09IDEpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gZWxlbTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHZhciBtYXliZUF0dHJzID0gc3BlY1sxXTsKICAgICAgICAgICAgICAgIHZhciBuID0gMjsKICAgICAgICAgICAgICAgIGlmICh0aGlzLl9pc0hhc2gobWF5YmVBdHRycykpIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLl9hcHBseUF0dHJzKGVsZW0sIG1heWJlQXR0cnMpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBuID0gMTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHdoaWxlIChuIDwgc3BlYy5sZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLl9tYWtlRWxlbShlbGVtLCBzcGVjW24rK10pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgcmV0dXJuIGVsZW07CiAgICAgICAgICAgIH0sCgogICAgICAgICAgICAvKioKICAgICAgICAgICAgICogU2V0cyBlbGVtZW50IGF0dHJpYnV0ZXMuCiAgICAgICAgICAgICAqIAogICAgICAgICAgICAgKiBAcGFyYW0gZQogICAgICAgICAgICAgKiAgICAgICAgICBlbGVtZW50IHRvIHNldCBhdHRyaWJ1dGVzCiAgICAgICAgICAgICAqIEBwYXJhbSBhdHRycwogICAgICAgICAgICAgKiAgICAgICAgICBhdHRyaWJ1dGVzIG9iamVjdAogICAgICAgICAgICAgKi8KICAgICAgICAgICAgX2FwcGx5QXR0cnMgOiBmdW5jdGlvbihlLCBhdHRycykgewogICAgICAgICAgICAgICAgZm9yIChhdHRyIGluIGF0dHJzKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJzLmhhc093blByb3BlcnR5KGF0dHIpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGUuc2V0QXR0cmlidXRlKGF0dHIsIGF0dHJzW2F0dHJdKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCgogICAgICAgICAgICAvKioKICAgICAgICAgICAgICogQ3JlYXRlcyBuZXN0ZWQgbm9kZS4KICAgICAgICAgICAgICogCiAgICAgICAgICAgICAqIEBwYXJhbSBlbGVtCiAgICAgICAgICAgICAqICAgICAgICAgIGVsZW1lbnQgaW5zZXJ0IG5vZGUgdG8KICAgICAgICAgICAgICogQHBhcmFtIHgKICAgICAgICAgICAgICogICAgICAgICAgdmFsdWUgdG8gY3JlYXRlIG5vZGUgZnJvbQogICAgICAgICAgICAgKiBAcmV0dXJuIERPTSBub2RlCiAgICAgICAgICAgICAqLwogICAgICAgICAgICBfbWFrZUVsZW0gOiBmdW5jdGlvbihlbGVtLCB4KSB7CiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZiAoeCk7CiAgICAgICAgICAgICAgICB2YXIgaSA9IDA7CiAgICAgICAgICAgICAgICBpZiAodHlwZSA9PSAic3RyaW5nIikgewogICAgICAgICAgICAgICAgICAgIGVsZW0uYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoeCkpOwogICAgICAgICAgICAgICAgfSBlbHNlIGlmICh4IGluc3RhbmNlb2YgQXJyYXkpIHsKICAgICAgICAgICAgICAgICAgICAvLyBmbGF0dGVuIGFycmF5IG9mIG5lc3RlZCBlbGVtZW50cwogICAgICAgICAgICAgICAgICAgIGlmICh4WzBdIGluc3RhbmNlb2YgQXJyYXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGkgPCB4Lmxlbmd0aCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fbWFrZUVsZW0oZWxlbSwgeFtpKytdKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW0uYXBwZW5kQ2hpbGQodGhpcy5yZW5kZXIoeCkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoeCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbWFrZUVsZW0oZWxlbSwgeC5hcHBseShudWxsKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCgogICAgICAgICAgICAvKioKICAgICAgICAgICAgICogQ2hlY2tzIHdoZXRoZXIgaXQncyBhcmd1bWVudCBhIGhhc2ggb3Igbm90LgogICAgICAgICAgICAgKiAKICAgICAgICAgICAgICogQHBhcmFtIHgKICAgICAgICAgICAgICogICAgICAgICAgdmFsdWUgdG8gdGVzdAogICAgICAgICAgICAgKiBAcmV0dXJuIHRydWUgaWYgb2JqZWN0IGlzIGEgaGFzaCwgZmFsc2Ugb3RoZXJ3aXNlCiAgICAgICAgICAgICAqLwogICAgICAgICAgICBfaXNIYXNoIDogZnVuY3Rpb24oeCkgewogICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiAoeCkgPT0gIm9iamVjdCIgJiYgISh4IGluc3RhbmNlb2YgQXJyYXkpOwogICAgICAgICAgICB9CiAgICAgICAgfTs=