@quenk/wml-runtime
Version:
Runtime for compiled wml files.
267 lines • 8.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var property = require("property-seek");
var Maybe_1 = require("afpl/lib/monad/Maybe");
;
/**
* Component is an abstract Widget implementation
* that can be used instead of manually implementing the whole interface.
*
*/
var Component = (function () {
/**
* attrs is the attributes this Component excepts.
*/
/**
* children is an array of content passed to this Component.
*/
function Component(attrs, children) {
this.attrs = attrs;
this.children = children;
}
Component.prototype.rendered = function () { };
Component.prototype.removed = function () { };
Component.prototype.render = function () { return this.view.render(); };
return Component;
}());
exports.Component = Component;
;
/**
* read a value form an object.
*
* This is an alternative to regular property access that will throw exceptions
* if any of the values in the part are null.
* @param {string} path - The path to look up on the object.
* @param {object} o - The object
* @param {A} [defaultValue] - This value is returned if the value is not set.
* @private
*/
exports.read = function (path, o, defaultValue) {
var ret = property.get(path.split(':').join('.'), o);
return (ret != null) ? ret : defaultValue;
};
/**
* @private
*/
var adopt = function (child, e) {
switch (typeof child) {
case 'string':
case 'number':
case 'boolean':
e.appendChild(document.createTextNode('' + child));
case 'object':
e.appendChild(child);
break;
default:
throw new TypeError("Can not adopt child " + child + " of type " + typeof child);
}
};
/**
* @private
*/
exports.box = function () {
var content = [];
for (var _i = 0; _i < arguments.length; _i++) {
content[_i] = arguments[_i];
}
var frag = document.createDocumentFragment();
content.forEach(function (c) { return frag.appendChild(c); });
return frag;
};
/**
* @private
*/
exports.domify = function (a) {
if (a instanceof Array) {
return exports.box.apply(null, a.map(exports.domify));
}
else if ((typeof a === 'string') ||
(typeof a === 'number') ||
(typeof a === 'boolean')) {
return exports.text(a);
}
else if (a instanceof Node) {
return a;
}
else if (a == null) {
return _empty;
}
else {
throw new TypeError("Can not use '" + a + "'(typeof " + typeof a + ") as Content!");
}
};
/**
* @private
*/
var _empty = document.createDocumentFragment();
/**
* @private
*/
exports.empty = function () { return _empty; };
/**
* text creates a new TextNode.
* @private
*/
exports.text = function (value) {
return document.createTextNode('' + value);
};
/**
* node is called to create a regular DOM node
* @private
*/
exports.node = function (tag, attributes, children, view) {
var e = document.createElement(tag);
if (typeof attributes['html'] === 'object')
Object.keys(attributes['html']).forEach(function (key) {
var value = attributes['html'][key];
if (typeof value === 'function') {
e[key] = value;
}
else if (typeof value === 'string') {
if (value !== '')
e.setAttribute(key, value);
}
else if (typeof value === 'boolean') {
e.setAttribute(key, "" + value);
}
});
children.forEach(function (c) { return adopt(c, e); });
var id = attributes['wml'].id;
var group = attributes.wml.group;
if (id)
view.register(id, e);
if (group)
view.registerGroup(group, e);
return e;
};
/**
* widget creates and renders a new wml widget instance.
* @param {function} Construtor
* @param {object} attributes
* @param {array<string|number|Widget>} children
* @param {View} view
* @private
* @return {Widget}
*/
exports.widget = function (Constructor, attributes, children, view) {
var childs = [];
var w;
children.forEach(function (child) { return (child instanceof Array) ?
childs.push.apply(childs, child) : childs.push(child); });
w = new Constructor(attributes, childs);
var id = attributes.wml.id;
var group = attributes.wml.group;
if (id)
view.register(id, w);
if (group)
view.registerGroup(group, w);
view.widgets.push(w);
return w.render();
};
/**
* ifE provides an if then expression
* @private
*/
exports.ifE = function (predicate, positive, negative) {
return (predicate) ? positive() : negative();
};
/**
* forE provides a for expression
* @private
*/
exports.forE = function (collection, cb, cb2) {
var frag = document.createDocumentFragment();
if (collection instanceof Array) {
if (collection.length > 0)
collection.forEach(function (v, k, a) { return frag.appendChild(cb(v, k, a)); });
else
frag.appendChild(cb2());
}
else if (typeof collection === 'object') {
var l = Object.keys(collection);
if (l.length > 0)
l.forEach(function (k) { return frag.appendChild(cb(collection[k], k, collection)); });
else
frag.appendChild(cb2());
}
return frag;
};
/**
* switchE simulates a switch statement
* @param {string|number|boolean} value
* @param {object} cases
* @private
*/
exports.switchE = function (value, cases) {
var result = cases[value];
var defaul = cases['default'];
if (result)
return result;
if (defaul)
return defaul;
};
/**
* AppView is the concrete implementation of a View.
*
* @property {<C>} context - The context the view is rendered in.
*/
var AppView = (function () {
function AppView(context) {
this.context = context;
this.ids = {};
this.groups = {};
this.widgets = [];
}
AppView.prototype.register = function (id, w) {
if (this.ids.hasOwnProperty(id))
throw new Error("Duplicate id '" + id + "' detected!");
this.ids[id] = w;
return this;
};
AppView.prototype.registerGroup = function (group, e) {
this.groups[group] = this.groups[group] || [];
this.groups[group].push(e);
return this;
};
AppView.prototype.findById = function (id) {
return Maybe_1.Maybe.fromAny(this.ids[id]);
};
AppView.prototype.findGroupByName = function (name) {
return Maybe_1.Maybe.fromArray(this.groups[name]);
};
AppView.prototype.invalidate = function () {
var childs;
var realFirstChild;
var realFirstChildIndex;
var tree = (this._fragRoot) ? this._fragRoot : this.tree;
var parent = tree.parentNode;
if (tree == null)
throw new ReferenceError('Cannot invalidate a view that has not been rendered!');
if (tree.parentNode == null)
throw new ReferenceError('Attempt to invalidate a view that has not been inserted to DOM!');
childs = tree.parentNode.children;
//for some reason the reference stored does not have the correct parent node.
//we do this to get a 'live' version of the node.
for (var i = 0; i < childs.length; i++)
if (childs[i] === tree) {
realFirstChild = childs[i];
realFirstChildIndex = i;
}
parent.replaceChild(this.render(), realFirstChild);
};
AppView.prototype.render = function () {
this.ids = {};
this.widgets.forEach(function (w) { return w.removed(); });
this.widgets = [];
this._fragRoot = null;
this.tree = this.template(this, this.context);
this.ids['root'] = (this.ids['root']) ? this.ids['root'] : this.tree;
if (this.tree.nodeName === (document.createDocumentFragment()).nodeName)
this._fragRoot = this.tree.firstChild;
this.widgets.forEach(function (w) { return w.rendered(); });
return this.tree;
};
return AppView;
}());
exports.AppView = AppView;
//# sourceMappingURL=index.js.map