From d3e2011486fe0c37316248d21f615df26cbb7c3b Mon Sep 17 00:00:00 2001 From: BorisMoore Date: Fri, 21 Sep 2018 17:19:23 -0700 Subject: [PATCH] Commit 91 (v0.9.91 - Beta) Major update Breaking change - Templates declared in
or other non script element are not supported. (Throws with error message) Minor breaking changes - The {{range}} tag has been removed - replaced by {{for}} tag using built-in range features. See https://www.jsviews.com#jsvfortag@jsvsortfilterrange Major feature improvements - The {{for}} tag now has built-in support for sort, filter, start and end. See https://www.jsviews.com#fortag@sortfilterrange - The {{props}} tag now has built-in support for sort, filter, start and end. See https://www.jsviews.com#propstag@sortfilterrange - New converters encode/unencode. See https://www.jsviews.com#convertersapi@encode - New tag options: bindFrom - together with tag option bindTo - provide improved features for custom tags. See https://www.jsviews.com#tagoptions@bindto and https://www.jsviews.com#tagoptions@bindfrom Minor feature improvements - New APIs added for tagCtx.ctxPrm(), tagCtx.cvtArgs() and tagCtx.bndArgs() even for non-data-linked tags - documentation to follow - The contentCtx option now works also for custom tag using render(), rather than a template. See https://www.jsviews.com#tagsapi@contentctx - In a template, ~tag.tagCtx.xxx can now be written ~tagCtx.xxx, and works correctly e.g. for data-linking using {{mytag}}{{else}}{{~tagCtx...}}{{/mytag}} - documentation to follow - ~tagCtx is now a reserved name like ~tag ~root ~parentTags... - New debug:true option on a compiled template. See https://www.jsviews.com#d.templates@debug - An error will be thrown if different versions of jsrender.js, jquery.observable.js and jquery.views.js are loaded together - DataMap, {{props}} and {{jsonview}} now include support for function properties too, unless opt out using {{props foo noFunctions=true}}. See https://www.jsviews.com#propstag@nofunctions - Support for nested {{for}} tags without iteration, and for then applying operations such as sorting to arrays in nexted context, as in {{for filter=... noIteration=true}}{{for sort=... noIteration=true}}{{for start=... end=...}}. See https://www.jsviews.com#fortag@itemvar Documentation - Extensive new documentation, especially on custom tag controls: See https://www.jsviews.com#jsvtagcontrols. For an example of a JsViews custom tag control see https://www.jsviews.com#samples/tag-controls/colorpicker Minor bug fixes, including: - a contentEditable bug for IE - a bug in jquery-1.x cleanData - Issue https://github.com/BorisMoore/jsviews/issues/404 Props Convert else statement not working - Issue https://github.com/BorisMoore/jsviews/issues/403 ~ operator support - Issue https://github.com/BorisMoore/jsviews/issues/400 Move the tag property in views to before rendering, to enable "get current path" path scenario - Issue https://github.com/BorisMoore/jsrender/issues/335 encode and unencode converters --- jsrender-node.js | 759 ++- jsrender.js | 773 ++- jsrender.min.js | 4 +- jsrender.min.js.map | 2 +- package.json | 4 +- test/browserify/bundles/1-bundle.js | 775 ++- test/browserify/bundles/12-nested-bundle.js | 775 ++- test/browserify/bundles/2-bundle.js | 4539 ++++++++++------- test/browserify/bundles/3-bundle.js | 4539 ++++++++++------- .../bundles/htm-jsrender-tmpl-bundle.js | 773 ++- .../bundles/html-jsr-tmpl-bundle.js | 773 ++- test/unit-tests/requirejs-config.js | 2 +- test/unit-tests/tests-jsrender-no-jquery.js | 218 +- test/unit-tests/tests-jsrender-with-jquery.js | 9 +- tmplify/index.js | 2 +- 15 files changed, 8844 insertions(+), 5103 deletions(-) diff --git a/jsrender-node.js b/jsrender-node.js index bc56d09..64115c2 100644 --- a/jsrender-node.js +++ b/jsrender-node.js @@ -1,11 +1,11 @@ -/*! JsRender v0.9.90 (Beta): http://jsviews.com/#jsrender */ +/*! JsRender v0.9.91 (Beta): http://jsviews.com/#jsrender */ /*! **VERSION FOR NODE.JS** (For WEB see http://jsviews.com/download/jsrender.js) */ /* * Best-of-breed templating in browser or on Node.js. * Does not require jQuery, or HTML DOM * Integrates with JsViews (http://jsviews.com/#jsviews) * - * Copyright 2017, Boris Moore + * Copyright 2018, Boris Moore * Released under the MIT License. */ @@ -19,7 +19,7 @@ if (typeof exports !== 'object' ) { //========================== Top-level vars ========================== -var versionNumber = "v0.9.90", +var versionNumber = "v0.9.91", // global var is the this object, which is window when running in the usual browser environment @@ -32,8 +32,8 @@ var versionNumber = "v0.9.90", rPath = /^(!*?)(?:null|true|false|\d[\d.]*|([\w$]+|\.|~([\w$]+)|#(view|([\w$]+))?)([\w$.^]*?)(?:[.[^]([\w$]+)\]?)?)$/g, // not object helper view viewProperty pathTokens leafToken - rParams = /(\()(?=\s*\()|(?:([([])\s*)?(?:(\^?)(!*?[#~]?[\w$.^]+)?\s*((\+\+|--)|\+|-|&&|\|\||===|!==|==|!=|<=|>=|[<>%*:?\/]|(=))\s*|(!*?[#~]?[\w$.^]+)([([])?)|(,\s*)|(\(?)\\?(?:(')|("))|(?:\s*(([)\]])(?=\s*[.^]|\s*$|[^([])|[)\]])([([]?))|(\s+)/g, - // lftPrn0 lftPrn bound path operator err eq path2 prn comma lftPrn2 apos quot rtPrn rtPrnDot prn2 space + rParams = /(\()(?=\s*\()|(?:([([])\s*)?(?:(\^?)(~?[\w$.^]+)?\s*((\+\+|--)|\+|-|~(?![\w$_])|&&|\|\||===|!==|==|!=|<=|>=|[<>%*:?\/]|(=))\s*|(!*?(@)?[#~]?[\w$.^]+)([([])?)|(,\s*)|(\(?)\\?(?:(')|("))|(?:\s*(([)\]])(?=[.^]|\s*$|[^([])|[)\]])([([]?))|(\s+)/g, + // lftPrn0 lftPrn bound path operator err eq path2 late prn comma lftPrn2 apos quot rtPrn rtPrnDot prn2 space // (left paren? followed by (path? followed by operator) or (path followed by left paren?)) or comma or apos or quot or right paren or space isRenderCall, @@ -48,6 +48,9 @@ var versionNumber = "v0.9.90", rHasHandlers = /^on[A-Z]|^convert(Back)?$/, rWrappedInViewMarker = /^\#\d+_`[\s\S]*\/\d+_`$/, rHtmlEncode = rAttrEncode, + rDataEncode = /[&<>]/g, + rDataUnencode = /&(amp|gt|lt);/g, + rBracketQuote = /\[['"]?|['"]?\]/g, viewId = 0, charEntities = { "&": "&", @@ -59,6 +62,11 @@ var versionNumber = "v0.9.90", "`": "`", "=": "=" }, + charsFromEntities = { + amp: "&", + gt: ">", + lt: "<" + }, HTML = "html", OBJECT = "object", tmplAttr = "data-jsv-tmpl", @@ -106,7 +114,7 @@ var versionNumber = "v0.9.90", allowCode: false }, advSet: noop, // Update advanced settings - _ths: tagHandlersFromProps, + _thp: tagHandlersFromProps, _gm: getMethod, _tg: function() {}, // Constructor for tagDef _cnvt: convertVal, @@ -161,7 +169,7 @@ function getMethod(baseMethod, method) { : getDerivedMethod(noop, baseMethod), // baseMethod is not derived so make its base method be the noop method method ); - method._d = 1; // Add flag that this is a derived method + method._d = (baseMethod && baseMethod._d || 0) + 1; // Add flag for derived method (incremented for derived of derived...) } return method; } @@ -323,66 +331,126 @@ getIndex.depends = "index"; // View.hlp //========== -function contextParameter(key, value, isContextCb) { +function getPathObject(ob, path, ltOb, fn) { // Iterate through path to late paths: @a.b.c paths + // Return "" (or noop if leaf is a function @a.b.c(...) ) if intermediate object not yet available + var prevOb, tokens, l, + i = 0; + if (ltOb === 1) { + fn = 1; + ltOb = undefined; + } + // Paths like ^a^b^c or ~^a^b^c will not throw if an object in path is undefined. + if (path) { + tokens = path.split("."); + l = tokens.length; + + for (; ob && i < l; i++) { + prevOb = ob; + ob = tokens[i] ? ob[tokens[i]] : ob; + } + } + if (ltOb) { + ltOb.lt = ltOb.lt || i 1, store = storeView.ctx; - if (key in store || key in (store = $helpers)) { - res = store && store[key]; - if (key === "tag" || key === "root" || key === "parentTags" || storeView._.it === key ) { - return res; + if (key) { + if (!storeView._) { // tagCtx.ctxPrm() call + tagElse = storeView.index; + storeView = storeView.tag; } - } else { - store = undefined; - } - if (!res || !$isFunction(res) && storeView.linked || storeView.tagCtx) { // Data-linked view, or tag instance - if (!res || !res._cxp) { - // Not a contextual parameter - if (store !== $helpers) { + callView = storeView; + if (store && store.hasOwnProperty(key) || (store = $helpers).hasOwnProperty(key)) { + res = store[key]; + if (key === "tag" || key === "tagCtx" || key === "root" || key === "parentTags" || storeView._.it === key ) { + return res; + } + } else { + store = undefined; + } + if (storeView.tagCtx || storeView.linked) { // Data-linked view, or tag instance + if (!res || !res._cxp) { + // Not a contextual parameter // Set storeView to tag (if this is a tag.ctxPrm() call) or to root view ("data" view of linked template) - storeView = storeView.tagCtx - ? storeView // Is a tag, not a view - : (storeView = storeView.scope || storeView, !storeView.isTop && storeView.ctx.tag || storeView); + storeView = storeView.tagCtx || $isFunction(res) + ? storeView // Is a tag, not a view, or is a computed contextual parameter, so scope to the callView, no the 'scope view' + : (storeView = storeView.scope || storeView, + !storeView.isTop && storeView.ctx.tag // If this view is in a tag, set storeView to the tag + || storeView); + if (res !== undefined && storeView.tagCtx) { + // If storeView is a tag, but the contextual parameter has been set at at higher level (e.g. helpers)... + storeView = storeView.tagCtx.view.scope; // then move storeView to the outer level (scope of tag container view) + } store = storeView._ocps; - res = store && store[key] || res; + res = store && store.hasOwnProperty(key) && store[key] || res; + if (!(res && res._cxp) && (get || isUpdate)) { + // Create observable contextual parameter + (store || (storeView._ocps = storeView._ocps || {}))[key] + = res + = [{ + _ocp: res, // The observable contextual parameter value + _vw: callView, + _key: key + }]; + res._cxp = { + path: _ocp, + ind: 0, + updateValue: function(val, path) { + $.observable(res[0]).setProperty(_ocp, val); // Set the value (res[0]._ocp) + return this; + } + }; + } } - if (!(res && res._cxp) && (isContextCb || isUpdate)) { - res = $sub._crcp(key, res, storeView, store); // Create observable contextual parameter + if (obsCtxPrm = res && res._cxp) { + // If this helper resource is an observable contextual parameter + if (arguments.length > 2) { + deps = res[1] ? $sub._ceo(res[1].deps) : [_ocp]; // fn deps (with any exprObs cloned using $sub._ceo) + deps.unshift(res[0]); // view + deps._cxp = obsCtxPrm; + // In a context callback for a contextual param, we set get = true, to get ctxPrm [view, dependencies...] array - needed for observe call + return deps; + } + tagElse = obsCtxPrm.tagElse; + newRes = res[1] // linkFn for compiled expression + ? obsCtxPrm.tag && obsCtxPrm.tag.cvtArgs + ? obsCtxPrm.tag.cvtArgs(1, tagElse)[obsCtxPrm.ind] // = tag.bndArgs() - for tag contextual parameter + : res[1](res[0].data, res[0], $sub) // = fn(data, view, $sub) for compiled binding expression + : res[0]._ocp; // Observable contextual parameter (uninitialized, or initialized as static expression, so no path dependencies) + if (isUpdate) { + if (res && newRes !== value) { + $sub._ucp(key, value, storeView, obsCtxPrm); // Update observable contextual parameter + } + return storeView; + } + res = newRes; } } - if (obsCtxPrm = res && res._cxp) { - if (isUpdate) { - return $sub._ucp(key, value, storeView, obsCtxPrm); // Update observable contextual parameter - } - if (isContextCb) { // If this helper resource is an observable contextual parameter - // In a context callback for a contextual param, return the [view, dependencies...] array - needed for observe call - deps = res[1] ? $sub._ceo(res[1].deps) : [_ocp]; // fn deps (with any exprObs cloned using $sub._ceo) - deps.unshift(res[0]); // view - deps._cxp = obsCtxPrm; - return deps; - } - res = res[1] // linkFn for compiled expression - ? obsCtxPrm.tag && obsCtxPrm.tag.cvtArgs - ? obsCtxPrm.tag.cvtArgs(true, obsCtxPrm.tagElse)[obsCtxPrm.ind] // = tag.bndArgs() - for tag contextual parameter - : res[1](res[0].data, res[0], $sub) // = fn(data, view, $sub) for compiled binding expression - : res[0]._ocp; // Observable contextual parameter (uninitialized, or initialized as static expression, so no path dependencies) - } - } - if (res && $isFunction(res)) { - // If a helper is of type function, and not already wrapped, we will wrap it, so if called with no this pointer it will be called with the - // view as 'this' context. If the helper ~foo() was in a data-link expression, the view will have a 'temporary' linkCtx property too. - // Note that helper functions on deeper paths will have specific this pointers, from the preceding path. - // For example, ~util.foo() will have the ~util object as 'this' pointer - wrapped = function() { - return res.apply((!this || this === global) ? storeView : this, arguments); - }; - $extend(wrapped, res); // Attach same expandos (if any) to the wrapped function - wrapped._vw = storeView; + if (res && $isFunction(res)) { + // If a helper is of type function we will wrap it, so if called with no this pointer it will be called with the + // view as 'this' context. If the helper ~foo() was in a data-link expression, the view will have a 'temporary' linkCtx property too. + // Note that helper functions on deeper paths will have specific this pointers, from the preceding path. + // For example, ~util.foo() will have the ~util object as 'this' pointer + wrapped = function() { + return res.apply((!this || this === global) ? callView : this, arguments); + }; + $extend(wrapped, res); // Attach same expandos (if any) to the wrapped function + wrapped._vw = callView; + } + return wrapped || res; } - return wrapped || res; } function getTemplate(tmpl) { @@ -412,7 +480,6 @@ function convertVal(converter, view, tagCtx, onError) { tagCtx = boundTag(view.data, view, $sub); } boundTag = boundTag._bd && boundTag; - value = tagCtx.args[0]; if (converter || boundTag) { tag = linkCtx && linkCtx.tag; tagCtx.view = view; @@ -420,13 +487,16 @@ function convertVal(converter, view, tagCtx, onError) { tag = $extend(new $sub._tg(), { _: { bnd: boundTag, - unlinked: true + unlinked: true, + lt: tagCtx.lt // If a late path @some.path has not returned @some object, mark tag as late }, inline: !linkCtx, tagName: ":", convert: converter, flow: true, - tagCtx: tagCtx + tagCtx: tagCtx, + tagCtxs: [tagCtx], + _is: "tag" }); argsLen = tagCtx.args.length; if (argsLen>1) { @@ -445,8 +515,10 @@ function convertVal(converter, view, tagCtx, onError) { tag._er = onError && value; tag.ctx = tagCtx.ctx || tag.ctx || {}; tagCtx.ctx = undefined; - value = tag.cvtArgs()[0]; // If there is a convertBack but no convert, converter will be "true" + tag._er = onError && value; + } else { + value = tagCtx.args[0]; } // Call onRender (used by JsViews if present, to add binding annotations around rendered content) @@ -456,8 +528,8 @@ function convertVal(converter, view, tagCtx, onError) { return value != undefined ? value : ""; } -function convertArgs(bound, tagElse) { // tag.cvtArgs() - var l, key, boundArgs, args, bindTo, tag, converter, +function convertArgs(bound, tagElse) { // tag.cvtArgs() or tag.cvtArgs(trueOrFalse, tagElse) + var l, key, boundArgs, args, bindFrom, tag, converter, tagCtx = this; if (tagCtx.tagName) { @@ -467,7 +539,7 @@ function convertArgs(bound, tagElse) { // tag.cvtArgs() tag = tagCtx.tag; } - bindTo = tag.bindTo; + bindFrom = tag.bindFrom; args = tagCtx.args; if ((converter = tag.convert) && "" + converter === converter) { @@ -476,38 +548,37 @@ function convertArgs(bound, tagElse) { // tag.cvtArgs() : (tagCtx.view.getRsc("converters", converter) || error("Unknown converter: '" + converter + "'")); } - if (bound && bound.length) { - args = bound; - } else { - if (converter && !bound) { // If there is a converter, use a copy of the tagCtx.args array for rendering, and replace the args[0] in - args = args.slice(); // the copied array with the converted value. But we do not modify the value of tag.tagCtx.args[0] (the original args array) + if (converter && !bound) { // If there is a converter, use a copy of the tagCtx.args array for rendering, and replace the args[0] in + args = args.slice(); // the copied array with the converted value. But we do not modify the value of tag.tagCtx.args[0] (the original args array) + } + if (bindFrom) { // Get the values of the boundArgs + boundArgs = []; + l = bindFrom.length; + while (l--) { + key = bindFrom[l]; + boundArgs.unshift(argOrProp(tagCtx, key)); } - if (bindTo) { // Get the values of the boundArgs - boundArgs = []; - l = bindTo.length; - while (l--) { - key = bindTo[l]; - boundArgs.unshift(argOrProp(tagCtx, key)); - } - if (bound) { - args = boundArgs; // Call to convertBoundArgs() - returns the boundArgs - } + if (bound) { + args = boundArgs; // Call to bndArgs() - returns the boundArgs } } if (converter) { - bindTo = bindTo || [0]; - l = bindTo.length; converter = converter.apply(tag, boundArgs || args); + if (converter === undefined) { + return args; // Returning undefined from a converter is equivalent to not having a converter. + } + bindFrom = bindFrom || [0]; + l = bindFrom.length; if (!$isArray(converter) || converter.length !== l) { converter = [converter]; - bindTo = [0]; + bindFrom = [0]; l = 1; } - if (bound) { // Call to bndArgs convertBoundArgs() - so apply converter to all boundArgs + if (bound) { // Call to bndArgs() - so apply converter to all boundArgs args = converter; // The array of values returned from the converter } else { // Call to cvtArgs() while (l--) { - key = bindTo[l]; + key = bindFrom[l]; if (+key === key) { args[key] = converter[l]; } @@ -523,7 +594,7 @@ function argOrProp(context, key) { } function convertBoundArgs(tagElse) { // tag.bndArgs() - return this.cvtArgs(true, tagElse); + return this.cvtArgs(1, tagElse); } //============= @@ -544,20 +615,26 @@ function getResource(resourceType, itemName) { } function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) { - function makeArray(type) { - var linkedElement; - if (linkedElement = tag[type]) { - tag[type] = linkedElement = $isArray(linkedElement) ? linkedElement: [linkedElement]; - - if (bindToLength !== linkedElement.length) { - error(type + " length not same as bindTo "); + function bindToOrBindFrom(type) { + var bindArray = tag[type]; + + if (bindArray !== undefined) { + bindArray = $isArray(bindArray) ? bindArray : [bindArray]; + m = bindArray.length; + while (m--) { + key = bindArray[m]; + if (!isNaN(parseInt(key))) { + bindArray[m] = parseInt(key); // Convert "0" to 0, etc. + } } } + + return bindArray || [0]; } parentView = parentView || topView; - var tag, tag_, tagDef, template, tags, attr, parentTag, l, m, n, itemRet, tagCtx, tagCtxCtx, ctxPrm, bindTo, - content, callInit, mapDef, thisMap, args, props, tagDataMap, contentCtx, key, bindToLength, + var tag, tagDef, template, tags, attr, parentTag, l, m, n, itemRet, tagCtx, tagCtxCtx, ctxPrm, bindTo, bindFrom, initVal, + content, callInit, mapDef, thisMap, args, bdArgs, props, tagDataMap, contentCtx, key, bindFromLength, bindToLength, linkedElement, defaultCtx, i = 0, ret = "", linkCtx = parentView.linkCtx || 0, @@ -575,14 +652,12 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) { tagDef = parentView.getRsc("tags", tagName) || error("Unknown tag: {{" + tagName + "}} "); template = tagDef.template; } - if (onError === undefined && boundTag) { - if (boundTag._lr = (tagDef.lateRender || boundTag._lr) && boundTag._lr !== "false") { - onError = ""; // If lateRender, set temporary onError, to skip initial rendering (and render just "") - } + if (onError === undefined && boundTag && (boundTag._lr = (tagDef.lateRender && boundTag._lr!== false || boundTag._lr))) { + onError = ""; // If lateRender, set temporary onError, to skip initial rendering (and render just "") } if (onError !== undefined) { ret += onError; - tagCtxs = onError = [{props: {}, args: [], params: {}}]; + tagCtxs = onError = [{props: {}, args: [], params: {props:{}}}]; } else if (boundTag) { tagCtxs = boundTag(parentView.data, parentView, $sub); } @@ -598,9 +673,12 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) { tagCtx.tmpl = tagCtx.content = parentTmpl.tmpls[content - 1]; // Set the tmpl property to the content of the block tag } tagCtx.index = i; + tagCtx.ctxPrm = contextParameter; tagCtx.render = renderContent; + tagCtx.cvtArgs = convertArgs; + tagCtx.bndArgs = convertBoundArgs; tagCtx.view = parentView; - tagCtx.ctx = extendCtx(tagCtx.ctx, ctx); // Clone and extend parentView.ctx + tagCtx.ctx = extendCtx(extendCtx(tagCtx.ctx, tagDef && tagDef.ctx), ctx); // Clone and extend parentView.ctx } if (tmpl = tagCtx.props.tmpl) { // If the tmpl property is overridden, set the value (when initializing, or, in case of binding: ^tmpl=..., when updating) @@ -618,7 +696,6 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) { tag.parent = parentTag = ctx && ctx.tag; tag.tagCtxs = tagCtxs; - tagDataMap = tag.dataMap; if (linkCtx) { tag.inline = false; @@ -627,14 +704,17 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) { } if (tag._.bnd = boundTag || linkCtx.fn) { // Bound if {^{tag...}} or data-link="{tag...}" + tag._.ths = tagCtx.params.props.this; // Tag has a this=expr binding, to get javascript reference to tag instance + tag._.lt = tagCtxs.lt; // If a late path @some.path has not returned @some object, mark tag as late tag._.arrVws = {}; } else if (tag.dataBoundOnly) { error(tagName + " must be data-bound:\n{^{" + tagName + "}}"); } //TODO better perf for childTags() - keep child tag.tags array, (and remove child, when disposed) // tag.tags = []; + } else if (linkCtx && linkCtx.fn._lr) { + callInit = !!tag.init; } - tagCtxs = tag.tagCtxs; tagDataMap = tag.dataMap; tagCtx.tag = tag; @@ -651,11 +731,12 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) { //TODO better perf for childTags: parentTag.tags.push(tag); } tags[tag.tagName] = tagCtxCtx.tag = tag; + tagCtxCtx.tagCtx = tagCtx; } } if (!(tag._er = onError)) { tagHandlersFromProps(tag, tagCtxs[0]); - tag.rendering = {}; // Provide object for state during render calls to tag and elses. (Used by {{if}} and {{for}}...) + tag.rendering = {rndr: tag.rendering}; // Provide object for state during render calls to tag and elses. (Used by {{if}} and {{for}}...) for (i = 0; i < l; i++) { // Iterate tagCtx for each {{else}} block tagCtx = tag.tagCtx = tagCtxs[i]; props = tagCtx.props; @@ -666,62 +747,95 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) { tag.init(tagCtx, linkCtx, tag.ctx); callInit = undefined; } - if (!tagCtx.args.length && tag.argDefault !== false) { + if (!tagCtx.args.length && tagCtx.argDefault !== false && tag.argDefault !== false) { tagCtx.args = args = [tagCtx.view.data]; // Missing first arg defaults to the current data context tagCtx.params.args = ["#data"]; } - bindTo = tag.bindTo; + bindTo = bindToOrBindFrom("bindTo"); - if (bindTo !== undefined) { - bindTo = tag.bindTo = $isArray(bindTo) ? bindTo : [bindTo]; - m = bindTo.length; - while (m--) { - key = bindTo[m]; - if (!isNaN(parseInt(key))) { - key = parseInt(key); // Convert "0" to 0, etc. - } - bindTo[m] = key; - } + if (tag.bindTo !== undefined) { + tag.bindTo = bindTo; } - bindTo = tag.bindTo || [0]; + if (tag.bindFrom !== undefined) { + tag.bindFrom = bindToOrBindFrom("bindFrom"); + } else if (tag.bindTo) { + tag.bindFrom = tag.bindTo = bindTo; + } + bindFrom = tag.bindFrom || bindTo; + bindToLength = bindTo.length; - if (tag._.bnd){ - makeArray("linkedElement"); - makeArray("linkedCtxParam"); + bindFromLength = bindFrom.length; + + if (tag._.bnd && (linkedElement = tag.linkedElement)) { + tag.linkedElement = linkedElement = $isArray(linkedElement) ? linkedElement: [linkedElement]; + + if (bindToLength !== linkedElement.length) { + error("linkedElement not same length as bindTo"); + } + } + if (linkedElement = tag.linkedCtxParam) { + tag.linkedCtxParam = linkedElement = $isArray(linkedElement) ? linkedElement: [linkedElement]; + + if (bindFromLength !== linkedElement.length) { + error("linkedCtxParam not same length as bindFrom/bindTo"); + } + } + + if (bindFrom) { + tag._.fromIndex = {}; // Hash of bindFrom index which has same path value as bindTo index. fromIndex = tag._.fromIndex[toIndex] + tag._.toIndex = {}; // Hash of bindFrom index which has same path value as bindTo index. fromIndex = tag._.fromIndex[toIndex] + n = bindFromLength; + while (n--) { + key = bindFrom[n]; + m = bindToLength; + while (m--) { + if (key === bindTo[m]) { + tag._.fromIndex[m] = n; + tag._.toIndex[n] = m; + } + } + } } if (linkCtx) { // Set attr on linkCtx to ensure outputting to the correct target attribute. // Setting either linkCtx.attr or this.attr in the init() allows per-instance choice of target attrib. - linkCtx.attr = tag.attr = linkCtx.attr || tag.attr; + linkCtx.attr = tag.attr = linkCtx.attr || tag.attr || linkCtx._dfAt; } attr = tag.attr; tag._.noVws = attr && attr !== HTML; } args = tag.cvtArgs(undefined, i); if (tag.linkedCtxParam) { - m = bindToLength; + bdArgs = tag.cvtArgs(1, i); + m = bindFromLength; + defaultCtx = tag.constructor.prototype.ctx; while (m--) { if (ctxPrm = tag.linkedCtxParam[m]) { - key = bindTo[m]; + key = bindFrom[m]; + initVal = bdArgs[m]; // Create tag contextual parameter - tagCtx.ctx[ctxPrm] = $sub._cp(argOrProp(tagCtx, key), argOrProp(tagCtx.params, key), tagCtx.view, tag._.bnd && {tag: tag, ind: m, tagElse: i}); + tagCtx.ctx[ctxPrm] = $sub._cp( + defaultCtx && initVal === undefined ? defaultCtx[ctxPrm]: initVal, + initVal !== undefined && argOrProp(tagCtx.params, key), + tagCtx.view, + tag._.bnd && {tag: tag, cvt: tag.convert, ind: m, tagElse: i} + ); } } } - if (mapDef = props.dataMap || tagDataMap) { - if (args.length || props.dataMap) { - thisMap = tagCtx.map; - if (!thisMap || thisMap.src !== args[0] || isUpdate) { - if (thisMap && thisMap.src) { - thisMap.unmap(); // only called if observable map - not when only used in JsRender, e.g. by {{props}} - } - thisMap = tagCtx.map = mapDef.map(args[0], props, undefined, !tag._.bnd); + if ((mapDef = props.dataMap || tagDataMap) && (args.length || props.dataMap)) { + thisMap = tagCtx.map; + if (!thisMap || thisMap.src !== args[0] || isUpdate) { + if (thisMap && thisMap.src) { + thisMap.unmap(); // only called if observable map - not when only used in JsRender, e.g. by {{props}} } - args = [thisMap.tgt]; + mapDef.map(args[0], tagCtx, thisMap, !tag._.bnd); + thisMap = tagCtx.map; } + args = [thisMap.tgt]; } itemRet = undefined; @@ -754,18 +868,16 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) { // No return value from render, and no template/content tagCtx.render(...), so return undefined ret = ret ? ret + (itemRet || "") : itemRet; // If no rendered content, this will be undefined } - tag.rendering = undefined; + tag.rendering = tag.rendering.rndr; // Remove tag.rendering object (if this is outermost render call. (In case of nested calls) } tag.tagCtx = tagCtxs[0]; tag.ctx = tag.tagCtx.ctx; - if (tag._.noVws) { - if (tag.inline) { - // inline tag with attr set to "text" will insert HTML-encoded content - as if it was element-based innerText - ret = attr === "text" - ? $converters.html(ret) - : ""; - } + if (tag._.noVws && tag.inline) { + // inline tag with attr set to "text" will insert HTML-encoded content - as if it was element-based innerText + ret = attr === "text" + ? $converters.html(ret) + : ""; } return boundTag && parentView._.onRender // Call onRender (used by JsViews if present, to add binding annotations around rendered content) @@ -805,6 +917,7 @@ function View(context, type, parentView, data, template, key, onRender, contentT parentView_ = parentView._; self.isTop = parentView_.scp; // Is top content view of a link("#container", ...) call self.scope = (!context.tag || context.tag === parentView.ctx.tag) && !self.isTop && parentView.scope || self; + // Scope for contextParams - closest non flow tag ancestor or root view if (parentView_.useKey) { // Parent is not an 'array view'. Add this view to its views object // self._key = is the key in the parent view hash @@ -830,6 +943,7 @@ View.prototype = { getRsc: getResource, getTmpl: getTemplate, ctxPrm: contextParameter, + getOb: getPathObject, _is: "view" }; @@ -854,8 +968,7 @@ function compileChildResources(parentTmpl) { //=============== function compileTag(name, tagDef, parentTmpl) { - var tmpl, baseTag, prop, l, key, bindToLength, - bindTo = tagDef.bindTo, + var tmpl, baseTag, prop, compiledDef = new $sub._tg(); function Tag() { @@ -879,10 +992,12 @@ function compileTag(name, tagDef, parentTmpl) { if (baseTag = tagDef.baseTag) { tagDef.flow = !!tagDef.flow; // Set flow property, so defaults to false even if baseTag has flow=true - tagDef.baseTag = baseTag = "" + baseTag === baseTag + baseTag = "" + baseTag === baseTag ? (parentTmpl && parentTmpl.tags[baseTag] || $tags[baseTag]) : baseTag; - + if (!baseTag) { + error('baseTag: "' + tagDef.baseTag + '" not found'); + } compiledDef = $extend(compiledDef, baseTag); for (prop in tagDef) { @@ -970,23 +1085,27 @@ function compileTmpl(name, tmpl, parentTmpl, options) { // If options, then this was already compiled from a (script) element template declaration. // If not, then if tmpl is a template object, use it for options - options = options || (tmpl.markup ? tmpl : {}); - options.tmplName = name; + options = options || (tmpl.markup + ? tmpl.bnds + ? $extend({}, tmpl) + : tmpl + : {} + ); + + options.tmplName = options.tmplName || name || "unnamed"; if (parentTmpl) { options._parentTmpl = parentTmpl; } // If tmpl is not a markup string or a selector string, then it must be a template object // In that case, get it from the markup property of the object - if (!tmplOrMarkup && tmpl.markup && (tmplOrMarkup = lookupTemplate(tmpl.markup))) { - if (tmplOrMarkup.fn) { - // If the string references a compiled template object, need to recompile to merge any modified options - tmplOrMarkup = tmplOrMarkup.markup; - } + if (!tmplOrMarkup && tmpl.markup && (tmplOrMarkup = lookupTemplate(tmpl.markup)) && tmplOrMarkup.fn) { + // If the string references a compiled template object, need to recompile to merge any modified options + tmplOrMarkup = tmplOrMarkup.markup; } if (tmplOrMarkup !== undefined) { - if (tmplOrMarkup.fn || tmpl.fn) { + if (tmplOrMarkup.render || tmpl.render) { // tmpl is already compiled, so use it - if (tmplOrMarkup.fn) { + if (tmplOrMarkup.tmpls) { compiledTmpl = tmplOrMarkup; } } else { @@ -1241,19 +1360,20 @@ function tmplObject(markup, options) { // Template object constructor var htmlTag, wrapMap = $subSettingsAdvanced._wm || {}, // Only used in JsViews. Otherwise empty: {} - tmpl = $extend( - { - tmpls: [], - links: {}, // Compiled functions for link expressions - bnds: [], - _is: "template", - render: renderContent - }, - options - ); + tmpl = { + tmpls: [], + links: {}, // Compiled functions for link expressions + bnds: [], + _is: "template", + render: renderContent + }; + + if (options) { + tmpl = $extend(tmpl, options); + } tmpl.markup = markup; - if (!options.htmlTag) { + if (!tmpl.htmlTag) { // Set tmpl.tag to the top-level HTML tag used in the template, if any... htmlTag = rFirstElem.exec(markup); tmpl.htmlTag = htmlTag ? htmlTag[1].toLowerCase() : ""; @@ -1344,13 +1464,14 @@ function addSetting(st) { }; } -//========= -// dataMap -//========= +//======================== +// dataMap for render only +//======================== function dataMap(mapDef) { function Map(source, options) { this.tgt = mapDef.getTgt(source, options); + options.map = this; } if ($isFunction(mapDef)) { @@ -1392,7 +1513,9 @@ function renderContent(data, context, noIteration, parentView, key, onRender) { view = view || tagCtx.view; tmpl = view.getTmpl(tag.template || tagCtx.tmpl); if (!arguments.length) { - data = view; + data = tag.contentCtx && $isFunction(tag.contentCtx) + ? data = tag.contentCtx(data) + : view; // Default data context for wrapped block content is the first argument } } else { // This is a template.render(...) call @@ -1459,7 +1582,7 @@ function renderWithViews(tmpl, data, context, noIteration, view, key, onRender, // Render template against data as a tree of subviews (nested rendered template instances), or as a string (top-level template). // If the data is the parent view, treat as noIteration, re-render with the same data context. // tmpl can be a string (e.g. rendered by a tag.render() method), or a compiled template. - var i, l, newView, childView, itemResult, swapContent, contentTmpl, outerOnRender, tmplName, itemVar, newCtx, tagCtx, + var i, l, newView, childView, itemResult, swapContent, contentTmpl, outerOnRender, tmplName, itemVar, newCtx, tagCtx, noLinking, result = ""; if (tag) { @@ -1490,7 +1613,6 @@ function renderWithViews(tmpl, data, context, noIteration, view, key, onRender, context = context || {}; context.link = false; } - if (itemVar = tagCtx.props.itemVar) { if (itemVar.charAt(0) !== "~") { syntaxError("Use itemVar='~myItem'"); @@ -1501,6 +1623,12 @@ function renderWithViews(tmpl, data, context, noIteration, view, key, onRender, if (view) { onRender = onRender || view._.onRender; + noLinking = context && context.link === false; + + if (noLinking && view._.nl) { + onRender = undefined; + } + context = extendCtx(context, view.ctx); } @@ -1510,7 +1638,7 @@ function renderWithViews(tmpl, data, context, noIteration, view, key, onRender, } // If link===false, do not call onRender, so no data-linking marker nodes - if (onRender && (context && context.link === false || tag && tag._.noVws)) { + if (onRender && tag && tag._.noVws) { onRender = undefined; } outerOnRender = onRender; @@ -1532,10 +1660,12 @@ function renderWithViews(tmpl, data, context, noIteration, view, key, onRender, ? view : (key !== undefined && view) || new View(context, "array", view, data, tmpl, key, onRender, contentTmpl); + newView._.nl= noLinking; if (view && view._.useKey) { // Parent is not an 'array view' newView._.bnd = !tag || tag._.bnd && tag; // For array views that are data bound for collection change events, set the // view._.bnd property to true for top-level link() or data-link="{for}", or to the tag instance for a data-bound tag, e.g. {^{for ...}} + newView.tag = tag; } for (i = 0, l = data.length; i < l; i++) { // Create a view for each data item. @@ -1556,10 +1686,11 @@ function renderWithViews(tmpl, data, context, noIteration, view, key, onRender, } newView = swapContent ? view : new View(newCtx, tmplName || "data", view, data, tmpl, key, onRender, contentTmpl); newView._.it = itemVar; + newView.tag = tag; + newView._.nl = noLinking; result += tmpl.fn(data, newView, $sub); } if (tag) { - newView.tag = tag; newView.tagElse = tagCtx.index; tagCtx.contentView = newView; } @@ -1664,7 +1795,7 @@ function tmplFn(markup, tmpl, isLinkExpr, convertBack, hasElse) { } slash = slash || isLinkExpr && !hasElse; - var late, + var late, openTagName, isLateOb, pathBindings = (bind || isLinkExpr) && [[]], // pathBindings is an array of arrays for arg bindings and a hash of arrays for prop bindings props = "", args = "", @@ -1688,23 +1819,31 @@ function tmplFn(markup, tmpl, isLinkExpr, convertBack, hasElse) { } else if (tagName) { if (tagName === "else") { if (rTestElseIf.test(params)) { - syntaxError('for "{{else if expr}}" use "{{else expr}}"'); + syntaxError('For "{{else if expr}}" use "{{else expr}}"'); } - pathBindings = current[8] && [[]]; - current[9] = markup.substring(current[9], index); // contentMarkup for block tag + pathBindings = current[9] && [[]]; + current[10] = markup.substring(current[10], index); // contentMarkup for block tag + openTagName = current[11] || current[0] || syntaxError("Mismatched: " + all); + // current[0] is tagName, but for {{else}} nodes, current[11] is tagName of preceding open tag current = stack.pop(); content = current[2]; block = true; } if (params) { // remove newlines from the params string, to avoid compiled code errors for unterminated strings - parseParams(params.replace(rNewLine, " "), pathBindings, tmpl) - .replace(rBuildHash, function(all, onerror, isCtx, key, keyToken, keyValue, arg, param) { + parseParams(params.replace(rNewLine, " "), pathBindings, tmpl, isLinkExpr) + .replace(rBuildHash, function(all, onerror, isCtxPrm, key, keyToken, keyValue, arg, param) { + if (key === "this:") { + keyValue = "undefined"; // this=some.path is always a to parameter (one-way), so don't need to compile/evaluate some.path initialization + } + if (param) { + isLateOb = isLateOb || param.charAt(0) === "@"; + } key = "'" + keyToken + "':"; if (arg) { - args += keyValue + ","; + args += isCtxPrm + keyValue + ","; paramsArgs += "'" + param + "',"; - } else if (isCtx) { + } else if (isCtxPrm) { // Contextual parameter, ~foo=expr ctxProps += key + 'j._cp(' + keyValue + ',"' + param + '",view),'; // Compiled code for evaluating tagCtx on a tag will have: ctx:{'foo':j._cp(compiledExpr, "expr", view)} paramsCtxProps += key + "'" + param + "',"; @@ -1715,7 +1854,7 @@ function tmplFn(markup, tmpl, isLinkExpr, convertBack, hasElse) { useTrigger += keyValue; } if (keyToken === "lateRender") { - late = param; // Render after first pass + late = param !== "false"; // Render after first pass } props += key + keyValue + ","; paramsProps += key + "'" + param + "',"; @@ -1738,17 +1877,19 @@ function tmplFn(markup, tmpl, isLinkExpr, convertBack, hasElse) { onError, useTrigger, late, + isLateOb, pathBindings || 0 ]; content.push(newNode); if (block) { stack.push(current); current = newNode; - current[9] = loc; // Store current location of open tag, to be able to add contentMarkup when we reach closing tag + current[10] = loc; // Store current location of open tag, to be able to add contentMarkup when we reach closing tag + current[11] = openTagName; // Used for checking syntax (matching close tag) } } else if (closeBlock) { - blockTagCheck(closeBlock !== current[0] && current[0] !== "else" && closeBlock, current[0]); - current[9] = markup.substring(current[9], index); // contentMarkup for block tag + blockTagCheck(closeBlock !== current[0] && closeBlock !== current[11] && closeBlock, current[0]); // Check matching close tag name + current[10] = markup.substring(current[10], index); // contentMarkup for block tag current = stack.pop(); } blockTagCheck(!current && closeBlock); @@ -1790,7 +1931,7 @@ function tmplFn(markup, tmpl, isLinkExpr, convertBack, hasElse) { pushprecedingContent(markup.length); if (loc = astTop[astTop.length - 1]) { - blockTagCheck("" + loc !== loc && (+loc[9] === loc[9]) && loc[0]); + blockTagCheck("" + loc !== loc && (+loc[10] === loc[10]) && loc[0]); } // result = tmplFnsCache[markup] = buildCode(astTop, tmpl); // } @@ -1800,7 +1941,7 @@ function tmplFn(markup, tmpl, isLinkExpr, convertBack, hasElse) { bindings = []; i = astTop.length; while (i--) { - bindings.unshift(astTop[i][8]); // With data-link expressions, pathBindings array for tagCtx[i] is astTop[i][8] + bindings.unshift(astTop[i][9]); // With data-link expressions, pathBindings array for tagCtx[i] is astTop[i][9] } setPaths(result, bindings); } else { @@ -1834,18 +1975,15 @@ function paramStructure(parts, type) { + (type ? type + ':{' : '') - + 'args:[' + parts[0] + ']' - + (parts[1] || !type - ? ',\n\tprops:{' + parts[1] + '}' - : "") + + 'args:[' + parts[0] + '],\n\tprops:{' + parts[1] + '}' + (parts[2] ? ',\n\tctx:{' + parts[2] + '}' : ""); } -function parseParams(params, pathBindings, tmpl) { +function parseParams(params, pathBindings, tmpl, isLinkExpr) { - function parseTokens(all, lftPrn0, lftPrn, bound, path, operator, err, eq, path2, prn, comma, lftPrn2, apos, quot, rtPrn, rtPrnDot, prn2, space, index, full) { - // /(\()(?=\s*\()|(?:([([])\s*)?(?:(\^?)(!*?[#~]?[\w$.^]+)?\s*((\+\+|--)|\+|-|&&|\|\||===|!==|==|!=|<=|>=|[<>%*:?\/]|(=))\s*|(!*?[#~]?[\w$.^]+)([([])?)|(,\s*)|(\(?)\\?(?:(')|("))|(?:\s*(([)\]])(?=\s*[.^]|\s*$|[^([])|[)\]])([([]?))|(\s+)/g, - // lftPrn0 lftPrn bound path operator err eq path2 prn comma lftPrn2 apos quot rtPrn rtPrnDot prn2 space + function parseTokens(all, lftPrn0, lftPrn, bound, path, operator, err, eq, path2, late, prn, comma, lftPrn2, apos, quot, rtPrn, rtPrnDot, prn2, space, index, full) { + // /(\()(?=\s*\()|(?:([([])\s*)?(?:(\^?)(~?[\w$.^]+)?\s*((\+\+|--)|\+|-|&&|\|\||===|!==|==|!=|<=|>=|[<>%*:?\/]|(=))\s*|(!*?(@)?[#~]?[\w$.^]+)([([])?)|(,\s*)|(\(?)\\?(?:(')|("))|(?:\s*(([)\]])(?=[.^]|\s*$|[^([])|[)\]])([([]?))|(\s+)/g, + // lftPrn0 lftPrn bound path operator err eq path2 late prn comma lftPrn2 apos quot rtPrn rtPrnDot prn2 space // (left paren? followed by (path? followed by operator) or (path followed by paren?)) or comma or apos or quot or right paren or space function parsePath(allPath, not, object, helper, view, viewProperty, pathTokens, leafToken) { //rPath = /^(!*?)(?:null|true|false|\d[\d.]*|([\w$]+|\.|~([\w$]+)|#(view|([\w$]+))?)([\w$.^]*?)(?:[.[^]([\w$]+)\]?)?)$/g, @@ -1857,11 +1995,19 @@ function parseParams(params, pathBindings, tmpl) { syntaxError(allPath); } if (!subPath) { - allPath = (helper + allPath = (late // late path @a.b.c: not throw on 'property of undefined' if a undefined, and will use getOb() after linking to resolve late. + ? (isLinkExpr ? '' : '(ltOb.lt=ltOb.lt||') + '(ob=' + : "" + ) + + (helper ? 'view.ctxPrm("' + helper + '")' : view ? "view" : "data") + + (late + ? ')===undefined' + (isLinkExpr ? '' : ')') + '?"":view.getOb(ob,"' + : "" + ) + (leafToken ? (viewProperty ? "." + viewProperty @@ -1870,15 +2016,18 @@ function parseParams(params, pathBindings, tmpl) { : (view ? "" : "." + object) ) + (pathTokens || "") : (leafToken = helper ? "" : view ? viewProperty || "" : object, "")); - allPath = allPath + (leafToken ? "." + leafToken : ""); allPath = not + (allPath.slice(0, 9) === "view.data" ? allPath.slice(5) // convert #view.data... to data... - : allPath); + : allPath) + + (late + ? (isLinkExpr ? '"': '",ltOb') + (prn ? ',1)':')') + : "" + ); } if (bindings) { - binds = named === "linkTo" ? (bindto = pathBindings._jsvto = pathBindings._jsvto || []) : bndCtx.bd; + binds = named === "_linkTo" ? (bindto = pathBindings._jsvto = pathBindings._jsvto || []) : bndCtx.bd; if (theOb = subPath && binds[binds.length-1]) { if (theOb._cpfn) { // Computed property exprOb while (theOb.sb) { @@ -1906,6 +2055,10 @@ function parseParams(params, pathBindings, tmpl) { operator = operator || ""; lftPrn = lftPrn || lftPrn0 || lftPrn2; path = path || path2; + + if (late && (late = !/\)|]/.test(full.charAt(index-1)))) { + path = path.slice(1).split(".").join("^"); // Late path @z.b.c. Use "^" rather than "." to ensure that deep binding will be used + } // Could do this - but not worth perf cost?? :- // if (!path.lastIndexOf("#data.", 0)) { path = path.slice(6); } // If path starts with "#data.", remove that. prn = prn || prn2 || ""; @@ -1914,7 +2067,7 @@ function parseParams(params, pathBindings, tmpl) { rtSq = ")"; if (prn === "[") { - prn ="[j._sq("; + prn = "[j._sq("; rtSq = ")]"; } @@ -1924,7 +2077,7 @@ function parseParams(params, pathBindings, tmpl) { if (bindings && rtPrnDot && !aposed && !quoted) { // This is a binding to a path in which an object is returned by a helper/data function/expression, e.g. foo()^x.y or (a?b:c)^x.y // We create a compiled function to get the object instance (which will be called when the dependent data of the subexpression changes, to return the new object, and trigger re-binding of the subsequent path) - if (!named || boundName || bindto) { + if (parenDepth && (!named || boundName || bindto)) { expr = pathStart[parenDepth - 1]; if (full.length - 1 > index - (expr || 0)) { // We need to compile a subexpression expr = full.slice(expr, index + all.length); @@ -1979,7 +2132,7 @@ function parseParams(params, pathBindings, tmpl) { ) : eq // named param. Remove bindings for arg and create instead bindings array for prop - ? (parenDepth && syntaxError(params), bindings && pathBindings.pop(), named = path, boundName = bound, paramIndex = index + all.length, + ? (parenDepth && syntaxError(params), bindings && pathBindings.pop(), named = "_" + path, boundName = bound, paramIndex = index + all.length, bindings && ((bindings = bndCtx.bd = pathBindings[named] = []), bindings.skp = !bound), path + ':') : path // path @@ -2022,7 +2175,12 @@ function parseParams(params, pathBindings, tmpl) { parenDepth = 0, fnCall = {}, // We are in a function call pathStart = {}, // tracks the start of the current path such as c^d() in the above example - result = (params + (tmpl ? " " : "")).replace(rParams, parseTokens); + result; + + if (params.charAt(0) === "@") { + params = params.replace(rBracketQuote, "."); + } + result = (params + (tmpl ? " " : "")).replace(rParams, parseTokens); return !parenDepth && result || syntaxError(params); // Syntax error if unbalanced parens in params expression } @@ -2032,7 +2190,7 @@ function buildCode(ast, tmpl, isLinkExpr) { // Used for compiling templates, and also by JsViews to build functions for data link expressions var i, node, tagName, converter, tagCtx, hasTag, hasEncoder, getsVal, hasCnvt, useCnvt, tmplBindings, pathBindings, params, boundOnErrStart, boundOnErrEnd, tagRender, nestedTmpls, tmplName, nestedTmpl, tagAndElses, content, markup, nextIsElse, oldCode, isElse, isGetVal, tagCtxFn, - onError, tagStart, trigger, lateRender, + onError, tagStart, trigger, lateRender, retStrOpen, retStrClose, tmplBindingKey = 0, useViews = $subSettingsAdvanced.useViews || tmpl.useViews || tmpl.tags || tmpl.templates || tmpl.helpers || tmpl.converters, code = "", @@ -2079,14 +2237,21 @@ function buildCode(ast, tmpl, isLinkExpr) { } // END NODE.JS-SPECIFIC CODE trigger = node[6]; lateRender = node[7]; - markup = node[9] && node[9].replace(rUnescapeQuotes, "$1"); + if (node[8]) { // latePath @a.b.c or @~a.b.c + retStrOpen = "\nvar ob,ltOb={},ctxs="; + retStrClose = ";\nctxs.lt=ltOb.lt;\nreturn ctxs;"; + } else { + retStrOpen = "\nreturn "; + retStrClose = ""; + } + markup = node[10] && node[10].replace(rUnescapeQuotes, "$1"); if (isElse = tagName === "else") { if (pathBindings) { - pathBindings.push(node[8]); + pathBindings.push(node[9]); } } else { onError = node[5] || $subSettings.debugMode !== false && "undefined"; // If debugMode not false, set default onError handler on tag to "undefined" (see onRenderError) - if (tmplBindings && (pathBindings = node[8])) { // Array of paths, or false if not data-bound + if (tmplBindings && (pathBindings = node[9])) { // Array of paths, or false if not data-bound pathBindings = [pathBindings]; tmplBindingKey = tmplBindings.push(1); // Add placeholder in tmplBindings for compiled function } @@ -2129,7 +2294,7 @@ function buildCode(ast, tmpl, isLinkExpr) { if (isGetVal && (pathBindings || trigger || converter && converter !== HTML || lateRender)) { // For convertVal we need a compiled function to return the new tagCtx(s) tagCtxFn = new Function("data,view,j,u", "// " + tmplName + " " + (++tmplBindingKey) + " " + tagName - + "\nreturn {" + tagCtx + "};"); + + retStrOpen + "{" + tagCtx + "};" + retStrClose); tagCtxFn._er = onError; tagCtxFn._tag = tagName; tagCtxFn._bd = !!pathBindings; // data-linked tag {^{.../}} @@ -2166,7 +2331,8 @@ function buildCode(ast, tmpl, isLinkExpr) { tagRender = 't("' + tagAndElses + '",view,this,'; if (isLinkExpr || pathBindings) { // This is a bound tag (data-link expression or inline bound tag {^{tag ...}}) so we store a compiled tagCtxs function in tmp.bnds - code = new Function("data,view,j,u", " // " + tmplName + " " + tmplBindingKey + " " + tagAndElses + "\nreturn " + code + ";"); + code = new Function("data,view,j,u", " // " + tmplName + " " + tmplBindingKey + " " + tagAndElses + retStrOpen + code + + retStrClose); code._er = onError; code._tag = tagAndElses; if (pathBindings) { @@ -2183,7 +2349,7 @@ function buildCode(ast, tmpl, isLinkExpr) { // This is the last {{else}} for an inline tag. // For a bound tag, pass the tagCtxs fn lookup key to renderTag. // For an unbound tag, include the code directly for evaluating tagCtxs array - code = oldCode + tagStart + tagRender + (code.deps && tmplBindingKey || code) + ")"; + code = oldCode + tagStart + tagRender + (pathBindings && tmplBindingKey || code) + ")"; pathBindings = 0; tagAndElses = 0; } @@ -2196,13 +2362,17 @@ function buildCode(ast, tmpl, isLinkExpr) { } // Include only the var references that are needed in the code code = "// " + tmplName - + + (tmplOptions.debug ? "\ndebugger;" : "") + "\nvar v" + (hasTag ? ",t=j._tag" : "") // has tag + (hasCnvt ? ",c=j._cnvt" : "") // converter + (hasEncoder ? ",h=j._html" : "") // html converter - + (isLinkExpr ? ";\n" : ',ret=""\n') - + (tmplOptions.debug ? "debugger;" : "") + + (isLinkExpr + ? (node[8] // late @... path? + ? ", ob" + : "" + ) + ";\n" + : ',ret=""') + code + (isLinkExpr ? "\n" : ";\nreturn ret;"); @@ -2233,26 +2403,103 @@ function extendCtx(context, parentContext) { : parentContext && $extend({}, parentContext); } -// Get character entity for HTML and Attribute encoding -function getCharEntity(ch) { - return charEntities[ch] || (charEntities[ch] = "&#" + ch.charCodeAt(0) + ";"); -} - -function getTargetProps(source) { +function getTargetProps(source, tagCtx) { // this pointer is theMap - which has tagCtx.props too // arguments: tagCtx.args. var key, prop, props = []; - if (typeof source === OBJECT) { + if (typeof source === OBJECT || $isFunction(source)) { for (key in source) { prop = source[key]; - if (source.hasOwnProperty(key) && !$isFunction(prop)) { + if (key !== $.expando && source.hasOwnProperty(key) && (!tagCtx.props.noFunctions || !$.isFunction(prop))) { props.push({key: key, prop: prop}); } } } - return props; + return getTargetSorted(props, tagCtx); +} + +function getTargetSorted(value, tagCtx) { + // getTgt + var mapped, start, end, + tag = tagCtx.tag, + props = tagCtx.props, + propParams = tagCtx.params.props, + filter = props.filter, + sort = props.sort, + directSort = sort === true, + step = parseInt(props.step), + reverse = props.reverse ? -1 : 1; + + if (!$isArray(value)) { + return value; + } + if (directSort || sort && "" + sort === sort) { + // Temporary mapped array holds objects with index and sort-value + mapped = value.map(function(item, i) { + item = directSort ? item : getPathObject(item, sort); + return {i: i, v: "" + item === item ? item.toLowerCase() : item}; + }); + // Sort mapped array + mapped.sort(function(a, b) { + return a.v > b.v ? reverse : a.v < b.v ? -reverse : 0; + }); + // Map to new array with resulting order + value = mapped.map(function(item){ + return value[item.i]; + }); + } else if ((sort || reverse < 0) && !tag.dataMap) { + value = value.slice(); // Clone array first if not already a new array + } + if ($isFunction(sort)) { + value = value.sort(sort); + } + if (reverse < 0 && !sort) { // Reverse result if not already reversed in sort + value = value.reverse(); + } + + if (value.filter && filter) { // IE8 does not support filter + value = value.filter(filter, tagCtx); + if (tagCtx.tag.onFilter) { + tagCtx.tag.onFilter(tagCtx); + } + } + + if (propParams.sorted) { + mapped = (sort || reverse < 0) ? value : value.slice(); + if (tag.sorted) { + $.observable(tag.sorted).refresh(mapped); // Note that this might cause the start and end props to be modified - e.g. by pager tag control + } else { + tagCtx.map.sorted = mapped; + } + } + + start = props.start; // Get current value - after possible changes triggered by tag.sorted refresh() above + end = props.end; + if (propParams.start && start === undefined || propParams.end && end === undefined) { + start = end = 0; + } + if (!isNaN(start) || !isNaN(end)) { // start or end specified, but not the auto-create Number array scenario of {{for start=xxx end=yyy}} + start = +start || 0; + end = end === undefined || end > value.length ? value.length : +end; +// end = end === undefined ? value.length : +end; + value = value.slice(start, end); + } + if (step > 1) { + start = 0; + end = value.length; + mapped = []; + for (; start & ' and " by corresponding entities. + // HTML encode: Replace < > & ' " ` etc. by corresponding entities. return text != undefined ? rIsHtml.test(text) && ("" + text).replace(rHtmlEncode, getCharEntity) || text : ""; } +function dataEncode(text) { + // Encode just < > and & - intended for 'safe data' along with {{:}} rather than {{>}} + return "" + text === text ? text.replace(rDataEncode, getCharEntity) : text; +} + +function dataUnencode(text) { + // Unencode just < > and & - intended for 'safe data' along with {{:}} rather than {{>}} + return "" + text === text ? text.replace(rDataUnencode, getCharFromEntity) : text; +} + //========================== Initialize ========================== $sub = $views.sub; @@ -2330,7 +2597,7 @@ $viewsSettings = $views.settings; : ( $subSettings.debugMode = debugMode, $subSettings.onError = debugMode + "" === debugMode - ? new Function("", "return '" + debugMode + "';") + ? function() { return debugMode; } : $isFunction(debugMode) ? debugMode : undefined, @@ -2353,7 +2620,7 @@ $viewsSettings = $views.settings; // Otherwise return "" var self = this, tagCtx = self.tagCtx, - ret = (self.rendering.done || !val && (arguments.length || !tagCtx.index)) + ret = (self.rendering.done || !val && (tagCtx.args.length || !tagCtx.index)) ? "" : (self.rendering.done = true, self.selected = tagCtx.index, @@ -2364,21 +2631,53 @@ $viewsSettings = $views.settings; flow: true }, "for": { + sortDataMap: dataMap(getTargetSorted), + init: function(val, cloned) { + var l, tagCtx, props, sort, + self = this, + tagCtxs = self.tagCtxs; + l = tagCtxs.length; + while (l--) { + tagCtx = tagCtxs[l]; + props = tagCtx.props; + tagCtx.argDefault = props.end === undefined || tagCtx.args.length > 0; // Default to #data except for auto-create range scenario {{for start=xxx end=yyy step=zzz}} + + if (tagCtx.argDefault !== false && $isArray(tagCtx.args[0]) + && (props.sort !== undefined || tagCtx.params.props.start || tagCtx.params.props.end || props.step !== undefined || props.filter || props.reverse)) { + props.dataMap = self.sortDataMap; + } + } + }, render: function(val) { // This function is called once for {{for}} and once for each {{else}}. // We will use the tag.rendering object for carrying rendering state across the calls. - var finalElse = !arguments.length, - value, + var value, filter, srtField, isArray, i, sorted, end, step, self = this, tagCtx = self.tagCtx, + range = tagCtx.argDefault === false, + props = tagCtx.props, + iterate = range || tagCtx.args.length, // Not final else and not auto-create range result = "", done = 0; if (!self.rendering.done) { - value = finalElse ? tagCtx.view.data : val; // For the final else, defaults to current data without iteration. + value = iterate ? val : tagCtx.view.data; // For the final else, defaults to current data without iteration. + + if (range) { + range = props.reverse ? "unshift" : "push"; + end = +props.end; + step = +props.step || 1; + value = []; // auto-create integer array scenario of {{for start=xxx end=yyy}} + for (i = +props.start || 0; (end - i) * step > 0; i += step) { + value[range](i); + } + } if (value !== undefined) { - result += tagCtx.render(value, finalElse); // Iterates except on final else, if data is an array. (Use {{include}} to compose templates without array iteration) - done += $isArray(value) ? value.length : 1; + isArray = $isArray(value); + result += tagCtx.render(value, !iterate || props.noIteration); + // Iterates if data is an array, except on final else - or if noIteration property + // set to true. (Use {{include}} to compose templates without array iteration) + done += isArray ? value.length : 1; } if (self.rendering.done = done) { self.selected = tagCtx.index; @@ -2392,6 +2691,7 @@ $viewsSettings = $views.settings; props: { baseTag: "for", dataMap: dataMap(getTargetProps), + init: noop, // Don't execute the base init() of the "for" tag flow: true }, include: { @@ -2413,6 +2713,8 @@ $viewsSettings = $views.settings; $converters({ html: htmlEncode, attr: htmlEncode, // Includes > encoding since rConvertMarkers in JsViews does not skip > characters in attribute strings + encode: dataEncode, + unencode: dataUnencode, // Includes > encoding since rConvertMarkers in JsViews does not skip > characters in attribute strings url: function(text) { // URL encoding helper. return text != undefined ? encodeURI("" + text) : text === null ? text : ""; // null returns null, e.g. to remove attribute. undefined returns "" @@ -2424,7 +2726,6 @@ $subSettings = $sub.settings; $isArray = ($||jsr).isArray; $viewsSettings.delimiters("{{", "}}", "^"); - // NODE.JS-SPECIFIC CODE: var nodeFs = require('fs'), nodePath = require('path'), diff --git a/jsrender.js b/jsrender.js index 9500ad3..a77d4df 100644 --- a/jsrender.js +++ b/jsrender.js @@ -1,11 +1,11 @@ -/*! JsRender v0.9.90 (Beta): http://jsviews.com/#jsrender */ +/*! JsRender v0.9.91 (Beta): http://jsviews.com/#jsrender */ /*! **VERSION FOR WEB** (For NODE.JS see http://jsviews.com/download/jsrender-node.js) */ /* * Best-of-breed templating in browser or on Node.js. * Does not require jQuery, or HTML DOM * Integrates with JsViews (http://jsviews.com/#jsviews) * - * Copyright 2017, Boris Moore + * Copyright 2018, Boris Moore * Released under the MIT License. */ @@ -44,8 +44,8 @@ var setGlobals = $ === false; // Only set globals if script block in browser (no $ = $ && $.fn ? $ : global.jQuery; // $ is jQuery passed in by CommonJS loader (Browserify), or global jQuery. -var versionNumber = "v0.9.90", - jsvStoreName, rTag, rTmplString, topView, $views, $expando, +var versionNumber = "v0.9.91", + jsvStoreName, rTag, rTmplString, topView, $views, $expando, _ocp = "_ocp", // Observable contextual parameter //TODO tmplFnsCache = {}, @@ -54,8 +54,8 @@ var versionNumber = "v0.9.90", rPath = /^(!*?)(?:null|true|false|\d[\d.]*|([\w$]+|\.|~([\w$]+)|#(view|([\w$]+))?)([\w$.^]*?)(?:[.[^]([\w$]+)\]?)?)$/g, // not object helper view viewProperty pathTokens leafToken - rParams = /(\()(?=\s*\()|(?:([([])\s*)?(?:(\^?)(!*?[#~]?[\w$.^]+)?\s*((\+\+|--)|\+|-|&&|\|\||===|!==|==|!=|<=|>=|[<>%*:?\/]|(=))\s*|(!*?[#~]?[\w$.^]+)([([])?)|(,\s*)|(\(?)\\?(?:(')|("))|(?:\s*(([)\]])(?=\s*[.^]|\s*$|[^([])|[)\]])([([]?))|(\s+)/g, - // lftPrn0 lftPrn bound path operator err eq path2 prn comma lftPrn2 apos quot rtPrn rtPrnDot prn2 space + rParams = /(\()(?=\s*\()|(?:([([])\s*)?(?:(\^?)(~?[\w$.^]+)?\s*((\+\+|--)|\+|-|~(?![\w$_])|&&|\|\||===|!==|==|!=|<=|>=|[<>%*:?\/]|(=))\s*|(!*?(@)?[#~]?[\w$.^]+)([([])?)|(,\s*)|(\(?)\\?(?:(')|("))|(?:\s*(([)\]])(?=[.^]|\s*$|[^([])|[)\]])([([]?))|(\s+)/g, + // lftPrn0 lftPrn bound path operator err eq path2 late prn comma lftPrn2 apos quot rtPrn rtPrnDot prn2 space // (left paren? followed by (path? followed by operator) or (path followed by left paren?)) or comma or apos or quot or right paren or space isRenderCall, @@ -70,6 +70,9 @@ var versionNumber = "v0.9.90", rHasHandlers = /^on[A-Z]|^convert(Back)?$/, rWrappedInViewMarker = /^\#\d+_`[\s\S]*\/\d+_`$/, rHtmlEncode = rAttrEncode, + rDataEncode = /[&<>]/g, + rDataUnencode = /&(amp|gt|lt);/g, + rBracketQuote = /\[['"]?|['"]?\]/g, viewId = 0, charEntities = { "&": "&", @@ -81,6 +84,11 @@ var versionNumber = "v0.9.90", "`": "`", "=": "=" }, + charsFromEntities = { + amp: "&", + gt: ">", + lt: "<" + }, HTML = "html", OBJECT = "object", tmplAttr = "data-jsv-tmpl", @@ -131,7 +139,7 @@ var versionNumber = "v0.9.90", allowCode: false }, advSet: noop, // Update advanced settings - _ths: tagHandlersFromProps, + _thp: tagHandlersFromProps, _gm: getMethod, _tg: function() {}, // Constructor for tagDef _cnvt: convertVal, @@ -186,7 +194,7 @@ function getMethod(baseMethod, method) { : getDerivedMethod(noop, baseMethod), // baseMethod is not derived so make its base method be the noop method method ); - method._d = 1; // Add flag that this is a derived method + method._d = (baseMethod && baseMethod._d || 0) + 1; // Add flag for derived method (incremented for derived of derived...) } return method; } @@ -348,66 +356,126 @@ getIndex.depends = "index"; // View.hlp //========== -function contextParameter(key, value, isContextCb) { +function getPathObject(ob, path, ltOb, fn) { // Iterate through path to late paths: @a.b.c paths + // Return "" (or noop if leaf is a function @a.b.c(...) ) if intermediate object not yet available + var prevOb, tokens, l, + i = 0; + if (ltOb === 1) { + fn = 1; + ltOb = undefined; + } + // Paths like ^a^b^c or ~^a^b^c will not throw if an object in path is undefined. + if (path) { + tokens = path.split("."); + l = tokens.length; + + for (; ob && i < l; i++) { + prevOb = ob; + ob = tokens[i] ? ob[tokens[i]] : ob; + } + } + if (ltOb) { + ltOb.lt = ltOb.lt || i 1, store = storeView.ctx; - if (key in store || key in (store = $helpers)) { - res = store && store[key]; - if (key === "tag" || key === "root" || key === "parentTags" || storeView._.it === key ) { - return res; + if (key) { + if (!storeView._) { // tagCtx.ctxPrm() call + tagElse = storeView.index; + storeView = storeView.tag; } - } else { - store = undefined; - } - if (!res || !$isFunction(res) && storeView.linked || storeView.tagCtx) { // Data-linked view, or tag instance - if (!res || !res._cxp) { - // Not a contextual parameter - if (store !== $helpers) { + callView = storeView; + if (store && store.hasOwnProperty(key) || (store = $helpers).hasOwnProperty(key)) { + res = store[key]; + if (key === "tag" || key === "tagCtx" || key === "root" || key === "parentTags" || storeView._.it === key ) { + return res; + } + } else { + store = undefined; + } + if (storeView.tagCtx || storeView.linked) { // Data-linked view, or tag instance + if (!res || !res._cxp) { + // Not a contextual parameter // Set storeView to tag (if this is a tag.ctxPrm() call) or to root view ("data" view of linked template) - storeView = storeView.tagCtx - ? storeView // Is a tag, not a view - : (storeView = storeView.scope || storeView, !storeView.isTop && storeView.ctx.tag || storeView); + storeView = storeView.tagCtx || $isFunction(res) + ? storeView // Is a tag, not a view, or is a computed contextual parameter, so scope to the callView, no the 'scope view' + : (storeView = storeView.scope || storeView, + !storeView.isTop && storeView.ctx.tag // If this view is in a tag, set storeView to the tag + || storeView); + if (res !== undefined && storeView.tagCtx) { + // If storeView is a tag, but the contextual parameter has been set at at higher level (e.g. helpers)... + storeView = storeView.tagCtx.view.scope; // then move storeView to the outer level (scope of tag container view) + } store = storeView._ocps; - res = store && store[key] || res; + res = store && store.hasOwnProperty(key) && store[key] || res; + if (!(res && res._cxp) && (get || isUpdate)) { + // Create observable contextual parameter + (store || (storeView._ocps = storeView._ocps || {}))[key] + = res + = [{ + _ocp: res, // The observable contextual parameter value + _vw: callView, + _key: key + }]; + res._cxp = { + path: _ocp, + ind: 0, + updateValue: function(val, path) { + $.observable(res[0]).setProperty(_ocp, val); // Set the value (res[0]._ocp) + return this; + } + }; + } } - if (!(res && res._cxp) && (isContextCb || isUpdate)) { - res = $sub._crcp(key, res, storeView, store); // Create observable contextual parameter + if (obsCtxPrm = res && res._cxp) { + // If this helper resource is an observable contextual parameter + if (arguments.length > 2) { + deps = res[1] ? $sub._ceo(res[1].deps) : [_ocp]; // fn deps (with any exprObs cloned using $sub._ceo) + deps.unshift(res[0]); // view + deps._cxp = obsCtxPrm; + // In a context callback for a contextual param, we set get = true, to get ctxPrm [view, dependencies...] array - needed for observe call + return deps; + } + tagElse = obsCtxPrm.tagElse; + newRes = res[1] // linkFn for compiled expression + ? obsCtxPrm.tag && obsCtxPrm.tag.cvtArgs + ? obsCtxPrm.tag.cvtArgs(1, tagElse)[obsCtxPrm.ind] // = tag.bndArgs() - for tag contextual parameter + : res[1](res[0].data, res[0], $sub) // = fn(data, view, $sub) for compiled binding expression + : res[0]._ocp; // Observable contextual parameter (uninitialized, or initialized as static expression, so no path dependencies) + if (isUpdate) { + if (res && newRes !== value) { + $sub._ucp(key, value, storeView, obsCtxPrm); // Update observable contextual parameter + } + return storeView; + } + res = newRes; } } - if (obsCtxPrm = res && res._cxp) { - if (isUpdate) { - return $sub._ucp(key, value, storeView, obsCtxPrm); // Update observable contextual parameter - } - if (isContextCb) { // If this helper resource is an observable contextual parameter - // In a context callback for a contextual param, return the [view, dependencies...] array - needed for observe call - deps = res[1] ? $sub._ceo(res[1].deps) : [_ocp]; // fn deps (with any exprObs cloned using $sub._ceo) - deps.unshift(res[0]); // view - deps._cxp = obsCtxPrm; - return deps; - } - res = res[1] // linkFn for compiled expression - ? obsCtxPrm.tag && obsCtxPrm.tag.cvtArgs - ? obsCtxPrm.tag.cvtArgs(true, obsCtxPrm.tagElse)[obsCtxPrm.ind] // = tag.bndArgs() - for tag contextual parameter - : res[1](res[0].data, res[0], $sub) // = fn(data, view, $sub) for compiled binding expression - : res[0]._ocp; // Observable contextual parameter (uninitialized, or initialized as static expression, so no path dependencies) - } - } - if (res && $isFunction(res)) { - // If a helper is of type function, and not already wrapped, we will wrap it, so if called with no this pointer it will be called with the - // view as 'this' context. If the helper ~foo() was in a data-link expression, the view will have a 'temporary' linkCtx property too. - // Note that helper functions on deeper paths will have specific this pointers, from the preceding path. - // For example, ~util.foo() will have the ~util object as 'this' pointer - wrapped = function() { - return res.apply((!this || this === global) ? storeView : this, arguments); - }; - $extend(wrapped, res); // Attach same expandos (if any) to the wrapped function - wrapped._vw = storeView; + if (res && $isFunction(res)) { + // If a helper is of type function we will wrap it, so if called with no this pointer it will be called with the + // view as 'this' context. If the helper ~foo() was in a data-link expression, the view will have a 'temporary' linkCtx property too. + // Note that helper functions on deeper paths will have specific this pointers, from the preceding path. + // For example, ~util.foo() will have the ~util object as 'this' pointer + wrapped = function() { + return res.apply((!this || this === global) ? callView : this, arguments); + }; + $extend(wrapped, res); // Attach same expandos (if any) to the wrapped function + wrapped._vw = callView; + } + return wrapped || res; } - return wrapped || res; } function getTemplate(tmpl) { @@ -437,7 +505,6 @@ function convertVal(converter, view, tagCtx, onError) { tagCtx = boundTag(view.data, view, $sub); } boundTag = boundTag._bd && boundTag; - value = tagCtx.args[0]; if (converter || boundTag) { tag = linkCtx && linkCtx.tag; tagCtx.view = view; @@ -445,13 +512,16 @@ function convertVal(converter, view, tagCtx, onError) { tag = $extend(new $sub._tg(), { _: { bnd: boundTag, - unlinked: true + unlinked: true, + lt: tagCtx.lt // If a late path @some.path has not returned @some object, mark tag as late }, inline: !linkCtx, tagName: ":", convert: converter, flow: true, - tagCtx: tagCtx + tagCtx: tagCtx, + tagCtxs: [tagCtx], + _is: "tag" }); argsLen = tagCtx.args.length; if (argsLen>1) { @@ -470,8 +540,10 @@ function convertVal(converter, view, tagCtx, onError) { tag._er = onError && value; tag.ctx = tagCtx.ctx || tag.ctx || {}; tagCtx.ctx = undefined; - value = tag.cvtArgs()[0]; // If there is a convertBack but no convert, converter will be "true" + tag._er = onError && value; + } else { + value = tagCtx.args[0]; } // Call onRender (used by JsViews if present, to add binding annotations around rendered content) @@ -481,8 +553,8 @@ function convertVal(converter, view, tagCtx, onError) { return value != undefined ? value : ""; } -function convertArgs(bound, tagElse) { // tag.cvtArgs() - var l, key, boundArgs, args, bindTo, tag, converter, +function convertArgs(bound, tagElse) { // tag.cvtArgs() or tag.cvtArgs(trueOrFalse, tagElse) + var l, key, boundArgs, args, bindFrom, tag, converter, tagCtx = this; if (tagCtx.tagName) { @@ -492,7 +564,7 @@ function convertArgs(bound, tagElse) { // tag.cvtArgs() tag = tagCtx.tag; } - bindTo = tag.bindTo; + bindFrom = tag.bindFrom; args = tagCtx.args; if ((converter = tag.convert) && "" + converter === converter) { @@ -501,38 +573,37 @@ function convertArgs(bound, tagElse) { // tag.cvtArgs() : (tagCtx.view.getRsc("converters", converter) || error("Unknown converter: '" + converter + "'")); } - if (bound && bound.length) { - args = bound; - } else { - if (converter && !bound) { // If there is a converter, use a copy of the tagCtx.args array for rendering, and replace the args[0] in - args = args.slice(); // the copied array with the converted value. But we do not modify the value of tag.tagCtx.args[0] (the original args array) + if (converter && !bound) { // If there is a converter, use a copy of the tagCtx.args array for rendering, and replace the args[0] in + args = args.slice(); // the copied array with the converted value. But we do not modify the value of tag.tagCtx.args[0] (the original args array) + } + if (bindFrom) { // Get the values of the boundArgs + boundArgs = []; + l = bindFrom.length; + while (l--) { + key = bindFrom[l]; + boundArgs.unshift(argOrProp(tagCtx, key)); } - if (bindTo) { // Get the values of the boundArgs - boundArgs = []; - l = bindTo.length; - while (l--) { - key = bindTo[l]; - boundArgs.unshift(argOrProp(tagCtx, key)); - } - if (bound) { - args = boundArgs; // Call to convertBoundArgs() - returns the boundArgs - } + if (bound) { + args = boundArgs; // Call to bndArgs() - returns the boundArgs } } if (converter) { - bindTo = bindTo || [0]; - l = bindTo.length; converter = converter.apply(tag, boundArgs || args); + if (converter === undefined) { + return args; // Returning undefined from a converter is equivalent to not having a converter. + } + bindFrom = bindFrom || [0]; + l = bindFrom.length; if (!$isArray(converter) || converter.length !== l) { converter = [converter]; - bindTo = [0]; + bindFrom = [0]; l = 1; } - if (bound) { // Call to bndArgs convertBoundArgs() - so apply converter to all boundArgs + if (bound) { // Call to bndArgs() - so apply converter to all boundArgs args = converter; // The array of values returned from the converter } else { // Call to cvtArgs() while (l--) { - key = bindTo[l]; + key = bindFrom[l]; if (+key === key) { args[key] = converter[l]; } @@ -548,7 +619,7 @@ function argOrProp(context, key) { } function convertBoundArgs(tagElse) { // tag.bndArgs() - return this.cvtArgs(true, tagElse); + return this.cvtArgs(1, tagElse); } //============= @@ -569,20 +640,26 @@ function getResource(resourceType, itemName) { } function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) { - function makeArray(type) { - var linkedElement; - if (linkedElement = tag[type]) { - tag[type] = linkedElement = $isArray(linkedElement) ? linkedElement: [linkedElement]; - - if (bindToLength !== linkedElement.length) { - error(type + " length not same as bindTo "); + function bindToOrBindFrom(type) { + var bindArray = tag[type]; + + if (bindArray !== undefined) { + bindArray = $isArray(bindArray) ? bindArray : [bindArray]; + m = bindArray.length; + while (m--) { + key = bindArray[m]; + if (!isNaN(parseInt(key))) { + bindArray[m] = parseInt(key); // Convert "0" to 0, etc. + } } } + + return bindArray || [0]; } parentView = parentView || topView; - var tag, tag_, tagDef, template, tags, attr, parentTag, l, m, n, itemRet, tagCtx, tagCtxCtx, ctxPrm, bindTo, - content, callInit, mapDef, thisMap, args, props, tagDataMap, contentCtx, key, bindToLength, + var tag, tagDef, template, tags, attr, parentTag, l, m, n, itemRet, tagCtx, tagCtxCtx, ctxPrm, bindTo, bindFrom, initVal, + content, callInit, mapDef, thisMap, args, bdArgs, props, tagDataMap, contentCtx, key, bindFromLength, bindToLength, linkedElement, defaultCtx, i = 0, ret = "", linkCtx = parentView.linkCtx || 0, @@ -600,14 +677,12 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) { tagDef = parentView.getRsc("tags", tagName) || error("Unknown tag: {{" + tagName + "}} "); template = tagDef.template; } - if (onError === undefined && boundTag) { - if (boundTag._lr = (tagDef.lateRender || boundTag._lr) && boundTag._lr !== "false") { - onError = ""; // If lateRender, set temporary onError, to skip initial rendering (and render just "") - } + if (onError === undefined && boundTag && (boundTag._lr = (tagDef.lateRender && boundTag._lr!== false || boundTag._lr))) { + onError = ""; // If lateRender, set temporary onError, to skip initial rendering (and render just "") } if (onError !== undefined) { ret += onError; - tagCtxs = onError = [{props: {}, args: [], params: {}}]; + tagCtxs = onError = [{props: {}, args: [], params: {props:{}}}]; } else if (boundTag) { tagCtxs = boundTag(parentView.data, parentView, $sub); } @@ -623,9 +698,12 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) { tagCtx.tmpl = tagCtx.content = parentTmpl.tmpls[content - 1]; // Set the tmpl property to the content of the block tag } tagCtx.index = i; + tagCtx.ctxPrm = contextParameter; tagCtx.render = renderContent; + tagCtx.cvtArgs = convertArgs; + tagCtx.bndArgs = convertBoundArgs; tagCtx.view = parentView; - tagCtx.ctx = extendCtx(tagCtx.ctx, ctx); // Clone and extend parentView.ctx + tagCtx.ctx = extendCtx(extendCtx(tagCtx.ctx, tagDef && tagDef.ctx), ctx); // Clone and extend parentView.ctx } if (tmpl = tagCtx.props.tmpl) { // If the tmpl property is overridden, set the value (when initializing, or, in case of binding: ^tmpl=..., when updating) @@ -643,7 +721,6 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) { tag.parent = parentTag = ctx && ctx.tag; tag.tagCtxs = tagCtxs; - tagDataMap = tag.dataMap; if (linkCtx) { tag.inline = false; @@ -652,14 +729,17 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) { } if (tag._.bnd = boundTag || linkCtx.fn) { // Bound if {^{tag...}} or data-link="{tag...}" + tag._.ths = tagCtx.params.props.this; // Tag has a this=expr binding, to get javascript reference to tag instance + tag._.lt = tagCtxs.lt; // If a late path @some.path has not returned @some object, mark tag as late tag._.arrVws = {}; } else if (tag.dataBoundOnly) { error(tagName + " must be data-bound:\n{^{" + tagName + "}}"); } //TODO better perf for childTags() - keep child tag.tags array, (and remove child, when disposed) // tag.tags = []; + } else if (linkCtx && linkCtx.fn._lr) { + callInit = !!tag.init; } - tagCtxs = tag.tagCtxs; tagDataMap = tag.dataMap; tagCtx.tag = tag; @@ -676,11 +756,12 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) { //TODO better perf for childTags: parentTag.tags.push(tag); } tags[tag.tagName] = tagCtxCtx.tag = tag; + tagCtxCtx.tagCtx = tagCtx; } } if (!(tag._er = onError)) { tagHandlersFromProps(tag, tagCtxs[0]); - tag.rendering = {}; // Provide object for state during render calls to tag and elses. (Used by {{if}} and {{for}}...) + tag.rendering = {rndr: tag.rendering}; // Provide object for state during render calls to tag and elses. (Used by {{if}} and {{for}}...) for (i = 0; i < l; i++) { // Iterate tagCtx for each {{else}} block tagCtx = tag.tagCtx = tagCtxs[i]; props = tagCtx.props; @@ -691,62 +772,95 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) { tag.init(tagCtx, linkCtx, tag.ctx); callInit = undefined; } - if (!tagCtx.args.length && tag.argDefault !== false) { + if (!tagCtx.args.length && tagCtx.argDefault !== false && tag.argDefault !== false) { tagCtx.args = args = [tagCtx.view.data]; // Missing first arg defaults to the current data context tagCtx.params.args = ["#data"]; } - bindTo = tag.bindTo; + bindTo = bindToOrBindFrom("bindTo"); - if (bindTo !== undefined) { - bindTo = tag.bindTo = $isArray(bindTo) ? bindTo : [bindTo]; - m = bindTo.length; - while (m--) { - key = bindTo[m]; - if (!isNaN(parseInt(key))) { - key = parseInt(key); // Convert "0" to 0, etc. - } - bindTo[m] = key; - } + if (tag.bindTo !== undefined) { + tag.bindTo = bindTo; } - bindTo = tag.bindTo || [0]; + if (tag.bindFrom !== undefined) { + tag.bindFrom = bindToOrBindFrom("bindFrom"); + } else if (tag.bindTo) { + tag.bindFrom = tag.bindTo = bindTo; + } + bindFrom = tag.bindFrom || bindTo; + bindToLength = bindTo.length; - if (tag._.bnd){ - makeArray("linkedElement"); - makeArray("linkedCtxParam"); + bindFromLength = bindFrom.length; + + if (tag._.bnd && (linkedElement = tag.linkedElement)) { + tag.linkedElement = linkedElement = $isArray(linkedElement) ? linkedElement: [linkedElement]; + + if (bindToLength !== linkedElement.length) { + error("linkedElement not same length as bindTo"); + } + } + if (linkedElement = tag.linkedCtxParam) { + tag.linkedCtxParam = linkedElement = $isArray(linkedElement) ? linkedElement: [linkedElement]; + + if (bindFromLength !== linkedElement.length) { + error("linkedCtxParam not same length as bindFrom/bindTo"); + } + } + + if (bindFrom) { + tag._.fromIndex = {}; // Hash of bindFrom index which has same path value as bindTo index. fromIndex = tag._.fromIndex[toIndex] + tag._.toIndex = {}; // Hash of bindFrom index which has same path value as bindTo index. fromIndex = tag._.fromIndex[toIndex] + n = bindFromLength; + while (n--) { + key = bindFrom[n]; + m = bindToLength; + while (m--) { + if (key === bindTo[m]) { + tag._.fromIndex[m] = n; + tag._.toIndex[n] = m; + } + } + } } if (linkCtx) { // Set attr on linkCtx to ensure outputting to the correct target attribute. // Setting either linkCtx.attr or this.attr in the init() allows per-instance choice of target attrib. - linkCtx.attr = tag.attr = linkCtx.attr || tag.attr; + linkCtx.attr = tag.attr = linkCtx.attr || tag.attr || linkCtx._dfAt; } attr = tag.attr; tag._.noVws = attr && attr !== HTML; } args = tag.cvtArgs(undefined, i); if (tag.linkedCtxParam) { - m = bindToLength; + bdArgs = tag.cvtArgs(1, i); + m = bindFromLength; + defaultCtx = tag.constructor.prototype.ctx; while (m--) { if (ctxPrm = tag.linkedCtxParam[m]) { - key = bindTo[m]; + key = bindFrom[m]; + initVal = bdArgs[m]; // Create tag contextual parameter - tagCtx.ctx[ctxPrm] = $sub._cp(argOrProp(tagCtx, key), argOrProp(tagCtx.params, key), tagCtx.view, tag._.bnd && {tag: tag, ind: m, tagElse: i}); + tagCtx.ctx[ctxPrm] = $sub._cp( + defaultCtx && initVal === undefined ? defaultCtx[ctxPrm]: initVal, + initVal !== undefined && argOrProp(tagCtx.params, key), + tagCtx.view, + tag._.bnd && {tag: tag, cvt: tag.convert, ind: m, tagElse: i} + ); } } } - if (mapDef = props.dataMap || tagDataMap) { - if (args.length || props.dataMap) { - thisMap = tagCtx.map; - if (!thisMap || thisMap.src !== args[0] || isUpdate) { - if (thisMap && thisMap.src) { - thisMap.unmap(); // only called if observable map - not when only used in JsRender, e.g. by {{props}} - } - thisMap = tagCtx.map = mapDef.map(args[0], props, undefined, !tag._.bnd); + if ((mapDef = props.dataMap || tagDataMap) && (args.length || props.dataMap)) { + thisMap = tagCtx.map; + if (!thisMap || thisMap.src !== args[0] || isUpdate) { + if (thisMap && thisMap.src) { + thisMap.unmap(); // only called if observable map - not when only used in JsRender, e.g. by {{props}} } - args = [thisMap.tgt]; + mapDef.map(args[0], tagCtx, thisMap, !tag._.bnd); + thisMap = tagCtx.map; } + args = [thisMap.tgt]; } itemRet = undefined; @@ -779,18 +893,16 @@ function renderTag(tagName, parentView, tmpl, tagCtxs, isUpdate, onError) { // No return value from render, and no template/content tagCtx.render(...), so return undefined ret = ret ? ret + (itemRet || "") : itemRet; // If no rendered content, this will be undefined } - tag.rendering = undefined; + tag.rendering = tag.rendering.rndr; // Remove tag.rendering object (if this is outermost render call. (In case of nested calls) } tag.tagCtx = tagCtxs[0]; tag.ctx = tag.tagCtx.ctx; - if (tag._.noVws) { - if (tag.inline) { - // inline tag with attr set to "text" will insert HTML-encoded content - as if it was element-based innerText - ret = attr === "text" - ? $converters.html(ret) - : ""; - } + if (tag._.noVws && tag.inline) { + // inline tag with attr set to "text" will insert HTML-encoded content - as if it was element-based innerText + ret = attr === "text" + ? $converters.html(ret) + : ""; } return boundTag && parentView._.onRender // Call onRender (used by JsViews if present, to add binding annotations around rendered content) @@ -830,6 +942,7 @@ function View(context, type, parentView, data, template, key, onRender, contentT parentView_ = parentView._; self.isTop = parentView_.scp; // Is top content view of a link("#container", ...) call self.scope = (!context.tag || context.tag === parentView.ctx.tag) && !self.isTop && parentView.scope || self; + // Scope for contextParams - closest non flow tag ancestor or root view if (parentView_.useKey) { // Parent is not an 'array view'. Add this view to its views object // self._key = is the key in the parent view hash @@ -855,6 +968,7 @@ View.prototype = { getRsc: getResource, getTmpl: getTemplate, ctxPrm: contextParameter, + getOb: getPathObject, _is: "view" }; @@ -879,8 +993,7 @@ function compileChildResources(parentTmpl) { //=============== function compileTag(name, tagDef, parentTmpl) { - var tmpl, baseTag, prop, l, key, bindToLength, - bindTo = tagDef.bindTo, + var tmpl, baseTag, prop, compiledDef = new $sub._tg(); function Tag() { @@ -904,10 +1017,12 @@ function compileTag(name, tagDef, parentTmpl) { if (baseTag = tagDef.baseTag) { tagDef.flow = !!tagDef.flow; // Set flow property, so defaults to false even if baseTag has flow=true - tagDef.baseTag = baseTag = "" + baseTag === baseTag + baseTag = "" + baseTag === baseTag ? (parentTmpl && parentTmpl.tags[baseTag] || $tags[baseTag]) : baseTag; - + if (!baseTag) { + error('baseTag: "' + tagDef.baseTag + '" not found'); + } compiledDef = $extend(compiledDef, baseTag); for (prop in tagDef) { @@ -966,11 +1081,9 @@ function compileTmpl(name, tmpl, parentTmpl, options) { }// END BROWSER-SPECIFIC CODE } //BROWSER-SPECIFIC CODE if (elem) { - // Generally this is a script element. - // However we allow it to be any element, so you can for example take the content of a div, - // use it as a template, and replace it by the same content rendered against data. - // e.g. for linking the content of a div to a container, and using the initial content as template: - // $.link("#content", model, {tmpl: "#content"}); + if (elem.tagName !== "SCRIPT") { + error(value + ": Use script block, not " + elem.tagName); + } if (options) { // We will compile a new template using the markup in the script element value = elem.innerHTML; @@ -1020,23 +1133,27 @@ function compileTmpl(name, tmpl, parentTmpl, options) { // If options, then this was already compiled from a (script) element template declaration. // If not, then if tmpl is a template object, use it for options - options = options || (tmpl.markup ? tmpl : {}); - options.tmplName = name; + options = options || (tmpl.markup + ? tmpl.bnds + ? $extend({}, tmpl) + : tmpl + : {} + ); + + options.tmplName = options.tmplName || name || "unnamed"; if (parentTmpl) { options._parentTmpl = parentTmpl; } // If tmpl is not a markup string or a selector string, then it must be a template object // In that case, get it from the markup property of the object - if (!tmplOrMarkup && tmpl.markup && (tmplOrMarkup = lookupTemplate(tmpl.markup))) { - if (tmplOrMarkup.fn) { - // If the string references a compiled template object, need to recompile to merge any modified options - tmplOrMarkup = tmplOrMarkup.markup; - } + if (!tmplOrMarkup && tmpl.markup && (tmplOrMarkup = lookupTemplate(tmpl.markup)) && tmplOrMarkup.fn) { + // If the string references a compiled template object, need to recompile to merge any modified options + tmplOrMarkup = tmplOrMarkup.markup; } if (tmplOrMarkup !== undefined) { - if (tmplOrMarkup.fn || tmpl.fn) { + if (tmplOrMarkup.render || tmpl.render) { // tmpl is already compiled, so use it - if (tmplOrMarkup.fn) { + if (tmplOrMarkup.tmpls) { compiledTmpl = tmplOrMarkup; } } else { @@ -1291,19 +1408,20 @@ function tmplObject(markup, options) { // Template object constructor var htmlTag, wrapMap = $subSettingsAdvanced._wm || {}, // Only used in JsViews. Otherwise empty: {} - tmpl = $extend( - { - tmpls: [], - links: {}, // Compiled functions for link expressions - bnds: [], - _is: "template", - render: renderContent - }, - options - ); + tmpl = { + tmpls: [], + links: {}, // Compiled functions for link expressions + bnds: [], + _is: "template", + render: renderContent + }; + + if (options) { + tmpl = $extend(tmpl, options); + } tmpl.markup = markup; - if (!options.htmlTag) { + if (!tmpl.htmlTag) { // Set tmpl.tag to the top-level HTML tag used in the template, if any... htmlTag = rFirstElem.exec(markup); tmpl.htmlTag = htmlTag ? htmlTag[1].toLowerCase() : ""; @@ -1394,13 +1512,14 @@ function addSetting(st) { }; } -//========= -// dataMap -//========= +//======================== +// dataMap for render only +//======================== function dataMap(mapDef) { function Map(source, options) { this.tgt = mapDef.getTgt(source, options); + options.map = this; } if ($isFunction(mapDef)) { @@ -1442,7 +1561,9 @@ function renderContent(data, context, noIteration, parentView, key, onRender) { view = view || tagCtx.view; tmpl = view.getTmpl(tag.template || tagCtx.tmpl); if (!arguments.length) { - data = view; + data = tag.contentCtx && $isFunction(tag.contentCtx) + ? data = tag.contentCtx(data) + : view; // Default data context for wrapped block content is the first argument } } else { // This is a template.render(...) call @@ -1509,7 +1630,7 @@ function renderWithViews(tmpl, data, context, noIteration, view, key, onRender, // Render template against data as a tree of subviews (nested rendered template instances), or as a string (top-level template). // If the data is the parent view, treat as noIteration, re-render with the same data context. // tmpl can be a string (e.g. rendered by a tag.render() method), or a compiled template. - var i, l, newView, childView, itemResult, swapContent, contentTmpl, outerOnRender, tmplName, itemVar, newCtx, tagCtx, + var i, l, newView, childView, itemResult, swapContent, contentTmpl, outerOnRender, tmplName, itemVar, newCtx, tagCtx, noLinking, result = ""; if (tag) { @@ -1540,7 +1661,6 @@ function renderWithViews(tmpl, data, context, noIteration, view, key, onRender, context = context || {}; context.link = false; } - if (itemVar = tagCtx.props.itemVar) { if (itemVar.charAt(0) !== "~") { syntaxError("Use itemVar='~myItem'"); @@ -1551,6 +1671,12 @@ function renderWithViews(tmpl, data, context, noIteration, view, key, onRender, if (view) { onRender = onRender || view._.onRender; + noLinking = context && context.link === false; + + if (noLinking && view._.nl) { + onRender = undefined; + } + context = extendCtx(context, view.ctx); } @@ -1560,7 +1686,7 @@ function renderWithViews(tmpl, data, context, noIteration, view, key, onRender, } // If link===false, do not call onRender, so no data-linking marker nodes - if (onRender && (context && context.link === false || tag && tag._.noVws)) { + if (onRender && tag && tag._.noVws) { onRender = undefined; } outerOnRender = onRender; @@ -1582,10 +1708,12 @@ function renderWithViews(tmpl, data, context, noIteration, view, key, onRender, ? view : (key !== undefined && view) || new View(context, "array", view, data, tmpl, key, onRender, contentTmpl); + newView._.nl= noLinking; if (view && view._.useKey) { // Parent is not an 'array view' newView._.bnd = !tag || tag._.bnd && tag; // For array views that are data bound for collection change events, set the // view._.bnd property to true for top-level link() or data-link="{for}", or to the tag instance for a data-bound tag, e.g. {^{for ...}} + newView.tag = tag; } for (i = 0, l = data.length; i < l; i++) { // Create a view for each data item. @@ -1606,10 +1734,11 @@ function renderWithViews(tmpl, data, context, noIteration, view, key, onRender, } newView = swapContent ? view : new View(newCtx, tmplName || "data", view, data, tmpl, key, onRender, contentTmpl); newView._.it = itemVar; + newView.tag = tag; + newView._.nl = noLinking; result += tmpl.fn(data, newView, $sub); } if (tag) { - newView.tag = tag; newView.tagElse = tagCtx.index; tagCtx.contentView = newView; } @@ -1714,7 +1843,7 @@ function tmplFn(markup, tmpl, isLinkExpr, convertBack, hasElse) { } slash = slash || isLinkExpr && !hasElse; - var late, + var late, openTagName, isLateOb, pathBindings = (bind || isLinkExpr) && [[]], // pathBindings is an array of arrays for arg bindings and a hash of arrays for prop bindings props = "", args = "", @@ -1738,23 +1867,31 @@ function tmplFn(markup, tmpl, isLinkExpr, convertBack, hasElse) { } else if (tagName) { if (tagName === "else") { if (rTestElseIf.test(params)) { - syntaxError('for "{{else if expr}}" use "{{else expr}}"'); + syntaxError('For "{{else if expr}}" use "{{else expr}}"'); } - pathBindings = current[8] && [[]]; - current[9] = markup.substring(current[9], index); // contentMarkup for block tag + pathBindings = current[9] && [[]]; + current[10] = markup.substring(current[10], index); // contentMarkup for block tag + openTagName = current[11] || current[0] || syntaxError("Mismatched: " + all); + // current[0] is tagName, but for {{else}} nodes, current[11] is tagName of preceding open tag current = stack.pop(); content = current[2]; block = true; } if (params) { // remove newlines from the params string, to avoid compiled code errors for unterminated strings - parseParams(params.replace(rNewLine, " "), pathBindings, tmpl) - .replace(rBuildHash, function(all, onerror, isCtx, key, keyToken, keyValue, arg, param) { + parseParams(params.replace(rNewLine, " "), pathBindings, tmpl, isLinkExpr) + .replace(rBuildHash, function(all, onerror, isCtxPrm, key, keyToken, keyValue, arg, param) { + if (key === "this:") { + keyValue = "undefined"; // this=some.path is always a to parameter (one-way), so don't need to compile/evaluate some.path initialization + } + if (param) { + isLateOb = isLateOb || param.charAt(0) === "@"; + } key = "'" + keyToken + "':"; if (arg) { - args += keyValue + ","; + args += isCtxPrm + keyValue + ","; paramsArgs += "'" + param + "',"; - } else if (isCtx) { + } else if (isCtxPrm) { // Contextual parameter, ~foo=expr ctxProps += key + 'j._cp(' + keyValue + ',"' + param + '",view),'; // Compiled code for evaluating tagCtx on a tag will have: ctx:{'foo':j._cp(compiledExpr, "expr", view)} paramsCtxProps += key + "'" + param + "',"; @@ -1765,7 +1902,7 @@ function tmplFn(markup, tmpl, isLinkExpr, convertBack, hasElse) { useTrigger += keyValue; } if (keyToken === "lateRender") { - late = param; // Render after first pass + late = param !== "false"; // Render after first pass } props += key + keyValue + ","; paramsProps += key + "'" + param + "',"; @@ -1788,17 +1925,19 @@ function tmplFn(markup, tmpl, isLinkExpr, convertBack, hasElse) { onError, useTrigger, late, + isLateOb, pathBindings || 0 ]; content.push(newNode); if (block) { stack.push(current); current = newNode; - current[9] = loc; // Store current location of open tag, to be able to add contentMarkup when we reach closing tag + current[10] = loc; // Store current location of open tag, to be able to add contentMarkup when we reach closing tag + current[11] = openTagName; // Used for checking syntax (matching close tag) } } else if (closeBlock) { - blockTagCheck(closeBlock !== current[0] && current[0] !== "else" && closeBlock, current[0]); - current[9] = markup.substring(current[9], index); // contentMarkup for block tag + blockTagCheck(closeBlock !== current[0] && closeBlock !== current[11] && closeBlock, current[0]); // Check matching close tag name + current[10] = markup.substring(current[10], index); // contentMarkup for block tag current = stack.pop(); } blockTagCheck(!current && closeBlock); @@ -1840,7 +1979,7 @@ function tmplFn(markup, tmpl, isLinkExpr, convertBack, hasElse) { pushprecedingContent(markup.length); if (loc = astTop[astTop.length - 1]) { - blockTagCheck("" + loc !== loc && (+loc[9] === loc[9]) && loc[0]); + blockTagCheck("" + loc !== loc && (+loc[10] === loc[10]) && loc[0]); } // result = tmplFnsCache[markup] = buildCode(astTop, tmpl); // } @@ -1850,7 +1989,7 @@ function tmplFn(markup, tmpl, isLinkExpr, convertBack, hasElse) { bindings = []; i = astTop.length; while (i--) { - bindings.unshift(astTop[i][8]); // With data-link expressions, pathBindings array for tagCtx[i] is astTop[i][8] + bindings.unshift(astTop[i][9]); // With data-link expressions, pathBindings array for tagCtx[i] is astTop[i][9] } setPaths(result, bindings); } else { @@ -1884,18 +2023,15 @@ function paramStructure(parts, type) { + (type ? type + ':{' : '') - + 'args:[' + parts[0] + ']' - + (parts[1] || !type - ? ',\n\tprops:{' + parts[1] + '}' - : "") + + 'args:[' + parts[0] + '],\n\tprops:{' + parts[1] + '}' + (parts[2] ? ',\n\tctx:{' + parts[2] + '}' : ""); } -function parseParams(params, pathBindings, tmpl) { +function parseParams(params, pathBindings, tmpl, isLinkExpr) { - function parseTokens(all, lftPrn0, lftPrn, bound, path, operator, err, eq, path2, prn, comma, lftPrn2, apos, quot, rtPrn, rtPrnDot, prn2, space, index, full) { - // /(\()(?=\s*\()|(?:([([])\s*)?(?:(\^?)(!*?[#~]?[\w$.^]+)?\s*((\+\+|--)|\+|-|&&|\|\||===|!==|==|!=|<=|>=|[<>%*:?\/]|(=))\s*|(!*?[#~]?[\w$.^]+)([([])?)|(,\s*)|(\(?)\\?(?:(')|("))|(?:\s*(([)\]])(?=\s*[.^]|\s*$|[^([])|[)\]])([([]?))|(\s+)/g, - // lftPrn0 lftPrn bound path operator err eq path2 prn comma lftPrn2 apos quot rtPrn rtPrnDot prn2 space + function parseTokens(all, lftPrn0, lftPrn, bound, path, operator, err, eq, path2, late, prn, comma, lftPrn2, apos, quot, rtPrn, rtPrnDot, prn2, space, index, full) { + // /(\()(?=\s*\()|(?:([([])\s*)?(?:(\^?)(~?[\w$.^]+)?\s*((\+\+|--)|\+|-|&&|\|\||===|!==|==|!=|<=|>=|[<>%*:?\/]|(=))\s*|(!*?(@)?[#~]?[\w$.^]+)([([])?)|(,\s*)|(\(?)\\?(?:(')|("))|(?:\s*(([)\]])(?=[.^]|\s*$|[^([])|[)\]])([([]?))|(\s+)/g, + // lftPrn0 lftPrn bound path operator err eq path2 late prn comma lftPrn2 apos quot rtPrn rtPrnDot prn2 space // (left paren? followed by (path? followed by operator) or (path followed by paren?)) or comma or apos or quot or right paren or space function parsePath(allPath, not, object, helper, view, viewProperty, pathTokens, leafToken) { //rPath = /^(!*?)(?:null|true|false|\d[\d.]*|([\w$]+|\.|~([\w$]+)|#(view|([\w$]+))?)([\w$.^]*?)(?:[.[^]([\w$]+)\]?)?)$/g, @@ -1907,11 +2043,19 @@ function parseParams(params, pathBindings, tmpl) { syntaxError(allPath); } if (!subPath) { - allPath = (helper + allPath = (late // late path @a.b.c: not throw on 'property of undefined' if a undefined, and will use getOb() after linking to resolve late. + ? (isLinkExpr ? '' : '(ltOb.lt=ltOb.lt||') + '(ob=' + : "" + ) + + (helper ? 'view.ctxPrm("' + helper + '")' : view ? "view" : "data") + + (late + ? ')===undefined' + (isLinkExpr ? '' : ')') + '?"":view.getOb(ob,"' + : "" + ) + (leafToken ? (viewProperty ? "." + viewProperty @@ -1920,15 +2064,18 @@ function parseParams(params, pathBindings, tmpl) { : (view ? "" : "." + object) ) + (pathTokens || "") : (leafToken = helper ? "" : view ? viewProperty || "" : object, "")); - allPath = allPath + (leafToken ? "." + leafToken : ""); allPath = not + (allPath.slice(0, 9) === "view.data" ? allPath.slice(5) // convert #view.data... to data... - : allPath); + : allPath) + + (late + ? (isLinkExpr ? '"': '",ltOb') + (prn ? ',1)':')') + : "" + ); } if (bindings) { - binds = named === "linkTo" ? (bindto = pathBindings._jsvto = pathBindings._jsvto || []) : bndCtx.bd; + binds = named === "_linkTo" ? (bindto = pathBindings._jsvto = pathBindings._jsvto || []) : bndCtx.bd; if (theOb = subPath && binds[binds.length-1]) { if (theOb._cpfn) { // Computed property exprOb while (theOb.sb) { @@ -1956,6 +2103,10 @@ function parseParams(params, pathBindings, tmpl) { operator = operator || ""; lftPrn = lftPrn || lftPrn0 || lftPrn2; path = path || path2; + + if (late && (late = !/\)|]/.test(full.charAt(index-1)))) { + path = path.slice(1).split(".").join("^"); // Late path @z.b.c. Use "^" rather than "." to ensure that deep binding will be used + } // Could do this - but not worth perf cost?? :- // if (!path.lastIndexOf("#data.", 0)) { path = path.slice(6); } // If path starts with "#data.", remove that. prn = prn || prn2 || ""; @@ -1964,7 +2115,7 @@ function parseParams(params, pathBindings, tmpl) { rtSq = ")"; if (prn === "[") { - prn ="[j._sq("; + prn = "[j._sq("; rtSq = ")]"; } @@ -1974,7 +2125,7 @@ function parseParams(params, pathBindings, tmpl) { if (bindings && rtPrnDot && !aposed && !quoted) { // This is a binding to a path in which an object is returned by a helper/data function/expression, e.g. foo()^x.y or (a?b:c)^x.y // We create a compiled function to get the object instance (which will be called when the dependent data of the subexpression changes, to return the new object, and trigger re-binding of the subsequent path) - if (!named || boundName || bindto) { + if (parenDepth && (!named || boundName || bindto)) { expr = pathStart[parenDepth - 1]; if (full.length - 1 > index - (expr || 0)) { // We need to compile a subexpression expr = full.slice(expr, index + all.length); @@ -2029,7 +2180,7 @@ function parseParams(params, pathBindings, tmpl) { ) : eq // named param. Remove bindings for arg and create instead bindings array for prop - ? (parenDepth && syntaxError(params), bindings && pathBindings.pop(), named = path, boundName = bound, paramIndex = index + all.length, + ? (parenDepth && syntaxError(params), bindings && pathBindings.pop(), named = "_" + path, boundName = bound, paramIndex = index + all.length, bindings && ((bindings = bndCtx.bd = pathBindings[named] = []), bindings.skp = !bound), path + ':') : path // path @@ -2072,7 +2223,12 @@ function parseParams(params, pathBindings, tmpl) { parenDepth = 0, fnCall = {}, // We are in a function call pathStart = {}, // tracks the start of the current path such as c^d() in the above example - result = (params + (tmpl ? " " : "")).replace(rParams, parseTokens); + result; + + if (params.charAt(0) === "@") { + params = params.replace(rBracketQuote, "."); + } + result = (params + (tmpl ? " " : "")).replace(rParams, parseTokens); return !parenDepth && result || syntaxError(params); // Syntax error if unbalanced parens in params expression } @@ -2082,7 +2238,7 @@ function buildCode(ast, tmpl, isLinkExpr) { // Used for compiling templates, and also by JsViews to build functions for data link expressions var i, node, tagName, converter, tagCtx, hasTag, hasEncoder, getsVal, hasCnvt, useCnvt, tmplBindings, pathBindings, params, boundOnErrStart, boundOnErrEnd, tagRender, nestedTmpls, tmplName, nestedTmpl, tagAndElses, content, markup, nextIsElse, oldCode, isElse, isGetVal, tagCtxFn, - onError, tagStart, trigger, lateRender, + onError, tagStart, trigger, lateRender, retStrOpen, retStrClose, tmplBindingKey = 0, useViews = $subSettingsAdvanced.useViews || tmpl.useViews || tmpl.tags || tmpl.templates || tmpl.helpers || tmpl.converters, code = "", @@ -2123,14 +2279,21 @@ function buildCode(ast, tmpl, isLinkExpr) { tagCtx = paramStructure(node[3], 'params') + '},' + paramStructure(params = node[4]); trigger = node[6]; lateRender = node[7]; - markup = node[9] && node[9].replace(rUnescapeQuotes, "$1"); + if (node[8]) { // latePath @a.b.c or @~a.b.c + retStrOpen = "\nvar ob,ltOb={},ctxs="; + retStrClose = ";\nctxs.lt=ltOb.lt;\nreturn ctxs;"; + } else { + retStrOpen = "\nreturn "; + retStrClose = ""; + } + markup = node[10] && node[10].replace(rUnescapeQuotes, "$1"); if (isElse = tagName === "else") { if (pathBindings) { - pathBindings.push(node[8]); + pathBindings.push(node[9]); } } else { onError = node[5] || $subSettings.debugMode !== false && "undefined"; // If debugMode not false, set default onError handler on tag to "undefined" (see onRenderError) - if (tmplBindings && (pathBindings = node[8])) { // Array of paths, or false if not data-bound + if (tmplBindings && (pathBindings = node[9])) { // Array of paths, or false if not data-bound pathBindings = [pathBindings]; tmplBindingKey = tmplBindings.push(1); // Add placeholder in tmplBindings for compiled function } @@ -2173,7 +2336,7 @@ function buildCode(ast, tmpl, isLinkExpr) { if (isGetVal && (pathBindings || trigger || converter && converter !== HTML || lateRender)) { // For convertVal we need a compiled function to return the new tagCtx(s) tagCtxFn = new Function("data,view,j,u", "// " + tmplName + " " + (++tmplBindingKey) + " " + tagName - + "\nreturn {" + tagCtx + "};"); + + retStrOpen + "{" + tagCtx + "};" + retStrClose); tagCtxFn._er = onError; tagCtxFn._tag = tagName; tagCtxFn._bd = !!pathBindings; // data-linked tag {^{.../}} @@ -2210,7 +2373,8 @@ function buildCode(ast, tmpl, isLinkExpr) { tagRender = 't("' + tagAndElses + '",view,this,'; if (isLinkExpr || pathBindings) { // This is a bound tag (data-link expression or inline bound tag {^{tag ...}}) so we store a compiled tagCtxs function in tmp.bnds - code = new Function("data,view,j,u", " // " + tmplName + " " + tmplBindingKey + " " + tagAndElses + "\nreturn " + code + ";"); + code = new Function("data,view,j,u", " // " + tmplName + " " + tmplBindingKey + " " + tagAndElses + retStrOpen + code + + retStrClose); code._er = onError; code._tag = tagAndElses; if (pathBindings) { @@ -2227,7 +2391,7 @@ function buildCode(ast, tmpl, isLinkExpr) { // This is the last {{else}} for an inline tag. // For a bound tag, pass the tagCtxs fn lookup key to renderTag. // For an unbound tag, include the code directly for evaluating tagCtxs array - code = oldCode + tagStart + tagRender + (code.deps && tmplBindingKey || code) + ")"; + code = oldCode + tagStart + tagRender + (pathBindings && tmplBindingKey || code) + ")"; pathBindings = 0; tagAndElses = 0; } @@ -2240,13 +2404,17 @@ function buildCode(ast, tmpl, isLinkExpr) { } // Include only the var references that are needed in the code code = "// " + tmplName - + + (tmplOptions.debug ? "\ndebugger;" : "") + "\nvar v" + (hasTag ? ",t=j._tag" : "") // has tag + (hasCnvt ? ",c=j._cnvt" : "") // converter + (hasEncoder ? ",h=j._html" : "") // html converter - + (isLinkExpr ? ";\n" : ',ret=""\n') - + (tmplOptions.debug ? "debugger;" : "") + + (isLinkExpr + ? (node[8] // late @... path? + ? ", ob" + : "" + ) + ";\n" + : ',ret=""') + code + (isLinkExpr ? "\n" : ";\nreturn ret;"); @@ -2277,26 +2445,103 @@ function extendCtx(context, parentContext) { : parentContext && $extend({}, parentContext); } -// Get character entity for HTML and Attribute encoding -function getCharEntity(ch) { - return charEntities[ch] || (charEntities[ch] = "&#" + ch.charCodeAt(0) + ";"); -} - -function getTargetProps(source) { +function getTargetProps(source, tagCtx) { // this pointer is theMap - which has tagCtx.props too // arguments: tagCtx.args. var key, prop, props = []; - if (typeof source === OBJECT) { + if (typeof source === OBJECT || $isFunction(source)) { for (key in source) { prop = source[key]; - if (key !== $expando && source.hasOwnProperty(key) && !$isFunction(prop)) { + if (key !== $expando && source.hasOwnProperty(key) && (!tagCtx.props.noFunctions || !$.isFunction(prop))) { props.push({key: key, prop: prop}); } } } - return props; + return getTargetSorted(props, tagCtx); +} + +function getTargetSorted(value, tagCtx) { + // getTgt + var mapped, start, end, + tag = tagCtx.tag, + props = tagCtx.props, + propParams = tagCtx.params.props, + filter = props.filter, + sort = props.sort, + directSort = sort === true, + step = parseInt(props.step), + reverse = props.reverse ? -1 : 1; + + if (!$isArray(value)) { + return value; + } + if (directSort || sort && "" + sort === sort) { + // Temporary mapped array holds objects with index and sort-value + mapped = value.map(function(item, i) { + item = directSort ? item : getPathObject(item, sort); + return {i: i, v: "" + item === item ? item.toLowerCase() : item}; + }); + // Sort mapped array + mapped.sort(function(a, b) { + return a.v > b.v ? reverse : a.v < b.v ? -reverse : 0; + }); + // Map to new array with resulting order + value = mapped.map(function(item){ + return value[item.i]; + }); + } else if ((sort || reverse < 0) && !tag.dataMap) { + value = value.slice(); // Clone array first if not already a new array + } + if ($isFunction(sort)) { + value = value.sort(sort); + } + if (reverse < 0 && !sort) { // Reverse result if not already reversed in sort + value = value.reverse(); + } + + if (value.filter && filter) { // IE8 does not support filter + value = value.filter(filter, tagCtx); + if (tagCtx.tag.onFilter) { + tagCtx.tag.onFilter(tagCtx); + } + } + + if (propParams.sorted) { + mapped = (sort || reverse < 0) ? value : value.slice(); + if (tag.sorted) { + $.observable(tag.sorted).refresh(mapped); // Note that this might cause the start and end props to be modified - e.g. by pager tag control + } else { + tagCtx.map.sorted = mapped; + } + } + + start = props.start; // Get current value - after possible changes triggered by tag.sorted refresh() above + end = props.end; + if (propParams.start && start === undefined || propParams.end && end === undefined) { + start = end = 0; + } + if (!isNaN(start) || !isNaN(end)) { // start or end specified, but not the auto-create Number array scenario of {{for start=xxx end=yyy}} + start = +start || 0; + end = end === undefined || end > value.length ? value.length : +end; +// end = end === undefined ? value.length : +end; + value = value.slice(start, end); + } + if (step > 1) { + start = 0; + end = value.length; + mapped = []; + for (; start & ' and " by corresponding entities. + // HTML encode: Replace < > & ' " ` etc. by corresponding entities. return text != undefined ? rIsHtml.test(text) && ("" + text).replace(rHtmlEncode, getCharEntity) || text : ""; } +function dataEncode(text) { + // Encode just < > and & - intended for 'safe data' along with {{:}} rather than {{>}} + return "" + text === text ? text.replace(rDataEncode, getCharEntity) : text; +} + +function dataUnencode(text) { + // Unencode just < > and & - intended for 'safe data' along with {{:}} rather than {{>}} + return "" + text === text ? text.replace(rDataUnencode, getCharFromEntity) : text; +} + //========================== Initialize ========================== $sub = $views.sub; @@ -2347,6 +2612,10 @@ if (!(jsr || $ && $.render)) { $.fn.render = $fnRender; $expando = $.expando; if ($.observable) { + if (versionNumber !== (versionNumber = $.views.jsviews)) { + // Different version of jsRender was loaded + throw "JsObservable requires JsRender " + versionNumber; + } $extend($sub, $.views.sub); // jquery.observable.js was loaded before jsrender.js $views.map = $.views.map; } @@ -2403,7 +2672,7 @@ if (!(jsr || $ && $.render)) { : ( $subSettings.debugMode = debugMode, $subSettings.onError = debugMode + "" === debugMode - ? new Function("", "return '" + debugMode + "';") + ? function() { return debugMode; } : $isFunction(debugMode) ? debugMode : undefined, @@ -2426,7 +2695,7 @@ if (!(jsr || $ && $.render)) { // Otherwise return "" var self = this, tagCtx = self.tagCtx, - ret = (self.rendering.done || !val && (arguments.length || !tagCtx.index)) + ret = (self.rendering.done || !val && (tagCtx.args.length || !tagCtx.index)) ? "" : (self.rendering.done = true, self.selected = tagCtx.index, @@ -2437,21 +2706,53 @@ if (!(jsr || $ && $.render)) { flow: true }, "for": { + sortDataMap: dataMap(getTargetSorted), + init: function(val, cloned) { + var l, tagCtx, props, sort, + self = this, + tagCtxs = self.tagCtxs; + l = tagCtxs.length; + while (l--) { + tagCtx = tagCtxs[l]; + props = tagCtx.props; + tagCtx.argDefault = props.end === undefined || tagCtx.args.length > 0; // Default to #data except for auto-create range scenario {{for start=xxx end=yyy step=zzz}} + + if (tagCtx.argDefault !== false && $isArray(tagCtx.args[0]) + && (props.sort !== undefined || tagCtx.params.props.start || tagCtx.params.props.end || props.step !== undefined || props.filter || props.reverse)) { + props.dataMap = self.sortDataMap; + } + } + }, render: function(val) { // This function is called once for {{for}} and once for each {{else}}. // We will use the tag.rendering object for carrying rendering state across the calls. - var finalElse = !arguments.length, - value, + var value, filter, srtField, isArray, i, sorted, end, step, self = this, tagCtx = self.tagCtx, + range = tagCtx.argDefault === false, + props = tagCtx.props, + iterate = range || tagCtx.args.length, // Not final else and not auto-create range result = "", done = 0; if (!self.rendering.done) { - value = finalElse ? tagCtx.view.data : val; // For the final else, defaults to current data without iteration. + value = iterate ? val : tagCtx.view.data; // For the final else, defaults to current data without iteration. + + if (range) { + range = props.reverse ? "unshift" : "push"; + end = +props.end; + step = +props.step || 1; + value = []; // auto-create integer array scenario of {{for start=xxx end=yyy}} + for (i = +props.start || 0; (end - i) * step > 0; i += step) { + value[range](i); + } + } if (value !== undefined) { - result += tagCtx.render(value, finalElse); // Iterates except on final else, if data is an array. (Use {{include}} to compose templates without array iteration) - done += $isArray(value) ? value.length : 1; + isArray = $isArray(value); + result += tagCtx.render(value, !iterate || props.noIteration); + // Iterates if data is an array, except on final else - or if noIteration property + // set to true. (Use {{include}} to compose templates without array iteration) + done += isArray ? value.length : 1; } if (self.rendering.done = done) { self.selected = tagCtx.index; @@ -2465,6 +2766,7 @@ if (!(jsr || $ && $.render)) { props: { baseTag: "for", dataMap: dataMap(getTargetProps), + init: noop, // Don't execute the base init() of the "for" tag flow: true }, include: { @@ -2486,6 +2788,8 @@ if (!(jsr || $ && $.render)) { $converters({ html: htmlEncode, attr: htmlEncode, // Includes > encoding since rConvertMarkers in JsViews does not skip > characters in attribute strings + encode: dataEncode, + unencode: dataUnencode, // Includes > encoding since rConvertMarkers in JsViews does not skip > characters in attribute strings url: function(text) { // URL encoding helper. return text != undefined ? encodeURI("" + text) : text === null ? text : ""; // null returns null, e.g. to remove attribute. undefined returns "" @@ -2497,7 +2801,6 @@ $subSettings = $sub.settings; $isArray = ($||jsr).isArray; $viewsSettings.delimiters("{{", "}}", "^"); - if (jsrToJq) { // Moving from jsrender namespace to jQuery namepace - copy over the stored items (templates, converters, helpers...) jsr.views.sub._jq($); } diff --git a/jsrender.min.js b/jsrender.min.js index 1c0437c..0ffdf8d 100644 --- a/jsrender.min.js +++ b/jsrender.min.js @@ -1,4 +1,4 @@ -/*! JsRender v0.9.90 (Beta): http://jsviews.com/#jsrender */ +/*! JsRender v0.9.91 (Beta): http://jsviews.com/#jsrender */ /*! **VERSION FOR WEB** (For NODE.JS see http://jsviews.com/download/jsrender-node.js) */ -!function(e,t){var n=t.jQuery;"object"==typeof exports?module.exports=n?e(t,n):function(n){if(n&&!n.fn)throw"Provide jQuery or null";return e(t,n)}:"function"==typeof define&&define.amd?define(function(){return e(t)}):e(t,!1)}(function(e,t){"use strict";function n(e,t){return function(){var n,r=this,i=r.base;return r.base=e,n=t.apply(r,arguments),r.base=i,n}}function r(e,t){return ne(t)&&(t=n(e?e._d?e:n(a,e):a,t),t._d=1),t}function i(e,t){var n,i=t.props;for(n in i)!Ee.test(n)||e[n]&&e[n].fix||(e[n]="convert"!==n?r(e.constructor.prototype[n],i[n]):i[n])}function o(e){return e}function a(){return""}function s(e){try{throw console.log("JsRender dbg breakpoint: "+e),"dbg breakpoint"}catch(t){}return this.base?this.baseApply(arguments):e}function d(e){this.name=(t.link?"JsViews":"JsRender")+" Error",this.message=e||this.name}function l(e,t){if(e){for(var n in t)e[n]=t[n];return e}}function u(e,t,n){return e?re(e)?u.apply(ee,e):(le.delimiters=[e,t,he=n?n.charAt(0):he],ce=e.charAt(0),fe=e.charAt(1),ge=t.charAt(0),ve=t.charAt(1),e="\\"+ce+"(\\"+he+")?\\"+fe,t="\\"+ge+"\\"+ve,X="(?:(\\w+(?=[\\/\\s\\"+ge+"]))|(\\w+)?(:)|(>)|(\\*))\\s*((?:[^\\"+ge+"]|\\"+ge+"(?!\\"+ve+"))*?)",de.rTag="(?:"+X+")",X=new RegExp("(?:"+e+X+"(\\/)?|\\"+ce+"(\\"+he+")?\\"+fe+"(?:(?:\\/(\\w+))\\s*|!--[\\s\\S]*?--))"+t,"g"),de.rTmpl=new RegExp("^\\s|\\s$|<.*>|([^\\\\]|^)[{}]|"+e+".*"+t),pe):le.delimiters}function p(e,t){t||e===!0||(t=e,e=void 0);var n,r,i,o,a=this,s=!t||"root"===t;if(e){if(o=t&&a.type===t&&a,!o)if(n=a.views,a._.useKey){for(r in n)if(o=t?n[r].get(e,t):n[r])break}else for(r=0,i=n.length;!o&&r1)for(d=o.bindTo=[];s--;)d.unshift(s);p&&(p.tag=o,o.linkCtx=p),n.ctx=Q(n.ctx,(p?p.view:t).ctx),i(o,n)}o._er=r&&a,o.ctx=n.ctx||o.ctx||{},n.ctx=void 0,a=o.cvtArgs()[0]}return a=u&&t._.onRender?t._.onRender(a,t,o):a,void 0!=a?a:""}function m(e,t){var n,r,i,o,a,s,d,l=this;if(l.tagName?(s=l,l=s.tagCtxs?s.tagCtxs[t||0]:s.tagCtx):s=l.tag,a=s.bindTo,o=l.args,(d=s.convert)&&""+d===d&&(d="true"===d?void 0:l.view.getRsc("converters",d)||I("Unknown converter: '"+d+"'")),e&&e.length)o=e;else if(d&&!e&&(o=o.slice()),a){for(i=[],n=a.length;n--;)r=a[n],i.unshift(w(l,r));e&&(o=i)}if(d)if(a=a||[0],n=a.length,d=d.apply(s,i||o),re(d)&&d.length===n||(d=[d],a=[0],n=1),e)o=d;else for(;n--;)r=a[n],+r===r&&(o[r]=d[n]);return o}function w(e,t){return e=e[+t===t?"args":"props"],e&&e[t]}function x(e){return this.cvtArgs(!0,e)}function _(e,t){var n,r,i=this;if(""+t===t){for(;void 0===n&&i;)r=i.tmpl&&i.tmpl[e],n=r&&r[t],i=i.parent;return n||ee[e][t]}}function b(e,t,n,r,o,a){function s(e){var t;(t=d[e])&&(d[e]=t=re(t)?t:[t],E!==t.length&&I(e+" length not same as bindTo "))}t=t||Y;var d,l,u,p,c,f,g,v,h,m,x,_,b,y,k,C,T,j,A,R,V,$,E,M=0,N="",P=t.linkCtx||0,O=t.ctx,U=n||t.tmpl,q="number"==typeof r&&t.tmpl.bnds[r-1];for("tag"===e._is?(d=e,e=d.tagName,r=d.tagCtxs,u=d.template):(l=t.getRsc("tags",e)||I("Unknown tag: {{"+e+"}} "),u=l.template),void 0===a&&q&&(q._lr=(l.lateRender||q._lr)&&"false"!==q._lr)&&(a=""),void 0!==a?(N+=a,r=a=[{props:{},args:[],params:{}}]):q&&(r=q(t.data,t,de)),g=r.length;M0&&(a=n)){if(!a)if(/^\.\/[^\\:*?"<>]*$/.test(n))(s=ie[e=e||n])?n=s:a=document.getElementById(n);else if(t.fn&&!de.rTmpl.test(n))try{a=t(n,document)[0]}catch(d){}a&&(i?n=a.innerHTML:(o=a.getAttribute(Oe),o&&(o!==Ue?(n=ie[o],delete ie[o]):t.fn&&(n=t.data(a)[Ue])),o&&n||(e=e||(t.fn?Ue:n),n=j(e,a.innerHTML,r,i)),n.tmplName=e=e||o,e!==Ue&&(ie[e]=n),a.setAttribute(Oe,e),t.fn&&t.data(a,Ue,n))),a=void 0}else n.fn||(n=void 0);return n}var a,s,d=n=n||"";if(de._html=oe.html,0===i&&(i=void 0,d=o(d)),i=i||(n.markup?n:{}),i.tmplName=e,r&&(i._parentTmpl=r),!d&&n.markup&&(d=o(n.markup))&&d.fn&&(d=d.markup),void 0!==d)return d.fn||n.fn?d.fn&&(s=d):(n=$(d,i),U(d.replace(Te,"\\$&"),n)),s||(s=l(function(){return s.render.apply(s,arguments)},n),k(s)),s}function A(e,t){return ne(e)?e.call(t):e}function R(e){for(var t=[],n=0,r=e.length;nS-(I||0))){if(I=F.slice(I,S+r.length),q!==!0)if(J=o||p[g-1].bd,K=J[J.length-1],K&&K.prm){for(;K.sb&&K.sb.prm;)K=K.sb;B=K.sb={path:K.sb,bnd:K.bnd}}else J.push(B={path:J.pop()});E=fe+":"+I+" onerror=''"+ge,q=f[E],q||(f[E]=!0,f[E]=q=U(E,n,!0)),q!==!0&&B&&(B._cpfn=q,B.prm=u.bd,B.bnd=B.bnd||B.path&&B.path.indexOf("^")>=0)}return d?(d=!R,d?r:A+'"'):s?(s=!V,s?r:A+'"'):(w?(h[g]=S++,u=p[++g]={bd:[]},w):"")+(N?g?"":(c=F.slice(c,S),(i?(i=a=o=!1,"\b"):"\b,")+c+(c=S+r.length,l&&t.push(u.bd=[]),"\b")):k?(g&&O(e),l&&t.pop(),i=_,a=x,c=S+r.length,l&&(l=u.bd=t[i]=[],l.skp=!x),_+":"):_?_.split("^").join(".").replace(be,P)+(T?(u=p[++g]={bd:[]},v[g]=L,T):b):b?b:$?($=v[g]||$,v[g]=!1,u=p[--g],$+(T?(u=p[++g],v[g]=L,T):"")):j?(v[g]||O(e),","):m?"":(d=R,s=V,'"'))}O(e)}var i,o,a,s,d,l=t&&t[0],u={bd:l},p={0:u},c=0,f=(n?n.links:l&&(l.links=l.links||{}))||Y.tmpl.links,g=0,v={},h={},m=(e+(n?" ":"")).replace(ye,r);return!g&&m||O(e)}function L(e,t,n){var r,i,o,a,s,d,l,u,p,c,f,g,v,h,m,w,x,_,b,y,k,C,T,j,A,R,V,E,M,N,S,F=0,P=ue.useViews||t.useViews||t.tags||t.templates||t.helpers||t.converters,I="",U={},J=e.length;for(""+t===t?(_=n?'data-link="'+t.replace(ke," ").slice(1,-1)+'"':t,t=0):(_=t.tmplName||"unnamed",t.allowCode&&(U.allowCode=!0),t.debug&&(U.debug=!0),f=t.bnds,x=t.tmpls),r=0;r":a+o):(k&&(b=$(C,U),b.tmplName=_+"/"+o,b.useViews=b.useViews||P,L(k,b),P=b.useViews,x.push(b)),A||(y=o,P=P||o&&(!se[o]||!se[o].flow),j=I,I=""),T=e[r+1],T=T&&"else"===T[0]),M=E?";\ntry{\nret+=":"\n+",h="",m="",R&&(g||N||a&&a!==Pe||S)){if(V=new Function("data,view,j,u","// "+_+" "+ ++F+" "+o+"\nreturn {"+s+"};"),V._er=E,V._tag=o,V._bd=!!g,V._lr=S,n)return V;q(V,g),w='c("'+a+'",view,',c=!0,h=w+F+",",m=")"}if(I+=R?(n?(E?"try{\n":"")+"return ":M)+(c?(c=void 0,P=p=!0,w+(V?(f[F-1]=V,F):"{"+s+"}")+")"):">"===o?(l=!0,"h("+v[0]+")"):(u=!0,"((v="+v[0]+")!=null?v:"+(n?"null)":'"")'))):(d=!0,"\n{view:view,tmpl:"+(k?x.length:"0")+","+s+"},"),y&&!T){if(I="["+I.slice(0,-1)+"]",w='t("'+y+'",view,this,',n||g){if(I=new Function("data,view,j,u"," // "+_+" "+F+" "+y+"\nreturn "+I+";"),I._er=E,I._tag=y,g&&q(f[F-1]=I,g),I._lr=S,n)return I;h=w+F+",undefined,",m=")"}I=j+M+w+(I.deps&&F||I)+")",g=0,y=0}E&&!T&&(P=!0,I+=";\n}catch(e){ret"+(n?"urn ":"+=")+h+"j._err(e,view,"+E+")"+m+";}"+(n?"":"ret=ret"))}I="// "+_+"\nvar v"+(d?",t=j._tag":"")+(p?",c=j._cnvt":"")+(l?",h=j._html":"")+(n?";\n":',ret=""\n')+(U.debug?"debugger;":"")+I+(n?"\n":";\nreturn ret;");try{I=new Function("data,view,j,u",I)}catch(B){O("Compiled template code:\n\n"+I+'\n: "'+(B.message||B)+'"')}return t&&(t.fn=I,t.useViews=!!P),I}function Q(e,t){return e&&e!==t?t?l(l({},t),e):e:t&&l({},t)}function H(e){return Fe[e]||(Fe[e]="&#"+e.charCodeAt(0)+";")}function D(e){var t,n,r=[];if(typeof e===Ie)for(t in e)n=e[t],t!==te&&e.hasOwnProperty(t)&&!ne(n)&&r.push({key:t,prop:n});return r}function Z(e,n,r){var i=this.jquery&&(this[0]||I("Unknown template")),o=i.getAttribute(Oe);return S.call(o&&t.data(i)[Ue]||ie(i),e,n,r)}function z(e){return void 0!=e?$e.test(e)&&(""+e).replace(Ne,H)||e:""}var G=t===!1;t=t&&t.fn?t:e.jQuery;var W,X,Y,ee,te,ne,re,ie,oe,ae,se,de,le,ue,pe,ce,fe,ge,ve,he,me,we,xe="v0.9.90",_e="_ocp",be=/^(!*?)(?:null|true|false|\d[\d.]*|([\w$]+|\.|~([\w$]+)|#(view|([\w$]+))?)([\w$.^]*?)(?:[.[^]([\w$]+)\]?)?)$/g,ye=/(\()(?=\s*\()|(?:([([])\s*)?(?:(\^?)(!*?[#~]?[\w$.^]+)?\s*((\+\+|--)|\+|-|&&|\|\||===|!==|==|!=|<=|>=|[<>%*:?\/]|(=))\s*|(!*?[#~]?[\w$.^]+)([([])?)|(,\s*)|(\(?)\\?(?:(')|("))|(?:\s*(([)\]])(?=\s*[.^]|\s*$|[^([])|[)\]])([([]?))|(\s+)/g,ke=/[ \t]*(\r\n|\n|\r)/g,Ce=/\\(['"])/g,Te=/['"\\]/g,je=/(?:\x08|^)(onerror:)?(?:(~?)(([\w$_\.]+):)?([^\x08]+))\x08(,)?([^\x08]+)/gi,Ae=/^if\s/,Re=/<(\w+)[>\s]/,Ve=/[\x00`><"'&=]/g,$e=/[\x00`><\"'&=]/,Ee=/^on[A-Z]|^convert(Back)?$/,Me=/^\#\d+_`[\s\S]*\/\d+_`$/,Ne=Ve,Se=0,Fe={"&":"&","<":"<",">":">","\0":"�","'":"'",'"':""","`":"`","=":"="},Pe="html",Ie="object",Oe="data-jsv-tmpl",Ue="jsvTmpl",qe="For #index in nested block use #getIndex().",Je={},Ke=e.jsrender,Be=Ke&&t&&!t.render,Le={template:{compile:j},tag:{compile:C},viewModel:{compile:V},helper:{},converter:{}};if(ee={jsviews:xe,sub:{View:y,Err:d,tmplFn:U,parse:B,extend:l,extendCtx:Q,syntaxErr:O,onStore:{template:function(e,t){null===t?delete Je[e]:Je[e]=t}},addSetting:M,settings:{allowCode:!1},advSet:a,_ths:i,_gm:r,_tg:function(){},_cnvt:h,_tag:b,_er:I,_err:P,_cp:o,_sq:function(e){return"constructor"===e&&O(""),e}},settings:{delimiters:u,advanced:function(e){return e?(l(ue,e),de.advSet(),pe):ue}},map:N},(d.prototype=new Error).constructor=d,c.depends=function(){return[this.get("item"),"index"]},f.depends="index",y.prototype={get:p,getIndex:f,getRsc:_,getTmpl:v,ctxPrm:g,_is:"view"},de=ee.sub,pe=ee.settings,!(Ke||t&&t.render)){for(W in Le)E(W,Le[W]);oe=ee.converters,ae=ee.helpers,se=ee.tags,de._tg.prototype={baseApply:T,cvtArgs:m,bndArgs:x,ctxPrm:g},Y=de.topView=new y,t?(t.fn.render=Z,te=t.expando,t.observable&&(l(de,t.views.sub),ee.map=t.views.map)):(t={},G&&(e.jsrender=t),t.renderFile=t.__express=t.compile=function(){throw"Node.js: use npm jsrender, or jsrender-node.js"},t.isFunction=function(e){return"function"==typeof e},t.isArray=Array.isArray||function(e){return"[object Array]"==={}.toString.call(e)},de._jq=function(e){e!==t&&(l(e,t),t=e,t.fn.render=Z,delete t.jsrender,te=t.expando)},t.jsrender=xe),le=de.settings,le.allowCode=!1,ne=t.isFunction,t.render=Je,t.views=ee,t.templates=ie=ee.templates;for(me in le)M(me);(pe.debugMode=function(e){return void 0===e?le.debugMode:(le.debugMode=e,le.onError=e+""===e?new Function("","return '"+e+"';"):ne(e)?e:void 0,pe)})(!1),ue=le.advanced={useViews:!1,_jsv:!1},se({"if":{render:function(e){var t=this,n=t.tagCtx,r=t.rendering.done||!e&&(arguments.length||!n.index)?"":(t.rendering.done=!0,void(t.selected=n.index));return r},contentCtx:!0,flow:!0},"for":{render:function(e){var t,n=!arguments.length,r=this,i=r.tagCtx,o="",a=0;return r.rendering.done||(t=n?i.view.data:e,void 0!==t&&(o+=i.render(t,n),a+=re(t)?t.length:1),(r.rendering.done=a)&&(r.selected=i.index)),o},flow:!0},props:{baseTag:"for",dataMap:N(D),flow:!0},include:{flow:!0},"*":{render:o,flow:!0},":*":{render:o,flow:!0},dbg:ae.dbg=oe.dbg=s}),oe({html:z,attr:z,url:function(e){return void 0!=e?encodeURI(""+e):null===e?e:""}})}return le=de.settings,re=(t||Ke).isArray,pe.delimiters("{{","}}","^"),Be&&Ke.views.sub._jq(t),t||Ke},window); +!function(t,e){var n=e.jQuery;"object"==typeof exports?module.exports=n?t(e,n):function(n){if(n&&!n.fn)throw"Provide jQuery or null";return t(e,n)}:"function"==typeof define&&define.amd?define(function(){return t(e)}):t(e,!1)}(function(t,e){"use strict";function n(t,e){return function(){var n,r=this,i=r.base;return r.base=t,n=e.apply(r,arguments),r.base=i,n}}function r(t,e){return st(e)&&(e=n(t?t._d?t:n(a,t):a,e),e._d=(t&&t._d||0)+1),e}function i(t,e){var n,i=e.props;for(n in i)!Ot.test(n)||t[n]&&t[n].fix||(t[n]="convert"!==n?r(t.constructor.prototype[n],i[n]):i[n])}function o(t){return t}function a(){return""}function s(t){try{throw console.log("JsRender dbg breakpoint: "+t),"dbg breakpoint"}catch(e){}return this.base?this.baseApply(arguments):t}function d(t){this.name=(e.link?"JsViews":"JsRender")+" Error",this.message=t||this.name}function l(t,e){if(t){for(var n in e)t[n]=e[n];return t}}function p(t,e,n){return t?dt(t)?p.apply(ot,t):(gt.delimiters=[t,e,wt=n?n.charAt(0):wt],mt=t.charAt(0),xt=t.charAt(1),_t=e.charAt(0),bt=e.charAt(1),t="\\"+mt+"(\\"+wt+")?\\"+xt,e="\\"+_t+"\\"+bt,rt="(?:(\\w+(?=[\\/\\s\\"+_t+"]))|(\\w+)?(:)|(>)|(\\*))\\s*((?:[^\\"+_t+"]|\\"+_t+"(?!\\"+bt+"))*?)",ft.rTag="(?:"+rt+")",rt=new RegExp("(?:"+t+rt+"(\\/)?|\\"+mt+"(\\"+wt+")?\\"+xt+"(?:(?:\\/(\\w+))\\s*|!--[\\s\\S]*?--))"+e,"g"),ft.rTmpl=new RegExp("^\\s|\\s$|<.*>|([^\\\\]|^)[{}]|"+t+".*"+e),ht):gt.delimiters}function c(t,e){e||t===!0||(e=t,t=void 0);var n,r,i,o,a=this,s=!e||"root"===e;if(t){if(o=e&&a.type===e&&a,!o)if(n=a.views,a._.useKey){for(r in n)if(o=e?n[r].get(t,e):n[r])break}else for(r=0,i=n.length;!o&&r1,v=f.ctx;if(n){if(f._||(p=f.index,f=f.tag),c=f,v&&v.hasOwnProperty(n)||(v=ct).hasOwnProperty(n)){if(s=v[n],"tag"===n||"tagCtx"===n||"root"===n||"parentTags"===n||f._.it===n)return s}else v=void 0;if((f.tagCtx||f.linked)&&(s&&s._cxp||(f=f.tagCtx||st(s)?f:(f=f.scope||f,!f.isTop&&f.ctx.tag||f),void 0!==s&&f.tagCtx&&(f=f.tagCtx.view.scope),v=f._ocps,s=v&&v.hasOwnProperty(n)&&v[n]||s,s&&s._cxp||!i&&!g||((v||(f._ocps=f._ocps||{}))[n]=s=[{_ocp:s,_vw:c,_key:n}],s._cxp={path:Tt,ind:0,updateValue:function(t,n){return e.observable(s[0]).setProperty(Tt,t),this}})),d=s&&s._cxp)){if(arguments.length>2)return a=s[1]?ft._ceo(s[1].deps):[Tt],a.unshift(s[0]),a._cxp=d,a;if(p=d.tagElse,u=s[1]?d.tag&&d.tag.cvtArgs?d.tag.cvtArgs(1,p)[d.ind]:s[1](s[0].data,s[0],ft):s[0]._ocp,g)return s&&u!==r&&ft._ucp(n,r,f,d),f;s=u}return s&&st(s)&&(o=function(){return s.apply(this&&this!==t?this:c,arguments)},l(o,s),o._vw=c),o||s}}function h(t){return t&&(t.fn?t:this.getRsc("templates",t)||lt(t))}function m(t,e,n,r){var o,a,s,d,p="number"==typeof n&&e.tmpl.bnds[n-1],c=e.linkCtx;if(void 0===r&&p&&p._lr&&(r=""),void 0!==r?n=r={props:{},args:[r]}:p&&(n=p(e.data,e,ft)),p=p._bd&&p,t||p){if(o=c&&c.tag,n.view=e,!o){if(o=l(new ft._tg,{_:{bnd:p,unlinked:!0,lt:n.lt},inline:!c,tagName:":",convert:t,flow:!0,tagCtx:n,tagCtxs:[n],_is:"tag"}),s=n.args.length,s>1)for(d=o.bindTo=[];s--;)d.unshift(s);c&&(c.tag=o,o.linkCtx=c),n.ctx=Q(n.ctx,(c?c.view:e).ctx),i(o,n)}o._er=r&&a,o.ctx=n.ctx||o.ctx||{},n.ctx=void 0,a=o.cvtArgs()[0],o._er=r&&a}else a=n.args[0];return a=p&&e._.onRender?e._.onRender(a,e,o):a,void 0!=a?a:""}function x(t,e){var n,r,i,o,a,s,d,l=this;if(l.tagName?(s=l,l=s.tagCtxs?s.tagCtxs[e||0]:s.tagCtx):s=l.tag,a=s.bindFrom,o=l.args,(d=s.convert)&&""+d===d&&(d="true"===d?void 0:l.view.getRsc("converters",d)||S("Unknown converter: '"+d+"'")),d&&!t&&(o=o.slice()),a){for(i=[],n=a.length;n--;)r=a[n],i.unshift(_(l,r));t&&(o=i)}if(d){if(d=d.apply(s,i||o),void 0===d)return o;if(a=a||[0],n=a.length,dt(d)&&d.length===n||(d=[d],a=[0],n=1),t)o=d;else for(;n--;)r=a[n],+r===r&&(o[r]=d[n])}return o}function _(t,e){return t=t[+e===e?"args":"props"],t&&t[e]}function b(t){return this.cvtArgs(1,t)}function w(t,e){var n,r,i=this;if(""+e===e){for(;void 0===n&&i;)r=i.tmpl&&i.tmpl[t],n=r&&r[e],i=i.parent;return n||ot[t][e]}}function y(t,e,n,r,o,a){function s(t){var e=d[t];if(void 0!==e)for(e=dt(e)?e:[e],h=e.length;h--;)J=e[h],isNaN(parseInt(J))||(e[h]=parseInt(J));return e||[0]}e=e||it;var d,l,p,c,u,f,g,h,m,w,y,k,C,T,j,A,N,R,F,V,M,$,E,I,D,J,U,q,K,L,B=0,H="",Z=e.linkCtx||0,z=e.ctx,G=n||e.tmpl,W="number"==typeof r&&e.tmpl.bnds[r-1];for("tag"===t._is?(d=t,t=d.tagName,r=d.tagCtxs,p=d.template):(l=e.getRsc("tags",t)||S("Unknown tag: {{"+t+"}} "),p=l.template),void 0===a&&W&&(W._lr=l.lateRender&&W._lr!==!1||W._lr)&&(a=""),void 0!==a?(H+=a,r=a=[{props:{},args:[],params:{props:{}}}]):W&&(r=W(e.data,e,ft)),g=r.length;B0&&(a=n)){if(!a)if(/^\.\/[^\\:*?"<>]*$/.test(n))(s=lt[t=t||n])?n=s:a=document.getElementById(n);else if(e.fn&&!ft.rTmpl.test(n))try{a=e(n,document)[0]}catch(d){}a&&("SCRIPT"!==a.tagName&&S(n+": Use script block, not "+a.tagName),i?n=a.innerHTML:(o=a.getAttribute(Ht),o&&(o!==Zt?(n=lt[o],delete lt[o]):e.fn&&(n=e.data(a)[Zt])),o&&n||(t=t||(e.fn?Zt:n),n=A(t,a.innerHTML,r,i)),n.tmplName=t=t||o,t!==Zt&&(lt[t]=n),a.setAttribute(Ht,t),e.fn&&e.data(a,Zt,n))),a=void 0}else n.fn||(n=void 0);return n}var a,s,d=n=n||"";if(ft._html=pt.html,0===i&&(i=void 0,d=o(d)),i=i||(n.markup?n.bnds?l({},n):n:{}),i.tmplName=i.tmplName||t||"unnamed",r&&(i._parentTmpl=r),!d&&n.markup&&(d=o(n.markup))&&d.fn&&(d=d.markup),void 0!==d)return d.render||n.render?d.tmpls&&(s=d):(n=V(d,i),J(d.replace(Ft,"\\$&"),n)),s||(s=l(function(){return s.render.apply(s,arguments)},n),C(s)),s}function N(t,e){return st(t)?t.call(e):t}function R(t){for(var e=[],n=0,r=t.length;nO-(U||0))){if(U=I.slice(U,O+i.length),q!==!0)if(K=a||f[h-1].bd,L=K[K.length-1],L&&L.prm){for(;L.sb&&L.sb.prm;)L=L.sb;B=L.sb={path:L.sb,bnd:L.bnd}}else K.push(B={path:K.pop()});$=xt+":"+U+" onerror=''"+_t,q=v[$],q||(v[$]=!0,v[$]=q=J($,n,!0)),q!==!0&&B&&(B._cpfn=q,B.prm=u.bd,B.bnd=B.bnd||B.path&&B.path.indexOf("^")>=0)}return l?(l=!F,l?i:R+'"'):d?(d=!V,d?i:R+'"'):(_?(x[h]=O++,u=f[++h]={bd:[]},_):"")+(P?h?"":(g=I.slice(g,O),(o?(o=s=a=!1,"\b"):"\b,")+g+(g=O+i.length,c&&e.push(u.bd=[]),"\b")):C?(h&&D(t),c&&e.pop(),o="_"+w,s=b,g=O+i.length,c&&(c=u.bd=e[o]=[],c.skp=!b),w+":"):w?w.split("^").join(".").replace(jt,S)+(A?(u=f[++h]={bd:[]},m[h]=Q,A):y):y?y:M?(M=m[h]||M,m[h]=!1,u=f[--h],M+(A?(u=f[++h],m[h]=Q,A):"")):N?(m[h]||D(t),","):p?"":(l=F,d=V,'"'))}D(t)}var o,a,s,d,l,p,c=e&&e[0],u={bd:c},f={0:u},g=0,v=(n?n.links:c&&(c.links=c.links||{}))||it.tmpl.links,h=0,m={},x={};return"@"===t.charAt(0)&&(t=t.replace(Ut,".")),p=(t+(n?" ":"")).replace(At,i),!h&&p||D(t)}function B(t,e,n){var r,i,o,a,s,d,l,p,c,u,f,g,v,h,m,x,_,b,w,y,k,C,T,j,A,N,R,F,M,$,E,P,O,I=0,S=vt.useViews||e.useViews||e.tags||e.templates||e.helpers||e.converters,J="",q={},L=t.length;for(""+e===e?(b=n?'data-link="'+e.replace(Nt," ").slice(1,-1)+'"':e,e=0):(b=e.tmplName||"unnamed",e.allowCode&&(q.allowCode=!0),e.debug&&(q.debug=!0),f=e.bnds,_=e.tmpls),r=0;r":a+o):(k&&(w=V(C,q),w.tmplName=b+"/"+o,w.useViews=w.useViews||S,B(k,w),S=w.useViews,_.push(w)),A||(y=o,S=S||o&&(!ut[o]||!ut[o].flow),j=J,J=""),T=t[r+1],T=T&&"else"===T[0]),M=F?";\ntry{\nret+=":"\n+",h="",m="",N&&(g||$||a&&a!==Bt||E)){if(R=new Function("data,view,j,u","// "+b+" "+ ++I+" "+o+P+"{"+s+"};"+O),R._er=F,R._tag=o,R._bd=!!g,R._lr=E,n)return R;U(R,g),x='c("'+a+'",view,',u=!0,h=x+I+",",m=")"}if(J+=N?(n?(F?"try{\n":"")+"return ":M)+(u?(u=void 0,S=c=!0,x+(R?(f[I-1]=R,I):"{"+s+"}")+")"):">"===o?(l=!0,"h("+v[0]+")"):(p=!0,"((v="+v[0]+")!=null?v:"+(n?"null)":'"")'))):(d=!0,"\n{view:view,tmpl:"+(k?_.length:"0")+","+s+"},"),y&&!T){if(J="["+J.slice(0,-1)+"]",x='t("'+y+'",view,this,',n||g){if(J=new Function("data,view,j,u"," // "+b+" "+I+" "+y+P+J+O),J._er=F,J._tag=y,g&&U(f[I-1]=J,g),J._lr=E,n)return J;h=x+I+",undefined,",m=")"}J=j+M+x+(g&&I||J)+")",g=0,y=0}F&&!T&&(S=!0,J+=";\n}catch(e){ret"+(n?"urn ":"+=")+h+"j._err(e,view,"+F+")"+m+";}"+(n?"":"ret=ret"))}J="// "+b+(q.debug?"\ndebugger;":"")+"\nvar v"+(d?",t=j._tag":"")+(c?",c=j._cnvt":"")+(l?",h=j._html":"")+(n?(i[8]?", ob":"")+";\n":',ret=""')+J+(n?"\n":";\nreturn ret;");try{J=new Function("data,view,j,u",J)}catch(Q){D("Compiled template code:\n\n"+J+'\n: "'+(Q.message||Q)+'"')}return e&&(e.fn=J,e.useViews=!!S),J}function Q(t,e){return t&&t!==e?e?l(l({},e),t):t:e&&l({},e)}function H(t,n){var r,i,o=[];if(typeof t===Qt||st(t))for(r in t)i=t[r],r===at||!t.hasOwnProperty(r)||n.props.noFunctions&&e.isFunction(i)||o.push({key:r,prop:i});return Z(o,n)}function Z(t,n){var r,i,o,a=n.tag,s=n.props,d=n.params.props,l=s.filter,p=s.sort,c=p===!0,u=parseInt(s.step),f=s.reverse?-1:1;if(!dt(t))return t;if(c||p&&""+p===p?(r=t.map(function(t,e){return t=c?t:g(t,p),{i:e,v:""+t===t?t.toLowerCase():t}}),r.sort(function(t,e){return t.v>e.v?f:t.vt.length?t.length:+o,t=t.slice(i,o)),u>1){for(i=0,o=t.length,r=[];i=|[<>%*:?\/]|(=))\s*|(!*?(@)?[#~]?[\w$.^]+)([([])?)|(,\s*)|(\(?)\\?(?:(')|("))|(?:\s*(([)\]])(?=[.^]|\s*$|[^([])|[)\]])([([]?))|(\s+)/g,Nt=/[ \t]*(\r\n|\n|\r)/g,Rt=/\\(['"])/g,Ft=/['"\\]/g,Vt=/(?:\x08|^)(onerror:)?(?:(~?)(([\w$_\.]+):)?([^\x08]+))\x08(,)?([^\x08]+)/gi,Mt=/^if\s/,$t=/<(\w+)[>\s]/,Et=/[\x00`><"'&=]/g,Pt=/[\x00`><\"'&=]/,Ot=/^on[A-Z]|^convert(Back)?$/,It=/^\#\d+_`[\s\S]*\/\d+_`$/,St=Et,Dt=/[&<>]/g,Jt=/&(amp|gt|lt);/g,Ut=/\[['"]?|['"]?\]/g,qt=0,Kt={"&":"&","<":"<",">":">","\0":"�","'":"'",'"':""","`":"`","=":"="},Lt={amp:"&",gt:">",lt:"<"},Bt="html",Qt="object",Ht="data-jsv-tmpl",Zt="jsvTmpl",zt="For #index in nested block use #getIndex().",Gt={},Wt=t.jsrender,Xt=Wt&&e&&!e.render,Yt={template:{compile:A},tag:{compile:T},viewModel:{compile:F},helper:{},converter:{}};if(ot={jsviews:Ct,sub:{View:k,Err:d,tmplFn:J,parse:L,extend:l,extendCtx:Q,syntaxErr:D,onStore:{template:function(t,e){null===e?delete Gt[t]:Gt[t]=e}},addSetting:$,settings:{allowCode:!1},advSet:a,_thp:i,_gm:r,_tg:function(){},_cnvt:m,_tag:y,_er:S,_err:I,_cp:o,_sq:function(t){return"constructor"===t&&D(""),t}},settings:{delimiters:p,advanced:function(t){return t?(l(vt,t),ft.advSet(),ht):vt}},map:E},(d.prototype=new Error).constructor=d,u.depends=function(){return[this.get("item"),"index"]},f.depends="index",k.prototype={get:c,getIndex:f,getRsc:w,getTmpl:h,ctxPrm:v,getOb:g,_is:"view"},ft=ot.sub,ht=ot.settings,!(Wt||e&&e.render)){for(nt in Yt)M(nt,Yt[nt]);if(pt=ot.converters,ct=ot.helpers,ut=ot.tags,ft._tg.prototype={baseApply:j,cvtArgs:x,bndArgs:b,ctxPrm:v},it=ft.topView=new k,e){if(e.fn.render=z,at=e.expando,e.observable){if(Ct!==(Ct=e.views.jsviews))throw"JsObservable requires JsRender "+Ct;l(ft,e.views.sub),ot.map=e.views.map}}else e={},et&&(t.jsrender=e),e.renderFile=e.__express=e.compile=function(){throw"Node.js: use npm jsrender, or jsrender-node.js"},e.isFunction=function(t){return"function"==typeof t},e.isArray=Array.isArray||function(t){return"[object Array]"==={}.toString.call(t)},ft._jq=function(t){t!==e&&(l(t,e),e=t,e.fn.render=z,delete e.jsrender,at=e.expando)},e.jsrender=Ct;gt=ft.settings,gt.allowCode=!1,st=e.isFunction,e.render=Gt,e.views=ot,e.templates=lt=ot.templates;for(yt in gt)$(yt);(ht.debugMode=function(t){return void 0===t?gt.debugMode:(gt.debugMode=t,gt.onError=t+""===t?function(){return t}:st(t)?t:void 0,ht)})(!1),vt=gt.advanced={useViews:!1,_jsv:!1},ut({"if":{render:function(t){var e=this,n=e.tagCtx,r=e.rendering.done||!t&&(n.args.length||!n.index)?"":(e.rendering.done=!0,void(e.selected=n.index));return r},contentCtx:!0,flow:!0},"for":{sortDataMap:E(Z),init:function(t,e){var n,r,i,o=this,a=o.tagCtxs;for(n=a.length;n--;)r=a[n],i=r.props,r.argDefault=void 0===i.end||r.args.length>0,r.argDefault!==!1&&dt(r.args[0])&&(void 0!==i.sort||r.params.props.start||r.params.props.end||void 0!==i.step||i.filter||i.reverse)&&(i.dataMap=o.sortDataMap)},render:function(t){var e,n,r,i,o,a=this,s=a.tagCtx,d=s.argDefault===!1,l=s.props,p=d||s.args.length,c="",u=0;if(!a.rendering.done){if(e=p?t:s.view.data,d)for(d=l.reverse?"unshift":"push",i=+l.end,o=+l.step||1,e=[],r=+l.start||0;(i-r)*o>0;r+=o)e[d](r);void 0!==e&&(n=dt(e),c+=s.render(e,!p||l.noIteration),u+=n?e.length:1),(a.rendering.done=u)&&(a.selected=s.index)}return c},flow:!0},props:{baseTag:"for",dataMap:E(H),init:a,flow:!0},include:{flow:!0},"*":{render:o,flow:!0},":*":{render:o,flow:!0},dbg:ct.dbg=pt.dbg=s}),pt({html:X,attr:X,encode:Y,unencode:tt,url:function(t){return void 0!=t?encodeURI(""+t):null===t?t:""}})}return gt=ft.settings,dt=(e||Wt).isArray,ht.delimiters("{{","}}","^"),Xt&&Wt.views.sub._jq(e),e||Wt},window); //# sourceMappingURL=jsrender.min.js.map diff --git a/jsrender.min.js.map b/jsrender.min.js.map index e857189..785ed52 100644 --- a/jsrender.min.js.map +++ b/jsrender.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["jsrender.js"],"names":["factory","global","$","jQuery","exports","module","fn","define","amd","getDerivedMethod","baseMethod","method","ret","tag","this","prevBase","base","apply","arguments","getMethod","$isFunction","_d","noop","tagHandlersFromProps","tagCtx","prop","props","rHasHandlers","test","fix","constructor","prototype","retVal","val","dbgBreak","console","log","e","baseApply","JsViewsError","message","name","link","$extend","target","source","$viewsDelimiters","openChars","closeChars","$isArray","$views","$subSettings","delimiters","linkChar","charAt","delimOpenChar0","delimOpenChar1","delimCloseChar0","delimCloseChar1","rTag","$sub","RegExp","rTmpl","$viewsSettings","getView","inner","type","undefined","views","i","l","found","view","root","_","useKey","get","length","parent","getNestedIndex","index","getIndex","contextParameter","key","value","isContextCb","wrapped","deps","res","obsCtxPrm","storeView","isUpdate","isRenderCall","store","ctx","$helpers","it","linked","_cxp","scope","isTop","_ocps","_crcp","_ucp","_ceo","_ocp","unshift","cvtArgs","tagElse","ind","data","_vw","getTemplate","tmpl","getRsc","$templates","convertVal","converter","onError","argsLen","bindTo","boundTag","bnds","linkCtx","_lr","args","_bd","_tg","bnd","unlinked","inline","tagName","convert","flow","extendCtx","_er","onRender","convertArgs","bound","boundArgs","tagCtxs","error","slice","argOrProp","context","convertBoundArgs","getResource","resourceType","itemName","renderTag","parentView","makeArray","linkedElement","bindToLength","topView","tagDef","template","tags","attr","parentTag","m","itemRet","tagCtxCtx","ctxPrm","content","callInit","mapDef","thisMap","tagDataMap","contentCtx","parentTmpl","_is","lateRender","params","tmpls","render","renderContent","getTmpl","_ctr","init","dataMap","arrVws","dataBoundOnly","map","parents","parentTags","rendering","argDefault","isNaN","parseInt","noVws","HTML","linkedCtxParam","_cp","src","unmap","tgt","rWrappedInViewMarker","links","renderWithViews","$converters","html","View","contentTmpl","parentView_","self_","self","isArray","id","viewId","scp","indexStr","push","splice","compileChildResources","storeName","storeNames","resources","jsvStores","compileTag","Tag","baseTag","compiledDef","depends","$tags","_parentTmpl","compileTmpl","options","lookupTemplate","currentName","nodeType","elem","document","getElementById","innerHTML","getAttribute","tmplAttr","jsvTmpl","tmplName","setAttribute","compiledTmpl","tmplOrMarkup","_html","markup","tmplObject","tmplFn","replace","rEscapeQuotes","getDefaultVal","defaultVal","call","unmapArray","modelArr","arr","compileViewModel","GetNew","vm","iterate","action","getterType","ob","j","g","getters","getter","viewModels","JSON","parse","merge","viewModel","$expando","getterNames","mod","assigned","newModArr","k","model","$observable","refresh","concat","extend","proto","body","observable","privField","setProperty","set","Function","htmlTag","wrapMap","$subSettingsAdvanced","_wm","rFirstElem","exec","toLowerCase","div","trim","registerStore","storeSettings","theStore","item","compile","thisStore","onStore","OBJECT","getTgt","addSetting","st","Map","baseMap","noIteration","isTopRenderCall","prevData","prevIndex","result","useViews","setItemVar","newCtx","itemVar","newView","childView","itemResult","swapContent","outerOnRender","_wrp","syntaxError","helpers","contentView","onRenderError","fallback","Err","isLinkExpr","convertBack","hasElse","pushprecedingContent","shift","loc","substr","rNewLine","blockTagCheck","block","parseTag","all","bind","colon","codeTag","slash","bind2","closeBlock","late","pathBindings","ctxProps","paramsArgs","paramsProps","paramsCtxProps","useTrigger","allowCode","rUnescapeQuotes","rTestElseIf","current","substring","stack","pop","parseParams","rBuildHash","onerror","isCtx","keyToken","keyValue","arg","param","hasHandlers","newNode","parsedParam","bindings","astTop","buildCode","setPaths","pathsArr","paths","hasOwnProperty","skp","paramStructure","parts","parseTokens","lftPrn0","lftPrn","path","operator","err","eq","path2","prn","comma","lftPrn2","apos","quot","rtPrn","rtPrnDot","prn2","space","full","parsePath","allPath","not","object","helper","viewProperty","pathTokens","leafToken","subPath","binds","named","bindto","_jsvto","bndCtx","bd","theOb","_cpfn","sb","pathStart","parenDepth","expr","exprFn","newOb","rtSq","aposed","quoted","boundName","bndStack","prm","tmplLinks","indexOf","paramIndex","split","join","rPath","fnCall","0","rParams","ast","node","hasTag","hasEncoder","getsVal","hasCnvt","useCnvt","tmplBindings","boundOnErrStart","boundOnErrEnd","tagRender","nestedTmpls","nestedTmpl","tagAndElses","nextIsElse","oldCode","isElse","isGetVal","tagCtxFn","tagStart","trigger","tmplBindingKey","templates","converters","code","tmplOptions","debug","debugMode","_tag","parentContext","getCharEntity","ch","charEntities","charCodeAt","getTargetProps","$fnRender","tmplElem","jquery","htmlEncode","text","rIsHtml","rHtmlEncode","setGlobals","jsvStoreName","setting","versionNumber","rAttrEncode","&","<",">","\u0000","'","\"","`","=","$render","jsr","jsrender","jsrToJq","jsviews","sub","syntaxErr","settings","advSet","_ths","_gm","_cnvt","_err","_sq","token","advanced","Error","bndArgs","expando","renderFile","__express","isFunction","Array","obj","_jq","jq","_jsv","if","done","selected","for","finalElse","include","*",":*","dbg","url","encodeURI","window"],"mappings":"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","file":"jsrender.min.js","sourcesContent":["/*! JsRender v0.9.90 (Beta): http://jsviews.com/#jsrender */\n/*! **VERSION FOR WEB** (For NODE.JS see http://jsviews.com/download/jsrender-node.js) */\n/*\n * Best-of-breed templating in browser or on Node.js.\n * Does not require jQuery, or HTML DOM\n * Integrates with JsViews (http://jsviews.com/#jsviews)\n *\n * Copyright 2017, Boris Moore\n * Released under the MIT License.\n */\n\n//jshint -W018, -W041, -W120\n\n(function(factory, global) {\n\t// global var is the this object, which is window when running in the usual browser environment\n\tvar $ = global.jQuery;\n\n\tif (typeof exports === \"object\") { // CommonJS e.g. Browserify\n\t\tmodule.exports = $\n\t\t\t? factory(global, $)\n\t\t\t: function($) { // If no global jQuery, take optional jQuery passed as parameter: require('jsrender')(jQuery)\n\t\t\t\tif ($ && !$.fn) {\n\t\t\t\t\tthrow \"Provide jQuery or null\";\n\t\t\t\t}\n\t\t\t\treturn factory(global, $);\n\t\t\t};\n\t} else if (typeof define === \"function\" && define.amd) { // AMD script loader, e.g. RequireJS\n\t\tdefine(function() {\n\t\t\treturn factory(global);\n\t\t});\n\t} else { // Browser using plain