/* appjet:version 0.1 */ /* appjet:library */ // Copyright (c) 2009, Herbert Vojčík // Licensed by MIT license (http://www.opensource.org/licenses/mit-license.php) // ====== Rendering context ====== var _stack = []; // ====== API ====== /** * A seq is like DIV() or SPAN() without having attributes and without * any tags rendered. */ function seq(element1, element2, etc) { return new _seq(arguments); } /** * A box is seq, which can have model set via given(model). * By default, model is false. * If a box's model evaluates to false, it renders to ""; otherwise, * it renders normally (eg. renders its contents). */ function box(element1, element2, etc) { return new _box(arguments); } /** * A lazy is an object which calls appropriate function when rendered * to obtain actual object to be rendered. * This function gets actually rendered boxes' models as its arguments, * the innermost model being the first argument, parent being the second, etc. @param f the rendering function. Returns the structure (eg. DIV(), TABLE() or whatever else which you would put inside print()). It should not print() directly. */ function lazy(f) { return new _lazy(f); } // ====== Convenience functions ====== /** Convenience lazy that returns data from model, arguments (if any) denote property chain. */ function data(prop1, prop2, etc) { var args = arguments; return lazy(function(model) { Array.forEach(args, function(p) { model = model[p]; }); return model; }); } /** Convenience lazy that returns data from parent's model, arguments (if any) denote property chain. */ function outerdata(prop1, prop2, etc) { var args = arguments; return lazy(function(model, parent) { Array.forEach(args, function(p) { parent = parent[p]; }); return parent; }); } /** * Convenience proxy lazily representing the box's model. * Use dot notation to lazily represent particular contents of the model, to any depth. */ //var data = _subdata([]); /** * Convenience proxy lazily representing the box's parent's model. * Use dot notation to lazily represent particular contents of the parent's model, to any depth. */ //var outerdata = _subdata([], 1); /** * Convenience lazy that wraps a box and sets its model from supplied value model * (either lazy or plain value). */ function sub(valueModel, box) { return lazy(function() { return box.given(valueModel.valueOf()); }); } /** * Convenience lazy that iteratively repeats a sub-box with elements * of supplied valueModel (either lazy or plain value) set as a sub-boxes' models. */ function iter(valueModel, box) { return lazy(function() { var result = seq(); valueModel.valueOf().forEach(function(element) { result.push(lazy(function() { return box.given(element); })); }); return result; }); } // ====== Workers ====== function _seq(content) { this.push.apply(this, content); } _seq.prototype = object(Array.prototype); _seq.prototype.toHTML = function() { return this.map(toHTML).join(""); }; _seq.prototype.toString = function() { return this.toHTML(); }; function _box(content) { _seq.apply(this, arguments); } _box.prototype = object(_seq.prototype); _box.prototype.model = false; _box.prototype.toHTML = function() { if (!this.model) { return ""; } try { _stack.unshift(this.model); return this.map(toHTML).join(""); } finally { _stack.shift(); } }; /** Sets model for the box. Returns the box. */ _box.prototype.given = function(model) { /** Model of the box */ this.model = model; return this; }; function _lazy(f) { this.f = f; } _lazy.prototype.valueOf = function() { return this.f.apply(null, _stack); }; _lazy.prototype.toHTML = function() { return toHTML(this.valueOf()); }; _lazy.prototype.toString = function() { return this.valueOf().toString(); }; /*function _subdata(props, i) { if (!i) { i = 0; } var valueFun = props.length ? function() { var inner = _stack[i]; props.forEach(function(p) { inner = inner[p]; }); return inner; } : function() { return _stack[i]; }; return appjet._native.createProxyObject( function(p) { switch(p) { case "valueOf": return valueFun; default: return _lazy.prototype[p] || _subdata(props.concat([p]), i); } }, function() {}, function() {}, function() {return [];}, _lazy.prototype ); }*/ /* appjet:server */ import("lib-app/liveui"); print( box( "
", data("hello"), "
<-- div tags should be written", HR(), sub(data("innerwld"), box( "
", outerdata("hello"), ", ", data("foo"), "
<-- here as well" )), UL(iter(data("squares"), box( LI(data("n")," squared is ", data("n2")) ))) ).given({ hello: "hello", innerwld: {foo: "world"}, squares: [1,2,3,4,5].map(function(x) { return { n:x, n2:x*x }; }) }) );