diff --git a/jquery.views.js b/jquery.views.js
index 83241ae..03c7082 100644
--- a/jquery.views.js
+++ b/jquery.views.js
@@ -7,7 +7,7 @@
* Copyright 2012, Boris Moore
* Released under the MIT License.
*/
-// informal pre beta commit counter: 14
+// informal pre beta commit counter: 15
this.jQuery && jQuery.link || (function(global, undefined) {
// global is the this object, which is window when running in the usual browser environment.
@@ -21,9 +21,10 @@ this.jQuery && jQuery.link || (function(global, undefined) {
// jsviews object (=== $.views) Note: JsViews requires jQuery is loaded)
jsv = $.views,
+ extend = $.extend,
sub = jsv.sub,
FALSE = false, TRUE = true, NULL = null,
- topView = jsv.topView,
+ topView = new jsv.View(jsv.helpers),
templates = jsv.templates,
observable = $.observable,
jsvData = "_jsvData",
@@ -223,8 +224,8 @@ this.jQuery && jQuery.link || (function(global, undefined) {
? attr.to.toAttr
: attr.from.fromAttr)
: to
- ? "text"
- : "";
+ ? "text" // Default is to bind to innerText. Use html{:...} to bind to innerHTML
+ : ""; // Default is not to bind from
}
function returnVal(value) {
@@ -331,7 +332,7 @@ this.jQuery && jQuery.link || (function(global, undefined) {
// Compile the linkFn expression which evaluates and binds a data-link expression
// TODO - optimize for the case of simple data path with no conversion, helpers, etc.:
// i.e. data-link="a.b.c". Avoid creating new instances of Function every time. Can use a default function for all of these...
- link[attr] = jsv.tmplFn(delimOpenChar0 + expression + delimCloseChar1, undefined, TRUE);
+ link[attr] = jsv._tmplFn(delimOpenChar0 + expression + delimCloseChar1, undefined, TRUE);
if (!attr && convertBack !== undefined) {
link[attr].to = convertBack;
}
@@ -744,7 +745,7 @@ this.jQuery && jQuery.link || (function(global, undefined) {
// Extend and initialize the view object created in JsRender, as a JsViews view
view = self.views[key];
if (!view.link) {
- $.extend(view, LinkedView);
+ extend(view, LinkedView);
view.parentElem = parentElem;
view._prevNode = node;
@@ -953,12 +954,10 @@ this.jQuery && jQuery.link || (function(global, undefined) {
$.fn.view = function(node){
return $.view(this[0]);
}
-
// Initialize default delimiters
jsv.delimiters();
- topView._lnk = 0;
- topView.links = [];
- $.extend(topView, LinkedView);
+ extend(topView, { tmpl: {}, _lnk: 0, links: [] });
+ extend(topView, LinkedView);
})(this);
diff --git a/jsrender.js b/jsrender.js
index d3f8a3a..04adab1 100644
--- a/jsrender.js
+++ b/jsrender.js
@@ -6,7 +6,7 @@
* Copyright 2012, Boris Moore
* Released under the MIT License.
*/
-// informal pre beta commit counter: 14
+// informal pre beta commit counter: 15
this.jsviews || this.jQuery && jQuery.views || (function(global, undefined) {
@@ -50,21 +50,20 @@ this.jsviews || this.jQuery && jQuery.views || (function(global, undefined) {
jsviews: versionNumber,
sub: sub, // subscription, e.g. JsViews integration
debugMode: TRUE,
- err: function(e) {
- return jsv.debugMode ? ("
Error: " + (e.message || e) + ". ") : '""';
- },
- tmplFn: tmplFn,
render: render,
templates: templates,
tags: tags,
helpers: helpers,
converters: converters,
View: View,
- convert: convert,
delimiters: setDelimiters,
- tag: renderTag
+ _convert: convert,
+ _err: function(e) {
+ return jsv.debugMode ? ("
Error: " + (e.message || e) + ". ") : '""';
+ },
+ _tmplFn: tmplFn,
+ _tag: renderTag
};
-
//========================== Top-level functions ==========================
//===================
@@ -118,8 +117,8 @@ this.jsviews || this.jQuery && jQuery.views || (function(global, undefined) {
// jsviews.convert
//=================
- function convert(converter, view, text) {
- var tmplConverters = view.tmpl.converters;
+ function convert(converter, view, tmpl, text) {
+ var tmplConverters = tmpl.converters;
converter = tmplConverters && tmplConverters[converter] || converters[converter];
return converter ? converter.call(view, text) : text;
}
@@ -128,13 +127,13 @@ this.jsviews || this.jQuery && jQuery.views || (function(global, undefined) {
// jsviews.tag
//=================
- function renderTag(tag, parentView, converter, content, tagObject) {
+ function renderTag(tag, parentView, parentTmpl, converter, content, tagObject) {
// Called from within compiled template function, to render a nested tag
// Returns the rendered tag
var ret,
+ tmplTags = parentTmpl.tags,
+ nestedTemplates = parentTmpl.templates,
tmpl = tagObject.props && tagObject.props.tmpl,
- tmplTags = parentView.tmpl.tags,
- nestedTemplates = parentView.tmpl.templates,
args = arguments,
tagFn = tmplTags && tmplTags[tag] || tags[tag];
@@ -142,7 +141,7 @@ this.jsviews || this.jQuery && jQuery.views || (function(global, undefined) {
return "";
}
// Set the tmpl property to the content of the block tag, unless set as an override property on the tag
- content = content && parentView.tmpl.tmpls[content - 1];
+ content = content && parentTmpl.tmpls[content - 1];
tmpl = tmpl || content || undefined;
tagObject.tmpl =
@@ -155,7 +154,7 @@ this.jsviews || this.jQuery && jQuery.views || (function(global, undefined) {
tagObject.view = parentView;
tagObject.renderContent = renderContent;
- ret = tagFn.apply(tagObject, args.length > 5 ? slice.call(args, 5) : []);
+ ret = tagFn.apply(tagObject, args.length > 6 ? slice.call(args, 6) : []);
return ret || (ret == undefined ? "" : ret.toString()); // (If ret is the value 0 or false, will render to string)
}
@@ -165,7 +164,7 @@ this.jsviews || this.jQuery && jQuery.views || (function(global, undefined) {
function View(context, path, parentView, data, template, key, onRender, isArray) {
// Constructor for view object in view hierarchy. (Augmented by JsViews if JsViews is loaded)
- var views = parentView.views,
+ var views,
self = {
tmpl: template,
path: path,
@@ -180,20 +179,23 @@ this.jsviews || this.jQuery && jQuery.views || (function(global, undefined) {
_onRender: onRender
};
- if (parentView.isArray) {
- // Parent is an 'Array View'. Add this view to its views array
- views.splice(
- // self.key = self.key - the index in the parent view array
- self.key = self.index = key !== undefined
- ? key
- : views.length,
- 0, self);
- } else {
- // Parent is an 'Instance View'. Add this view to its views object
- // self.key = is the key in the parent view map
- views[self.key = "_" + autoViewKey++] = self;
- // self.index = is index of the parent
- self.index = parentView.index;
+ if (parentView) {
+ views = parentView.views;
+ if (parentView.isArray) {
+ // Parent is an 'Array View'. Add this view to its views array
+ views.splice(
+ // self.key = self.key - the index in the parent view array
+ self.key = self.index = key !== undefined
+ ? key
+ : views.length,
+ 0, self);
+ } else {
+ // Parent is an 'Instance View'. Add this view to its views object
+ // self.key = is the key in the parent view map
+ views[self.key = "_" + autoViewKey++] = self;
+ // self.index = is index of the parent
+ self.index = parentView.index;
+ }
}
return self;
}
@@ -301,36 +303,35 @@ this.jsviews || this.jQuery && jQuery.views || (function(global, undefined) {
key = key || self.key;
props = self.props;
} else {
- tmpl = self.jquery && self[0] // This is a call $.fn.render
+ tmpl = self.jquery && self[0] // This is a call from $(selector).render
|| self; // This is a call from tmpl.render
}
- parentView = parentView || jsv.topView;
- parentContext = parentView.ctx;
if (tmpl) {
- if (data === parentView) {
- // Inherit the data from the parent view.
- // This may be the contents of an {{if}} block
- // Set isLayout = true so we don't iterate the if block if the data is an array.
- data = parentView.data;
- isLayout = TRUE;
+ if (parentView) {
+ parentContext = parentView.ctx;
+ if (data === parentView) {
+ // Inherit the data from the parent view.
+ // This may be the contents of an {{if}} block
+ // Set isLayout = true so we don't iterate the if block if the data is an array.
+ data = parentView.data;
+ isLayout = TRUE;
+ }
+ onRender = onRender || parentView._onRender;
+ } else {
+ parentContext = jsv.helpers;
}
// Set additional context on views created here, (as modified context inherited from the parent, and to be inherited by child views)
// Note: If no jQuery, extend does not support chained copies - so limit extend() to two parameters
// TODO could make this a reusable helper for merging context.
- context = (context && context === parentContext)
- ? parentContext
- : context
- // If context, merge context with copied parentContext
- ? extend(extend({}, parentContext), context)
- : parentContext;
+ context = (context && context !== parentContext)
+ ? extend(extend({}, parentContext), context)
+ : parentContext;
if (!tmpl.fn) {
tmpl = templates[tmpl] || templates(tmpl);
}
- onRender = onRender || parentView._onRender;
-
if (tmpl) {
if ($.isArray(data) && !isLayout) {
// Create a view for the array, whose child views correspond to each data item.
@@ -349,7 +350,6 @@ this.jsviews || this.jQuery && jQuery.views || (function(global, undefined) {
newView._onRender = onRender;
result += tmpl.fn(data, newView, jsv);
}
- parentView.topKey = newView.key;
return onRender ? onRender(result, tmpl, props, newView.key, path) : result;
}
}
@@ -497,10 +497,10 @@ this.jsviews || this.jQuery && jQuery.views || (function(global, undefined) {
? (converter === "html"
? (hasEncoder = TRUE, "e(" + params)
: converter
- ? (hasConverter = TRUE, 'c("' + converter + '",view,' + params)
+ ? (hasConverter = TRUE, 'c("' + converter + '",view,this,' + params)
: (getsValue = TRUE, "((v=" + params + ')!=u?v:""')
)
- : (hasTag = TRUE, 't("' + tag + '",view,"' + (converter || "") + '",'
+ : (hasTag = TRUE, 't("' + tag + '",view,this,"' + (converter || "") + '",'
+ (content ? nested.length : '""') // For block tags, pass in the key (nested.length) to the nested content template
+ "," + hash + (params ? "," : "") + params))
+ ")+";
@@ -508,15 +508,15 @@ this.jsviews || this.jQuery && jQuery.views || (function(global, undefined) {
}
code = fnDeclStr
+ (getsValue ? "v," : "")
- + (hasTag ? "t=j.tag," : "")
- + (hasConverter ? "c=j.convert," : "")
+ + (hasTag ? "t=j._tag," : "")
+ + (hasConverter ? "c=j._convert," : "")
+ (hasEncoder ? "e=j.converters.html," : "")
+ "ret; try{\n\n"
+ (tmplOptions.debug ? "debugger;" : "")
+ (allowCode ? 'ret=' : 'return ')
+ code.slice(0, -1) + ";\n\n"
+ (allowCode ? "return ret;" : "")
- + "}catch(e){return j.err(e);}";
+ + "}catch(e){return j._err(e);}";
try {
code = new Function("data, view, j, b, u", code);
@@ -527,7 +527,6 @@ this.jsviews || this.jQuery && jQuery.views || (function(global, undefined) {
// Include only the var references that are needed in the code
if (tmpl) {
tmpl.fn = code;
- tmpl.useVw = hasConverter || hasViewPath || hasTag;
}
return code;
}
@@ -800,8 +799,6 @@ this.jsviews || this.jQuery && jQuery.views || (function(global, undefined) {
extend = $.extend;
- jsv.topView = { views: {}, tmpl: {}, _hlp: getHelper, ctx: jsv.helpers };
-
function replacerForHtml(ch) {
// Original code from Mike Samuel
return escapeMapForHtml[ch]