Modified:
trunk/jsevalcontext.js
trunk/jstemplate.js
trunk/jstemplate_test.js
trunk/util.js
Log:
Adding support for the $count variable
Modified: trunk/jsevalcontext.js
==============================================================================
--- trunk/jsevalcontext.js (original)
+++ trunk/jsevalcontext.js Tue Aug 19 13:47:00 2008
@@ -25,6 +25,7 @@
* attributes.
*/
var VAR_index = '$index';
+var VAR_count = '$count';
var VAR_this = '$this';
var VAR_context = '$context';
var VAR_top = '$top';
@@ -243,12 +244,16 @@
*
* @param {number} index Position of the new context when multiply
* instantiated. (See implementation of jstSelect().)
+ *
+ * @param {number} count The total number of contexts that were multiply
+ * instantiated. (See implementation of jstSelect().)
*
* @return {JsEvalContext}
*/
-JsEvalContext.prototype.clone = function(data, index) {
+JsEvalContext.prototype.clone = function(data, index, count) {
var ret = JsEvalContext.create(data, this);
ret.setVariable(VAR_index, index);
+ ret.setVariable(VAR_count, count);
return ret;
};
Modified: trunk/jstemplate.js
==============================================================================
--- trunk/jstemplate.js (original)
+++ trunk/jstemplate.js Tue Aug 19 13:47:00 2008
@@ -111,10 +111,10 @@
*/
processor.document_ = ownerDocument(template);
- processor.run_(eventCallbackArgs(processor, processor.jstProcessOuter_,
- context, template));
+ processor.run_(bindFully(processor, processor.jstProcessOuter_,
+ context, template));
if (MAPS_DEBUG && opt_debugging) {
- logHtml('jstProcess:' + '<br/>' + processor.getLogs().join('<br/>'));
+ log('jstProcess:' + '\n' + processor.getLogs().join('\n'));
}
}
@@ -615,7 +615,8 @@
// also matches input data with a length property, so this property
// name should be avoided in input data.
var multiple = isArray(value);
- var multipleEmpty = (multiple && value.length == 0);
+ var count = multiple ? jsLength(value) : 1;
+ var multipleEmpty = (multiple && count == 0);
if (multiple) {
if (multipleEmpty) {
@@ -644,36 +645,37 @@
// essential, because 0 == "", presumably via type coercion to
// boolean.
if (instance === null || instance === STRING_empty ||
- (instanceLast && instance < jsLength(value) - 1)) {
+ (instanceLast && instance < count - 1)) {
// A queue of calls to push.
var queue = me.createArray_();
var instancesStart = instance || 0;
var i, I, clone;
- for (i = instancesStart, I = jsLength(value) - 1;
- i < I; ++i) {
+ for (i = instancesStart, I = count - 1; i < I; ++i) {
var node = domCloneNode(template);
domInsertBefore(node, template);
jstSetInstance(/** @type Element */(node), value, i);
- clone = context.clone(value[i], i);
+ clone = context.clone(value[i], i, count);
+
queue.push(me.jstProcessInner_, clone, node,
JsEvalContext.recycle, clone, null);
+
}
// Push the originally present template instance last to keep
// the order aligned with the DOM order, because the newly
// created template instances are inserted *before* the
// original instance.
jstSetInstance(template, value, i);
- clone = context.clone(value[i], i);
+ clone = context.clone(value[i], i, count);
queue.push(me.jstProcessInner_, clone, template,
JsEvalContext.recycle, clone, null);
me.push_(queue);
- } else if (instance < jsLength(value)) {
+ } else if (instance < count) {
var v = value[instance];
jstSetInstance(template, value, instance);
- var clone = context.clone(v, instance);
+ var clone = context.clone(v, instance, count);
var queue = me.createArray_();
queue.push(me.jstProcessInner_, clone, template,
JsEvalContext.recycle, clone, null);
@@ -687,7 +689,7 @@
displayNone(template);
} else {
displayDefault(template);
- var clone = context.clone(value, 0);
+ var clone = context.clone(value, 0, 1);
var queue = me.createArray_();
queue.push(me.jstProcessInner_, clone, template,
JsEvalContext.recycle, clone, null);
@@ -891,7 +893,7 @@
*/
function jstGetTemplateOrDie(name, opt_loadHtmlFn) {
var x = jstGetTemplate(name, opt_loadHtmlFn);
- check(x != null);
+ check(x !== null);
return /** @type Element */(x);
}
@@ -929,8 +931,8 @@
* Loads the given HTML text into the given document, so that
* jstGetTemplate can find it.
*
- * We append it a div named jsts, which is hidden. If it doesn't
- * exist, it is created.
+ * We append it to the element identified by targetId, which is hidden.
+ * If it doesn't exist, it is created.
*
* @param {Document} doc The document to create the template in.
*
@@ -945,7 +947,7 @@
var target;
if (!existing_target) {
target = domCreateElement(doc, STRING_div);
- target.id = target;
+ target.id = targetId;
displayNone(target);
positionAbsolute(target);
domAppendChild(doc.body, target);
Modified: trunk/jstemplate_test.js
==============================================================================
--- trunk/jstemplate_test.js (original)
+++ trunk/jstemplate_test.js Tue Aug 19 13:47:00 2008
@@ -231,10 +231,27 @@
}
function testJstLoadTemplate() {
+ var wrapperId = 'testJstLoadTemplateWrapper';
var id = 'testJstLoadTemplate';
- jstLoadTemplate_(document, '<div id="' + id + '">content</div>');
+ jstLoadTemplate_(document, '<div id="' + id + '">content</div>',
wrapperId);
+ var wrapperElem = document.getElementById(wrapperId);
+ assertTrue('Expected wrapper element to be in document',
+ !!wrapperElem);
+ var newTemplate = document.getElementById(id);
assertTrue('Expected newly loaded template to be in document',
- !!document.getElementById(id));
+ !!newTemplate);
+ assertTrue('Expected wrapper to be grandparent of template',
+ newTemplate.parentNode.parentNode == wrapperElem);
+
+ // Make sure the next template loaded with the same wrapper id re-uses
the
+ // wrapper element.
+ var id2 = 'testJstLoadTemplate2';
+ jstLoadTemplate_(document, '<div id="' + id2 + '">content</div>',
wrapperId);
+ var newTemplate2 = document.getElementById(id2);
+ assertTrue('Expected newly loaded template to be in document',
+ !!newTemplate2);
+ assertTrue('Expected wrapper to be grandparent of template',
+ newTemplate2.parentNode.parentNode == wrapperElem);
}
function testJstGetTemplateFromDom() {
Modified: trunk/util.js
==============================================================================
--- trunk/util.js (original)
+++ trunk/util.js Tue Aug 19 13:47:00 2008
@@ -158,14 +158,17 @@
/**
- * Returns an event handler that calls the method on the given object
- * with the given arguments.
+ * Prebinds "this" within the given method to an object, but ignores all
+ * arguments passed to the resulting function.
+ * I.e. var_args are all the arguments that method is invoked with when
+ * invoking the bound function.
*
- * @param {Object|null} object Observer object.
- * @param {Function} method Observer method.
- * @return {Function} Resulting handler.
+ * @param {Object|null} object The object that the method call targets.
+ * @param {Function} method The target method.
+ * @return {Function} Method with the target object bound to it and
curried by
+ * the provided arguments.
*/
-function eventCallbackArgs(object, method, var_args) {
+function bindFully(object, method, var_args) {
var args = arraySlice(arguments, 2);
return function() {
return method.apply(object, args);