Commits

Stephen McKamey committed 7324c5f

- adding external view calling and tests
- cleaning up JSDocs

  • Participants
  • Parent commits 843a16e

Comments (0)

Files changed (2)

 /**
- * @fileOverview  duel.js: client-side template engine
+ * @fileoverview  duel.js: client-side template engine
  * 
  * http://duelengine.org
  * 
 	/**
 	 * Wraps a binding result with rendering methods
 	 * 
-	 * @constructor
 	 * @this {Result}
 	 * @param {Array|Object|string} view The result tree
+	 * @constructor
 	 */
 	function Result(view) {
+		/**
+		 * @type {Array|Object|string}
+		 * @const
+		 * @protected
+		 */
 		this.value = view;
 	}
 
 	 * Returns result as DOM objects
 	 * 
 	 * @this {Result}
-	 * @returns {Object}
+	 * @returns {DOMElement}
 	 */
 	Result.prototype.toDOM = function() {
 		return build(this.value);
 	/**
 	 * Wraps a template definition with binding methods
 	 * 
-	 * @constructor
 	 * @this {View}
 	 * @param {Array|Object|string} view The template definition
+	 * @constructor
 	 */
 	function View(view) {
 		/**
-		 * Appends a node to a parent
-		 * 
-		 * @this {View}
-		 * @param {*} model The data item being bound
-		 * @param {Array|Object|string} child The child node
+		 * @type {Array|Object|string}
+		 * @const
+		 * @protected
 		 */
-		this.bind = function(model) {
-			var result = bind(view, model);
-			return new Result(result);
-		};
+		this.value = view;
 	}
 
 	/**
+	 * Binds and wraps the result
+	 * 
+	 * @this {View}
+	 * @param {*} model The data item being bound
+	 * @param {Array|Object|string} child The child node
+	 */
+	View.prototype.bind = function(model) {
+		var result = bind(this.value, model);
+		return new Result(result);
+	};
+
+	/**
+	 * Returns result as HTML text
+	 * 
+	 * @this {Result}
+	 * @returns {string}
+	 */
+	View.prototype.toString = function() {
+		return render(this.value);
+	};
+
+	/**
 	 * Wraps a data value to maintain as raw markup in output
 	 * 
-	 * @constructor
 	 * @this {Markup}
 	 * @param {string} value The value
+	 * @constructor
 	 */
 	function Markup(value) {
+		/**
+		 * @type {string}
+		 * @const
+		 * @protected
+		 */
 		this.value = value;
 	}
 
 	};
 
 	/**
-	 * @constant
+	 * @type {number}
+	 * @const
 	 */
 	var NUL = 0,
 	/**
-	 * @constant
+	 * @type {number}
+	 * @const
 	 */
 	FUN = 1,
 	/**
-	 * @constant
+	 * @type {number}
+	 * @const
 	 */
 	ARY = 2,
 	/**
-	 * @constant
+	 * @type {number}
+	 * @const
 	 */
 	OBJ = 3,
 	/**
-	 * @constant
+	 * @type {number}
+	 * @const
 	 */
 	VAL = 4,
 	/**
-	 * @constant
+	 * @type {number}
+	 * @const
 	 */
 	RAW = 5,
 
 	/**
-	 * @constant
+	 * @type {string}
+	 * @const
 	 */
 	FOR = "$for",
 	/**
-	 * @constant
+	 * @type {string}
+	 * @const
 	 */
 	CHOOSE = "$choose",
 	/**
-	 * @constant
+	 * @type {string}
+	 * @const
 	 */
 	IF = "$if",
 	/**
-	 * @constant
+	 * @type {string}
+	 * @const
 	 */
 	ELSE = "$else",
 	/**
-	 * @constant
+	 * @type {string}
+	 * @const
 	 */
 	CALL = "$call",
 	/**
-	 * @constant
+	 * @type {string}
+	 * @const
 	 */
 	INIT = "$init",
 	/**
-	 * @constant
+	 * @type {string}
+	 * @const
 	 */
 	LOAD = "$load";
 
 	 */
 	function call(node, model, index, count) {
 		var args = node[1];
-		return "TODO";
+		if (!args) {
+			return null;
+		}
+
+		// evaluate the arguments
+		var v = bind(args.view, model, index, count),
+			m = bind(args.model, model, index, count),
+			i = bind(args.index, model, index, count),
+			c = bind(args.count, model, index, count);
+
+		return bind(duel(v).value, m, i, c);
 	}
 
 	/**
 			case FUN:
 				// execute code block
 				result = node(model, index, count);
-
-				while (result instanceof View) {
-					// allow recursively binding templates
-					// useful for creating "switcher" methods
-					result = result.bind(model, index, count);
-				}
 				break;
 
 			case ARY:

File src/tests/bind.js

 test("call view", function() {
 
 	var model = {
-	        details: "<blink>Lorem ipsum dolor sit amet</blink>"
+	        name: "Outer list",
+	        items: ["One", "Two", "Three"]
 	    };
 
-	var view = duel(
-		["div", { "class" : "test" },
-			["p",
-			 	"Description: ",
-			 	function(model, index, count) { return duel.raw(model.details); }
-			]
-		]);
+	var Foo = {
+			itemView: duel(
+					["li",
+					 	"model: ",
+					 	function(model, index, count) { return model; },
+					 	["br"],
+					 	"index: ",
+					 	function(model, index, count) { return index; },
+					 	["br"],
+					 	"count: ",
+					 	function(model, index, count) { return count; },
+					]),
+			listView: duel(
+					["div",
+					 	["h2", function(model, index, count) { return model.name; } ],
+						["ul",
+						 	["$for", { "each" : function(model, index, count) { return model.items; } },
+						 		["$call", {
+							 			"view" : function(model, index, count) { return Foo.itemView; },
+							 			"model" :  function(model, index, count) { return model; },
+							 			"index" :  function(model, index, count) { return index; },
+							 			"count" :  function(model, index, count) { return count; }
+						 			}
+						 		]
+						 	]
+						]
+					])
+			};
 
-	var actual = view.bind(model).value;
+	var actual = Foo.listView.bind(model).value;
 
 	var expected = 
-		["div", { "class" : "test" },
-			["p",
-			 	"Description: ",
-			 	duel.raw("<blink>Lorem ipsum dolor sit amet</blink>")
+		["div",
+		 	["h2", "Outer list" ],
+			["ul",
+				["li",
+					"model: One",
+					["br"],
+					"index: 0",
+					["br"],
+					"count: 3"
+				],
+				["li",
+					"model: Two",
+					["br"],
+					"index: 1",
+					["br"],
+					"count: 3"
+				],
+				["li",
+					"model: Three",
+					["br"],
+					"index: 2",
+					["br"],
+					"count: 3"
+				]
 			]
 		];