diff --git a/jquery.observable.js b/jquery.observable.js index 8ee6e4e..07bc179 100644 --- a/jquery.observable.js +++ b/jquery.observable.js @@ -1,9 +1,9 @@ -/*! JsObservable v0.9.90 (Beta): http://jsviews.com/#jsobservable */ +/*! JsObservable v0.9.91 (Beta): http://jsviews.com/#jsobservable */ /* * Subcomponent of JsViews * Data change events for data-linking * - * Copyright 2017, Boris Moore + * Copyright 2018, Boris Moore * Released under the MIT License. */ @@ -44,7 +44,7 @@ if (!$ || !$.fn) { throw "JsObservable requires jQuery"; // We require jQuery } -var versionNumber = "v0.9.90", +var versionNumber = "v0.9.91", _ocp = "_ocp", // Observable contextual parameter $observe, $observable, @@ -78,6 +78,11 @@ var versionNumber = "v0.9.90", $isArray = $.isArray, OBJECT = "object"; +if ($views.jsviews !== versionNumber) { + // Different version of jsRender was loaded + throw "JsObservable requires JsRender " + versionNumber; +} + if (!$.observe) { var $eventSpecial = $.event.special, @@ -86,6 +91,7 @@ if (!$.observe) { concat = [].concat, PARSEINT = parseInt, rNotWhite = /\S+/g, + rShallowPath = /^[^.[]*$/, // No '.' or '[' in path propertyChangeStr = $sub.propChng = $sub.propChng || "propertyChange",// These two settings can be overridden on settings after loading arrayChangeStr = $sub.arrChng = $sub.arrChng || "arrayChange", // jsRender, and prior to loading jquery.observable.js and/or JsViews cbBindingsStore = {}, @@ -93,14 +99,15 @@ if (!$.observe) { observeObjKey = 1, observeCbKey = 1, observeInnerCbKey = 1, - $hasData = $.hasData, $data = $.data, remove = {}, // flag for removeProperty //========================== Top-level functions ========================== getCbKey = function(cb) { - return cb._cId = cb._cId || (".obs" + observeCbKey++); + return cb + ? (cb._cId = cb._cId || (".obs" + observeCbKey++)) + : ""; }, ObjectObservable = function(ns, data) { @@ -143,7 +150,7 @@ if (!$.observe) { out = out.concat(dependsPaths(path.call(root, rt, callback), rt, callback)); continue; } else if ("" + path !== path) { - root = nextObj = path; + root = nextObj = path = (path === undefined ? null : path); if (nextObj !== object) { out.push(object = nextObj); } @@ -155,7 +162,8 @@ if (!$.observe) { out.push(path); } if (out.length) { - out.unshift({_ar: 1}); // Switch on allowArray, for depends paths. + // Switch on allowArray, for depends paths, by passing {_ar: ...} objects to switch on allowArray then return to contextual allowArray value + out.unshift({_ar: 1}); out.push({_ar: -1}); } return out; @@ -171,7 +179,7 @@ if (!$.observe) { onDataChange = function(ev, eventArgs) { function isOb(val) { - return typeof val === OBJECT && (paths[0] || allowArray && $isArray(val)); + return typeof val === OBJECT && (paths[0] || !noArray && $isArray(val)); } if (!(ev.data && ev.data.off)) { @@ -182,7 +190,7 @@ if (!$.observe) { ctx = ev.data, observeAll = ctx.observeAll, cb = ctx.cb, - allowArray = ctx.arOk, + noArray = ctx.arOk ? 0 : 1, paths = ctx.paths, ns = ctx.ns; @@ -203,10 +211,10 @@ if (!$.observe) { } } else { if (isOb(oldValue)) { // oldValue is an object, so unobserve - observe_apply(undefined, ns, [oldValue], paths, cb, true); // unobserve + observe_apply(noArray, ns, [oldValue], paths, cb, true); // unobserve. Observe array change events too if this change is not from an 'observeAndBind' tag binding, or is from a 'depends' path } if (isOb(value)) { // value is an object, so observe - observe_apply(undefined, ns, [value], paths, cb); + observe_apply(noArray, ns, [value], paths, cb); // observe. Observe array change events too if this change is not from an 'observeAndBind' tag binding, or is from a 'depends' path } } ctx.cb(ev, eventArgs); @@ -239,15 +247,13 @@ if (!$.observe) { function filterAndObserveAll(obj, prop, unobs, nestedArray) { var newObject, newParentObs; - if (prop !== $expando) { - if (newObject = $observable._fltr(newAllPath, obj[prop], nextParentObs, filter)) { - newParentObs = nextParentObs.slice(); - if (nestedArray && updatedTgt && newParentObs[0] !== updatedTgt) { - newParentObs.unshift(updatedTgt); // For array change events when observing an array which is not the root, need to add updated array to parentObs - } - observeAll(namespace, newObject, cb, filter || (nestedArray ? undefined : 0), newParentObs, newAllPath, unobs, objMap); - // If nested array, need to observe the array too - so set filter to undefined + if (prop !== $expando && (newObject = $observable._fltr(newAllPath, obj[prop], nextParentObs, filter))) { + newParentObs = nextParentObs.slice(); + if (nestedArray && updatedTgt && newParentObs[0] !== updatedTgt) { + newParentObs.unshift(updatedTgt); // For array change events when observing an array which is not the root, need to add updated array to parentObs } + observeAll(namespace, newObject, cb, filter || (nestedArray ? undefined : 0), newParentObs, newAllPath, unobs, objMap); + // If nested array, need to observe the array too - so set filter to undefined } } @@ -278,7 +284,7 @@ if (!$.observe) { if (object && typeof object === OBJECT) { nextParentObs = [object].concat(parentObs); // The parentObs chain for the next depth of observeAll isObject = $isArray(object) ? "" : "*"; - if (objMap && notRemoving && $hasData(object) && objMap[obId = $data(object).obId]) { + if (objMap && notRemoving && $.hasData(object) && objMap[obId = $data(object).obId]) { objMap[obId]++; return; // This object has already being observed/unobserved by this observeAll/unobserveAll call (must be a cyclic object graph) so skip, to avoid // stack overflow/multiple instances of listener. See jsviews/pull/305 @@ -332,8 +338,8 @@ if (!$.observe) { } }, - shallowFilter = function(allPath /*, object, parentObs*/) { - return allPath.indexOf(".") < 0 && allPath.indexOf("[") < 0; + shallowFilter = function(path /*, object, parentObs*/) { + return rShallowPath.test(path); // No '.' and no '[' in path }, $unobserve = function() { @@ -345,10 +351,23 @@ if (!$.observe) { // $.observe([namespace, ]root, [1 or more objects, path or path Array params...], callback[, contextCallback][, unobserve]) function innerObserve() { + var p, parts, unobserve, callback, cbId, inId, data, contextCb, items, cbBindings, + innerCb, parentObs, allPath, filter, initNsArr, initNsArrLen, view, prop, events, el; + + function unobserveBinding(cb, binding) { + var object; + for (data in binding) { + object = binding[data]; + if ($isArray(object)) { + bindArray(cb, object, unobserve, unobserve); + } else { + observeOnOff(cb, object, undefined, ns, ""); + } + } + } - function observeOnOff(namespace, pathStr, isArrayBinding, off) { + function observeOnOff(cb, object, fullPath, namespace, pathStr, isArrayBinding, off) { var j, evData, - obIdExpando = $hasData(object), boundObOrArr = wrapArray(object), prntObs = parentObs, allPth = allPath; @@ -356,15 +375,14 @@ if (!$.observe) { namespace = initialNs ? namespace + "." + initialNs : namespace; if (!unobserve && (off || isArrayBinding)) { - events = obIdExpando && $._data(object); - events = events && events.events; + events = $._data(object).events; events = events && events[isArrayBinding ? arrayChangeStr : propertyChangeStr]; el = events && events.length; while (el--) { // Skip duplicates data = events[el] && events[el].data; if (data && (off && data.ns !== initialNs // When observing, don't unbind dups unless they have the same namespace - || !off && data.ns === initialNs && data.cb && data.cb._cId === callback._cId && (!callback._wrp || data.cb._wrp))) + || !off && data.ns === initialNs && data.cb && data.cb._cId === cb._cId && (!cb._wrp || data.cb._wrp))) // When observing and doing array binding, don't bind dups if they have the same namespace (Dups can happen e.g. with {^{for people ^~foo=people}}) { return; @@ -376,13 +394,13 @@ if (!$.observe) { } else { evData = isArrayBinding ? {} : { - fullPath: path, + fullPath: fullPath, paths: pathStr ? [pathStr] : [], prop: prop, arOk: allowArray }; evData.ns = initialNs; - evData.cb = callback; + evData.cb = cb; if (allPath) { // This is an observeAll call @@ -412,48 +430,11 @@ if (!$.observe) { } } - function getInnerCb(exprOb) { - // Returns the innerCb used for updating a computed in a compiled expression (setting the new instance as exprOb.ob, unobserving the previous object, - // and observing the new one), then calling the outerCB - i.e. the handler for the whole compiled expression. - // Initialized exprOb.ob to the current object. - // Uses the contextCb callback to execute the compiled exprOb template in the context of the view/data etc. to get the returned value, typically an object or array. - // If it is an array, registers array binding - var origRt = root; - // Note: For jsviews/issues/292 ctxCb will need var ctxCb = contextCb || function(exprOb, origRt) {return exprOb._cpfn(origRt);}; - - exprOb.ob = contextCb(exprOb, origRt); // Initialize object - - return exprOb.cb = function(ev, eventArgs) { - var obj = exprOb.ob, // The old object - sub = exprOb.sb, - newObj = contextCb(exprOb, origRt); - - if (newObj !== obj) { - if (typeof obj === OBJECT) { - bindArray(obj, true); - if (sub || allowArray && $isArray(obj)) { - innerObserve([obj], sub, callback, contextCb, true); // unobserve on the old object - } - } - exprOb.ob = newObj; - // Put the updated object instance onto the exprOb in the paths array, so subsequent string paths are relative to this object - if (typeof newObj === OBJECT) { - bindArray(newObj); - if (sub || allowArray && $isArray(newObj)) { // observe on new object - innerObserve([newObj], sub, callback, contextCb); - } - } - } - // Call the outerCb - to execute the compiled expression that this computed is part of - callback(ev, eventArgs); - }; - } - - function bindArray(arr, unbind, isArray, relPath) { + function bindArray(cb, arr, unbind, isArray, relPath) { if (allowArray) { // allowArray is 1 if this is a call to observe that does not come from observeAndBind (tag binding), or is from a 'depends' path, // so we allow arrayChange binding. Otherwise allowArray is zero. - var prevObj = object, + var object, prevAllPath = allPath; object = arr; @@ -465,186 +446,84 @@ if (!$.observe) { object = $observable._fltr(allPath, object, relPath ? [arr].concat(parentObs) : parentObs, filter); } if (object && (isArray || $isArray(object))) { - observeOnOff(arrayChangeStr + ".observe" + (callback ? getCbKey(callback) : ""), undefined, true, unbind); + observeOnOff(cb, object, undefined, arrayChangeStr + ".observe" + getCbKey(cb), undefined, true, unbind); } - object = prevObj; allPath = prevAllPath; } } - var i, p, skip, parts, prop, path, dep, unobserve, callback, cbId, inId, el, data, events, contextCb, innerContextCb, - items, cbBindings, depth, innerCb, parentObs, allPath, filter, initNsArr, initNsArrLen, view, cbItemCount, - ns = observeStr, - paths = this != 1 // Using != for IE<10 bug- see jsviews/issues/237 - ? concat.apply([], arguments) // Flatten the arguments - this is a 'recursive call' with params using the 'wrapped array' - // style - such as innerObserve([object], path.path, [origRoot], path.prm, innerCb, ...); - : slice.call(arguments), // Don't flatten - this is the first 'top-level call, to innerObserve.apply(1, paths) - lastArg = paths.pop() || false, - root = paths.shift(), - object = root, - l = paths.length; - - if (lastArg + "" === lastArg) { // If last arg is a string then this observe call is part of an observeAll call, - allPath = lastArg; // and the last three args are the parentObs array, the filter, and the allPath string. - parentObs = paths.pop(); - filter = paths.pop(); - lastArg = !!paths.pop(); // unobserve - l -= 3; - } - if (lastArg === !!lastArg) { - unobserve = lastArg; - lastArg = paths[l-1]; - lastArg = l && lastArg + "" !== lastArg && (!lastArg || $isFunction(lastArg)) ? (l--, paths.pop()) : undefined; - if (unobserve && !l && $isFunction(root)) { - lastArg = root; - root = undefined; - } - } - callback = lastArg; - if (l && $isFunction(paths[l - 1])) { - innerContextCb = contextCb = callback; - callback = paths.pop(); - l--; - } - - if (unobserve && callback && !callback._cId) { - return; - } - - // Use a unique namespace (e.g. obs7) associated with each observe() callback to allow unobserve to remove handlers - ns += callback - ? ((inId = callback._inId || ""), unobserve) - ? callback._cId + inId - : (cbId = getCbKey(callback)) + inId - : ""; - - if (cbId && !unobserve) { - cbBindings = cbBindingsStore[cbId] = cbBindingsStore[cbId] || {}; - } + function observeObjects(paths) { + + function observeObjectPaths(object, pths, callback, contextCb) { + + function getInnerCb(exprOb) { + exprOb.ob = contextCb(exprOb, object); // Initialize object + return exprOb.cb = function(ev, eventArgs) { + // The innerCb used for updating a computed in a compiled expression (setting the new instance as exprOb.ob, unobserving the previous object, + // and observing the new one), then calling the outerCB - i.e. the handler for the whole compiled expression. + // Initialized exprOb.ob to the current object. + // Uses the contextCb callback to execute the compiled exprOb template in the context of the view/data etc. to get the returned value, typically an object or array. + // If it is an array, registers array binding + // Note: For jsviews/issues/292 ctxCb will need var ctxCb = contextCb || function(exprOb, origRt) {return exprOb._cpfn(origRt);}; + var obj = exprOb.ob, // The old object + sub = exprOb.sb, + newObj = contextCb(exprOb, object); + + if (newObj !== obj) { + if (typeof obj === OBJECT) { + bindArray(callback, obj, true); + if (sub || allowArray && $isArray(obj)) { + innerObserve([obj], sub, callback, contextCb, true); // unobserve on the old object + } + } + exprOb.ob = newObj; + // Put the updated object instance onto the exprOb in the paths array, so subsequent string paths are relative to this object + if (typeof newObj === OBJECT) { + bindArray(callback, newObj); + if (sub || allowArray && $isArray(newObj)) { // observe on new object + innerObserve([newObj], sub, callback, contextCb); + } + } + } + // Call the outerCb - to execute the compiled expression that this computed is part of + callback(ev, eventArgs); + }; + } - initNsArr = initialNs && initialNs.match(rNotWhite) || [""]; - initNsArrLen = initNsArr.length; + function observePath(object, prts) { // Step through the path parts "this.is^some.path" and observe changes (on the leaf, or down to the bound depth) - while (initNsArrLen--) { - initialNs = initNsArr[initNsArrLen]; - if (root && !paths[0]) { - if ($isArray(root)) { - bindArray(root, unobserve, true); // observe(array, handler) - } - if (unobserve) { - observeOnOff(ns, ""); // unobserve(objectOrArray[, handler]) - } - } - if (unobserve && !l && !root) { // unobserve() - unobserves all - for (p in cbBindingsStore) { - p = cbBindingsStore[p]; - for (data in p) { - object = p[data]; - if ($isArray(object)) { - bindArray(object, unobserve, unobserve); - } else { - observeOnOff(ns, ""); + function obArrAddRemove(ev, eventArgs) { + // If a "[].*" or "[].prop" wild card path (for observing properties of array items) we need to observe or unobserve added or removed items + var l; + if (eventArgs.change === "insert" || (unobserve = eventArgs.change === "remove")) { + l = eventArgs.items.length; + while (l--) { + observePath(eventArgs.items[l], prts.slice()); + } + unobserve = false; } } - } - } - depth = 0; - cbItemCount = 0; - for (i = 0; i < l; i++) { - if (cbItemCount) { - cbItemCount--; // contextCb was moved to a contextual parameter outer context. Needs to revert after cbItemCount - } else { - contextCb = innerContextCb; - } - path = paths[i]; - if (path === "" || path === root) { - continue; - } - if (path && path._ar) { - allowArray += path._ar; // Switch on allowArray for depends paths, and off, afterwards. - continue; - } - object = root; - if ("" + path === path) { - // Consider support for computed paths: jsviews/issues/292 - //if (/[\(\[\+]/.test(path)) { - // var b={links:{}}, t = $sub.tmplFn("{:"+path+"}", b, true), items = t.paths[0]; - // l += items.length - 1; - // splice.apply(paths, [i--, 1].concat(items)); - // continue; - //} - parts = path.split("^"); - if (parts[1]) { - // We bind the leaf, plus additional nodes based on depth. - // "a.b.c^d.e" is depth 2, so listens to changes of e, plus changes of d and of c - depth = parts[0].split(".").length; - path = parts.join("."); - depth = path.split(".").length - depth; - // if more than one ^ in the path, the first one determines depth + //prts = $isArray(prts) ? prts : [prts]; + if (callback) { + obArrAddRemove._cId = getCbKey(callback); // Identify wrapped callback with unwrapped callback, so unobserveAll will + // remove previous observeAll wrapped callback, if inner callback was the same; } - if (contextCb) { - items = contextCb(path, root, depth); - } - contextCb = innerContextCb; - parts = path.split("."); - } else if (path && path._cxp) { // contextual parameter - view = path.shift(); // Contextual data - if (_ocp in view) { - root = view; // observable contextual parameter - contextCb = 0; - } else { - contextCb = $sub._gccb(view); // getContextCb: Get context callback for the contextual view (where contextual param evaluated/assigned) - root = view.data; - } - items = path; - items.push(origRoot); - cbItemCount = items.length; - } else { - if (!$isFunction(path)) { - if (path && path._cpfn) { - // Path is an exprOb returned by a computed property - helper/data function (compiled expr function). - // Set current object on exprOb.ob, and get innerCb for updating the object - innerCb = unobserve ? path.cb : getInnerCb(path); - // innerCb._ctx = callback._ctx; Could pass context (e.g. linkCtx) for use in a depends = function() {} call, so depends is different for different linkCtx's - innerCb._cId = callback._cId; - // Set the same cbBindingsStore key as for callback, so when callback is disposed, disposal of innerCb happens too. - innerCb._inId = innerCb._inId || ".obIn" + observeInnerCbKey++; - if (path.bnd || path.prm && path.prm.length || !path.sb) { - // If the exprOb is bound e.g. foo()^sub.path, or has parameters e.g. foo(bar) or is a leaf object (so no sub path) e.g. foo() - // then observe changes on the object, or its parameters and sub-path - innerObserve([object], path.path, [path.root||root], path.prm, innerCb, contextCb, unobserve); - } - if (path.sb) { // subPath - if (path.sb.prm) { - path.sb.root = root; - } - innerObserve([path.ob], path.sb, callback, contextCb, unobserve); - } - path = origRoot; - object = undefined; - } + + var arrIndex, skip, dep, obArr, prt, + obj = object; + if (object && object._cxp) { + return observeObjectPaths(object[0], [object[1]], callback, contextCb); } - parts = [root = path]; - } - if (items) { - // If the array of objects and paths returned by contextCb is non empty, insert them - // into the sequence, replacing the current item (path). Otherwise simply remove current item (path) - l += items.length - 1; - splice.apply(paths, [i--, 1].concat(items)); - items = undefined; - continue; - } - while (object && (prop = parts.shift()) !== undefined) { - if (typeof object === OBJECT) { - if ("" + prop === prop) { + + while ((prop = prts.shift()) !== undefined) { + if (obj && typeof obj === OBJECT && "" + prop === prop) { if (prop === "") { continue; } - if ((parts.length < depth + 1) && !object.nodeType) { + if ((prts.length < depth + 1) && !obj.nodeType) { // Add observer for each token in path starting at depth, and on to the leaf - if (!unobserve && (events = $hasData(object) && $._data(object))) { - events = events.events; + if (!unobserve && (events = $._data(obj).events)) { events = events && events[propertyChangeStr]; el = events && events.length; skip = 0; @@ -655,60 +534,254 @@ if (!$.observe) { && data.cb._cId === callback._cId && data.cb._inId === callback._inId && (data.prop === prop || data.prop === "*" || data.prop === "**")) { - if (p = parts.join(".")) { - data.paths.push(p); // We will skip this binding, but if it is not a leaf binding, - // need to keep bindings for rest of path, ready for if the object gets swapped. + if (prt = prts.join(".")) { + data.paths.push(prt); // We will skip this binding, but if it is not a leaf binding, + // need to keep bindings for rest of path, ready for if the obj gets swapped. } skip++; } } if (skip) { // Duplicate binding(s) found, so move on - object = object[prop]; + obj = obj[prop]; continue; } } if (prop === "*" || prop === "**") { // "*" => all properties. "**" => all properties and sub-properties (i.e. deep observeAll behavior) if (!unobserve && events && events.length) { // Remove existing bindings, since they will be duplicates with "*" or "**" - observeOnOff(ns, "", false, true); + observeOnOff(callback, obj, path, ns, "", false, true); } if (prop === "*") { - observeOnOff(ns, ""); // observe the object for any property change - for (p in object) { + observeOnOff(callback, obj, path, ns, ""); // observe the object for any property change + for (prt in obj) { // observing "*": So (in addition to listening to prop change, above) listen to arraychange on props of type array - if (p !== $expando) { - bindArray(object, unobserve, undefined, p); + if (prt !== $expando) { + bindArray(callback, obj, unobserve, undefined, prt); } } } else { - $.observable(initialNs, object)[(unobserve ? "un" : "") + "observeAll"](callback); // observe or unobserve the object for any property change + $.observable(initialNs, obj)[(unobserve ? "un" : "") + "observeAll"](callback); // observe or unobserve the object for any property change } break; + } else if (prop == "[]") { // "[].*" or "[].prop" wild card path, for observing properties of array items + if ($isArray(obj)) { + if (unobserve) { + observeOnOff(callback, obj, path, arrayChangeStr + getCbKey(callback), undefined, unobserve, unobserve); + } else { + $observe(initialNs, obj, obArrAddRemove, unobserve); // observe or unobserve added or removed items + } + } } else if (prop) { - observeOnOff(ns + ".p_" + prop, parts.join("^")); // By using "^" rather than "." we ensure that deep binding will be used on newly inserted object graphs + observeOnOff(callback, obj, path, ns + ".p_" + prop, prts.join("^")); // By using "^" rather than "." we ensure that deep binding will be used on newly inserted object graphs } } if (allPath) { allPath += "." + prop; } - prop = object[prop]; - if (!parts[0]) { - bindArray(prop, unobserve); // [un]observe(object, "arrayProperty") observes array changes on property of type array + if (prop === "[]") { + if ($isArray(obj)) { + obArr = obj; + arrIndex = obj.length; + } + while (arrIndex--) { + obj = obArr[arrIndex]; + observePath(obj, prts.slice()); + } + return; + } + prop = obj[prop]; + if (!prts[0]) { + bindArray(callback, prop, unobserve); // [un]observe(object, "arrayProperty") observes array changes on property of type array } } if ($isFunction(prop)) { if (dep = prop.depends) { // This is a computed observable. We will observe any declared dependencies. - // Pass {_ar: ...} objects to switch on allowArray, for depends paths, then return to contextual allowArray value - innerObserve([object], dependsPaths(dep, object, callback), callback, contextCb, unobserve); + if (obj._vw && obj._ocp) { + // Observable contextual parameter, so context was ocp object. Now move context to view.data for dependencies + obj = obj._vw; // storeView or tag (scope of contextual parameter) + if (obj._tgId) { + // Is a tag, so get view + obj = obj.tagCtx.view; + } + obj = obj.data; // view.data + } + observeObjects(concat.apply([], [[obj], dependsPaths(dep, obj, callback)])); } break; } - object = prop; + obj = prop; + } + } + + var i, path, + depth = 0, + l = pths.length; + if (object && !contextCb && ((view = object._is === "view") || object._is === "tag")) { + contextCb = $sub._gccb(view ? object : object.tagCtx.contentView); + if (callback && !unobserve) { + (function() { + var ob = object, + cb = callback; + callback = function(ev, eventArgs) { + // Wrapped callback so this pointer is tag or view + cb.call(ob, ev, eventArgs); + }; + callback._cId = cb._cId; + callback._inId = cb._inId; + })(); + } + object = view ? object.data : object; + } + if (!pths[0]) { + if ($isArray(object)) { + bindArray(callback, object, unobserve, true); // observe(array, handler) + } else if (unobserve) { + observeOnOff(callback, object, undefined, ns, ""); // unobserve(objectOrArray[, handler]) + } + } + for (i = 0; i < l; i++) { // Step through objects and paths + path = pths[i]; + if (path === "") { + continue; + } + if (path && path._ar) { + allowArray += path._ar; // Switch on allowArray for depends paths, and off, afterwards. + continue; + } + if ("" + path === path) { + parts = path.split("^"); + if (parts[1]) { + // We bind the leaf, plus additional nodes based on depth. + // "a.b.c^d.e" is depth 2, so listens to changes of e, plus changes of d and of c + depth = parts[0].split(".").length; + path = parts.join("."); + depth = path.split(".").length - depth; + // if more than one ^ in the path, the first one determines depth + } + if (contextCb && (items = contextCb(path, object, depth))) { + //object, paths + if (items.length) { + var ob = items[0], + pth = items[1]; + if (ob && ob._cxp) { // contextual parameter + pth = ob[1]; + ob = ob[0]; + if (ob._is === "view") { + observeObjectPaths(ob, [pth], callback); // Setting contextCb to undefined, to use passed in view for new contextCb + continue; + } + } + if (pth + "" === pth) { + observePath(ob, pth.split(".")); + } else { + observeObjectPaths(items.shift(), items, callback, contextCb); + } + } + } else { + observePath(object, path.split(".")); + } + } else if (!$isFunction(path) && path && path._cpfn) { + // Path is an exprOb returned by a computed property - helper/data function (compiled expr function). + // Get innerCb for updating the object + innerCb = unobserve ? path.cb : getInnerCb(path); + // innerCb._ctx = callback._ctx; Could pass context (e.g. linkCtx) for use in a depends = function() {} call, so depends is different for different linkCtx's + innerCb._cId = callback._cId; + // Set the same cbBindingsStore key as for callback, so when callback is disposed, disposal of innerCb happens too. + innerCb._inId = innerCb._inId || ".obIn" + observeInnerCbKey++; + if (path.bnd || path.prm && path.prm.length || !path.sb) { + // If the exprOb is bound e.g. foo()^sub.path, or has parameters e.g. foo(bar) or is a leaf object (so no sub path) e.g. foo() + // then observe changes on the object, or its parameters and sub-path + innerObserve([object], path.path, (path.prm.length ? [path.root||object] : []), path.prm, innerCb, contextCb, unobserve); + } + if (path.sb) { // Has a subPath + // Observe changes on the sub-path + if (path.sb.prm) { + path.sb.root = object; + } + // Set current object on exprOb.ob + observeObjectPaths(path.ob, [path.sb], callback, contextCb); + } } } } + + var pth, + pths = [], // Array of paths for current object + l = paths.length; + while (l--) { // Step backwards through paths and objects + pth = paths[l]; + if (pth + "" === pth || pth && (pth._ar || pth._cpfn)) { + pths.unshift(pth); // This is a path so add to arr + } else { // This is an object + observeObjectPaths(pth, pths, callback, contextCb); + pths = []; // New array for next object + } + } + } + + var ns = observeStr, + paths = this != 1 // Using != for IE<10 bug- see jsviews/issues/237 + ? concat.apply([], arguments) // Flatten the arguments - this is a 'recursive call' with params using the 'wrapped array' + // style - such as innerObserve([object], path.path, [origRoot], path.prm, innerCb, ...); + : slice.call(arguments), // Don't flatten - this is the first 'top-level call, to innerObserve.apply(1, paths) + lastArg = paths.pop() || false, + m = paths.length; + +//END OF FUNCTIONS + if (lastArg + "" === lastArg) { // If last arg is a string then this observe call is part of an observeAll call, + allPath = lastArg; // and the last three args are the parentObs array, the filter, and the allPath string. + parentObs = paths.pop(); + filter = paths.pop(); + lastArg = !!paths.pop(); // unobserve + m -= 3; + } + if (lastArg === !!lastArg) { + unobserve = lastArg; + lastArg = paths[m-1]; + lastArg = m && lastArg + "" !== lastArg && (!lastArg || $isFunction(lastArg)) ? (m--, paths.pop()) : undefined; + if (unobserve && !m && $isFunction(paths[0])) { + lastArg = paths.shift(); + } + } + callback = lastArg; + if (m && $isFunction(paths[m - 1])) { + contextCb = callback; + lastArg = callback = paths.pop(); + m--; + } + + if (unobserve && callback && !callback._cId) { + return; + } + + // Use a unique namespace (e.g. obs7) associated with each observe() callback to allow unobserve to remove handlers + ns += callback + ? ((inId = callback._inId || ""), unobserve) + ? callback._cId + inId + : (cbId = getCbKey(callback)) + inId + : ""; + + if (cbId && !unobserve) { + cbBindings = cbBindingsStore[cbId] = cbBindingsStore[cbId] || {}; + } + + initNsArr = initialNs && initialNs.match(rNotWhite) || [""]; + initNsArrLen = initNsArr.length; + + while (initNsArrLen--) { // Step through multiple white-space separated namespaces if there are any + initialNs = initNsArr[initNsArrLen]; + if (unobserve && arguments.length < 3) { + if (callback) { + unobserveBinding(callback, cbBindingsStore[callback._cId]); // unobserve(handler) - unobserves this handler, all objects + } else if (!paths[0]) { + for (p in cbBindingsStore) { + unobserveBinding(callback, cbBindingsStore[p]); // unobserve() - unobserves all + } + } + } + observeObjects(paths); } if (cbId) { removeCbBindings(cbBindings, cbId); @@ -723,12 +796,11 @@ if (!$.observe) { // arrayChange events in this scenario. Instead, {^{for}} and similar do specific arrayChange binding to the tagCtx.args[0] value, in onAfterLink. // Note deliberately using this == 1, rather than this === 1 because of IE<10 bug- see jsviews/issues/237 paths = slice.call(arguments), - origRoot = paths[0]; + pth = paths[0]; - if (origRoot + "" === origRoot && allowArray) { - initialNs = origRoot; // The first arg is a namespace, since it is a string, and this call is not from observeAndBind + if (pth + "" === pth) { + initialNs = pth; // The first arg is a namespace, since it is a string paths.shift(); - origRoot = paths[0]; } return innerObserve.apply(1, paths); }; @@ -746,10 +818,10 @@ if (!$.observe) { //========================== Initialize ========================== $.observable = $observable; - $observable._fltr = function(allPath, object, parentObs, filter) { + $observable._fltr = function(path, object, parentObs, filter) { if (filter && $isFunction(filter) - ? filter(allPath, object, parentObs) - : true // TODO Consider supporting filter being a string or strings to do RegEx filtering based on key and/or allPath + ? filter(path, object, parentObs) + : true // TODO Consider supporting filter being a string or strings to do RegEx filtering based on key and/or path ) { object = $isFunction(object) ? object.set && object.call(parentObs[0]) // It is a getter/setter @@ -777,7 +849,7 @@ if (!$.observe) { setProperty: function(path, value, nonStrict) { path = path || ""; var key, pair, parts, - multi = path + "" !== path && !path._is, // Hash of paths, not view object + multi = path + "" !== path, // Hash of paths self = this, object = self._data; @@ -800,13 +872,9 @@ if (!$.observe) { } } else if (path !== $expando) { // Simple single property case. - if (path._is) { - parts = [path]; - } else { - parts = path.split(/[.^]/); - while (object && parts.length > 1) { - object = object[parts.shift()]; - } + parts = path.split(/[.^]/); + while (object && parts.length > 1) { + object = object[parts.shift()]; } if (object) { self._setProperty(object, parts[0], value, nonStrict); @@ -822,20 +890,18 @@ if (!$.observe) { }, _setProperty: function(leaf, path, value, nonStrict) { - var setter, getter, removeProp, + var setter, getter, removeProp, eventArgs, view, property = path ? leaf[path] : leaf; - if ($isFunction(property)) { - if (property.set) { - // Case of property setter/getter - with convention that property is getter and property.set is setter - leaf = leaf._vw // Case of JsViews 2-way data-linking to an observable context parameter, with a setter. - // The view will be the this pointer for getter and setter. Note: this is the one scenario where path is "". - || leaf; - getter = property; - setter = getter.set === true ? getter : getter.set; - property = getter.call(leaf); // get - only treated as getter if also a setter. Otherwise it is simply a property of type function. - // See unit tests 'Can observe properties of type function'. - } + if ($isFunction(property) && property.set) { + // Case of property setter/getter - with convention that property is getter and property.set is setter + view = leaf._vw // Case of JsViews 2-way data-linking to an observable context parameter, with a setter. + // The view will be the this pointer for getter and setter. Note: this is the one scenario where path is "". + || leaf; + getter = property; + setter = getter.set === true ? getter : getter.set; + property = getter.call(view); // get - only treated as getter if also a setter. Otherwise it is simply a property of type function. + // See unit tests 'Can observe properties of type function'. } if ((property !== value || nonStrict && property != value) @@ -843,8 +909,8 @@ if (!$.observe) { // Date objects don't support != comparison. Treat as special case. && (!(property instanceof Date && value instanceof Date) || property > value || property < value)) { if (setter) { - setter.call(leaf, value); //set - value = getter.call(leaf); //get updated value + setter.call(view, value); // set + value = getter.call(view); // get updated value } else if (removeProp = value === remove) { if (property !== undefined) { delete leaf[path]; @@ -856,7 +922,11 @@ if (!$.observe) { leaf[path] = value; } if (path) { - this._trigger(leaf, {change: "set", path: path, value: value, oldValue: property, remove: removeProp}); + eventArgs = {change: "set", path: path, value: value, oldValue: property, remove: removeProp}; + if (leaf._ocp) { + eventArgs.ctxPrm = leaf._key; + } + this._trigger(leaf, eventArgs); } } }, @@ -1010,7 +1080,9 @@ if (!$.observe) { self.remove(j, dataLength - j); } self._srt = undefined; // We have finished sort operations during refresh - self._trigger({change: "refresh", oldItems: oldItems}, oldLength); + if (oldLength || newLength) { + self._trigger({change: "refresh", oldItems: oldItems}, oldLength); + } return self; }, @@ -1055,19 +1127,31 @@ if (!$.observe) { } }; +//========================== +// dataMap with data-linking +//========================== + $views.map = function(mapDef) { - function Map(source, options, target, unbound) { - var changing, + function Map(source, options, oldMapOrTarget, unbound) { + var changing, updatedMap, map = this; - if (this.src) { - this.unmap(); // We are re-mapping a new source + if (map.src) { + map.unmap(); // We are re-mapping a new source + } + if (options) { + options.map = map; } - if (typeof source === OBJECT) { + if (typeof source === OBJECT || $isFunction(source)) { map.src = source; - map.tgt = target || map.tgt || []; + if (oldMapOrTarget) { + map.tgt = oldMapOrTarget.tgt || oldMapOrTarget; // Can provide an existing map, or a target array to be used on new map + } else { + map.tgt = map.tgt || []; + } map.options = options || map.options; - map.update(); - if (!unbound) { + if (updatedMap = map.update()) { + map = updatedMap; // If updating returns another map, then we can replace this one (so no need to bind it) + } else if (!unbound) { if (mapDef.obsSrc) { $observable(map.src).observeAll(map.obs = function(ev, eventArgs) { if (!changing) { @@ -1079,11 +1163,11 @@ if (!$.observe) { } if (mapDef.obsTgt) { $observable(map.tgt).observeAll(map.obt = function(ev, eventArgs) { - if (!changing) { - changing = true; - mapDef.obsTgt(map, ev, eventArgs); - changing = undefined; - } + if (!changing && !map.tgt._updt) { + changing = true; + mapDef.obsTgt(map, ev, eventArgs); + changing = undefined; + } }, map.tgtFlt); } } @@ -1101,28 +1185,37 @@ if (!$.observe) { mapDef = $.extend({}, mapDef.baseMap, mapDef); } - mapDef.map = function(source, options, target, unbound) { - return new Map(source, options, target, unbound); + mapDef.map = function(source, options, oldMap, unbound) { + return new Map(source, options, oldMap, unbound); }; (Map.prototype = { srcFlt: mapDef.srcFlt || shallowFilter, // default to shallowFilter tgtFlt: mapDef.tgtFlt || shallowFilter, update: function(options) { - var map = this; - $observable(map.tgt).refresh(mapDef.getTgt(map.src, map.options = options || map.options)); + var oldMap, newMap, + map = this, + tgt = map.tgt; + if (!tgt._updt) { + tgt._updt = true; + oldMap = map.options && map.options.map; + $observable(tgt).refresh(mapDef.getTgt(map.src, map.options = options || map.options)); + tgt._updt = false; + newMap = map.options && map.options.map; + if (newMap && oldMap !== newMap) { + return newMap; + } + } }, unmap: function() { var map = this; - if (map.src) { - if (map.obs) { - $observable(map.src).unobserveAll(map.obs, map.srcFlt); - } - if (map.obt) { - $observable(map.tgt).unobserveAll(map.obt, map.tgtFlt); - } - map.src = undefined; + if (map.src && map.obs) { + $observable(map.src).unobserveAll(map.obs, map.srcFlt); + } + if (map.tgt && map.obt) { + $observable(map.tgt).unobserveAll(map.obt, map.tgtFlt); } + map.src = undefined; }, map: Map, _def: mapDef @@ -1140,6 +1233,8 @@ if (!$.observe) { : undefined; // In IE8 cannot do delete global._jsv }; $sub._dp = dependsPaths; + $sub._gck = getCbKey; + $sub._obs = $observe; } return $; diff --git a/jquery.observable.min.js b/jquery.observable.min.js index f268f51..6351e71 100644 --- a/jquery.observable.min.js +++ b/jquery.observable.min.js @@ -1,3 +1,3 @@ -/*! JsObservable v0.9.90 (Beta): http://jsviews.com/#jsobservable */ -!function(t,e){var n=e.jQuery;"object"==typeof exports?module.exports=n?t(e,n):function(n){return t(e,n)}:"function"==typeof define&&define.amd?define(["jquery"],function(n){return t(e,n)}):t(e,!1)}(function(t,e){"use strict";var n=e===!1;if(e=e||t.jQuery,!e||!e.fn)throw"JsObservable requires jQuery";var r,i,o="v0.9.90",s="_ocp",a=e.views=e.views||n&&t.jsrender&&jsrender.views||{jsviews:o,sub:{settings:{}},settings:{advanced:function(t){return f=l.advanced=l.advanced||{_jsv:!0},t?("_jsv"in t&&(f._jsv=t._jsv),c.advSet(),a.settings):f}}},c=a.sub,l=c.settings,f=l.advanced,u=e.isFunction,p=e.expando,d=e.isArray,h="object";if(!e.observe){var v=e.event.special,_=[].slice,g=[].splice,b=[].concat,y=parseInt,m=/\S+/g,I=c.propChng=c.propChng||"propertyChange",j=c.arrChng=c.arrChng||"arrayChange",w={},A=I+".observe",x=1,F=1,P=1,k=e.hasData,C=e.data,S={},O=function(t){return t._cId=t._cId||".obs"+F++},T=function(t,e){return this._data=e,this._ns=t,this},V=function(t,e){return this._data=e,this._ns=t,this},D=function(t){return d(t)?[t]:t},H=function(t,e,n){t=t?d(t)?t:[t]:[];var r,i,o,s,a=o=e,c=t&&t.length,l=[];for(r=0;r1;)c=c[o.shift()];c&&a._setProperty(c,o[0],e,n)}return a},removeProperty:function(t){return this.setProperty(t,S),this},_setProperty:function(t,e,n,r){var i,o,s,a=e?t[e]:t;u(a)&&a.set&&(t=t._vw||t,o=a,i=o.set===!0?o:o.set,a=o.call(t)),(a!==n||r&&a!=n)&&(!(a instanceof Date&&n instanceof Date)||a>n||a-1&&(e=d(e)?e:[e],e.length&&this._insert(t,e)),this},_insert:function(t,e){var n=this._data,r=n.length;t>r&&(t=r),g.apply(n,[t,0].concat(e)),this._trigger({change:"insert",index:t,items:e},r)},remove:function(t,e){var n,r=this._data;return void 0===t&&(t=r.length-1),t=y(t),e=e?y(e):0===e?0:1,e>0&&t>-1&&(n=r.slice(t,t+e),(e=n.length)&&this._remove(t,e,n)),this},_remove:function(t,e,n){var r=this._data,i=r.length;r.splice(t,e),this._trigger({change:"remove",index:t,items:n},i)},move:function(t,e,n){return n=n?y(n):0===n?0:1,t=y(t),e=y(e),n>0&&t>-1&&e>-1&&t!==e&&this._move(t,e,n),this},_move:function(t,e,n){var r,i=this._data,o=i.length,s=t+n-o;s>0&&(n-=s),n&&(r=i.splice(t,n),e>i.length&&(e=i.length),g.apply(i,[e,0].concat(r)),e!==t&&this._trigger({change:"move",oldIndex:t,index:e,items:r},o))},refresh:function(t){function e(){i&&(a.insert(r-i,c),p+=i,n+=i,i=0,c=[])}var n,r,i,o,s,a=this,c=[],l=a._data,f=l.slice(),u=l.length,p=u,d=t.length;for(a._srt=!0,r=i=0;rr&&a.remove(r,p-r),a._srt=void 0,a._trigger({change:"refresh",oldItems:f},u),a},_trigger:function(t,n){var r=this,i=r._data,o=i.length,s=e([i]);r._srt?t.refresh=!0:o!==n&&s.triggerHandler(I,{change:"set",path:"length",value:o,oldValue:n}),s.triggerHandler(j+(r._ns?"."+/^\S+/.exec(r._ns)[0]:""),t)}},v[I]=v[j]={remove:function(t){var n,r,i,o,s,a=t.data;if(a&&(a.off=!0,a=a.cb)&&(n=w[a._cId])){for(i=e._data(this).events[t.type],o=i.length;o--&&!r;)r=(s=i[o].data)&&s.cb&&s.cb._cId===a._cId;r||(delete n[C(this).obId],Q(n,a._cId))}}},a.map=function(t){function n(e,n,r,o){var s,a=this;this.src&&this.unmap(),typeof e===h&&(a.src=e,a.tgt=r||a.tgt||[],a.options=n||a.options,a.update(),o||(t.obsSrc&&i(a.src).observeAll(a.obs=function(e,n){s||(s=!0,t.obsSrc(a,e,n),s=void 0)},a.srcFlt),t.obsTgt&&i(a.tgt).observeAll(a.obt=function(e,n){s||(s=!0,t.obsTgt(a,e,n),s=void 0)},a.tgtFlt)))}return u(t)&&(t={getTgt:t}),t.baseMap&&(t=e.extend({},t.baseMap,t)),t.map=function(t,e,r,i){return new n(t,e,r,i)},(n.prototype={srcFlt:t.srcFlt||z,tgtFlt:t.tgtFlt||z,update:function(e){var n=this;i(n.tgt).refresh(t.getTgt(n.src,n.options=e||n.options))},unmap:function(){var t=this;t.src&&(t.obs&&i(t.src).unobserveAll(t.obs,t.srcFlt),t.obt&&i(t.tgt).unobserveAll(t.obt,t.tgtFlt),t.src=void 0)},map:n,_def:t}).constructor=n,t},c.advSet=function(){c._gccb=this._gccb,t._jsv=l.advanced._jsv?{cbBindings:w}:void 0},c._dp=H}return e},window); +/*! JsObservable v0.9.91 (Beta): http://jsviews.com/#jsobservable */ +!function(t,e){var n=e.jQuery;"object"==typeof exports?module.exports=n?t(e,n):function(n){return t(e,n)}:"function"==typeof define&&define.amd?define(["jquery"],function(n){return t(e,n)}):t(e,!1)}(function(t,e){"use strict";var n=e===!1;if(e=e||t.jQuery,!e||!e.fn)throw"JsObservable requires jQuery";var r,i,o="v0.9.91",s=e.views=e.views||n&&t.jsrender&&jsrender.views||{jsviews:o,sub:{settings:{}},settings:{advanced:function(t){return f=c.advanced=c.advanced||{_jsv:!0},t?("_jsv"in t&&(f._jsv=t._jsv),a.advSet(),s.settings):f}}},a=s.sub,c=a.settings,f=c.advanced,l=e.isFunction,u=e.expando,p=e.isArray,d="object";if(s.jsviews!==o)throw"JsObservable requires JsRender "+o;if(!e.observe){var h=e.event.special,v=[].slice,_=[].splice,g=[].concat,b=parseInt,y=/\S+/g,m=/^[^.[]*$/,I=a.propChng=a.propChng||"propertyChange",w=a.arrChng=a.arrChng||"arrayChange",j={},x=I+".observe",A=1,k=1,C=1,F=e.data,P={},S=function(t){return t?t._cId=t._cId||".obs"+k++:""},O=function(t,e){return this._data=e,this._ns=t,this},T=function(t,e){return this._data=e,this._ns=t,this},V=function(t){return p(t)?[t]:t},q=function(t,e,n){t=t?p(t)?t:[t]:[];var r,i,o,s,a=o=e,c=t&&t.length,f=[];for(r=0;r1;)c=c[o.shift()];c&&a._setProperty(c,o[0],e,n)}return a},removeProperty:function(t){return this.setProperty(t,P),this},_setProperty:function(t,e,n,r){var i,o,s,a,c,f=e?t[e]:t;l(f)&&f.set&&(c=t._vw||t,o=f,i=o.set===!0?o:o.set,f=o.call(c)),(f!==n||r&&f!=n)&&(!(f instanceof Date&&n instanceof Date)||f>n||f-1&&(e=p(e)?e:[e],e.length&&this._insert(t,e)),this},_insert:function(t,e){var n=this._data,r=n.length;t>r&&(t=r),_.apply(n,[t,0].concat(e)),this._trigger({change:"insert",index:t,items:e},r)},remove:function(t,e){var n,r=this._data;return void 0===t&&(t=r.length-1),t=b(t),e=e?b(e):0===e?0:1,e>0&&t>-1&&(n=r.slice(t,t+e),(e=n.length)&&this._remove(t,e,n)),this},_remove:function(t,e,n){var r=this._data,i=r.length;r.splice(t,e),this._trigger({change:"remove",index:t,items:n},i)},move:function(t,e,n){return n=n?b(n):0===n?0:1,t=b(t),e=b(e),n>0&&t>-1&&e>-1&&t!==e&&this._move(t,e,n),this},_move:function(t,e,n){var r,i=this._data,o=i.length,s=t+n-o;s>0&&(n-=s),n&&(r=i.splice(t,n),e>i.length&&(e=i.length),_.apply(i,[e,0].concat(r)),e!==t&&this._trigger({change:"move",oldIndex:t,index:e,items:r},o))},refresh:function(t){function e(){i&&(a.insert(r-i,c),p+=i,n+=i,i=0,c=[])}var n,r,i,o,s,a=this,c=[],f=a._data,l=f.slice(),u=f.length,p=u,d=t.length;for(a._srt=!0,r=i=0;rr&&a.remove(r,p-r),a._srt=void 0,(u||d)&&a._trigger({change:"refresh",oldItems:l},u),a},_trigger:function(t,n){var r=this,i=r._data,o=i.length,s=e([i]);r._srt?t.refresh=!0:o!==n&&s.triggerHandler(I,{change:"set",path:"length",value:o,oldValue:n}),s.triggerHandler(w+(r._ns?"."+/^\S+/.exec(r._ns)[0]:""),t)}},h[I]=h[w]={remove:function(t){var n,r,i,o,s,a=t.data;if(a&&(a.off=!0,a=a.cb)&&(n=j[a._cId])){for(i=e._data(this).events[t.type],o=i.length;o--&&!r;)r=(s=i[o].data)&&s.cb&&s.cb._cId===a._cId;r||(delete n[F(this).obId],D(n,a._cId))}}},s.map=function(t){function n(e,n,r,o){var s,a,c=this;c.src&&c.unmap(),n&&(n.map=c),(typeof e===d||l(e))&&(c.src=e,r?c.tgt=r.tgt||r:c.tgt=c.tgt||[],c.options=n||c.options,(a=c.update())?c=a:o||(t.obsSrc&&i(c.src).observeAll(c.obs=function(e,n){s||(s=!0,t.obsSrc(c,e,n),s=void 0)},c.srcFlt),t.obsTgt&&i(c.tgt).observeAll(c.obt=function(e,n){s||c.tgt._updt||(s=!0,t.obsTgt(c,e,n),s=void 0)},c.tgtFlt)))}return l(t)&&(t={getTgt:t}),t.baseMap&&(t=e.extend({},t.baseMap,t)),t.map=function(t,e,r,i){return new n(t,e,r,i)},(n.prototype={srcFlt:t.srcFlt||N,tgtFlt:t.tgtFlt||N,update:function(e){var n,r,o=this,s=o.tgt;if(!s._updt&&(s._updt=!0,n=o.options&&o.options.map,i(s).refresh(t.getTgt(o.src,o.options=e||o.options)),s._updt=!1,r=o.options&&o.options.map,r&&n!==r))return r},unmap:function(){var t=this;t.src&&t.obs&&i(t.src).unobserveAll(t.obs,t.srcFlt),t.tgt&&t.obt&&i(t.tgt).unobserveAll(t.obt,t.tgtFlt),t.src=void 0},map:n,_def:t}).constructor=n,t},a.advSet=function(){a._gccb=this._gccb,t._jsv=c.advanced._jsv?{cbBindings:j}:void 0},a._dp=q,a._gck=S,a._obs=r}return e},window); //# sourceMappingURL=jquery.observable.min.js.map diff --git a/jquery.observable.min.js.map b/jquery.observable.min.js.map index 5be1f1c..1eec524 100644 --- a/jquery.observable.min.js.map +++ b/jquery.observable.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["jquery.observable.js"],"names":["factory","global","$","jQuery","exports","module","define","amd","setGlobals","fn","$observe","$observable","versionNumber","_ocp","$views","views","jsrender","jsviews","sub","settings","advanced","value","$subSettingsAdvanced","$subSettings","_jsv","$sub","advSet","$isFunction","isFunction","$expando","expando","$isArray","isArray","OBJECT","observe","$eventSpecial","event","special","slice","splice","concat","PARSEINT","parseInt","rNotWhite","propertyChangeStr","propChng","arrayChangeStr","arrChng","cbBindingsStore","observeStr","observeObjKey","observeCbKey","observeInnerCbKey","$hasData","hasData","$data","data","remove","getCbKey","cb","_cId","ObjectObservable","ns","this","_data","_ns","ArrayObservable","wrapArray","dependsPaths","paths","root","callback","i","path","object","rt","nextObj","l","length","out","tagName","linkCtx","call","push","unshift","_ar","removeCbBindings","cbBindings","cbBindingsId","onDataChange","ev","eventArgs","isOb","val","allowArray","off","allPath","filter","parentObs","oldValue","ctx","observeAll","arOk","type","array","prop","_path","target","parents","observe_apply","undefined","args","apply","arguments","shift","$observeAll","unobserve","$unobserveAll","namespace","objMap","observeArrayItems","arr","unobs","newAllPath","filterAndObserveAll","obj","nestedArray","newObject","newParentObs","_fltr","nextParentObs","updatedTgt","wrappedCb","change","items","_wrp","isObject","obId","notRemoving","un","shallowFilter","indexOf","$unobserve","innerObserve","observeOnOff","pathStr","isArrayBinding","j","evData","obIdExpando","boundObOrArr","prntObs","allPth","initialNs","events","el","fullPath","replace","all","inArray","on","getInnerCb","exprOb","origRt","ob","contextCb","sb","newObj","bindArray","unbind","relPath","prevObj","prevAllPath","p","skip","parts","dep","cbId","inId","innerContextCb","depth","innerCb","initNsArr","initNsArrLen","view","cbItemCount","lastArg","pop","_inId","match","split","join","_cxp","_gccb","origRoot","_cpfn","bnd","prm","nodeType","observable","depends","s","set","Object","Array","_apply","prototype","unobserveAll","setProperty","nonStrict","key","pair","multi","_is","self","name","_setProperty","removeProperty","leaf","setter","getter","removeProp","property","_vw","Date","_trigger","triggerHandler","exec","insert","index","_insert","oldLength","numToRemove","_remove","move","oldIndex","newIndex","numToMove","_move","excess","refresh","newItems","insertAdded","k","addedItems","dataLength","newItem","num","oldItems","newLength","_srt","$_data","handleObj","found","map","mapDef","Map","source","options","unbound","changing","src","unmap","tgt","update","obsSrc","obs","srcFlt","obsTgt","obt","tgtFlt","getTgt","baseMap","extend","_def","constructor","_dp","window"],"mappings":"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","file":"jquery.observable.min.js","sourcesContent":["/*! JsObservable v0.9.90 (Beta): http://jsviews.com/#jsobservable */\n/*\n * Subcomponent of JsViews\n * Data change events for data-linking\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 jQuery passed as parameter: require(\"jsobservable\")(jQuery)\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([\"jquery\"], function($) {\n\t\t\treturn factory(global, $); // Require jQuery\n\t\t});\n\t} else { // Browser using plain ',He='',Qe='',\n\topenScript = ' - data-linked tag, close marker\n\t\t\t// We validate with inTag so no script markers are inserted in attribute context e.g. for:\n\t\t\t// \"\" or \"
...{{/if}}...\"\n\t\t\tpreceding = id\n\t\t\t\t? (preceding + endOfElCnt + spaceBefore + (inTag ? \"\" : openScript + id + closeScript)+ spaceAfter + tag)\n\t\t\t\t: endOfElCnt || all;\n\t\t}\n\n\t\tif (validate && boundId) {\n\t\t\tif (inTag) {\n\t\t\t\t// JsViews data-linking tags are not allowed within element markup.\n\t\t\t\t// See jsviews/issues/303\n\t\t\t\tsyntaxError('{^{ within elem markup (' + inTag + ' ). Use data-link=\"...\"');\n\t\t\t}\n\t\t\tif (id.charAt(0) === \"#\") {\n\t\t\t\ttagStack.unshift(id.slice(1));\n\t\t\t} else if (id.slice(1) !== (bndId = tagStack.shift())) {\n\t\t\t\t// See jsviews/issues/213\n\t\t\t\tsyntaxError('Closing tag for {^{...}} under different elem: <' + bndId + '>');\n\t\t\t}\n\t\t}\n\t\tif (tag) {\n\t\t\tinTag = tag;\n\t\t\t// If there are ids (markers since the last tag), move them to the defer string\n\t\t\ttagStack.unshift(parentTag);\n\t\t\tparentTag = tag.slice(1);\n\t\t\tif (validate && tagStack[0] && tagStack[0] === badParent[parentTag]) {\n\t\t\t\t// Missing \n\t\t\t\t// TODO: replace this by smart insertion of tags\n\t\t\t\terror('Parent of must be ');\n\t\t\t}\n\t\t\tisVoid = voidElems[parentTag];\n\t\t\tif ((elCnt = elContent[parentTag]) && !prevElCnt) {\n\t\t\t\tdeferStack.unshift(defer);\n\t\t\t\tdefer = \"\";\n\t\t\t}\n\t\t\tprevElCnt = elCnt;\n//TODO Consider providing validation which throws if you place as child of , etc. - since if not caught,\n//this can cause errors subsequently which are difficult to debug.\n//\t\t\t\tif (elContent[tagStack[0]]>2 && !elCnt) {\n//\t\t\t\t\terror(parentTag + \" in \" + tagStack[0]);\n//\t\t\t\t}\n\t\t\tif (defer && elCnt) {\n\t\t\t\tdefer += \"+\"; // Will be used for stepping back through deferred tokens\n\t\t\t}\n\t\t}\n\t\treturn preceding;\n\t}\n\n\tfunction processViewInfos(vwInfos, targetParent) {\n\t\t// If targetParent, we are processing viewInfos (which may include navigation through '+-' paths) and hooking up to the right parentElem etc.\n\t\t// (and elem may also be defined - the next node)\n\t\t// If no targetParent, then we are processing viewInfos on newly inserted content\n\t\tvar deferPath, deferChar, bindChar, parentElem, id, onAftCr, deep,\n\t\t\taddedBindEls = [];\n\n\t\t// In elCnt context (element-only content model), prevNode is the first node after the open, nextNode is the first node after the close.\n\t\t// If both are null/undefined, then open and close are at end of parent content, so the view is empty, and its placeholder is the\n\t\t// 'lastChild' of the parentNode. If there is a prevNode, then it is either the first node in the view, or the view is empty and\n\t\t// its placeholder is the 'previousSibling' of the prevNode, which is also the nextNode.\n\t\tif (vwInfos) {\n\t\t\tif (vwInfos._tkns.charAt(0) === \"@\") {\n\t\t\t\t// We are processing newly inserted content. This is a special script element that was created in convertMarkers() to process deferred bindings,\n\t\t\t\t// and inserted following the target parent element - because no element tags (outside elCnt) were encountered to carry those binding tokens.\n\t\t\t\t// We will step back from the preceding sibling of this element, looking at targetParent elements until we find the one that the current binding\n\t\t\t\t// token belongs to. Set elem to null (the special script element), and remove it from the DOM.\n\t\t\t\ttargetParent = elem.previousSibling;\n\t\t\t\telem.parentNode.removeChild(elem);\n\t\t\t\telem = undefined;\n\t\t\t}\n\t\t\tlen = vwInfos.length;\n\t\t\twhile (len--) {\n\t\t\t\tvwInfo = vwInfos[len];\n//if (prevIds.indexOf(vwInfo.token) < 0) { // This token is a newly created view or tag binding\n\t\t\t\tbindChar = vwInfo.ch;\n\t\t\t\tif (deferPath = vwInfo.path) {\n\t\t\t\t\t// We have a 'deferred path'\n\t\t\t\t\tj = deferPath.length - 1;\n\t\t\t\t\twhile (deferChar = deferPath.charAt(j--)) {\n\t\t\t\t\t\t// Use the \"+\" and\"-\" characters to navigate the path back to the original parent node where the deferred bindings ocurred\n\t\t\t\t\t\tif (deferChar === \"+\") {\n\t\t\t\t\t\t\tif (deferPath.charAt(j) === \"-\") {\n\t\t\t\t\t\t\t\tj--;\n\t\t\t\t\t\t\t\ttargetParent = targetParent.previousSibling;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttargetParent = targetParent.parentNode;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttargetParent = targetParent.lastChild;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Note: Can use previousSibling and lastChild, not previousElementSibling and lastElementChild,\n\t\t\t\t\t\t// since we have removed white space within elCnt. Hence support IE < 9\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (bindChar === \"^\") {\n\t\t\t\t\tif (tag = bindingStore[id = vwInfo.id]) {\n\t\t\t\t\t\t// The binding may have been deleted, for example in a different handler to an array collectionChange event\n\t\t\t\t\t\t// This is a tag binding\n\t\t\t\t\t\tdeep = targetParent && (!elem || elem.parentNode !== targetParent); // We are stepping back looking for the right targetParent,\n\t\t\t\t\t\t// or we are linking existing content and this element is in elCnt, not an immediate child of the targetParent.\n\t\t\t\t\t\tif (!elem || deep) {\n\t\t\t\t\t\t\ttag.parentElem = targetParent;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (vwInfo.elCnt && deep) {\n\t\t\t\t\t\t\t// With element only content, if there is no following element, or if the binding is deeper than the following element\n\t\t\t\t\t\t\t// then we need to set the open or close token as a deferred binding annotation on the parent\n\t\t\t\t\t\t\tsetDefer(targetParent, (vwInfo.open ? \"#\" : \"/\") + id + bindChar + (targetParent._df || \"\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// This is an open or close marker for a data-linked tag {^{...}}. Add it to bindEls.\n\t\t\t\t\t\taddedBindEls.push([deep ? null : elem, vwInfo]);\n\t\t\t\t\t}\n\t\t\t\t} else if (view = viewStore[id = vwInfo.id]) {\n\t\t\t\t\t// The view may have been deleted, for example in a different handler to an array collectionChange event\n\t\t\t\t\tif (!view.parentElem) {\n\t\t\t\t\t\t// If view is not already extended for JsViews, extend and initialize the view object created in JsRender, as a JsViews view\n\t\t\t\t\t\tview.parentElem = targetParent || elem && elem.parentNode || parentNode;\n\t\t\t\t\t\tview._.onRender = addBindingMarkers;\n\t\t\t\t\t\tview._.onArrayChange = arrayChangeHandler;\n\t\t\t\t\t\tsetArrayChangeLink(view);\n\t\t\t\t\t}\n\t\t\t\t\tparentElem = view.parentElem;\n\t\t\t\t\tif (vwInfo.open) {\n\t\t\t\t\t\t// This is an 'open view' node (preceding script marker node,\n\t\t\t\t\t\t// or if elCnt, the first element in the view, with a data-jsv annotation) for binding\n\t\t\t\t\t\tview._elCnt = vwInfo.elCnt;\n\t\t\t\t\t\tif (targetParent && !elem) {\n\t\t\t\t\t\t\tsetDefer(targetParent, \"#\" + id + bindChar + (targetParent._df || \"\"));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// No targetParent, so there is a ._nxt elem (and this is processing tokens on the elem)\n\t\t\t\t\t\t\tif (!view._prv) {\n\t\t\t\t\t\t\t\tsetDefer(parentElem, removeSubStr(parentElem._df, \"#\" + id + bindChar));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tview._prv = elem;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// This is a 'close view' marker node for binding\n\t\t\t\t\t\tif (targetParent && (!elem || elem.parentNode !== targetParent)) {\n\t\t\t\t\t\t\t// There is no ._nxt so add token to _df. It is deferred.\n\t\t\t\t\t\t\tsetDefer(targetParent, \"/\" + id + bindChar + (targetParent._df || \"\"));\n\t\t\t\t\t\t\tview._nxt = undefined;\n\t\t\t\t\t\t} else if (elem) {\n\t\t\t\t\t\t\t// This view did not have a ._nxt, but has one now, so token may be in _df, and must be removed. (No longer deferred)\n\t\t\t\t\t\t\tif (!view._nxt) {\n\t\t\t\t\t\t\t\tsetDefer(parentElem, removeSubStr(parentElem._df, \"/\" + id + bindChar));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tview._nxt = elem;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (onAftCr = view.ctx && view.ctx[onAfterCreateStr] || onAfterCreate) {\n\t\t\t\t\t\t\tonAftCr.call(view.ctx.tag, view);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n//}\n\t\t\t\t}\n\t\t\t}\n\t\t\tlen = addedBindEls.length;\n\t\t\twhile (len--) {\n\t\t\t\t// These were added in reverse order to addedBindEls. We push them in BindEls in the correct order.\n\t\t\t\tbindEls.push(addedBindEls[len]);\n\t\t\t}\n\t\t}\n\t\treturn !vwInfos || vwInfos.elCnt;\n\t}\n\n\tfunction getViewInfos(vwInfos) {\n\t\t// Used by view.childTags() and tag.childTags()\n\t\t// Similar to processViewInfos in how it steps through bindings to find tags. Only finds data-linked tags.\n\t\tvar level, parentTag, named;\n\n\t\tif (vwInfos) {\n\t\t\tlen = vwInfos.length;\n\t\t\tfor (j = 0; j < len; j++) {\n\t\t\t\tvwInfo = vwInfos[j];\n\t\t\t\t// This is an open marker for a data-linked tag {^{...}}, within the content of the tag whose id is get.id. Add it to bindEls.\n\t\t\t\t// Note - if bindingStore[vwInfo.id]._is === \"tag\" then getViewInfos is being called too soon - during first linking pass\n\t\t\t\ttag = bindingStore[vwInfo.id];\n\t\t\t\tif (!tag._is && tag.linkCtx) {\n\t\t\t\t\tparentTag = tag = tag.linkCtx.tag;\n\t\t\t\t\tnamed = tag.tagName === tagName;\n\t\t\t\t\tif (!tag.flow || named) {\n\t\t\t\t\t\tif (!deep) {\n\t\t\t\t\t\t\tlevel = 1;\n\t\t\t\t\t\t\twhile (parentTag = parentTag.parent) {\n\t\t\t\t\t\t\t\tlevel++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttagDepth = tagDepth || level; // The level of the first tag encountered.\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ((deep || level === tagDepth) && (!tagName || named)) {\n\t\t\t\t\t\t\t// Filter on top-level or tagName as appropriate\n\t\t\t\t\t\t\ttags.push(tag);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction dataLink() {\n\t\t//================ Data-link and fixup of data-jsv annotations ================\n\t\tvar j, index,\n\t\t\ttokens = \"\",\n\t\t\twrap = {},\n\t\t\tselector = linkViewsSel + (get ? \",[\" + deferAttr + \"]\" : \"\");\n\t\t\t// If a childTags() call, get = \",[\" + deferAttr + \"]\" - since we need to include elements that have a ._df expando for deferred tokens\n\n\t\telems = qsa ? parentNode.querySelectorAll(selector) : $(selector, parentNode).get();\n\t\tl = elems.length;\n\n\t\t// The prevNode will be in the returned query, since we called markPrevOrNextNode() on it.\n\t\t// But it may have contained nodes that satisfy the selector also.\n\t\tif (prevNode && prevNode.innerHTML) {\n\t\t\t// Find the last contained node of prevNode, to use as the prevNode - so we only link subsequent elems in the query\n\t\t\tprevNodes = qsa ? prevNode.querySelectorAll(selector) : $(selector, prevNode).get();\n\t\t\tprevNode = prevNodes.length ? prevNodes[prevNodes.length - 1] : prevNode;\n\t\t}\n\n\t\ttagDepth = 0;\n\t\tfor (i = 0; i < l; i++) {\n\t\t\telem = elems[i];\n\t\t\tif (prevNode && !found) {\n\t\t\t\t// If prevNode is set, not false, skip linking. If this element is the prevNode, set to false so subsequent elements will link.\n\t\t\t\tfound = (elem === prevNode);\n\t\t\t} else if (nextNode && elem === nextNode) {\n\t\t\t\t// If nextNode is set then break when we get to nextNode\n\t\t\t\tif (get) {\n\t\t\t\t\ttokens += markerNodeInfo(elem);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t} else if (elem.parentNode) {\n\t\t\t\t// elem has not been removed from DOM\n\t\t\t\tif (get) {\n\t\t\t\t\ttokens += markerNodeInfo(elem);\n\t\t\t\t\tif (elem._df) {\n\t\t\t\t\t\tj = i + 1;\n\t\t\t\t\t\twhile (j < l && elem.contains(elems[j])) {\n\t\t\t\t\t\t\tj++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Add deferred tokens after any tokens on descendant elements of this one\n\t\t\t\t\t\twrap[j-1] = elem._df;\n\t\t\t\t\t}\n\t\t\t\t\tif (wrap[i]) {\n\t\t\t\t\t\ttokens += wrap[i] || \"\";\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (isLink && (vwInfo = viewInfos(elem, undefined, rViewMarkers)) && (vwInfo = vwInfo[0])) {\n\t\t\t\t\t\t// If this is a link(trueOrString ...) call we will avoid re-binding to elems that are within template-rendered views\n\t\t\t\t\t\tskip = skip ? (vwInfo.id !== skip && skip) : vwInfo.open && vwInfo.id;\n\t\t\t\t\t}\n\t\t\t\t\tif (!skip && processInfos(viewInfos(elem))\n\t\t\t\t\t\t// If a link() call, processViewInfos() adds bindings to bindEls, and returns true for non-script nodes, for adding data-link bindings\n\t\t\t\t\t\t// If a childTags() call, getViewInfos returns array of tag bindings.\n\t\t\t\t\t\t\t&& elem.getAttribute($viewsLinkAttr)) {\n\t\t\t\t\t\tbindEls.push([elem]); // A data-linked element so add to bindEls too\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (get) {\n\t\t\ttokens += parentNode._df || \"\";\n\t\t\tif (index = tokens.indexOf(\"#\" + get.id) + 1) {\n\t\t\t\t// We are looking for view.childTags() or tag.childTags() - so start after the open token of the parent view or tag.\n\t\t\t\ttokens = tokens.slice(index + get.id.length);\n\t\t\t}\n\t\t\tindex = tokens.indexOf(\"/\" + get.id);\n\t\t\tif (index + 1) {\n\t\t\t\t// We are looking for view.childTags() or tag.childTags() - so don't look beyond the close token of the parent view or tag.\n\t\t\t\ttokens = tokens.slice(0, index);\n\t\t\t}\n\t\t\t// Call getViewInfos to add the found childTags to the tags array\n\t\t\tgetViewInfos(viewInfos(tokens, undefined, rOpenTagMarkers));\n\t\t}\n\n\t\tif (html === undefined && parentNode.getAttribute($viewsLinkAttr)) {\n\t\t\tbindEls.push([parentNode]); // Support data-linking top-level element directly (not within a data-linked container)\n\t\t}\n\n\t\t// Remove temporary marker script nodes they were added by markPrevOrNextNode\n\t\tunmarkPrevOrNextNode(prevNode, elCnt);\n\t\tunmarkPrevOrNextNode(nextNode, elCnt);\n\n\t\tif (get) {\n\t\t\treturn; // We have added childTags to the tags array, so we are done\n\t\t}\n\n\t\tif (elCnt && defer + ids) {\n\t\t\t// There are some views with elCnt, for which the open or close did not precede any HTML tag - so they have not been processed yet\n\t\t\telem = nextNode;\n\t\t\tif (defer) {\n\t\t\t\tif (nextNode) {\n\t\t\t\t\tprocessViewInfos(viewInfos(defer + \"+\", true), nextNode);\n\t\t\t\t} else {\n\t\t\t\t\tprocessViewInfos(viewInfos(defer, true), parentNode);\n\t\t\t\t}\n\t\t\t}\n\t\t\tprocessViewInfos(viewInfos(ids, true), parentNode);\n\t\t\t// If there were any tokens on nextNode which have now been associated with inserted HTML tags, remove them from nextNode\n\t\t\tif (nextNode) {\n\t\t\t\ttokens = nextNode.getAttribute(jsvAttrStr);\n\t\t\t\tif (l = tokens.indexOf(prevIds) + 1) {\n\t\t\t\t\ttokens = tokens.slice(l + prevIds.length - 1);\n\t\t\t\t}\n\t\t\t\tnextNode.setAttribute(jsvAttrStr, ids + tokens);\n\t\t\t}\n\t\t}\n\n// if (context.lazyLink) {\n// setTimeout(doLinking) (doLinking is function wrapper of following lines)\n// See Future tasks, and https://github.com/BorisMoore/jsviews/issues/368.\n// Could call context.lazyLink as callback, on async completion - or return promise.\n\t\t//================ Bind the data-linked elements and tags ================\n\t\tl = bindEls.length;\n\t\tfor (i = 0; i < l; i++) {\n\t\t\telem = bindEls[i];\n\t\t\tlinkInfo = elem[1];\n\t\t\telem = elem[0];\n\t\t\tif (linkInfo) {\n\t\t\t\tif (tag = bindingStore[linkInfo.id]) {\n\t\t\t\t\tif (linkCtx = tag.linkCtx) {\n\t\t\t\t\t\t// The tag may have been stored temporarily on the bindingStore - or may have already been replaced by the actual binding\n\t\t\t\t\t\ttag = linkCtx.tag;\n\t\t\t\t\t\ttag.linkCtx = linkCtx;\n\t\t\t\t\t}\n\t\t\t\t\tif (linkInfo.open) {\n\t\t\t\t\t\t// This is an 'open linked tag' binding annotation for a data-linked tag {^{...}}\n\t\t\t\t\t\tif (elem) {\n\t\t\t\t\t\t\ttag.parentElem = elem.parentNode;\n\t\t\t\t\t\t\ttag._prv = elem;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttag._elCnt = linkInfo.elCnt;\n\t\t\t\t\t\t// We data-link depth-first (\"on the way in\"), which is better for perf - and allows setting parent tags etc.\n\t\t\t\t\t\tview = tag.tagCtx.view;\n\n\t\t\t\t\t\t// Add data binding (unless skipped due to lateRender)\n\t\t\t\t\t\taddDataBinding(late, undefined, tag._prv, view, linkInfo.id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttag._nxt = elem;\n\t\t\t\t\t\tif (tag._.unlinked && !tag._toLk) {\n\t\t\t\t\t\t\t// This is a 'close linked tag' binding annotation (and data-binding was not skipped due to lateRender)\n\t\t\t\t\t\t\ttagCtx = tag.tagCtx;\n\t\t\t\t\t\t\tview = tagCtx.view;\n\t\t\t\t\t\t\tcallAfterLink(tag);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Add data binding for a data-linked element (with data-link attribute)\n\t\t\t\taddDataBinding(late, elem.getAttribute($viewsLinkAttr), elem, $view(elem), undefined, isLink, outerData, context);\n\t\t\t}\n\t\t}\n//});\n\t}\n\t//==== /end of nested functions ====\n\n\tvar inTag, linkCtx, tag, i, l, j, len, elems, elem, view, vwInfo, linkInfo, prevNodes, token, prevView, nextView,\n\t\tnode, tags, deep, tagName, tagCtx, validate, tagDepth, depth, fragment, copiedNode, firstTag, parentTag,\n\t\tisVoid, wrapper, div, tokens, elCnt, prevElCnt, htmlTag, ids, prevIds, found, skip, isLink, get,\n\t\tself = this,\n\t\tthisId = self._.id + \"_\",\n\t\tdefer = \"\",\n\t\t// The marker ids for which no tag was encountered (empty views or final closing markers) which we carry over to container tag\n\t\tbindEls = [],\n\t\ttagStack = [],\n\t\tdeferStack = [],\n\t\tlate = [],\n\t\tonAfterCreate = changeHandler(self, onAfterCreateStr),\n\t\tprocessInfos = processViewInfos;\n\n\tif (refresh) {\n\t\tif (refresh.tmpl) {\n\t\t\t// refresh is the prevView, passed in from addViews()\n\t\t\tprevView = \"/\" + refresh._.id + \"_\";\n\t\t} else {\n\t\t\tisLink = refresh.lnk; // Top-level linking\n\t\t\tif (refresh.tag) {\n\t\t\t\tthisId = refresh.tag + \"^\";\n\t\t\t\trefresh = true;\n\t\t\t}\n\t\t\tif (get = refresh.get) {\n\t\t\t\tprocessInfos = getViewInfos;\n\t\t\t\ttags = get.tags;\n\t\t\t\tdeep = get.deep;\n\t\t\t\ttagName = get.name;\n\t\t\t}\n\t\t}\n\t\trefresh = refresh === true;\n\t}\n\n\tparentNode = parentNode\n\t\t? (\"\" + parentNode === parentNode\n\t\t\t? $(parentNode)[0] // It is a string, so treat as selector\n\t\t\t: parentNode.jquery\n\t\t\t\t? parentNode[0] // A jQuery object - take first element.\n\t\t\t\t: parentNode)\n\t\t: (self.parentElem // view.link()\n\t\t\t|| document.body); // link(null, data) to link the whole document\n\n\tvalidate = !$subSettingsAdvanced.noValidate && parentNode.contentEditable !== TRUE;\n\tparentTag = parentNode.tagName.toLowerCase();\n\telCnt = !!elContent[parentTag];\n\n\tprevNode = prevNode && markPrevOrNextNode(prevNode, elCnt);\n\tnextNode = nextNode && markPrevOrNextNode(nextNode, elCnt) || null;\n\n\tif (html != undefined) {\n\t\t//================ Insert html into DOM using documentFragments (and wrapping HTML appropriately). ================\n\t\t// Also convert markers to DOM annotations, based on content model.\n\t\t// Corresponds to nextNode ? $(nextNode).before(html) : $(parentNode).html(html);\n\t\t// but allows insertion to wrap correctly even with inserted script nodes. jQuery version will fail e.g. under tbody or select.\n\t\t// This version should also be slightly faster\n\t\tdiv = document.createElement(\"div\");\n\t\twrapper = div;\n\t\tprevIds = ids = \"\";\n\t\thtmlTag = parentNode.namespaceURI === \"http://www.w3.org/2000/svg\" ? \"svg_ns\" : (firstTag = rFirstElem.exec(html)) && firstTag[1] || \"\";\n\t\tif (elCnt) {\n\t\t\t// Now look for following view, and find its tokens, or if not found, get the parentNode._df tokens\n\t\t\tnode = nextNode;\n\t\t\twhile (node && !(nextView = viewInfos(node))) {\n\t\t\t\tnode = node.nextSibling;\n\t\t\t}\n\t\t\tif (tokens = nextView ? nextView._tkns : parentNode._df) {\n\t\t\t\ttoken = prevView || \"\";\n\t\t\t\tif (refresh || !prevView) {\n\t\t\t\t\ttoken += \"#\" + thisId;\n\t\t\t\t}\n\t\t\t\tj = tokens.indexOf(token);\n\t\t\t\tif (j + 1) {\n\t\t\t\t\tj += token.length;\n\t\t\t\t\t// Transfer the initial tokens to inserted nodes, by setting them as the ids variable, picked up in convertMarkers\n\t\t\t\t\tprevIds = ids = tokens.slice(0, j);\n\t\t\t\t\ttokens = tokens.slice(j);\n\t\t\t\t\tif (nextView) {\n\t\t\t\t\t\tnode.setAttribute(jsvAttrStr, tokens);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetDefer(parentNode, tokens);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//================ Convert the markers to DOM annotations, based on content model. ================\n//\t\t\toldElCnt = elCnt;\n\t\tisVoid = undefined;\n\t\thtml = (\"\" + html).replace(rConvertMarkers, convertMarkers);\n//\t\t\tif (!!oldElCnt !== !!elCnt) {\n//\t\t\t\terror(\"Parse: \" + html); // Parse error. Content not well-formed?\n//\t\t\t}\n\t\tif (validate && tagStack.length) {\n\t\t\tsyntaxError(\"Mismatched '<\" + parentTag + \"...>' in:\\n\" + html); // Unmatched tag\n\t\t}\n\t\tif (validateOnly) {\n\t\t\treturn;\n\t\t}\n\t\t// Append wrapper element to doc fragment\n\t\tsafeFragment.appendChild(div);\n\n\t\t// Go to html and back, then peel off extra wrappers\n\t\t// Corresponds to jQuery $(nextNode).before(html) or $(parentNode).html(html);\n\t\t// but supports svg elements, and other features missing from jQuery version (and this version should also be slightly faster)\n\t\thtmlTag = wrapMap[htmlTag] || wrapMap.div;\n\t\tdepth = htmlTag[0];\n\t\twrapper.innerHTML = htmlTag[1] + html + htmlTag[2];\n\t\twhile (depth--) {\n\t\t\twrapper = wrapper.lastChild;\n\t\t}\n\t\tsafeFragment.removeChild(div);\n\t\tfragment = document.createDocumentFragment();\n\t\twhile (copiedNode = wrapper.firstChild) {\n\t\t\tfragment.appendChild(copiedNode);\n\t\t}\n\t\t// Insert into the DOM\n\t\tparentNode.insertBefore(fragment, nextNode);\n\t}\n\tdataLink();\n\n\treturn late;\n}\n\nfunction addDataBinding(late, linkMarkup, node, currentView, boundTagId, isLink, data, context) {\n\t// Add data binding for data-linked elements or {^{...}} data-linked tags\n\tvar tmpl, tokens, attr, convertBack, tagExpr, linkFn, linkCtx, tag, rTagIndex, hasElse, lastIndex,\n\t\tlinkExpressions = [];\n\n\tif (boundTagId) {\n\t\t// boundTagId is a string for {^{...}} data-linked tag. So only one linkTag in linkMarkup\n\t\t// data and context arguments are undefined\n\t\ttag = bindingStore[boundTagId];\n\t\ttag = tag.linkCtx ? tag.linkCtx.tag : tag;\n\n\t\tlinkCtx = tag.linkCtx || {\n\t\t\ttype: \"inline\",\n\t\t\tdata: currentView.data, // source\n\t\t\telem: tag._elCnt ? tag.parentElem : node, // target\n\t\t\tview: currentView,\n\t\t\tctx: currentView.ctx,\n\t\t\tattr: HTML, // Script marker nodes are associated with {^{ and always target HTML.\n\t\t\tfn: tag._.bnd,\n\t\t\ttag: tag,\n\t\t\t// Pass the boundTagId in the linkCtx, so that it can be picked up in observeAndBind\n\t\t\t_bndId: boundTagId\n\t\t};\n\t\ttag.linkCtx = linkCtx;\n\t\tbindDataLinkTarget(linkCtx, late);\n\t\ttag._toLk = linkCtx._bndId; // If data binding happened, remove _toLk flag from tag\n\t} else if (linkMarkup && node) {\n\t\t// Data-linked element\n\n\t\t// If isLink then this is a top-level linking: .link(expression, target, data, ....) or\n\t\t// .link(true, target, data, ....) scenario - and data and context are passed in separately from the view\n\t\tdata = isLink ? data : currentView.data;\n\n\t\t// Compiled linkFn expressions could be stored in the tmpl.links array of the template\n\t\t// TODO - consider also caching globally so that if {{:foo}} or data-link=\"foo\" occurs in different places,\n\t\t// the compiled template for this is cached and only compiled once...\n\t\t//links = currentView.links || currentView.tmpl.links;\n\n\t\ttmpl = currentView.tmpl;\n\n//\t\t\tif (!(linkTags = links[linkMarkup])) {\n\t\t// This is the first time this view template has been linked, so we compile the data-link expressions, and store them on the template.\n\n\t\tlinkMarkup = normalizeLinkTag(linkMarkup, defaultAttr(node));\n\t\tlastIndex = rTagDatalink.lastIndex = 0;\n\t\twhile (tokens = rTagDatalink.exec(linkMarkup)) { // TODO require } to be followed by whitespace or $, and remove the \\}(!\\}) option.\n\t\t\tlinkExpressions.push(tokens);\n\t\t\tlastIndex = rTagDatalink.lastIndex;\n\t\t}\n\t\tif (lastIndex < linkMarkup.length) {\n\t\t\tsyntaxError(linkMarkup);\n\t\t}\n\t\twhile (tokens = linkExpressions.shift()) {\n\t\t\t// Iterate over the data-link expressions, for different target attrs,\n\t\t\t// e.g. ~description(firstName, lastName)}\"\n\t\t\t// tokens: [all, attr, bindOnly, tagExpr, tagName, converter, colon, html, comment, code, params]\n\t\t\trTagIndex = rTagDatalink.lastIndex;\n\t\t\tattr = tokens[1];\n\t\t\ttagExpr = tokens[3];\n\t\t\twhile (linkExpressions[0] && linkExpressions[0][4] === \"else\") { // If this is {sometag...} and is followed by an {else...} add to tagExpr\n\t\t\t\ttagExpr += delimCloseChar1 + delimOpenChar0 + linkExpressions.shift()[3];\n\t\t\t\thasElse = true;\n\t\t\t}\n\t\t\tif (hasElse) { // If an {else} has been added, need also to add closing {{/sometag}}\n\t\t\t\ttagExpr += delimCloseChar1 + delimOpenChar0 + delimOpenChar1 + \"/\" + tokens[4] + delimCloseChar0;\n\t\t\t}\n\t\t\tlinkCtx = {\n\t\t\t\ttype: isLink ? \"top\" : \"link\",\n\t\t\t\tdata: data, // source\n\t\t\t\telem: node, // target\n\t\t\t\tview: currentView,\n\t\t\t\tctx: context,\n\t\t\t\tattr: attr,\n\t\t\t\tisLk: isLink, // top-level linking?\n\t\t\t\t_toLk : 1, // Flag to data-link on initial data-link call rendering call\n\t\t\t\t_noUpd : tokens[2] // Flag for data-link=\"^{...}\" so on initial data-link call will bind, but not render)\n\t\t\t};\n\n\t\t\tconvertBack = undefined;\n\t\t\tif (tokens[6]) {\n\t\t\t\tconvertBack = tokens[10] || undefined;\n\t\t\t\tlinkCtx.convert = tokens[5] || \"\";\n\t\t\t\tif (convertBack !== undefined && defaultAttr(node)) {\n\t\t\t\t\tif (attr) {\n\t\t\t\t\t\tsyntaxError(tagExpr + \"- Remove target: \" + attr);\n\t\t\t\t\t}\n\t\t\t\t\t// Default target, so allow 2 way binding\n\t\t\t\t\tlinkCtx.convertBack = convertBack = convertBack.slice(1);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Compile the linkFn expression which evaluates and binds a data-link expression\n\t\t\t// TODO - optimize for the case of simple data path with no conversion, helpers, etc.:\n\t\t\t// i.e. data-link=\"a.b.c\". Avoid creating new instances of Function every time. Can use a default function for all of these...\n\n\t\t\tlinkCtx.expr = attr + tagExpr;\n\t\t\tlinkFn = tmpl.links[tagExpr];\n\t\t\tif (!linkFn) {\n\t\t\t\ttmpl.links[tagExpr] = linkFn = $sub.tmplFn(tagExpr, tmpl, true, convertBack, hasElse);\n\t\t\t}\n\t\t\tlinkCtx.fn = linkFn;\n\t\t\tbindDataLinkTarget(linkCtx, late);\n\t\t\t// We store rTagIndex in local scope, since this addDataBinding method can sometimes be called recursively,\n\t\t\t// and each is using the same rTagDatalink instance.\n\t\t\trTagDatalink.lastIndex = rTagIndex;\n\t\t}\n//\t\t}\n\t}\n}\n\nfunction bindDataLinkTarget(linkCtx, late) {\n\t// Add data link bindings for a link expression in data-link attribute markup\n\tfunction handler(ev, eventArgs) {\n\t\tonDataLinkedTagChange.call(linkCtx, ev, eventArgs);\n\t\t// If the link expression uses a custom tag, the onDataLinkedTagChange call will call renderTag, which will set tagCtx on linkCtx\n\t}\n\tif (linkCtx.isLk) {\n\t\t// Top-level linking: .link(expressionOrTrue, data, context) - so we need to create a view for the linking, with the data and ctx\n\t\t// which may be different than the current context of the target. Note that this view is not a standard data-linked view, so it will\n\t\t// be disposed only when its parent view is disposed.\n\t\tlinkCtx.view = new $sub.View(\n\t\t\t$sub.extendCtx(linkCtx.ctx, linkCtx.view.ctx),\n\t\t\t\"link\", linkCtx.view, linkCtx.data, linkCtx.expr, undefined, addBindingMarkers);\n\t}\n\tlinkCtx._ctxCb = $sub._gccb(linkCtx.view); // getContextCallback: _ctxCb, for filtering/appending to dependency paths: function(path, object) { return [(object|path)*]}\n\tlinkCtx._hdl = handler;\n\t// handler._ctx = linkCtx; Could pass linkCtx for use in a depends = function() {} call, so depends is different for different linkCtx's\n\tif (linkCtx.fn._lr) {\n\t\tlinkCtx._toLk = 1;\n\t\tlate.push(linkCtx); // lateRender - defer rendering and linking (sync but after first linking pass)\n\t} else {\n\t\thandler(true);\n\t}\n}\n\n//=====================\n// Data-linking helpers\n//=====================\n\nfunction removeSubStr(str, substr) {\n\tvar k;\n\treturn str\n\t\t? (k = str.indexOf(substr),\n\t\t\t(k + 1\n\t\t\t\t? str.slice(0, k) + str.slice(k + substr.length)\n\t\t\t\t: str))\n\t\t: \"\";\n}\n\nfunction markerNodeInfo(node) {\n\treturn node &&\n\t\t(\"\" + node === node\n\t\t\t? node\n\t\t\t: node.tagName === SCRIPT\n\t\t\t\t? node.type.slice(3)\n\t\t\t\t: node.nodeType === 1 && node.getAttribute(jsvAttrStr) || \"\");\n}\n\nfunction viewInfos(node, isVal, rBinding) {\n\t// Test whether node is a script marker node, and if so, return metadata\n\tfunction getInfos(all, open, close, id, ch, elPath) {\n\t\tinfos.push({\n\t\t\telCnt: elCnt,\n\t\t\tid: id,\n\t\t\tch: ch,\n\t\t\topen: open,\n\t\t\tclose: close,\n\t\t\tpath: elPath,\n\t\t\ttoken: all\n\t\t});\n\t}\n\tvar elCnt, tokens,\n\t\tinfos = [];\n\tif (tokens = isVal ? node : markerNodeInfo(node)) {\n\t\telCnt = infos.elCnt = node.tagName !== SCRIPT;\n\t\telCnt = tokens.charAt(0) === \"@\" || elCnt;\n\t\tinfos._tkns = tokens;\n\t\t// rMarkerTokens = /(?:(#)|(\\/))(\\d+)([_^])([-+@\\d]+)?/g;\n\t\ttokens.replace(rBinding || rMarkerTokens, getInfos);\n\t\treturn infos;\n\t}\n}\n\nfunction unmarkPrevOrNextNode(node, elCnt) {\n\tif (node) {\n\t\tif (node.type === \"jsv\") {\n\t\t\tnode.parentNode.removeChild(node);\n\t\t} else if (elCnt && node.getAttribute($viewsLinkAttr) === \"\") {\n\t\t\tnode.removeAttribute($viewsLinkAttr);\n\t\t}\n\t}\n}\n\nfunction markPrevOrNextNode(node, elCnt) {\n\tvar marker = node;\n\twhile (elCnt && marker && marker.nodeType !== 1) {\n\t\tmarker = marker.previousSibling;\n\t}\n\tif (marker) {\n\t\tif (marker.nodeType !== 1) {\n\t\t\t// For text nodes, we will add a script node before\n\t\t\tmarker = document.createElement(SCRIPT);\n\t\t\tmarker.type = \"jsv\";\n\t\t\tnode.parentNode.insertBefore(marker, node);\n\t\t} else if (!markerNodeInfo(marker) && !marker.getAttribute($viewsLinkAttr)) {\n\t\t\t// For element nodes, we will add a data-link attribute (unless there is already one)\n\t\t\t// so that this node gets included in the node linking process.\n\t\t\tmarker.setAttribute($viewsLinkAttr, \"\");\n\t\t}\n\t}\n\treturn marker;\n}\n\nfunction normalizeLinkTag(linkMarkup, twoway) {\n\tlinkMarkup = $.trim(linkMarkup).replace(rEscapeQuotes, \"\\\\$&\");\n\treturn linkMarkup.slice(-1) !== delimCloseChar0\n\t// If simplified syntax is used: data-link=\"expression\", convert to data-link=\"{:expression}\",\n\t// or for inputs, data-link=\"{:expression:}\" for (default) two-way binding\n\t\t? linkMarkup = delimOpenChar1 + \":\" + linkMarkup + (twoway ? \":\" : \"\") + delimCloseChar0\n\t\t: linkMarkup;\n}\n\n//===========================\n// Methods for views and tags\n//===========================\n\nfunction callAfterLink(tag, ev, eventArgs) {\n\tfunction copyFromTagCtxToTag() {\n\t\tlinkedElems = tagCtx.linkedElems || tag.linkedElems || tag.linkedElem && [tag.linkedElem];\n\t\tif (linkedElems) {\n\t\t\ttag.linkedElems = tagCtx.linkedElems = linkedElems;\n\t\t\ttag.linkedElem = linkedElems[0] = tag.linkedElem || linkedElems[0];\n\t\t}\n\t\tif (linkedElem = tagCtx.mainElem || tag.mainElem) {\n\t\t\ttagCtx.mainElem = tag.mainElem = linkedElem;\n\t\t}\n\t\tif (linkedElem = tagCtx.displayElem || tag.displayElem) {\n\t\t\ttagCtx.displayElem = tag.displayElem = linkedElem;\n\t\t}\n\t}\n\n\tvar linkedElems, linkedElements, linkedElem, l, m, $linkCtxElem, linkCtxElem, tagCtxElse, props, val, oldVal,\n\t\ttagCtx = tag.tagCtx,\n\t\ttagCtxs = tag.tagCtxs,\n\t\ttagCtxslength = tagCtxs && tagCtxs.length,\n\t\tlinkCtx = tag.linkCtx,\n\t\tbindTo = tag.bindTo || {};\n\n\tif (tag._.unlinked) { // First call to onAfterLink, or first call after onUpdate: updateContent. Initialize and call onBind and set properties\n\t\t$linkCtxElem = $(linkCtx.elem);\n\t\tif (tag.linkedElement || tag.mainElement || tag.displayElement) {\n\t\t\tif (linkedElements = tag.linkedElement) {\n\t\t\t\t// tag.linkedElement: - selector, or array of selectors, for identifying linked elements in template/rendered content.\n\t\t\t\t// (But for tag bindings on data-linked elements, defaults to data-linked element)\n\t\t\t\ttag.linkedElem = undefined;\n\t\t\t\tl = linkedElements.length;\n\t\t\t\twhile (l--) {\n\t\t\t\t\tif (linkedElements[l]) {\n\t\t\t\t\t\tm = tagCtxslength;\n\t\t\t\t\t\twhile (m--) {\n\t\t\t\t\t\t\tlinkCtxElem = !m && !tag.inline && $linkCtxElem.filter(linkedElements[l]);\n\t\t\t\t\t\t\ttagCtxElse = tagCtxs[m];\n\t\t\t\t\t\t\tlinkedElems = tagCtxElse.linkedElems = tagCtxElse.linkedElems || new Array(l);\n\t\t\t\t\t\t\tlinkedElem = linkCtxElem[0] ? linkCtxElem : tagCtxElse.contents(true, linkedElements[l]);\n\t\t\t\t\t\t\tif (linkedElem[0] && linkedElem[0].type !== RADIO) {\n\t\t\t\t\t\t\t\tlinkedElems[l] = linkedElem.eq(0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (linkedElements = tag.mainElement) {\n\t\t\t\t// tag.mainElement: - selector for identifying mainElem in template/rendered content\n\t\t\t\t// (But for tag bindings on data-linked elements, defaults to data-linked element)\n\t\t\t\tm = tagCtxslength;\n\t\t\t\twhile (m--) {\n\t\t\t\t\tlinkCtxElem = !m && !tag.inline && $linkCtxElem.filter(linkedElements);\n\t\t\t\t\ttagCtxElse = tagCtxs[m];\n\t\t\t\t\tlinkedElem = linkCtxElem[0] ? linkCtxElem : tagCtxElse.contents(true, linkedElements).eq(0);\n\t\t\t\t\tif (linkedElem[0]) {\n\t\t\t\t\t\ttagCtxElse.mainElem = linkedElem;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (linkedElements = tag.displayElement) {\n\t\t\t\t// tag.mainElement: - selector for identifying mainElem in template/rendered content\n\t\t\t\t// (But for tag bindings on data-linked elements, defaults to data-linked element)\n\t\t\t\tm = tagCtxslength;\n\t\t\t\twhile (m--) {\n\t\t\t\t\tlinkCtxElem = !m && !tag.inline && $linkCtxElem.filter(linkedElements);\n\t\t\t\t\ttagCtxElse = tagCtxs[m];\n\t\t\t\t\tlinkedElem = linkCtxElem[0] ? linkCtxElem : tagCtxElse.contents(true, linkedElements).eq(0);\n\t\t\t\t\tif (linkedElem[0]) {\n\t\t\t\t\t\ttagCtxElse.displayElem = linkedElem;\n\t\t\t\t\t\tif (!m) {\n\t\t\t\t\t\t\ttag.displayElem = linkedElem;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcopyFromTagCtxToTag();\n\t\t}\n\t\tif (tag.onBind) {\n\t\t\ttag.onBind(tagCtx, linkCtx, tag.ctx, ev, eventArgs);\n\t\t\tcopyFromTagCtxToTag();\n\t\t}\n\t}\n\n\tm = tagCtxslength;\n\twhile (m--) {\n\t\ttagCtxElse = tagCtxs[m];\n\t\tprops = tagCtxElse.props;\n\n\t\tif (linkedElem = tagCtxElse.mainElem || !tag.mainElement && tagCtxElse.linkedElems && tagCtxElse.linkedElems[0]) {\n\t\t\t// linkedElem is the mainElem (defaulting to linkedElem)\n\t\t\tif (linkedElem[0] && props.id && !linkedElem[0].id) {\n\t\t\t\tlinkedElem[0].id = props.id;\n\t\t\t}\n\t\t\tif (tag.setSize) {\n\t\t\t\tif (val = !bindTo.height && props.height || tag.height) {\n\t\t\t\t\tlinkedElem.height(val);\n\t\t\t\t}\n\t\t\t\tif (val = !bindTo.width && props.width || tag.width) {\n\t\t\t\t\tlinkedElem.width(val);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (val = (linkedElem = tagCtxElse.displayElem || linkedElem) && (!bindTo[\"class\"] && props[\"class\"] || tag.className)) {\n\t\t\t// This code supports dynamic binding to class - where it adds the class if absent, and removes/adds if a previous value is present\n\t\t\toldVal = linkedElem[0]._jsvCl;\n\t\t\tif (val !== oldVal) {\n\t\t\t\tif (linkedElem.hasClass(oldVal)) {\n\t\t\t\t\tlinkedElem.removeClass(oldVal);\n\t\t\t\t}\n\t\t\t\tlinkedElem.addClass(val);\n\t\t\t\tlinkedElem[0]._jsvCl = val;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (tag.onAfterLink) {\n\t\ttag.onAfterLink(tagCtx, linkCtx, tag.ctx, ev, eventArgs);\n\t\tcopyFromTagCtxToTag();\n\t}\n\n\tif (!tag.flow && !tag._.chg) {\n\t\tif (tag.inline && tag._.unlinked && (tag.linkedElems || bindTo)) {\n\t\t\tdefineBindToDataTargets(bindingStore[tag._tgId], tag);\n\t\t}\n\t\ttag.setValue();\n\t}\n\ttag._.unlinked = undefined;\n}\n\nfunction asyncOnElemChange(ev) {\n\tvar which = ev.which;\n\tif (!(which > 15 && which < 21 || which > 32 && which < 41 || which > 111 && which < 131 || which === 27 || which === 144)) {\n\t\t// Shift, Ctrl, Alt, Pause, Caplock, Page up/down End, Home, Left, Up, Right, Down, Function keys, Escape, Numlock\n\t\tsetTimeout(function() {\n\t\t\tonElemChange(ev);\n\t\t});\n\t}\n}\n\nfunction bindTriggerEvent($elem, trig, onoff) {\n\t// Bind keydown, or other trigger - (rather than use the default change event bubbled to activeBody)\n\tif (trig === true && useInput) {\n\t\t$elem[onoff](\"input.jsv\", onElemChange); // For HTML5 browser with \"oninput\" support - for mouse editing of text\n\t} else {\n\t\ttrig = \"\" + trig === trig ? trig : \"keydown.jsv\"; // Set trigger to (true || truey non-string (e.g. 1) || 'keydown')\n\t\t$elem[onoff](trig, trig.indexOf(\"keydown\") >= 0 ? asyncOnElemChange : onElemChange); // Get 'keydown' with async\n\t}\n}\n\nfunction bindLinkedElChange(tag, linkedElem) {\n\t// Two-way binding for linkedElem - in the case of input, textarea or contentEditable elements.\n\t// Trigger setting may have changed. Unbind previous trigger binding (if any) and bind new one.\n\n\tvar $linkedElem, newTrig,\n\t\toldTrig = linkedElem._jsvTr || false;\n\n\tif (tag) {\n\t\tnewTrig = tag.tagCtx.props.trigger;\n\t\tif (newTrig === undefined) {\n\t\t\tnewTrig = tag.trigger;\n\t\t}\n\t}\n\tif (newTrig === undefined) {\n\t\tnewTrig = $subSettings.trigger;\n\t}\n\t// Trigger is noop except for text box, textarea, contenteditable...\n\tnewTrig = newTrig && (linkedElem.tagName === \"INPUT\" && linkedElem.type !== CHECKBOX && linkedElem.type !== RADIO\n\t\t|| linkedElem.type === \"textarea\" || linkedElem.contentEditable === TRUE) && newTrig || false;\n\n\tif (oldTrig !== newTrig) {\n\t\t$linkedElem = $(linkedElem);\n\t\tbindTriggerEvent($linkedElem, oldTrig, \"off\");\n\t\tbindTriggerEvent($linkedElem, linkedElem._jsvTr = newTrig, \"on\");\n\t}\n}\n\nfunction defineBindToDataTargets(binding, tag, cvtBk) {\n\t// Two-way binding.\n\t// We set the binding.to[1] to be the cvtBack, and binding.to[0] to be either the path to the target, or [object, path] where the target is the\n\t// path on the provided object. So for a computed path with an object call: a.b.getObject().d.e, we set to[0] to be [exprOb, \"d.e\"], and\n\t// we bind to the path on the returned object, exprOb.ob, as target. Otherwise our target is the first path, paths[0], which we will convert\n\t// with contextCb() for paths like ~a.b.c or #x.y.z\n\n\tvar pathIndex, path, lastPath, bindtoOb, to, bindTo, paths, k, l, obsCtxPrm, linkedCtxParam, contextCb, targetPaths, bindTos,\n\t\ttagElse = 1,\n\t\ttos = [],\n\t\tlinkCtx = binding.linkCtx,\n\t\tsource = linkCtx.data,\n\t\ttargetPathsElses = linkCtx.fn.paths;\n\n\tif (binding && !binding.to) {\n\t\tif (tag) {\n\t\t\ttag.convertBack = tag.convertBack || cvtBk;\n\t\t\tbindTo = tag.bindTo;\n\t\t\ttagElse = tag.tagCtxs ? tag.tagCtxs.length : 1;\n\t\t}\n\t\twhile (tagElse--) {\n\t\t\tbindTos = [];\n\t\t\tif (targetPaths = targetPathsElses[tagElse]) {\n\t\t\t\tbindTo = targetPaths._jsvto ? [\"_jsvto\"] : (bindTo || [0]);\n\t\t\t\tk = bindTo.length;\n\t\t\t\twhile (k--) {\n\t\t\t\t\tpath = \"\";\n\t\t\t\t\tcontextCb = linkCtx._ctxCb;\n\t\t\t\t\tpaths = targetPaths[bindTo[k]];\n\t\t\t\t\tif (pathIndex = paths && paths.length) {\n\t\t\t\t\t\tlastPath = paths[pathIndex - 1];\n\t\t\t\t\t\tif (lastPath._cpfn) { // Computed property exprOb\n\n\t\t\t\t\t\t\tbindtoOb = lastPath;\n\t\t\t\t\t\t\twhile (lastPath.sb && lastPath.sb._cpfn) {\n\t\t\t\t\t\t\t\tpath = lastPath = lastPath.sb;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tpath = lastPath.sb || path && path.path;\n\t\t\t\t\t\t\tlastPath = path ? path.slice(1) : bindtoOb.path;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tto = path\n\t\t\t\t\t\t\t? [bindtoOb, // 'exprOb' for this expression and view-binding. So bindtoOb.ob is current object returned by expression.\n\t\t\t\t\t\t\t\t\tlastPath]\n\t\t\t\t\t\t\t: resolveDataTargetPath(lastPath, source, contextCb); // Get 'to' for target path: lastPath\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Contextual parameter ~foo with no external binding - has ctx.foo = [{_ocp: xxx}] and binds to ctx.foo._ocp\n\t\t\t\t\t\tlinkedCtxParam = tag.linkedCtxParam;\n\t\t\t\t\t\tto = [];\n\t\t\t\t\t\tif (linkedCtxParam && linkedCtxParam[k]) {\n\t\t\t\t\t\t\t// This is a tag binding, with linked tag contextual parameters\n\t\t\t\t\t\t\tto = [tag.tagCtxs[tagElse].ctx[linkedCtxParam[k]][0], _ocp];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ((obsCtxPrm = to._cxp) && obsCtxPrm.tag && lastPath.indexOf(\".\")<0) {\n\t\t\t\t\t\t// This is a binding for a tag contextual parameter (e.g. within a tag block content\n\t\t\t\t\t\tto = obsCtxPrm;\n\t\t\t\t\t}\n\t\t\t\t\tbindTos.unshift(to);\n\t\t\t\t}\n\t\t\t}\n\t\t\ttos.unshift(bindTos);\n\t\t}\n\t\tbinding.to = tos;\n\t}\n}\n\nfunction resolveDataTargetPath(targetPath, source, contextCb) {\n\t// Iteratively process targetPath, resolving ~a.b.c paths for contextual parameters\n\tvar path, bindtoOb, to, l, obsCtxPrm, view, topCp, data;\n\n\twhile (targetPath && targetPath !== _ocp && (to = contextCb(path = targetPath.split(\"^\").join(\".\"), source)) && (l = to.length)) {\n\t\tif (obsCtxPrm = to[0]._cxp) { // Two-way binding to a contextual parameter reference, ~foo (declared as ~foo=expr on a parent tag)\n\t\t\ttopCp = topCp || obsCtxPrm;\n\t\t\tview = to[0][0];\n\t\t\tif (_ocp in view) {\n\t\t\t\tdata = view;\n\t\t\t\tview = view._vw;\n\t\t\t} else {\n\t\t\t\tdata = view.data;\n\t\t\t}\n\t\t\ttopCp.path = targetPath = to[0][1];\n\t\t\tto = [topCp.data = data, targetPath];\n\t\t\t\tcontextCb = $sub._gccb(view);\n\t\t\t\tif (targetPath._cpfn) { // computed property\n\t\t\t\t\tbindtoOb = targetPath;\n\t\t\t\t\tbindtoOb.data = to[0];\n\t\t\t\t\tbindtoOb._cpCtx = contextCb;\n\t\t\t\t\twhile (targetPath.sb && targetPath.sb._cpfn) {\n\t\t\t\t\t\tpath = targetPath = targetPath.sb;\n\t\t\t\t\t}\n\t\t\t\t\tpath = targetPath.sb || path && path.path;\n\t\t\t\t\ttargetPath = path ? path.slice(1) : bindtoOb.path;\n\t\t\t\t\tto = [\n\t\t\t\t\t\tbindtoOb, // 'exprOb' for this expression and view-binding. So bindtoOb.ob is current object returned by expression.\n\t\t\t\t\t\ttargetPath\n\t\t\t\t\t];\n\t\t\t\t} else if (obsCtxPrm.tag && obsCtxPrm.path === _ocp) {\n\t\t\t\t\tto = obsCtxPrm;\n\t\t\t\t}\n\t\t} else { // Two-way binding to a helper - e.g. ~address.street, or computed, e.g. ~fullName(), or view property e.g. #data.foo\n\t\t\tto = l>2\n\t\t\t\t? [to[l-3], to[l-2]] // With path: [object, path]\n\t\t\t\t: [to[l-2]]; // No path, (e.g. [function] for computed with setter)\n\t\t}\n\t\tsource = to[0];\n\t\ttargetPath = to[1];\n\t}\n\tto = to || [source, path];\n\tto._cxp = topCp;\n\treturn to;\n}\n\nfunction mergeCtxs(tag, newCtxs, replace) { // Merge updated tagCtxs into tag.tagCtxs\n\tvar tagCtx, newTagCtx,\n\t\tview = tag.tagCtx.view,\n\t\ttagCtxs = tag.tagCtxs || [tag.tagCtx],\n\t\tl = tagCtxs.length,\n\t\trefresh = !newCtxs;\n\n\tnewCtxs = newCtxs || tag._.bnd.call(view.tmpl, (tag.linkCtx || view).data, view, $sub);\n\n\tif (replace) {\n\t\t// Replace previous tagCtxs by new ones, rather than merging\n\t\ttagCtxs = tag.tagCtxs = newCtxs;\n\t\ttag.tagCtx = tagCtxs[0];\n\t\taddLinkMethods(tag);\n\t} else {\n\t\twhile (l--) {\n\t\t\ttagCtx = tagCtxs[l];\n\t\t\tnewTagCtx = newCtxs[l];\n\t\t\t$observable(tagCtx.props).setProperty(newTagCtx.props);\n\t\t\t$extend(tagCtx.ctx, newTagCtx.ctx); // We don't support propagating ctx variables, ~foo, observably, to nested views. So extend, not setProperty...\n\t\t\ttagCtx.args = newTagCtx.args;\n\t\t\tif (refresh) {\n\t\t\t\ttagCtx.tmpl = newTagCtx.tmpl;\n\t\t\t}\n\t\t}\n\t}\n\t$sub._ths(tag, tagCtxs[0]); // tagHandlersFromProps\n\treturn tagCtxs;\n}\n\n//=========\n// Disposal\n//=========\n\nfunction clean(elems) {\n\t// Remove data-link bindings, or contained views\n\tvar l, elem, bindings,\n\t\telemArray = [],\n\t\tlen = elems.length,\n\t\ti = len;\n\twhile (i--) {\n\t\t// Copy into an array, so that deletion of nodes from DOM will not cause our 'i' counter to get shifted\n\t\t// (Note: This seems as fast or faster than elemArray = [].slice.call(elems); ...)\n\t\telemArray.push(elems[i]);\n\t}\n\ti = len;\n\twhile (i--) {\n\t\telem = elemArray[i];\n\t\tif (elem.parentNode) {\n\t\t\t// Has not already been removed from the DOM\n\t\t\tif (bindings = elem._jsvBnd) {\n\t\t\t\t// Get propertyChange bindings for this element\n\t\t\t\t// This may be an element with data-link, or the opening script marker node for a data-linked tag {^{...}}\n\t\t\t\t// bindings is a string with the syntax: \"(&bindingId)*\"\n\t\t\t\tbindings = bindings.slice(1).split(\"&\");\n\t\t\t\telem._jsvBnd = \"\";\n\t\t\t\tl = bindings.length;\n\t\t\t\twhile (l--) {\n\t\t\t\t\t// Remove associated bindings\n\t\t\t\t\tremoveViewBinding(bindings[l], elem._jsvLkEl, elem); // unbind bindings with this bindingId on this view\n\t\t\t\t}\n\t\t\t}\n\t\t\tdisposeTokens(markerNodeInfo(elem) + (elem._df || \"\"), elem);\n\t\t}\n\t}\n}\n\nfunction removeViewBinding(bindId, linkedElemTag, elem) {\n\t// Unbind\n\tvar objId, linkCtx, tag, object, obsId, tagCtxs, l, map, linkedElem, trigger, view, tagCtx, linkedElems, allLinkedElems,\n\t\tbinding = bindingStore[bindId];\n\n\tif (linkedElemTag) {\n\t\telem._jsvLkEl = undefined;\n\t} else if (binding && (!elem || elem === binding.elem)) { // Test that elem is actually binding.elem, since cloned elements can have inappropriate markerNode info\n\t\tdelete bindingStore[bindId]; // Delete already, so call to onDispose handler below cannot trigger recursive deletion (through recursive call to jQuery cleanData)\n\t\tfor (objId in binding.bnd) {\n\t\t\tobject = binding.bnd[objId];\n\t\t\tobsId = binding.cbId;\n\t\t\tif ($isArray(object)) {\n\t\t\t\t$([object]).off(arrayChangeStr + obsId).off(propertyChangeStr + obsId); // There may be either or both of arrayChange and propertyChange\n\t\t\t} else {\n\t\t\t\t$(object).off(propertyChangeStr + obsId);\n\t\t\t}\n\t\t\tdelete binding.bnd[objId];\n\t\t}\n\n\t\tif (linkCtx = binding.linkCtx) {\n\t\t\tif (tag = linkCtx.tag) {\n\t\t\t\tif (tagCtxs = tag.tagCtxs) {\n\t\t\t\t\tl = tagCtxs.length;\n\t\t\t\t\twhile (l--) {\n\t\t\t\t\t\ttagCtx = tagCtxs[l];\n\t\t\t\t\t\tif (map = tagCtx.map) {\n\t\t\t\t\t\t\tmap.unmap(); //unobserve\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Copy linkedElems in case tag.linkedElem or tag.linkedElems are undefined in onUnbind\n\t\t\t\t\t\tif (linkedElems = tagCtx.linkedElems) {\n\t\t\t\t\t\t\tallLinkedElems = (allLinkedElems || []).concat(linkedElems);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (tag.onUnbind) {\n\t\t\t\t\ttag.onUnbind(tag.tagCtx, linkCtx, tag.ctx, true);\n\t\t\t\t}\n\t\t\t\tif (tag.onDispose) {\n\t\t\t\t\ttag.onDispose();\n\t\t\t\t}\n\n\t\t\t\tif (!tag._elCnt) {\n\t\t\t\t\tif (tag._prv) {\n\t\t\t\t\t\ttag._prv.parentNode.removeChild(tag._prv);\n\t\t\t\t\t}\n\t\t\t\t\tif (tag._nxt) {\n\t\t\t\t\t\ttag._nxt.parentNode.removeChild(tag._nxt);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlinkedElems = allLinkedElems || [$(linkCtx.elem)];\n\t\t\tl = linkedElems.length;\n\t\t\twhile (l--) {\n\t\t\t\tlinkedElem = linkedElems[l];\n\t\t\t\tif (trigger = linkedElem && linkedElem[0] && linkedElem[0]._jsvTr) {\n\t\t\t\t\tbindTriggerEvent(linkedElem, trigger, \"off\");\n\t\t\t\t\tlinkedElem[0]._jsvTr = undefined;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tview = linkCtx.view;\n\t\t\tif (view.type === \"link\") {\n\t\t\t\tview.parent.removeViews(view._.key, undefined, true); // A \"link\" view is associated with the binding, so should be disposed with binding.\n\t\t\t} else {\n\t\t\t\tdelete view._.bnds[bindId];\n\t\t\t}\n\t\t}\n\t\tdelete binding.s[binding.cbId];\n\t}\n}\n\nfunction $unlink(to) {\n\tif (to) {\n\t\tto = to.jquery ? to : $(to);\n\t\tto.each(function() {\n\t\t\tvar innerView;\n\t\t\t//TODO fix this for better perf. Rather that calling inner view multiple times which does querySelectorAll each time, consider a single querySelectorAll\n\t\t\t// or simply call view.removeViews() on the top-level views under the target 'to' node, then clean(...)\n\t\t\twhile ((innerView = $view(this, true)) && innerView.parent) {\n\t\t\t\tinnerView.parent.removeViews(innerView._.key, undefined, true);\n\t\t\t}\n\t\t\tclean(this.getElementsByTagName(\"*\"));\n\t\t});\n\t\tclean(to);\n\t} else {\n\t\t// Call to $.unlink() is equivalent to $.unlink(true, \"body\")\n\t\tif (activeBody) {\n\t\t\t$(activeBody)\n\t\t\t\t.off(elementChangeStr, onElemChange)\n\t\t\t\t.off('blur.jsv', '[contenteditable]', onElemChange);\n\t\t\tactiveBody = undefined;\n\t\t}\n\t\ttopView.removeViews();\n\t\tclean(document.body.getElementsByTagName(\"*\"));\n\t}\n}\n\n//========\n// Helpers\n//========\n\nfunction inputAttrib(elem) {\n\treturn elem.type === CHECKBOX ? elem[CHECKED] : elem.value;\n}\n\nfunction changeHandler(view, name, tag) {\n\t// Get onBeforeChange, onAfterChange, onAfterCreate handler - if there is one;\n\treturn tag && tag[name] || view.ctx[name] && view.ctxPrm(name) || $views.helpers[name];\n}\n\n//========================== Initialize ==========================\n\n//=====================\n// JsRender integration\n//=====================\n\naddLinkMethods($sub.View.prototype); // Modify the View prototype to include link methods\n\n$sub.onStore.template = function(name, item, parentTmpl) {\n\tif (item === null) {\n\t\tdelete $.link[name];\n\t\tdelete $.render[name];\n\t} else {\n\t\titem.link = tmplLink;\n\n\t\tif (name && !parentTmpl && name !== \"jsvTmpl\") {\n\t\t\t$.render[name] = item;\n\t\t\t$.link[name] = function() {\n\t\t\t\treturn tmplLink.apply(item, arguments);\n\t\t\t};\n\t\t}\n\t}\n};\n\n$sub.viewInfos = viewInfos; // Expose viewInfos() as public helper method\n\n// Define JsViews version of delimiters(), and initialize\n($viewsSettings.delimiters = function() {\n\t// Run delimiters initialization in context of jsrender.js\n\tvar ret = oldJsvDelimiters.apply(0, arguments),\n\t\t// Now set also delimOpenChar0 etc. in context of jquery.views.js...\n\t\tdelimChars = $subSettings.delimiters;\n\n\tdelimOpenChar0 = delimChars[0].charAt(0);\n\tdelimOpenChar1 = delimChars[0].charAt(1);\n\tdelimCloseChar0 = delimChars[1].charAt(0);\n\tdelimCloseChar1 = delimChars[1].charAt(1);\n\tlinkChar = delimChars[2];\n\n\t// Data-linking must use new delimiters\n\trTagDatalink = new RegExp(\"(?:^|\\\\s*)([\\\\w-]*)(\\\\\" + linkChar + \")?(\\\\\" + delimOpenChar1 + $sub.rTag + \"(:\\\\w*)?\\\\\" + delimCloseChar0 + \")\", \"g\");\n\treturn ret;\n})(); // jshint ignore:line\n\n$sub.addSetting(\"trigger\");\n\n//====================================\n// Additional members for linked views\n//====================================\n\nfunction transferViewTokens(prevNode, nextNode, parentElem, id, viewOrTagChar, refresh) {\n\t// Transfer tokens on prevNode of viewToRemove/viewToRefresh to nextNode or parentElem._df\n\t// view marker tokens: #m_...VIEW.../m_\n\t// tag marker tokens: #m^...TAG..../m^\n\n\tvar i, l, vwInfos, vwInfo, viewOrTag, viewId, tokens,\n\t\tprecedingLength = 0,\n\t\temptyView = prevNode === nextNode;\n\n\tif (prevNode) {\n\t\t// prevNode is either the first node in the viewOrTag, or has been replaced by the vwInfos tokens string\n\t\tvwInfos = viewInfos(prevNode) || [];\n\t\tfor (i = 0, l = vwInfos.length; i < l; i++) {\n\t\t\t// Step through views or tags on the prevNode\n\t\t\tvwInfo = vwInfos[i];\n\t\t\tviewId = vwInfo.id;\n\t\t\tif (viewId === id && vwInfo.ch === viewOrTagChar) {\n\t\t\t\tif (refresh) {\n\t\t\t\t\t// This is viewOrTagToRefresh, this is the last viewOrTag to process...\n\t\t\t\t\tl = 0;\n\t\t\t\t} else {\n\t\t\t\t\t// This is viewOrTagToRemove, so we are done...\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!emptyView) {\n\t\t\t\tviewOrTag = vwInfo.ch === \"_\"\n\t\t\t\t\t? viewStore[viewId] // A view: \"#m_\" or \"/m_\"\n\t\t\t\t\t: bindingStore[viewId].linkCtx.tag; // A tag \"#m^\" or \"/m^\"\n\t\t\t\tif (vwInfo.open) { // A \"#m_\" or \"#m^\" token\n\t\t\t\t\tviewOrTag._prv = nextNode;\n\t\t\t\t} else if (vwInfo.close) { // A \"/m_\" or \"/m^\" token\n\t\t\t\t\tviewOrTag._nxt = nextNode;\n\t\t\t\t}\n\t\t\t}\n\t\t\tprecedingLength += viewId.length + 2;\n\t\t}\n\n\t\tif (precedingLength) {\n\t\t\tprevNode.setAttribute(jsvAttrStr, prevNode.getAttribute(jsvAttrStr).slice(precedingLength));\n\t\t}\n\t\ttokens = nextNode ? nextNode.getAttribute(jsvAttrStr) : parentElem._df;\n\t\tif (l = tokens.indexOf(\"/\" + id + viewOrTagChar) + 1) {\n\t\t\ttokens = vwInfos._tkns.slice(0, precedingLength) + tokens.slice(l + (refresh ? -1 : id.length + 1));\n\t\t}\n\t\tif (tokens) {\n\t\t\tif (nextNode) {\n\t\t\t\t// If viewOrTagToRemove was an empty viewOrTag, we will remove both #n and /n\n\t\t\t\t// (and any intervening tokens) from the nextNode (=== prevNode)\n\t\t\t\t// If viewOrTagToRemove was not empty, we will take tokens preceding #n from prevNode,\n\t\t\t\t// and concatenate with tokens following /n on nextNode\n\t\t\t\tnextNode.setAttribute(jsvAttrStr, tokens);\n\t\t\t} else {\n\t\t\t\tsetDefer(parentElem, tokens);\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// !prevNode, so there may be a deferred nodes token on the parentElem. Remove it.\n\t\tsetDefer(parentElem, removeSubStr(parentElem._df, \"#\" + id + viewOrTagChar));\n\t\tif (!refresh && !nextNode) {\n\t\t\t// If this viewOrTag is being removed, and there was no .nxt, remove closing token from deferred tokens\n\t\t\tsetDefer(parentElem, removeSubStr(parentElem._df, \"/\" + id + viewOrTagChar));\n\t\t}\n\t}\n}\n\nfunction disposeTokens(tokens, elem) {\n\tvar i, l, vwItem, vwInfos;\n\tif (vwInfos = viewInfos(tokens, true, rOpenMarkers)) {\n\t\tfor (i = 0, l = vwInfos.length; i < l; i++) {\n\t\t\tvwItem = vwInfos[i];\n\t\t\tif (vwItem.ch === \"_\") {\n\t\t\t\tif ((vwItem = viewStore[vwItem.id]) && vwItem.type && (!elem || vwItem._prv === elem || vwItem.parentElem === elem )) {\n\t\t\t\t\t// If this is the _prv (prevNode) for a view, remove the view\n\t\t\t\t\t// - unless view.type is undefined, in which case it is already being removed\n\t\t\t\t\t// (or unless the elem is not related - e.g. a cloned element which 'accidentally' picked up the data-jsv atttribute of the ._df expando)\n\t\t\t\t\tvwItem.parent.removeViews(vwItem._.key, undefined, true);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tremoveViewBinding(vwItem.id, undefined, elem); // unbind bindings with this bindingId on this view\n\t\t\t}\n\t\t}\n\t}\n}\n\n//============================================\n// Add link methods to data-linked view or tag\n//============================================\n\nfunction updateValue(val, index, tagElse, bindId, ev) {\n// Observably update a data value targeted by bindTo\n// Called when linkedElem changes: called as updateValue(val, index, tagElse, bindId, ev) - this: undefined\n// Called directly as tag.updateValue(val, index, tagElse) - this: tag\n\tvar values = [];\n\tif (this && this._tgId) {\n\t\tbindId = this;\n\t}\n\tvalues[index||0] = val;\n\tupdateValues(values, tagElse, bindId, ev);\n\treturn this;\n}\n\nfunction setValues() {\n\tvar args = arguments,\n\t\tm = args.length;\n\n\tif (!m) {\n\t\targs = this.tag.cvtArgs(true, this.index); // setValues() with no arguments calls setValue with boundArgs values\n\t\tm = args.length;\n\t}\n\twhile (m--) {\n\t\tthis.tag.setValue(args[m], m, this.index);\n\t}\n}\n\nfunction addLinkMethods(tagOrView) { // tagOrView is View prototype or tag instance\n\n\tvar l, m, tagCtx, boundProps, bindTo, key, theTag, theView;\n\n\ttagOrView.contents = function(deep, select) {\n\t\t// For a view, a tag or a tagCtx, return jQuery object with the content nodes,\n\t\tif (deep !== !!deep) {\n\t\t\t// deep not boolean, so this is contents(selector)\n\t\t\tselect = deep;\n\t\t\tdeep = undefined;\n\t\t}\n\t\tvar filtered,\n\t\t\tnodes = $(this.nodes());\n\t\tif (nodes[0]) {\n\t\t\tfiltered = select ? nodes.filter(select) : nodes;\n\t\t\tnodes = deep && select ? filtered.add(nodes.find(select)) : filtered;\n\t\t}\n\t\treturn nodes;\n\t};\n\n\ttagOrView.nodes = function(withMarkers, prevNode, nextNode) {\n\t\t// For a view, a tag or a tagCtx, return top-level nodes\n\t\t// Do not return any script marker nodes, unless withMarkers is true\n\t\t// Optionally limit range, by passing in prevNode or nextNode parameters\n\n\t\tvar node,\n\t\t\tself = this.contentView || this, // If tagCtx, use tagCtx.contentView\n\t\t\telCnt = self._elCnt,\n\t\t\tprevIsFirstNode = !prevNode && elCnt,\n\t\t\tnodes = [];\n\n\t\tif (!self.args) { // If tagCtx with no content (so no contentView) self is tagCtx: return empty [];\n\t\t\tprevNode = prevNode || self._prv;\n\t\t\tnextNode = nextNode || self._nxt;\n\n\t\t\tnode = prevIsFirstNode\n\t\t\t\t? (prevNode === self._nxt\n\t\t\t\t\t? self.parentElem.lastSibling\n\t\t\t\t\t: prevNode)\n\t\t\t\t: (self.inline === false\n\t\t\t\t\t? prevNode || self.linkCtx.elem.firstChild\n\t\t\t\t\t: prevNode && prevNode.nextSibling);\n\n\t\t\twhile (node && (!nextNode || node !== nextNode)) {\n\t\t\t\tif (withMarkers || elCnt || node.tagName !== SCRIPT) {\n\t\t\t\t\t// All the top-level nodes in the view\n\t\t\t\t\t// (except script marker nodes, unless withMarkers = true)\n\t\t\t\t\t// (Note: If a script marker node, viewInfo.elCnt undefined)\n\t\t\t\t\tnodes.push(node);\n\t\t\t\t}\n\t\t\t\tnode = node.nextSibling;\n\t\t\t}\n\t\t}\n\t\treturn nodes;\n\t};\n\n\ttagOrView.childTags = function(deep, tagName) {\n\t\t// For a view, a tagor a tagCtx, return child tags - at any depth, or as immediate children only.\n\t\tif (deep !== !!deep) {\n\t\t\t// deep not boolean, so this is childTags(tagName) - which looks for top-level tags of given tagName\n\t\t\ttagName = deep;\n\t\t\tdeep = undefined;\n\t\t}\n\n\t\tvar self = this.contentView || this, // If tagCtx, use tagCtx.contentView\n\t\t\tview = self.link ? self : self.tagCtx.view, // This may be a view or a tag. If a tag, get the view from tag.tagCtx.view\n\t\t\tprevNode = self._prv,\n\t\t\telCnt = self._elCnt,\n\t\t\ttags = [];\n\n\t\tif (!self.args) { // If tagCtx with no content (so no contentView) self is tagCtx: return empty [];\n\t\t\tview.link(\n\t\t\t\tundefined,\n\t\t\t\tself.parentElem,\n\t\t\t\telCnt ? prevNode && prevNode.previousSibling : prevNode,\n\t\t\t\tself._nxt,\n\t\t\t\tundefined,\n\t\t\t\t{get:{\n\t\t\t\t\ttags: tags,\n\t\t\t\t\tdeep: deep,\n\t\t\t\t\tname: tagName,\n\t\t\t\t\tid: self.link ? self._.id + \"_\" : self._tgId + \"^\"\n\t\t\t\t}}\n\t\t\t);\n\t\t}\n\t\treturn tags;\n\t};\n\n\tif (tagOrView._is === \"tag\") {\n\t\t//=======================\n\t\t// This is a TAG instance\n\t\t//=======================\n\n\t\ttheTag = tagOrView;\n\n\t\tm = theTag.tagCtxs.length;\n\t\twhile (m--) {\n\t\t\ttagCtx = theTag.tagCtxs[m];\n\n\t\t\ttagCtx.setValues = setValues;\n\t\t\ttagCtx.cvtArgs = $sub._tg.prototype.cvtArgs;\n\t\t\ttagCtx.bndArgs = $sub._tg.prototype.bndArgs;\n\t\t\ttagCtx.contents = tagOrView.contents;\n\t\t\ttagCtx.childTags = tagOrView.childTags;\n\t\t\ttagCtx.nodes = tagOrView.nodes;\n\t\t}\n\n\t\tboundProps = theTag.boundProps = theTag.boundProps || [];\n\t\tif (bindTo = theTag.linkTo ? [\"linkTo\"] : theTag.bindTo) {\n\t\t\tl = bindTo.length;\n\t\t\twhile (l--) {\n\t\t\t\tkey = bindTo[l];\n\t\t\t\tif (key + \"\" === key) {\n\t\t\t\t\tbindTo[key] = 1;\n\t\t\t\t\tif ($.inArray(key, boundProps) < 0) {\n\t\t\t\t\t\tboundProps.push(key); // Add any 'bindTo' props to boundProps array. (So two-way binding works without writing ^foo=expression)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttheTag.setValue = $sub._gm(theTag.constructor.prototype.setValue, function(val, index, tagElse) {\n\t\t\tif (!arguments.length) { // tag.setValue() calls setValue(val, index) for each parameter in bindTo array\n\t\t\t\ttheTag.setValues(); // = theTag.bndArgs()\n\t\t\t\treturn theTag;\n\t\t\t}\n\t\t\tvar linkedElem, linkedEl, linkedTag,\n\t\t\t\tlinkedCtxParam = theTag.linkedCtxParam,\n\t\t\t\ttagCtx = theTag.tagCtxs[tagElse || 0],\n\t\t\t\tprops = tagCtx.props,\n\t\t\t\tlinkCtx = theTag.linkCtx,\n\t\t\t\tlinkedElems = tagCtx.linkedElems || theTag.linkedElem && [theTag.linkedElem];\n\n\t\t\tif (val !== undefined) {\n\t\t\t\ttheTag.base.call(theTag , val, index, tagElse);\n\t\t\t} else if (theTag.getValue && (val = theTag.getValue(tagElse)) && val !== undefined) {\n\t\t\t\t// If bound args are not initialized, and getValue is defined, use getValue to initialize\n\t\t\t\tif (theTag.bindTo.length > 1) {\n\t\t\t\t\tval = val[index]; // getVal returns value if tag.bndArgs() (and bindTo) length is 1, or array of values if bindTo.length > 1\n\t\t\t\t}\n\t\t\t\tif (linkedCtxParam && linkedCtxParam[index]) {\n\t\t\t\t\t// Values of tag contextual param were already intialized (during rendering) so need to observably update to values from tag.getValue()\n\t\t\t\t\t$.observable(tagCtx.ctx[linkedCtxParam[index]][0]).setProperty(_ocp, val);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ((linkedElem = linkedElems && linkedElems[index]) && linkedElem[0]) {\n\t\t\t\tl = linkedElem.length;\n\t\t\t\twhile (l--) {\n\t\t\t\t\tlinkedEl = linkedElem[l];\n\t\t\t\t\tif (theTag._.unlinked) {\n\t\t\t\t\t\tlinkedTag = linkedEl._jsvLkEl;\n\t\t\t\t\t\tif (!linkedTag || linkedTag !== theTag) {\n\t\t\t\t\t\t\tif (linkedTag) {\n\t\t\t\t\t\t\t\tval = linkedTag.cvtArgs(true, tagElse)[index]; // Need to use converter of linked tag\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// For data-linked tags, identify the linkedEl with the tag, for \"to\" binding\n\t\t\t\t\t\t\t// (For data-linked elements, if not yet bound, we identify later when the linkCtx.elem is bound)\n\t\t\t\t\t\t\tlinkedEl._jsvLkEl = theTag;\n\t\t\t\t\t\t\tlinkedEl._jsvInd = index;\n\t\t\t\t\t\t\tlinkedEl._jsvElse = tagElse;\n\t\t\t\t\t\t\tbindLinkedElChange(theTag, linkedEl);\n\t\t\t\t\t\t\tlinkedEl._jsvBnd = \"&\" + theTag._tgId + \"+\"; // Add a \"+\" for cloned binding - so removing\n\t\t\t\t\t\t\t// elems with cloned bindings will not remove the 'parent' binding from the bindingStore.\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (val !== undefined && !linkedEl._jsvChg && linkCtx._val !== val) {\n\t\t\t\t\t\tif (linkedEl.value !== undefined) {\n\t\t\t\t\t\t\tif (linkedEl.type === CHECKBOX) {\n\t\t\t\t\t\t\t\tlinkedEl[CHECKED] = val && val !== \"false\";\n\t\t\t\t\t\t\t} else if (linkedEl.type === RADIO) {\n\t\t\t\t\t\t\t\tlinkedEl[CHECKED] = (linkedEl.value === val);\n\t\t\t\t\t\t\t} else if ($isArray(val)) {\n\t\t\t\t\t\t\t\tlinkedEl.value = val; // Don't use jQuery since it replaces array by mapped clone\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t$(linkedEl).val(val); // Use jQuery for attrHooks - can't just set value (on select, for example)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (linkedEl.contentEditable === TRUE) {\n\t\t\t\t\t\t\tlinkedEl.innerHTML = val;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (props.name) {\n\t\t\t\t\t\tlinkedEl.name = linkedEl.name || props.name;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn theTag;\n\t\t});\n\n\t\ttheTag.updateValue = updateValue;\n\n\t\ttheTag.updateValues = function() {\n\t\t\treturn updateValues(arguments, undefined, this);\n\t\t};\n\n\t\ttheTag.setValues = function() {\n\t\t\tvar m = arguments.length ? 1 : theTag.tagCtxs.length;\n\t\t\twhile (m--) {\n\t\t\t\tsetValues.apply(theTag.tagCtxs[m], arguments);\n\t\t\t}\n\t\t};\n\n\t\ttheTag.refresh = function(sourceValue) {\n\t\t\tvar attr,\n\t\t\t\tlinkCtx = theTag.linkCtx,\n\t\t\t\tview = theTag.tagCtx.view;\n\n\t\t\tif (theTag.onUnbind) {\n\t\t\t\ttheTag.onUnbind(theTag.tagCtx, linkCtx, theTag.ctx);\n\t\t\t}\n\t\t\tattr = theTag.inline ? HTML : (linkCtx.attr || defaultAttr(theTag.parentElem, true));\n\t\t\tsourceValue = $sub._tag(theTag, view, view.tmpl, mergeCtxs(theTag), true); // Get rendered HTML for tag, based on refreshed tagCtxs\n\t\t\tupdateContent(sourceValue, linkCtx, attr, theTag);\n\t\t\tcallAfterLink(theTag);\n\t\t\treturn theTag;\n\t\t};\n\n\t\ttheTag.domChange = function() { // domChange notification support\n\t\t\tvar elem = this.parentElem,\n\t\t\t\thasListener = $.hasData(elem) && $._data(elem).events,\n\t\t\t\tdomChangeNotification = \"jsv-domchange\";\n\n\t\t\tif (hasListener && hasListener[domChangeNotification]) {\n\t\t\t\t// Only trigger handler if there is a handler listening for this event. (Note using triggerHandler - so no event bubbling.)\n\t\t\t\t$(elem).triggerHandler(domChangeNotification, arguments);\n\t\t\t}\n\t\t};\n\n\t\t//====================================\n\t\t// End of added link methods for TAG\n\t\t//====================================\n\t} else {\n\t\t//=========================\n\t\t// This is a VIEW prototype\n\t\t//=========================\n\n\t\ttheView = tagOrView;\n\n\t\t// Note: a linked view will also, after linking have nodes[], _prv (prevNode), _nxt (nextNode) ...\n\t\ttheView.addViews = function(index, dataItems) {\n\t\t\t// if view is not an array view, do nothing\n\t\t\tvar i, viewsCount,\n\t\t\t\tview = this,\n\t\t\t\titemsCount = dataItems.length,\n\t\t\t\tviews = view.views;\n\n\t\t\tif (!view._.useKey && itemsCount) {\n\t\t\t\t// view is of type \"array\"\n\t\t\t\tviewsCount = views.length + itemsCount;\n\n\t\t\t\tif (viewsCount === view.data.length // If views not already synced to array (e.g. triggered by array.length propertyChange - jsviews/issues/301)\n\t\t\t\t\t\t&& renderAndLink(view, index, view.tmpl, views, dataItems, view.ctx) !== false) {\n\t\t\t\t\tif (!view._.srt) { // Not part of a 'sort' on refresh\n\t\t\t\t\t\tview.fixIndex(index + itemsCount);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\ttheView.removeViews = function(index, itemsCount, keepNodes, isMove) {\n\t\t\t// view.removeViews() removes all the child views\n\t\t\t// view.removeViews(index) removes the child view with specified index or key\n\t\t\t// view.removeViews(index, count) removes the specified nummber of child views, starting with the specified index\n\t\t\tfunction removeView(index) {\n\t\t\t\tvar id, bindId, parentElem, prevNode, nextNode, nodesToRemove,\n\t\t\t\t\tviewToRemove = views[index];\n\n\t\t\t\tif (viewToRemove && viewToRemove.link) {\n\t\t\t\t\tid = viewToRemove._.id;\n\t\t\t\t\tif (!keepNodes) {\n\t\t\t\t\t\t// Remove the HTML nodes from the DOM, unless they have already been removed, including nodes of child views\n\t\t\t\t\t\tnodesToRemove = viewToRemove.nodes();\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove child views, without removing nodes\n\t\t\t\t\tviewToRemove.removeViews(undefined, undefined, true);\n\n\t\t\t\t\tviewToRemove.type = undefined; // Set type to undefined: used as a flag that this view is being removed\n\t\t\t\t\tprevNode = viewToRemove._prv;\n\t\t\t\t\tnextNode = viewToRemove._nxt;\n\t\t\t\t\tparentElem = viewToRemove.parentElem;\n\t\t\t\t\t// If prevNode and nextNode are the same, the view is empty\n\t\t\t\t\tif (!keepNodes) {\n\t\t\t\t\t\t// Remove the HTML nodes from the DOM, unless they have already been removed, including nodes of child views\n\t\t\t\t\t\tif (viewToRemove._elCnt) {\n\t\t\t\t\t\t\t// if keepNodes is false (and transferring of tokens has not already been done at a higher level)\n\t\t\t\t\t\t\t// then transfer tokens from prevNode which is being removed, to nextNode.\n\t\t\t\t\t\t\ttransferViewTokens(prevNode, nextNode, parentElem, id, \"_\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$(nodesToRemove).remove();\n\t\t\t\t\t}\n\t\t\t\t\tif (!viewToRemove._elCnt) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tprevNode.parentNode.removeChild(prevNode); // (prevNode.parentNode is parentElem, except if jQuery Mobile or similar has inserted an intermediate wrapper\n\t\t\t\t\t\t\tnextNode.parentNode.removeChild(nextNode);\n\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t}\n\t\t\t\t\tsetArrayChangeLink(viewToRemove);\n\t\t\t\t\tfor (bindId in viewToRemove._.bnds) {\n\t\t\t\t\t\tremoveViewBinding(bindId);\n\t\t\t\t\t}\n\t\t\t\t\tdelete viewStore[id];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar current, childView, viewsCount,\n\t\t\t\tview = this,\n\t\t\t\tisArray = !view._.useKey,\n\t\t\t\tviews = view.views;\n\n\t\t\tif (isArray) {\n\t\t\t\tviewsCount = views.length;\n\t\t\t}\n\t\t\tif (index === undefined) {\n\t\t\t\t// Remove all child views\n\t\t\t\tif (isArray) {\n\t\t\t\t\t// views and data are arrays\n\t\t\t\t\tcurrent = viewsCount;\n\t\t\t\t\twhile (current--) {\n\t\t\t\t\t\tremoveView(current);\n\t\t\t\t\t}\n\t\t\t\t\tview.views = [];\n\t\t\t\t} else {\n\t\t\t\t\t// views and data are objects\n\t\t\t\t\tfor (childView in views) {\n\t\t\t\t\t\t// Remove by key\n\t\t\t\t\t\tremoveView(childView);\n\t\t\t\t\t}\n\t\t\t\t\tview.views = {};\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (itemsCount === undefined) {\n\t\t\t\t\tif (isArray) {\n\t\t\t\t\t\t// The parentView is data array view.\n\t\t\t\t\t\t// Set itemsCount to 1, to remove this item\n\t\t\t\t\t\titemsCount = 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Remove child view with key 'index'\n\t\t\t\t\t\tremoveView(index);\n\t\t\t\t\t\tdelete views[index];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (isArray && itemsCount\n\t\t\t\t\t&& (isMove || viewsCount - itemsCount === view.data.length)) { // If views not already synced to array (e.g. triggered by array.length propertyChange - jsviews/issues/301)\n\t\t\t\t\tcurrent = index + itemsCount;\n\t\t\t\t\t// Remove indexed items (parentView is data array view);\n\t\t\t\t\twhile (current-- > index) {\n\t\t\t\t\t\tremoveView(current);\n\t\t\t\t\t}\n\t\t\t\t\tviews.splice(index, itemsCount);\n\t\t\t\t\tif (!view._.srt) {\n\t\t\t\t\t\tview.fixIndex(index);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\ttheView.moveViews = function(oldIndex, index, itemsCount) {\n\t\t\tfunction parts(itemView, str) {\n\t\t\t\treturn RegExp(\"^(.*)(\" + (str ? \"\\\\/\" : \"#\") + itemView._.id + \"_.*)$\").exec(str || itemView._prv.getAttribute(jsvAttrStr));\n\t\t\t}\n\t\t\tfunction setPrv(itemView, tokens) {\n\t\t\t\titemView._prv.setAttribute(jsvAttrStr, tokens);\n\t\t\t}\n\t\t\tvar nodes, childView, nxtView, insertBefore, viewId,\n\t\t\t\tview = this,\n\t\t\t\tselfNxt = view._nxt,\n\t\t\t\tviews = view.views,\n\t\t\t\tbackwards = index < oldIndex,\n\t\t\t\tfirstChange = backwards ? index : oldIndex,\n\t\t\t\tlastChange = backwards ? oldIndex : index,\n\t\t\t\ti = index,\n\t\t\t\tmovedNodes = [],\n\n\t\t\t\tviewsToMove = views.splice(oldIndex, itemsCount); // remove\n\n\t\t\tif (index > views.length) {\n\t\t\t\tindex = views.length;\n\t\t\t}\n\t\t\tviews.splice.apply(views, [index, 0].concat(viewsToMove)); //re-insert\n\n\t\t\titemsCount = viewsToMove.length;\n\t\t\tinsertBefore = index + itemsCount;\n\t\t\tlastChange += itemsCount;\n\n\t\t\tfor (i; i < insertBefore; i++) {\n\t\t\t\tchildView = views[i];\n\t\t\t\tnodes = childView.nodes(true);\n\t\t\t\tmovedNodes = view._elCnt ? movedNodes.concat(nodes) : movedNodes.concat(childView._prv, nodes, childView._nxt);\n\t\t\t}\n\t\t\tmovedNodes = $(movedNodes);\n\n\t\t\tif (insertBefore < views.length) {\n\t\t\t\tmovedNodes.insertBefore(views[insertBefore]._prv);\n\t\t\t} else if (selfNxt) {\n\t\t\t\tmovedNodes.insertBefore(selfNxt);\n\t\t\t} else {\n\t\t\t\tmovedNodes.appendTo(view.parentElem);\n\t\t\t}\n\n\t\t\tif (view._elCnt) {\n\t\t\t\tvar afterParts,\n\t\t\t\t\tendChange = backwards ? firstChange + itemsCount : lastChange - itemsCount,\n\t\t\t\t\tbeforeView = views[firstChange-1],\n\t\t\t\t\tstartView = views[firstChange],\n\t\t\t\t\tendView = views[endChange],\n\t\t\t\t\tafterView = views[lastChange],\n\t\t\t\t\tstartParts = parts(startView),\n\t\t\t\t\tendParts = parts(endView);\n\n\t\t\t\tsetPrv(startView, endParts[1] + startParts[2]);\n\t\t\t\tif (afterView) {\n\t\t\t\t\tafterParts = parts(afterView);\n\t\t\t\t\tsetPrv(afterView, startParts[1] + afterParts[2]);\n\t\t\t\t} else {\n\t\t\t\t\tif (selfNxt) {\n\t\t\t\t\t\tafterParts = parts(view, selfNxt.getAttribute(jsvAttrStr));\n\t\t\t\t\t\tselfNxt.setAttribute(jsvAttrStr, startParts[1] + afterParts[2]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tafterParts = parts(view, view.parentElem._df);\n\t\t\t\t\t\tsetDefer(view.parentElem, startParts[1] + afterParts[2]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsetPrv(endView, afterParts[1] + endParts[2]);\n\t\t\t\tif (beforeView) {\n\t\t\t\t\tbeforeView._nxt = startView._prv;\n\t\t\t\t} else {\n\t\t\t\t\tview._prv = startView._prv;\n\t\t\t\t}\n\t\t\t\tviews[endChange-1]._nxt = endView._prv;\n\t\t\t\tviews[lastChange-1]._nxt = afterView ? afterView._prv : selfNxt;\n\t\t\t}\n\t\t\tview.fixIndex(firstChange);\n\t\t};\n\n\t\ttheView.refresh = function() {\n\t\t\tvar view = this,\n\t\t\t\tparent = view.parent;\n\n\t\t\tif (parent) {\n\t\t\t\trenderAndLink(view, view.index, view.tmpl, parent.views, view.data, undefined, true);\n\t\t\t\tsetArrayChangeLink(view);\n\t\t\t}\n\t\t};\n\n\t\ttheView.fixIndex = function(fromIndex) {\n\t\t\t// Fixup index on following view items...\n\t\t\tvar views = this.views,\n\t\t\t\tindex = views.length;\n\t\t\twhile (fromIndex < index--) {\n\t\t\t\tif (views[index].index !== index) {\n\t\t\t\t\t$observable(views[index]).setProperty(\"index\", index);\n\t\t\t\t\t// This is fixing up index, but not key, and not index on child views. From child views, use view.getIndex()\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\ttheView.link = viewLink;\n\n\t\t//====================================\n\t\t// End of added link methods for VIEW\n\t\t//====================================\n\t}\n}\n\n//========================\n// JsViews-specific converters\n//========================\n\n$converters.merge = function(val) {\n\t// Special converter used in data-linking to space-separated lists, such as className:\n\t// Currently only supports toggle semantics - and has no effect if toggle string is not specified\n\t// data-link=\"class{merge:boolExpr toggle=className}\"\n\tvar regularExpression,\n\t\tcurrentValue = this.linkCtx.elem.className,\n\t\ttoggle = this.tagCtx.props.toggle;\n\n\tif (toggle) {\n\t\t// We are toggling the class specified by the toggle property,\n\t\t// and the boolean val binding is driving the insert/remove toggle\n\n\t\tregularExpression = toggle.replace(/[\\\\^$.|?*+()[{]/g, \"\\\\$&\");\n\t\t// Escape any regular expression special characters (metacharacters) within the toggle string\n\t\tregularExpression = \"(\\\\s(?=\" + regularExpression + \"$)|(\\\\s)|^)(\" + regularExpression + \"(\\\\s|$))\";\n\t\t// Example: /(\\s(?=myclass$)|(\\s)|^)?(myclass(\\s|$))/ - so matches (\" myclass\" or \" \" or ^ ) followed by (\"myclass \" or \"myclass$\") where ^/$ are beginning/end of string\n\t\tcurrentValue = currentValue.replace(new RegExp(regularExpression), \"$2\");\n\t\tval = currentValue + (val ? (currentValue && \" \") + toggle : \"\");\n\t}\n\treturn val;\n};\n\n//========================\n// JsViews-specific tags\n//========================\n\n$tags({\n\ton: {\n\t\tattr: NONE,\n\t\tinit: function(tagCtx) {\n\t\t\tvar content,\n\t\t\t\ttag = this,\n\t\t\t\ti = 0,\n\t\t\t\targs = tagCtx.args, // [events,] [selector,] handler\n\t\t\t\tl = args.length;\n\n\t\t\tfor (; ii && i+1; // handler index\n\t\t\tif (tag.inline) {\n\t\t\t\tif (!$sub.rTmpl.exec(content = $.trim(tagCtx.tmpl.markup))) {\n\t\t\t\t\t// Inline {^{on}} tag with no content (or external template content) or with content containing\n\t\t\t\t\t// no HTML or JsRender tags: We will wrap the (text) content, or the operation name in a \";\n\t\t\t\t}\n\t\t\t\ttag.attr = HTML;\n\t\t\t}\n\t\t},\n\t\tonBind: function() {\n\t\t\tif (this.template) { // {^{on/}} with no content has template rendering
\", \"
\"],\n\t\ttr: [2, \"\", \"
\"],\n\t\ttd: [3, \"\", \"
\"],\n\t\tcol: [2, \"\", \"
\"],\n\t\tsvg_ns: [1, \"\", \"\"],\n\t\t// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,\n\t\t// unless wrapped in a div with non-breaking characters in front of it.\n\t\tdiv: $.support.htmlSerialize ? [0, \"\", \"\"] : [1, \"X
\", \"
\"]\n\t},\n\t_fe: {\n\t\tinput: {\n\t\t\tfrom: inputAttrib, to: VALUE\n\t\t},\n\t\ttextarea: valueBinding,\n\t\tselect: valueBinding,\n\t\toptgroup: {\n\t\t\tto: \"label\"\n\t\t}\n\t}\n});\n\n\treturn $;\n}, window));\n"]} \ No newline at end of file +{"version":3,"sources":["jquery.views.js"],"names":["factory","global","$","jQuery","exports","module","define","amd","jsr","jso","updateValues","sourceValues","tagElse","bindId","ev","linkCtx","cvtBack","cnvtName","target","view","binding","sourceValue","origVals","sourceElem","sourceEl","oldLinkCtx","tos","to","tcpTag","exprOb","contextCb","l","m","tag","_tgId","bindTo","defineBindToDataTargets","bindingStore","elem","_cxp","path","_ocp","ind","_","chg","convertBack","$isFunction","getRsc","nodeName","multiple","_jsvSel","apply","undefined","$isArray","length","data","_vw","onBeforeUpdateVal","change","index","value","toIndex","updateValue","setValue","_jsvInd","_jsvLkEl","fromIndex","_jsvElse","_cpfn","_ctxCb","_cpCtx","sb","$observable","setProperty","onElemChange","val","source","fromAttr","defaultAttr","setter","fnSetters","_jsvTr","delegateTarget","activeBody","type","attr","_jsvChg","rSplitBindings","lastIndex","exec","_jsvBnd","onDataLinkedTagChange","eventArgs","noUpdate","forceUpdate","hasError","onError","bindEarly","this","linkFn","fn","cvt","convert","parentElem","parentNode","onEvent","changeHandler","onBeforeChangeStr","call","prop","_toLk","_er","$sub","e","onRenderError","Function","props","args","_dfAt","VALUE","CHECKBOX","CHECKED","onUpdate","mergeCtxs","HTML","NONE","callAfterLink","observeAndBind","onAfterChangeStr","tagCtx","dataMap","map","bnd","onUnbind","ctx","tagName","_cnvt","_tag","tmpl","TRUE","addLinkMethods","inline","_lr","template","updateContent","_noUpd","ths","setDefer","_df","deferAttr","prevNode","nextNode","late","nodesToRemove","useProp","tokens","id","openIndex","closeIndex","testElem","cStyle","jsvSel","renders","targetParent","$target","targetVal","_val","unlinked","expr","_elCnt","_prv","_nxt","test","currentStyle","getComputedStyle","display","_jsvd","displayStyles","document","createElement","body","appendChild","removeChild","style","slice","RADIO","nodes","transferViewTokens","getAttribute","jsvAttrStr","indexOf","disposeTokens","setAttribute","previousSibling","lastChild","remove","link","empty","children","TEXTCONTENT","selected","$inArray","lateLink","arrayChangeHandler","self","onBeforeChange","onAfterChange","action","items","srt","refresh","addViews","removeViews","moveViews","oldIndex","fixIndex","setArrayChangeLink","handler","arrayBinding","bound","useKey","bndArr","off","arrayChangeStr","arrVws","arguments","on","linkGetVal","toLowerCase","$subSettingsAdvanced","_fe","contentEditable","from","renderAndLink","views","context","html","linkToNode","prevView","elCnt","error","bnds","removeViewBinding","nextSibling","render","addBindingMarkers","end","bindingKey","viewStore","k","linkedElem","exprFnDeps","propDeps","depends","tagDepends","linkedElems","cvtBk","_hdl","_dp","concat","_depends","deps","bdId","_apply","boundProps","paths","skp","$extend","_bndId","bindLinkedElChange","flow","lnkCtx","pop","tmplLink","noIteration","parentView","$link","tmplOrLinkExpr","jquery","useInput","elementChangeStr","i","vwInfos","placeholderParent","targetEl","topLevelCall","onRender","replaceMode","$view","topView","root","addDataBinding","markup","scp","cleanData","lnk","viewInfos","rOpenViewMarkers","parent","key","viewLink","outerData","validateOnly","convertMarkers","all","preceding","selfClose","closeTag","spaceBefore","boundId","spaceAfter","tag1","tag2","closeTag2","spaceAfterClose","selfClose2","endOpenTag","errorMsg","bndId","endOfElCnt","inTag","isVoid","parentTag","tagStack","shift","validate","voidElems","join","syntaxError","prevElCnt","elContent","defer","ids","openScript","closeScript","deferStack","charAt","unshift","badParent","processViewInfos","deferPath","deferChar","bindChar","onAftCr","deep","addedBindEls","_tkns","len","vwInfo","ch","j","open","push","onArrayChange","removeSubStr","onAfterCreateStr","onAfterCreate","bindEls","getViewInfos","level","named","_is","tagDepth","tags","dataLink","wrap","selector","linkViewsSel","get","elems","qsa","querySelectorAll","innerHTML","prevNodes","found","markerNodeInfo","contains","isLink","rViewMarkers","skip","processInfos","$viewsLinkAttr","rOpenTagMarkers","unmarkPrevOrNextNode","prevIds","linkInfo","token","nextView","node","depth","fragment","copiedNode","firstTag","wrapper","div","htmlTag","thisId","name","noValidate","markPrevOrNextNode","namespaceURI","rFirstElem","replace","rConvertMarkers","safeFragment","wrapMap","createDocumentFragment","firstChild","insertBefore","linkMarkup","currentView","boundTagId","tagExpr","rTagIndex","hasElse","linkExpressions","bindDataLinkTarget","normalizeLinkTag","rTagDatalink","delimCloseChar1","delimOpenChar0","delimOpenChar1","delimCloseChar0","isLk","links","tmplFn","rEscapeQuotes","View","extendCtx","_gccb","$elem","str","substr","SCRIPT","nodeType","isVal","rBinding","getInfos","close","elPath","infos","rMarkerTokens","removeAttribute","marker","twoway","trim","copyFromTagCtxToTag","mainElem","displayElem","linkedElements","$linkCtxElem","linkCtxElem","linkedEl","linkedTag","tagCtxElse","oldVal","indexTo","tagCtxs","tagCtxslength","linkedElement","mainElement","displayElement","filter","Array","contents","eq","onBind","setSize","height","width","className","_jsvCl","hasClass","removeClass","addClass","onAfterLink","cvtArgs","lt","asyncOnElemChange","which","setTimeout","bindTriggerEvent","trig","onoff","isIE","$linkedElem","newTrig","oldTrig","trigger","$subSettings","pathIndex","lastPath","bindtoOb","obsCtxPrm","linkedCtxParam","targetPaths","bindTos","targetPathsElses","_jsvto","resolveDataTargetPath","targetPath","topCp","split","newCtxs","newTagCtx","_thp","clean","bindings","elemArray","linkedElemTag","objId","object","obsId","allLinkedElems","cbId","propertyChangeStr","unmap","onDispose","s","$unlink","each","innerView","getElementsByTagName","inputAttrib","ctxPrm","$views","helpers","viewOrTagChar","viewOrTag","viewId","precedingLength","emptyView","vwItem","rOpenMarkers","async","values","setValues","tagOrView","bindFrom","theTag","theView","select","filtered","add","find","withMarkers","contentView","prevIsFirstNode","lastSibling","childTags","_gm","constructor","prototype","indexFrom","linkedCtxPrmKey","newVal","base","domChange","hasListener","_data","events","domChangeNotification","triggerHandler","dataItems","viewsCount","itemsCount","keepNodes","isMove","removeView","viewToRemove","current","childView","isArray","splice","parts","itemView","RegExp","setPrv","prv","rTagMarkers","selfNxt","backwards","firstChange","lastChange","movedNodes","viewsToMove","appendTo","afterParts","endChange","startView","endView","afterView","startParts","endParts","observeProps","options","sort","start","step","reverse","update","tgt","insert","observeMappedProps","src","removeProperty","oldValue","shallowArrayFilter","rShallowArrayPath","setGlobals","jsrender","versionNumber","requiresStr","sub","_jq","$observe","jsviews","linkChar","$viewsSettings","settings","extend","isFunction","$converters","expando","converters","$tags","advanced","propChng","arrChng","syntaxErr","_err","oldAdvSet","window","navigator","userAgent","textContent","bindElsSel","input","text","valueBinding","isCleanCall","oldCleanData","oldJsvDelimiters","delimiters","querySelector","ol","ul","table","tbody","thead","tfoot","tr","colgroup","dl","optgroup","svg","svg_ns","br","img","hr","area","col","meta","command","embed","keygen","param","track","wbr","rViewPath","inArray","observable","observe","onStore","item","parentTmpl","ret","delimChars","rTag","addSetting","merge","regularExpression","currentValue","toggle","init","content","_hi","rTmpl","params","activeElem","contextOb","_sel","_evs","_hlr","contentCtx","dataBoundOnly","radiogroup","Math","random","domChngCntnr","useDisable","disabled","forOrIfTagCtx","parentTags","checked","propParams","sortDataMap","getTgt","obsSrc","obsTgt","arrayView","targetLength","rendering","noVws","done","argDefault","arrayBindings","_ars","tagCt","paged","sorted","newTagCtxs","prevArg","different","tci","baseTag","tgtFlt","inner","getInnerView","nd","isVl","unlink","oldFn","result","0","_glt","regEx","linkCtxs","helper","last","nextPath","addedTagCpDep","_cp","paramVal","paramExpr","tagCtxPrm","linked","_ucp","_ceo","cloneExprObjects","obs","ob","clones","prm","advSet","_jsv","linkAttr","_wm","option","caption","th","td","useViews","legend","support","htmlSerialize","textarea"],"mappings":"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","file":"jquery.views.min.js","sourcesContent":["/*! jquery.views.js v0.9.91 (Beta): http://jsviews.com/ */\n/*\n * Interactive data-driven views using JsRender templates.\n * Subcomponent of JsViews\n * Requires jQuery and jsrender.js (Best-of-breed templating in browser or on Node.js)\n * See JsRender at http://jsviews.com/#download and http://github.com/BorisMoore/jsrender\n * Also requires jquery.observable.js\n * See JsObservable at http://jsviews.com/#download and http://github.com/BorisMoore/jsviews\n *\n * Copyright 2018, 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 jQuery passed as parameter (with JsRender and JsObservable): require(\"jquery.views\")(jQuery)\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([\"jquery\", \"./jsrender\", \"./jquery.observable\"], function($, jsr, jso) {\n\t\t\treturn factory(global, $, jsr, jso);\n\t\t}); // Require jQuery, JsRender, JsObservable\n\t} else { // Browser using plain ',\n\topenScript = ' - data-linked tag, close marker\n\t\t\t// We validate with inTag so no script markers are inserted in attribute context e.g. for:\n\t\t\t// \"\" or \"
...{{/if}}...\"\n\t\t\tpreceding = id\n\t\t\t\t? (preceding + endOfElCnt + spaceBefore + (inTag ? \"\" : openScript + id + closeScript)+ spaceAfter + tag)\n\t\t\t\t: endOfElCnt || all;\n\t\t}\n\n\t\tif (validate && boundId) {\n\t\t\tif (inTag) {\n\t\t\t\t// JsViews data-linking tags are not allowed within element markup.\n\t\t\t\t// See jsviews/issues/303\n\t\t\t\tsyntaxError('{^{ within elem markup (' + inTag + ' ). Use data-link=\"...\"');\n\t\t\t}\n\t\t\tif (id.charAt(0) === \"#\") {\n\t\t\t\ttagStack.unshift(id.slice(1));\n\t\t\t} else if (id.slice(1) !== (bndId = tagStack.shift())) {\n\t\t\t\t// See jsviews/issues/213\n\t\t\t\tsyntaxError('Closing tag for {^{...}} under different elem: <' + bndId + '>');\n\t\t\t}\n\t\t}\n\t\tif (tag) {\n\t\t\tinTag = tag;\n\t\t\t// If there are ids (markers since the last tag), move them to the defer string\n\t\t\ttagStack.unshift(parentTag);\n\t\t\tparentTag = tag.slice(1);\n\t\t\tif (validate && tagStack[0] && tagStack[0] === badParent[parentTag]) {\n\t\t\t\t// Missing \n\t\t\t\t// TODO: replace this by smart insertion of tags\n\t\t\t\terror('Parent of must be ');\n\t\t\t}\n\t\t\tisVoid = voidElems[parentTag];\n\t\t\tif ((elCnt = elContent[parentTag]) && !prevElCnt) {\n\t\t\t\tdeferStack.unshift(defer);\n\t\t\t\tdefer = \"\";\n\t\t\t}\n\t\t\tprevElCnt = elCnt;\n//TODO Consider providing validation which throws if you place as child of , etc. - since if not caught,\n//this can cause errors subsequently which are difficult to debug.\n//\t\t\t\tif (elContent[tagStack[0]]>2 && !elCnt) {\n//\t\t\t\t\terror(parentTag + \" in \" + tagStack[0]);\n//\t\t\t\t}\n\t\t\tif (defer && elCnt) {\n\t\t\t\tdefer += \"+\"; // Will be used for stepping back through deferred tokens\n\t\t\t}\n\t\t}\n\t\treturn preceding;\n\t}\n\n\tfunction processViewInfos(vwInfos, targetParent) {\n\t\t// If targetParent, we are processing viewInfos (which may include navigation through '+-' paths) and hooking up to the right parentElem etc.\n\t\t// (and elem may also be defined - the next node)\n\t\t// If no targetParent, then we are processing viewInfos on newly inserted content\n\t\tvar deferPath, deferChar, bindChar, parentElem, id, onAftCr, deep,\n\t\t\taddedBindEls = [];\n\n\t\t// In elCnt context (element-only content model), prevNode is the first node after the open, nextNode is the first node after the close.\n\t\t// If both are null/undefined, then open and close are at end of parent content, so the view is empty, and its placeholder is the\n\t\t// 'lastChild' of the parentNode. If there is a prevNode, then it is either the first node in the view, or the view is empty and\n\t\t// its placeholder is the 'previousSibling' of the prevNode, which is also the nextNode.\n\t\tif (vwInfos) {\n\t\t\tif (vwInfos._tkns.charAt(0) === \"@\") {\n\t\t\t\t// We are processing newly inserted content. This is a special script element that was created in convertMarkers() to process deferred bindings,\n\t\t\t\t// and inserted following the target parent element - because no element tags (outside elCnt) were encountered to carry those binding tokens.\n\t\t\t\t// We will step back from the preceding sibling of this element, looking at targetParent elements until we find the one that the current binding\n\t\t\t\t// token belongs to. Set elem to null (the special script element), and remove it from the DOM.\n\t\t\t\ttargetParent = elem.previousSibling;\n\t\t\t\telem.parentNode.removeChild(elem);\n\t\t\t\telem = undefined;\n\t\t\t}\n\t\t\tlen = vwInfos.length;\n\t\t\twhile (len--) {\n\t\t\t\tvwInfo = vwInfos[len];\n//if (prevIds.indexOf(vwInfo.token) < 0) { // This token is a newly created view or tag binding\n\t\t\t\tbindChar = vwInfo.ch;\n\t\t\t\tif (deferPath = vwInfo.path) {\n\t\t\t\t\t// We have a 'deferred path'\n\t\t\t\t\tj = deferPath.length - 1;\n\t\t\t\t\twhile (deferChar = deferPath.charAt(j--)) {\n\t\t\t\t\t\t// Use the \"+\" and\"-\" characters to navigate the path back to the original parent node where the deferred bindings ocurred\n\t\t\t\t\t\tif (deferChar === \"+\") {\n\t\t\t\t\t\t\tif (deferPath.charAt(j) === \"-\") {\n\t\t\t\t\t\t\t\tj--;\n\t\t\t\t\t\t\t\ttargetParent = targetParent.previousSibling;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttargetParent = targetParent.parentNode;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttargetParent = targetParent.lastChild;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Note: Can use previousSibling and lastChild, not previousElementSibling and lastElementChild,\n\t\t\t\t\t\t// since we have removed white space within elCnt. Hence support IE < 9\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (bindChar === \"^\") {\n\t\t\t\t\tif (tag = bindingStore[id = vwInfo.id]) {\n\t\t\t\t\t\t// The binding may have been deleted, for example in a different handler to an array collectionChange event\n\t\t\t\t\t\t// This is a tag binding\n\t\t\t\t\t\tdeep = targetParent && (!elem || elem.parentNode !== targetParent); // We are stepping back looking for the right targetParent,\n\t\t\t\t\t\t// or we are linking existing content and this element is in elCnt, not an immediate child of the targetParent.\n\t\t\t\t\t\tif (!elem || deep) {\n\t\t\t\t\t\t\ttag.parentElem = targetParent;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (vwInfo.elCnt && deep) {\n\t\t\t\t\t\t\t// With element only content, if there is no following element, or if the binding is deeper than the following element\n\t\t\t\t\t\t\t// then we need to set the open or close token as a deferred binding annotation on the parent\n\t\t\t\t\t\t\tsetDefer(targetParent, (vwInfo.open ? \"#\" : \"/\") + id + bindChar + (targetParent._df || \"\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// This is an open or close marker for a data-linked tag {^{...}}. Add it to bindEls.\n\t\t\t\t\t\taddedBindEls.push([deep ? null : elem, vwInfo]);\n\t\t\t\t\t}\n\t\t\t\t} else if (view = viewStore[id = vwInfo.id]) {\n\t\t\t\t\t// The view may have been deleted, for example in a different handler to an array collectionChange event\n\t\t\t\t\tif (!view.parentElem) {\n\t\t\t\t\t\t// If view is not already extended for JsViews, extend and initialize the view object created in JsRender, as a JsViews view\n\t\t\t\t\t\tview.parentElem = targetParent || elem && elem.parentNode || parentNode;\n\t\t\t\t\t\tview._.onRender = addBindingMarkers;\n\t\t\t\t\t\tview._.onArrayChange = arrayChangeHandler;\n\t\t\t\t\t\tsetArrayChangeLink(view);\n\t\t\t\t\t}\n\t\t\t\t\tparentElem = view.parentElem;\n\t\t\t\t\tif (vwInfo.open) {\n\t\t\t\t\t\t// This is an 'open view' node (preceding script marker node,\n\t\t\t\t\t\t// or if elCnt, the first element in the view, with a data-jsv annotation) for binding\n\t\t\t\t\t\tview._elCnt = vwInfo.elCnt;\n\t\t\t\t\t\tif (targetParent && !elem) {\n\t\t\t\t\t\t\tsetDefer(targetParent, \"#\" + id + bindChar + (targetParent._df || \"\"));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// No targetParent, so there is a ._nxt elem (and this is processing tokens on the elem)\n\t\t\t\t\t\t\tif (!view._prv) {\n\t\t\t\t\t\t\t\tsetDefer(parentElem, removeSubStr(parentElem._df, \"#\" + id + bindChar));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tview._prv = elem;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// This is a 'close view' marker node for binding\n\t\t\t\t\t\tif (targetParent && (!elem || elem.parentNode !== targetParent)) {\n\t\t\t\t\t\t\t// There is no ._nxt so add token to _df. It is deferred.\n\t\t\t\t\t\t\tsetDefer(targetParent, \"/\" + id + bindChar + (targetParent._df || \"\"));\n\t\t\t\t\t\t\tview._nxt = undefined;\n\t\t\t\t\t\t} else if (elem) {\n\t\t\t\t\t\t\t// This view did not have a ._nxt, but has one now, so token may be in _df, and must be removed. (No longer deferred)\n\t\t\t\t\t\t\tif (!view._nxt) {\n\t\t\t\t\t\t\t\tsetDefer(parentElem, removeSubStr(parentElem._df, \"/\" + id + bindChar));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tview._nxt = elem;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (onAftCr = changeHandler(view, onAfterCreateStr) || onAfterCreate) {\n\t\t\t\t\t\t\tonAftCr.call(view.ctx.tag, view);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n//}\n\t\t\t\t}\n\t\t\t}\n\t\t\tlen = addedBindEls.length;\n\t\t\twhile (len--) {\n\t\t\t\t// These were added in reverse order to addedBindEls. We push them in BindEls in the correct order.\n\t\t\t\tbindEls.push(addedBindEls[len]);\n\t\t\t}\n\t\t}\n\t\treturn !vwInfos || vwInfos.elCnt;\n\t}\n\n\tfunction getViewInfos(vwInfos) {\n\t\t// Used by view.childTags() and tag.childTags()\n\t\t// Similar to processViewInfos in how it steps through bindings to find tags. Only finds data-linked tags.\n\t\tvar level, parentTag, named;\n\n\t\tif (vwInfos) {\n\t\t\tlen = vwInfos.length;\n\t\t\tfor (j = 0; j < len; j++) {\n\t\t\t\tvwInfo = vwInfos[j];\n\t\t\t\t// This is an open marker for a data-linked tag {^{...}}, within the content of the tag whose id is get.id. Add it to bindEls.\n\t\t\t\t// Note - if bindingStore[vwInfo.id]._is === \"tag\" then getViewInfos is being called too soon - during first linking pass\n\t\t\t\ttag = bindingStore[vwInfo.id];\n\t\t\t\tif (!tag._is && tag.linkCtx) {\n\t\t\t\t\tparentTag = tag = tag.linkCtx.tag;\n\t\t\t\t\tnamed = tag.tagName === tagName;\n\t\t\t\t\tif (!tag.flow || named) {\n\t\t\t\t\t\tif (!deep) {\n\t\t\t\t\t\t\tlevel = 1;\n\t\t\t\t\t\t\twhile (parentTag = parentTag.parent) {\n\t\t\t\t\t\t\t\tlevel++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttagDepth = tagDepth || level; // The level of the first tag encountered.\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ((deep || level === tagDepth) && (!tagName || named)) {\n\t\t\t\t\t\t\t// Filter on top-level or tagName as appropriate\n\t\t\t\t\t\t\ttags.push(tag);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction dataLink() {\n\t\t//================ Data-link and fixup of data-jsv annotations ================\n\t\tvar j, index,\n\t\t\ttokens = \"\",\n\t\t\twrap = {},\n\t\t\tselector = linkViewsSel + (get ? \",[\" + deferAttr + \"]\" : \"\");\n\t\t\t// If a childTags() call, get = \",[\" + deferAttr + \"]\" - since we need to include elements that have a ._df expando for deferred tokens\n\n\t\telems = qsa ? parentNode.querySelectorAll(selector) : $(selector, parentNode).get();\n\t\tl = elems.length;\n\n\t\t// The prevNode will be in the returned query, since we called markPrevOrNextNode() on it.\n\t\t// But it may have contained nodes that satisfy the selector also.\n\t\tif (prevNode && prevNode.innerHTML) {\n\t\t\t// Find the last contained node of prevNode, to use as the prevNode - so we only link subsequent elems in the query\n\t\t\tprevNodes = qsa ? prevNode.querySelectorAll(selector) : $(selector, prevNode).get();\n\t\t\tprevNode = prevNodes.length ? prevNodes[prevNodes.length - 1] : prevNode;\n\t\t}\n\n\t\ttagDepth = 0;\n\t\tfor (i = 0; i < l; i++) {\n\t\t\telem = elems[i];\n\t\t\tif (prevNode && !found) {\n\t\t\t\t// If prevNode is set, not false, skip linking. If this element is the prevNode, set to false so subsequent elements will link.\n\t\t\t\tfound = (elem === prevNode);\n\t\t\t} else if (nextNode && elem === nextNode) {\n\t\t\t\t// If nextNode is set then break when we get to nextNode\n\t\t\t\tif (get) {\n\t\t\t\t\ttokens += markerNodeInfo(elem);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t} else if (elem.parentNode) {\n\t\t\t\t// elem has not been removed from DOM\n\t\t\t\tif (get) {\n\t\t\t\t\ttokens += markerNodeInfo(elem);\n\t\t\t\t\tif (elem._df) {\n\t\t\t\t\t\tj = i + 1;\n\t\t\t\t\t\twhile (j < l && elem.contains(elems[j])) {\n\t\t\t\t\t\t\tj++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Add deferred tokens after any tokens on descendant elements of this one\n\t\t\t\t\t\twrap[j-1] = elem._df;\n\t\t\t\t\t}\n\t\t\t\t\tif (wrap[i]) {\n\t\t\t\t\t\ttokens += wrap[i] || \"\";\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (isLink && (vwInfo = viewInfos(elem, undefined, rViewMarkers)) && (vwInfo = vwInfo[0])) {\n\t\t\t\t\t\t// If this is a link(trueOrString ...) call we will avoid re-binding to elems that are within template-rendered views\n\t\t\t\t\t\tskip = skip ? (vwInfo.id !== skip && skip) : vwInfo.open && vwInfo.id;\n\t\t\t\t\t}\n\t\t\t\t\tif (!skip && processInfos(viewInfos(elem))\n\t\t\t\t\t\t// If a link() call, processViewInfos() adds bindings to bindEls, and returns true for non-script nodes, for adding data-link bindings\n\t\t\t\t\t\t// If a childTags() call, getViewInfos returns array of tag bindings.\n\t\t\t\t\t\t\t&& elem.getAttribute($viewsLinkAttr)) {\n\t\t\t\t\t\tbindEls.push([elem]); // A data-linked element so add to bindEls too\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (get) {\n\t\t\ttokens += parentNode._df || \"\";\n\t\t\tif (index = tokens.indexOf(\"#\" + get.id) + 1) {\n\t\t\t\t// We are looking for view.childTags() or tag.childTags() - so start after the open token of the parent view or tag.\n\t\t\t\ttokens = tokens.slice(index + get.id.length);\n\t\t\t}\n\t\t\tindex = tokens.indexOf(\"/\" + get.id);\n\t\t\tif (index + 1) {\n\t\t\t\t// We are looking for view.childTags() or tag.childTags() - so don't look beyond the close token of the parent view or tag.\n\t\t\t\ttokens = tokens.slice(0, index);\n\t\t\t}\n\t\t\t// Call getViewInfos to add the found childTags to the tags array\n\t\t\tgetViewInfos(viewInfos(tokens, undefined, rOpenTagMarkers));\n\t\t}\n\n\t\tif (html === undefined && parentNode.getAttribute($viewsLinkAttr)) {\n\t\t\tbindEls.push([parentNode]); // Support data-linking top-level element directly (not within a data-linked container)\n\t\t}\n\n\t\t// Remove temporary marker script nodes they were added by markPrevOrNextNode\n\t\tunmarkPrevOrNextNode(prevNode, elCnt);\n\t\tunmarkPrevOrNextNode(nextNode, elCnt);\n\n\t\tif (get) {\n\t\t\treturn; // We have added childTags to the tags array, so we are done\n\t\t}\n\n\t\tif (elCnt && defer + ids) {\n\t\t\t// There are some views with elCnt, for which the open or close did not precede any HTML tag - so they have not been processed yet\n\t\t\telem = nextNode;\n\t\t\tif (defer) {\n\t\t\t\tif (nextNode) {\n\t\t\t\t\tprocessViewInfos(viewInfos(defer + \"+\", true), nextNode);\n\t\t\t\t} else {\n\t\t\t\t\tprocessViewInfos(viewInfos(defer, true), parentNode);\n\t\t\t\t}\n\t\t\t}\n\t\t\tprocessViewInfos(viewInfos(ids, true), parentNode);\n\t\t\t// If there were any tokens on nextNode which have now been associated with inserted HTML tags, remove them from nextNode\n\t\t\tif (nextNode) {\n\t\t\t\ttokens = nextNode.getAttribute(jsvAttrStr);\n\t\t\t\tif (l = tokens.indexOf(prevIds) + 1) {\n\t\t\t\t\ttokens = tokens.slice(l + prevIds.length - 1);\n\t\t\t\t}\n\t\t\t\tnextNode.setAttribute(jsvAttrStr, ids + tokens);\n\t\t\t}\n\t\t}\n\n// if (context.lazyLink) {\n// setTimeout(doLinking) (doLinking is function wrapper of following lines)\n// See Future tasks, and https://github.com/BorisMoore/jsviews/issues/368.\n// Could call context.lazyLink as callback, on async completion - or return promise.\n\t\t//================ Bind the data-linked elements and tags ================\n\t\tl = bindEls.length;\n\t\tfor (i = 0; i < l; i++) {\n\t\t\telem = bindEls[i];\n\t\t\tlinkInfo = elem[1];\n\t\t\telem = elem[0];\n\t\t\tif (linkInfo) {\n\t\t\t\tif (tag = bindingStore[linkInfo.id]) {\n\t\t\t\t\tif (linkCtx = tag.linkCtx) {\n\t\t\t\t\t\t// The tag may have been stored temporarily on the bindingStore - or may have already been replaced by the actual binding\n\t\t\t\t\t\ttag = linkCtx.tag;\n\t\t\t\t\t\ttag.linkCtx = linkCtx;\n\t\t\t\t\t}\n\t\t\t\t\tif (linkInfo.open) {\n\t\t\t\t\t\t// This is an 'open linked tag' binding annotation for a data-linked tag {^{...}}\n\t\t\t\t\t\tif (elem) {\n\t\t\t\t\t\t\ttag.parentElem = elem.parentNode;\n\t\t\t\t\t\t\ttag._prv = elem;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttag._elCnt = linkInfo.elCnt;\n\t\t\t\t\t\t// We data-link depth-first (\"on the way in\"), which is better for perf - and allows setting parent tags etc.\n\t\t\t\t\t\tview = tag.tagCtx.view;\n\n\t\t\t\t\t\t// Add data binding (unless skipped due to lateRender)\n\t\t\t\t\t\taddDataBinding(late, undefined, tag._prv, view, linkInfo.id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttag._nxt = elem;\n\t\t\t\t\t\tif (tag._.unlinked && !tag._toLk) {\n\t\t\t\t\t\t\t// This is a 'close linked tag' binding annotation (and data-binding was not skipped due to lateRender)\n\t\t\t\t\t\t\ttagCtx = tag.tagCtx;\n\t\t\t\t\t\t\tview = tagCtx.view;\n\t\t\t\t\t\t\tcallAfterLink(tag);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Add data binding for a data-linked element (with data-link attribute)\n\t\t\t\taddDataBinding(late, elem.getAttribute($viewsLinkAttr), elem, $view(elem), undefined, isLink, outerData, context);\n\t\t\t}\n\t\t}\n//});\n\t}\n\t//==== /end of nested functions ====\n\n\tvar inTag, linkCtx, tag, i, l, j, len, elems, elem, view, vwInfo, linkInfo, prevNodes, token, prevView, nextView,\n\t\tnode, tags, deep, tagName, tagCtx, validate, tagDepth, depth, fragment, copiedNode, firstTag, parentTag,\n\t\tisVoid, wrapper, div, tokens, elCnt, prevElCnt, htmlTag, ids, prevIds, found, skip, isLink, get,\n\t\tself = this,\n\t\tthisId = self._.id + \"_\",\n\t\tdefer = \"\",\n\t\t// The marker ids for which no tag was encountered (empty views or final closing markers) which we carry over to container tag\n\t\tbindEls = [],\n\t\ttagStack = [],\n\t\tdeferStack = [],\n\t\tlate = [],\n\t\tonAfterCreate = changeHandler(self, onAfterCreateStr),\n\t\tprocessInfos = processViewInfos;\n\n\tif (refresh) {\n\t\tif (refresh.tmpl) {\n\t\t\t// refresh is the prevView, passed in from addViews()\n\t\t\tprevView = \"/\" + refresh._.id + \"_\";\n\t\t} else {\n\t\t\tisLink = refresh.lnk; // Top-level linking\n\t\t\tif (refresh.tag) {\n\t\t\t\tthisId = refresh.tag + \"^\";\n\t\t\t\trefresh = true;\n\t\t\t}\n\t\t\tif (get = refresh.get) {\n\t\t\t\tprocessInfos = getViewInfos;\n\t\t\t\ttags = get.tags;\n\t\t\t\tdeep = get.deep;\n\t\t\t\ttagName = get.name;\n\t\t\t}\n\t\t}\n\t\trefresh = refresh === true;\n\t}\n\n\tparentNode = parentNode\n\t\t? (\"\" + parentNode === parentNode\n\t\t\t? $(parentNode)[0] // It is a string, so treat as selector\n\t\t\t: parentNode.jquery\n\t\t\t\t? parentNode[0] // A jQuery object - take first element.\n\t\t\t\t: parentNode)\n\t\t: (self.parentElem // view.link()\n\t\t\t|| document.body); // link(null, data) to link the whole document\n\n\tvalidate = !$subSettingsAdvanced.noValidate && parentNode.contentEditable !== TRUE;\n\tparentTag = parentNode.tagName.toLowerCase();\n\telCnt = !!elContent[parentTag];\n\n\tprevNode = prevNode && markPrevOrNextNode(prevNode, elCnt);\n\tnextNode = nextNode && markPrevOrNextNode(nextNode, elCnt) || null;\n\n\tif (html != undefined) {\n\t\t//================ Insert html into DOM using documentFragments (and wrapping HTML appropriately). ================\n\t\t// Also convert markers to DOM annotations, based on content model.\n\t\t// Corresponds to nextNode ? $(nextNode).before(html) : $(parentNode).html(html);\n\t\t// but allows insertion to wrap correctly even with inserted script nodes. jQuery version will fail e.g. under tbody or select.\n\t\t// This version should also be slightly faster\n\t\tdiv = document.createElement(\"div\");\n\t\twrapper = div;\n\t\tprevIds = ids = \"\";\n\t\thtmlTag = parentNode.namespaceURI === \"http://www.w3.org/2000/svg\" ? \"svg_ns\" : (firstTag = rFirstElem.exec(html)) && firstTag[1] || \"\";\n\t\tif (elCnt) {\n\t\t\t// Now look for following view, and find its tokens, or if not found, get the parentNode._df tokens\n\t\t\tnode = nextNode;\n\t\t\twhile (node && !(nextView = viewInfos(node))) {\n\t\t\t\tnode = node.nextSibling;\n\t\t\t}\n\t\t\tif (tokens = nextView ? nextView._tkns : parentNode._df) {\n\t\t\t\ttoken = prevView || \"\";\n\t\t\t\tif (refresh || !prevView) {\n\t\t\t\t\ttoken += \"#\" + thisId;\n\t\t\t\t}\n\t\t\t\tj = tokens.indexOf(token);\n\t\t\t\tif (j + 1) {\n\t\t\t\t\tj += token.length;\n\t\t\t\t\t// Transfer the initial tokens to inserted nodes, by setting them as the ids variable, picked up in convertMarkers\n\t\t\t\t\tprevIds = ids = tokens.slice(0, j);\n\t\t\t\t\ttokens = tokens.slice(j);\n\t\t\t\t\tif (nextView) {\n\t\t\t\t\t\tnode.setAttribute(jsvAttrStr, tokens);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetDefer(parentNode, tokens);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//================ Convert the markers to DOM annotations, based on content model. ================\n//\t\t\toldElCnt = elCnt;\n\t\tisVoid = undefined;\n\t\thtml = (\"\" + html).replace(rConvertMarkers, convertMarkers);\n//\t\t\tif (!!oldElCnt !== !!elCnt) {\n//\t\t\t\terror(\"Parse: \" + html); // Parse error. Content not well-formed?\n//\t\t\t}\n\t\tif (validate && tagStack.length) {\n\t\t\tsyntaxError(\"Mismatched '<\" + parentTag + \"...>' in:\\n\" + html); // Unmatched tag\n\t\t}\n\t\tif (validateOnly) {\n\t\t\treturn;\n\t\t}\n\t\t// Append wrapper element to doc fragment\n\t\tsafeFragment.appendChild(div);\n\n\t\t// Go to html and back, then peel off extra wrappers\n\t\t// Corresponds to jQuery $(nextNode).before(html) or $(parentNode).html(html);\n\t\t// but supports svg elements, and other features missing from jQuery version (and this version should also be slightly faster)\n\t\thtmlTag = wrapMap[htmlTag] || wrapMap.div;\n\t\tdepth = htmlTag[0];\n\t\twrapper.innerHTML = htmlTag[1] + html + htmlTag[2];\n\t\twhile (depth--) {\n\t\t\twrapper = wrapper.lastChild;\n\t\t}\n\t\tsafeFragment.removeChild(div);\n\t\tfragment = document.createDocumentFragment();\n\t\twhile (copiedNode = wrapper.firstChild) {\n\t\t\tfragment.appendChild(copiedNode);\n\t\t}\n\t\t// Insert into the DOM\n\t\tparentNode.insertBefore(fragment, nextNode);\n\t}\n\tdataLink();\n\n\treturn late;\n}\n\nfunction addDataBinding(late, linkMarkup, node, currentView, boundTagId, isLink, data, context) {\n\t// Add data binding for data-linked elements or {^{...}} data-linked tags\n\tvar tmpl, tokens, attr, convertBack, tagExpr, linkFn, linkCtx, tag, rTagIndex, hasElse, lastIndex,\n\t\tlinkExpressions = [];\n\n\tif (boundTagId) {\n\t\t// boundTagId is a string for {^{...}} data-linked tag. So only one linkTag in linkMarkup\n\t\t// data and context arguments are undefined\n\t\ttag = bindingStore[boundTagId];\n\t\ttag = tag.linkCtx ? tag.linkCtx.tag : tag;\n\n\t\tlinkCtx = tag.linkCtx || {\n\t\t\ttype: \"inline\",\n\t\t\tdata: currentView.data, // source\n\t\t\telem: tag._elCnt ? tag.parentElem : node, // target\n\t\t\tview: currentView,\n\t\t\tctx: currentView.ctx,\n\t\t\tattr: HTML, // Script marker nodes are associated with {^{ and always target HTML.\n\t\t\tfn: tag._.bnd,\n\t\t\ttag: tag,\n\t\t\t// Pass the boundTagId in the linkCtx, so that it can be picked up in observeAndBind\n\t\t\t_bndId: boundTagId\n\t\t};\n\t\ttag.linkCtx = linkCtx;\n\t\tbindDataLinkTarget(linkCtx, late);\n\t\ttag._toLk = linkCtx._bndId; // If data binding happened, remove _toLk flag from tag\n\t} else if (linkMarkup && node) {\n\t\t// Data-linked element\n\n\t\t// If isLink then this is a top-level linking: .link(expression, target, data, ....) or\n\t\t// .link(true, target, data, ....) scenario - and data and context are passed in separately from the view\n\t\tdata = isLink ? data : currentView.data;\n\n\t\t// Compiled linkFn expressions could be stored in the tmpl.links array of the template\n\t\t// TODO - consider also caching globally so that if {{:foo}} or data-link=\"foo\" occurs in different places,\n\t\t// the compiled template for this is cached and only compiled once...\n\t\t//links = currentView.links || currentView.tmpl.links;\n\n\t\ttmpl = currentView.tmpl;\n\n//\t\t\tif (!(linkTags = links[linkMarkup])) {\n\t\t// This is the first time this view template has been linked, so we compile the data-link expressions, and store them on the template.\n\n\t\tlinkMarkup = normalizeLinkTag(linkMarkup, defaultAttr(node));\n\t\tlastIndex = rTagDatalink.lastIndex = 0;\n\t\twhile (tokens = rTagDatalink.exec(linkMarkup)) { // TODO require } to be followed by whitespace or $, and remove the \\}(!\\}) option.\n\t\t\tlinkExpressions.push(tokens);\n\t\t\tlastIndex = rTagDatalink.lastIndex;\n\t\t}\n\t\tif (lastIndex < linkMarkup.length) {\n\t\t\tsyntaxError(linkMarkup);\n\t\t}\n\t\twhile (tokens = linkExpressions.shift()) {\n\t\t\t// Iterate over the data-link expressions, for different target attrs,\n\t\t\t// e.g. ~description(firstName, lastName)}\"\n\t\t\t// tokens: [all, attr, bindOnly, tagExpr, tagName, converter, colon, html, comment, code, params]\n\t\t\trTagIndex = rTagDatalink.lastIndex;\n\t\t\tattr = tokens[1];\n\t\t\ttagExpr = tokens[3];\n\t\t\twhile (linkExpressions[0] && linkExpressions[0][4] === \"else\") { // If this is {sometag...} and is followed by an {else...} add to tagExpr\n\t\t\t\ttagExpr += delimCloseChar1 + delimOpenChar0 + linkExpressions.shift()[3];\n\t\t\t\thasElse = true;\n\t\t\t}\n\t\t\tif (hasElse) { // If an {else} has been added, need also to add closing {{/sometag}}\n\t\t\t\ttagExpr += delimCloseChar1 + delimOpenChar0 + delimOpenChar1 + \"/\" + tokens[4] + delimCloseChar0;\n\t\t\t}\n\t\t\tlinkCtx = {\n\t\t\t\ttype: isLink ? \"top\" : \"link\",\n\t\t\t\tdata: data, // source\n\t\t\t\telem: node, // target\n\t\t\t\tview: currentView,\n\t\t\t\tctx: context,\n\t\t\t\tattr: attr,\n\t\t\t\tisLk: isLink, // top-level linking?\n\t\t\t\t_toLk : 1, // Flag to data-link on initial data-link call rendering call\n\t\t\t\t_noUpd : tokens[2] // Flag for data-link=\"^{...}\" so on initial data-link call will bind, but not render)\n\t\t\t};\n\n\t\t\tconvertBack = undefined;\n\t\t\tif (tokens[6]) {\n\t\t\t\tconvertBack = tokens[10] || undefined;\n\t\t\t\tlinkCtx.convert = tokens[5] || \"\";\n\t\t\t\tif (convertBack !== undefined && defaultAttr(node)) {\n\t\t\t\t\tif (attr) {\n\t\t\t\t\t\tsyntaxError(tagExpr + \"- Remove target: \" + attr);\n\t\t\t\t\t}\n\t\t\t\t\t// Default target, so allow 2 way binding\n\t\t\t\t\tlinkCtx.convertBack = convertBack = convertBack.slice(1);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Compile the linkFn expression which evaluates and binds a data-link expression\n\t\t\t// TODO - optimize for the case of simple data path with no conversion, helpers, etc.:\n\t\t\t// i.e. data-link=\"a.b.c\". Avoid creating new instances of Function every time. Can use a default function for all of these...\n\n\t\t\tlinkCtx.expr = attr + tagExpr;\n\t\t\tlinkFn = tmpl.links[tagExpr];\n\t\t\tif (!linkFn) {\n\t\t\t\ttmpl.links[tagExpr] = linkFn = $sub.tmplFn(tagExpr.replace(rEscapeQuotes, \"\\\\$&\"), tmpl, true, convertBack, hasElse);\n\t\t\t}\n\t\t\tlinkCtx.fn = linkFn;\n\t\t\tbindDataLinkTarget(linkCtx, late);\n\t\t\t// We store rTagIndex in local scope, since this addDataBinding method can sometimes be called recursively,\n\t\t\t// and each is using the same rTagDatalink instance.\n\t\t\trTagDatalink.lastIndex = rTagIndex;\n\t\t}\n//\t\t}\n\t}\n}\n\nfunction bindDataLinkTarget(linkCtx, late) {\n\t// Add data link bindings for a link expression in data-link attribute markup\n\tfunction handler(ev, eventArgs) {\n\t\tonDataLinkedTagChange.call(linkCtx, ev, eventArgs);\n\t\t// If the link expression uses a custom tag, the onDataLinkedTagChange call will call renderTag, which will set tagCtx on linkCtx\n\t}\n\tvar view;\n\tif (linkCtx.isLk) {\n\t\t// Top-level linking: .link(expressionOrTrue, data, context) - so we need to create a view for the linking, with the data and ctx\n\t\t// which may be different than the current context of the target. Note that this view is not a standard data-linked view, so it will\n\t\t// be disposed only when its parent view is disposed.\n\t\tlinkCtx.view = new $sub.View(\n\t\t\t$sub.extendCtx(linkCtx.ctx, linkCtx.view.ctx),\n\t\t\t\"link\", linkCtx.view, linkCtx.data, linkCtx.expr, undefined, addBindingMarkers);\n\t}\n\tlinkCtx._ctxCb = $sub._gccb(view = linkCtx.view); // getContextCallback: _ctxCb, for filtering/appending to dependency paths: function(path, object) { return [(object|path)*]}\n\tlinkCtx._hdl = handler;\n\t// handler._ctx = linkCtx; Could pass linkCtx for use in a depends = function() {} call, so depends is different for different linkCtx's\n\tif (linkCtx.elem.nodeName === \"SELECT\" && linkCtx.type === \"link\" && !linkCtx.attr) {\n\t\tvar $elem = $(linkCtx.elem);\n\t\t$elem.on(\"jsv-domchange\", function() {\n\t\t\t// If the options have changed dynamically under the select, we need to refresh the data-linked selection, using the new options\n\t\t\tif (!arguments[3].refresh) { // eventArgs.refresh !== true - so a refresh action will only set the selection once\n\t\t\t\tvar source = linkCtx.fn(view.data, view, $sub);\n\t\t\t\t$elem.val(linkCtx.convert || linkCtx.convertBack ? $sub._cnvt(linkCtx.convert, view, source) : source);\n\t\t\t}\n\t\t});\n\t}\n\n\tif (linkCtx.fn._lr) {\n\t\tlinkCtx._toLk = 1;\n\t\tlate.push(linkCtx); // lateRender - defer rendering and linking (sync but after first linking pass)\n\t} else {\n\t\thandler(true);\n\t}\n}\n\n//=====================\n// Data-linking helpers\n//=====================\n\nfunction removeSubStr(str, substr) {\n\tvar k;\n\treturn str\n\t\t? (k = str.indexOf(substr),\n\t\t\t(k + 1\n\t\t\t\t? str.slice(0, k) + str.slice(k + substr.length)\n\t\t\t\t: str))\n\t\t: \"\";\n}\n\nfunction markerNodeInfo(node) {\n\treturn node &&\n\t\t(\"\" + node === node\n\t\t\t? node\n\t\t\t: node.tagName === SCRIPT\n\t\t\t\t? node.type.slice(3)\n\t\t\t\t: node.nodeType === 1 && node.getAttribute(jsvAttrStr) || \"\");\n}\n\nfunction viewInfos(node, isVal, rBinding) {\n\t// Test whether node is a script marker node, and if so, return metadata\n\tfunction getInfos(all, open, close, id, ch, elPath) {\n\t\tinfos.push({\n\t\t\telCnt: elCnt,\n\t\t\tid: id,\n\t\t\tch: ch,\n\t\t\topen: open,\n\t\t\tclose: close,\n\t\t\tpath: elPath,\n\t\t\ttoken: all\n\t\t});\n\t}\n\tvar elCnt, tokens,\n\t\tinfos = [];\n\tif (tokens = isVal ? node : markerNodeInfo(node)) {\n\t\telCnt = infos.elCnt = node.tagName !== SCRIPT;\n\t\telCnt = tokens.charAt(0) === \"@\" || elCnt;\n\t\tinfos._tkns = tokens;\n\t\t// rMarkerTokens = /(?:(#)|(\\/))(\\d+)([_^])([-+@\\d]+)?/g;\n\t\ttokens.replace(rBinding || rMarkerTokens, getInfos);\n\t\treturn infos;\n\t}\n}\n\nfunction unmarkPrevOrNextNode(node, elCnt) {\n\tif (node) {\n\t\tif (node.type === \"jsv\") {\n\t\t\tnode.parentNode.removeChild(node);\n\t\t} else if (elCnt && node.getAttribute($viewsLinkAttr) === \"\") {\n\t\t\tnode.removeAttribute($viewsLinkAttr);\n\t\t}\n\t}\n}\n\nfunction markPrevOrNextNode(node, elCnt) {\n\tvar marker = node;\n\twhile (elCnt && marker && marker.nodeType !== 1) {\n\t\tmarker = marker.previousSibling;\n\t}\n\tif (marker) {\n\t\tif (marker.nodeType !== 1) {\n\t\t\t// For text nodes, we will add a script node before\n\t\t\tmarker = document.createElement(SCRIPT);\n\t\t\tmarker.type = \"jsv\";\n\t\t\tnode.parentNode.insertBefore(marker, node);\n\t\t} else if (!markerNodeInfo(marker) && !marker.getAttribute($viewsLinkAttr)) {\n\t\t\t// For element nodes, we will add a data-link attribute (unless there is already one)\n\t\t\t// so that this node gets included in the node linking process.\n\t\t\tmarker.setAttribute($viewsLinkAttr, \"\");\n\t\t}\n\t}\n\treturn marker;\n}\n\nfunction normalizeLinkTag(linkMarkup, twoway) {\n\tlinkMarkup = $.trim(linkMarkup);\n\treturn linkMarkup.slice(-1) !== delimCloseChar0\n\t// If simplified syntax is used: data-link=\"expression\", convert to data-link=\"{:expression}\",\n\t// or for inputs, data-link=\"{:expression:}\" for (default) two-way binding\n\t\t? linkMarkup = delimOpenChar1 + \":\" + linkMarkup + (twoway ? \":\" : \"\") + delimCloseChar0\n\t\t: linkMarkup;\n}\n\n//===========================\n// Methods for views and tags\n//===========================\n\nfunction callAfterLink(tag, ev, eventArgs) {\n\tfunction copyFromTagCtxToTag() {\n\t\tlinkedElems = tagCtx.linkedElems || tag.linkedElems || tag.linkedElem && [tag.linkedElem];\n\t\tif (linkedElems) {\n\t\t\ttag.linkedElems = tagCtx.linkedElems = linkedElems;\n\t\t\ttag.linkedElem = linkedElems[0] = tag.linkedElem || linkedElems[0];\n\t\t}\n\t\tif (linkedElem = tagCtx.mainElem || tag.mainElem) {\n\t\t\ttagCtx.mainElem = tag.mainElem = linkedElem;\n\t\t}\n\t\tif (linkedElem = tagCtx.displayElem || tag.displayElem) {\n\t\t\ttagCtx.displayElem = tag.displayElem = linkedElem;\n\t\t}\n\t}\n\n\tvar linkedElems, linkedElements, linkedElem, l, m, $linkCtxElem, linkCtxElem, linkedEl, linkedTag, tagCtxElse, props, val, oldVal, indexTo,\n\t\ttagCtx = tag.tagCtx,\n\t\ttagCtxs = tag.tagCtxs,\n\t\ttagCtxslength = tagCtxs && tagCtxs.length,\n\t\tlinkCtx = tag.linkCtx,\n\t\tbindTo = tag.bindTo || {};\n\n\tif (tag._.unlinked) { // First call to onAfterLink, or first call after onUpdate: updateContent. Initialize and call onBind and set properties\n\t\t$linkCtxElem = $(linkCtx.elem);\n\t\tif (tag.linkedElement || tag.mainElement || tag.displayElement) {\n\t\t\tif (linkedElements = tag.linkedElement) {\n\t\t\t\t// tag.linkedElement: - selector, or array of selectors, for identifying linked elements in template/rendered content.\n\t\t\t\t// (But for tag bindings on data-linked elements, defaults to data-linked element)\n\t\t\t\ttag.linkedElem = undefined;\n\t\t\t\tl = linkedElements.length;\n\t\t\t\twhile (l--) {\n\t\t\t\t\tif (linkedElements[l]) {\n\t\t\t\t\t\tm = tagCtxslength;\n\t\t\t\t\t\twhile (m--) {\n\t\t\t\t\t\t\tlinkCtxElem = !m && !tag.inline && $linkCtxElem.filter(linkedElements[l]);\n\t\t\t\t\t\t\ttagCtxElse = tagCtxs[m];\n\t\t\t\t\t\t\tlinkedElems = tagCtxElse.linkedElems = tagCtxElse.linkedElems || new Array(l);\n\t\t\t\t\t\t\tlinkedElem = linkCtxElem[0] ? linkCtxElem : tagCtxElse.contents(true, linkedElements[l]);\n\t\t\t\t\t\t\tif (linkedElem[0] && linkedElem[0].type !== RADIO) {\n\t\t\t\t\t\t\t\tlinkedElems[l] = linkedElem.eq(0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (linkedElements = tag.mainElement) {\n\t\t\t\t// tag.mainElement: - selector for identifying mainElem in template/rendered content\n\t\t\t\t// (But for tag bindings on data-linked elements, defaults to data-linked element)\n\t\t\t\tm = tagCtxslength;\n\t\t\t\twhile (m--) {\n\t\t\t\t\tlinkCtxElem = !m && !tag.inline && $linkCtxElem.filter(linkedElements);\n\t\t\t\t\ttagCtxElse = tagCtxs[m];\n\t\t\t\t\tlinkedElem = linkCtxElem[0] ? linkCtxElem : tagCtxElse.contents(true, linkedElements).eq(0);\n\t\t\t\t\tif (linkedElem[0]) {\n\t\t\t\t\t\ttagCtxElse.mainElem = linkedElem;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (linkedElements = tag.displayElement) {\n\t\t\t\t// tag.displayElement: - selector for identifying displayElem in template/rendered content\n\t\t\t\t// (But for tag bindings on data-linked elements, defaults to data-linked element)\n\t\t\t\tm = tagCtxslength;\n\t\t\t\twhile (m--) {\n\t\t\t\t\tlinkCtxElem = !m && !tag.inline && $linkCtxElem.filter(linkedElements);\n\t\t\t\t\ttagCtxElse = tagCtxs[m];\n\t\t\t\t\tlinkedElem = linkCtxElem[0] ? linkCtxElem : tagCtxElse.contents(true, linkedElements).eq(0);\n\t\t\t\t\tif (linkedElem[0]) {\n\t\t\t\t\t\ttagCtxElse.displayElem = linkedElem;\n\t\t\t\t\t\tif (!m) {\n\t\t\t\t\t\t\ttag.displayElem = linkedElem;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcopyFromTagCtxToTag();\n\t\t}\n\t\tif (tag.onBind) {\n\t\t\ttag.onBind(tagCtx, linkCtx, tag.ctx, ev, eventArgs);\n\t\t\tcopyFromTagCtxToTag();\n\t\t}\n\t}\n\n\tm = tagCtxslength;\n\twhile (m--) {\n\t\ttagCtxElse = tagCtxs[m];\n\t\tprops = tagCtxElse.props;\n\n\t\tif (linkedElem = tagCtxElse.mainElem || !tag.mainElement && tagCtxElse.linkedElems && tagCtxElse.linkedElems[0]) {\n\t\t\t// linkedElem is the mainElem (defaulting to linkedElem)\n\t\t\tif (linkedElem[0] && props.id && !linkedElem[0].id) {\n\t\t\t\tlinkedElem[0].id = props.id;\n\t\t\t}\n\t\t\tif (tag.setSize) {\n\t\t\t\tif (val = !bindTo.height && props.height || tag.height) {\n\t\t\t\t\tlinkedElem.height(val);\n\t\t\t\t}\n\t\t\t\tif (val = !bindTo.width && props.width || tag.width) {\n\t\t\t\t\tlinkedElem.width(val);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (val = (linkedElem = tagCtxElse.displayElem || linkedElem) && (!bindTo[\"class\"] && props[\"class\"] || tag.className)) {\n\t\t\t// This code supports dynamic binding to class - where it adds the class if absent, and removes/adds if a previous value is present\n\t\t\toldVal = linkedElem[0]._jsvCl;\n\t\t\tif (val !== oldVal) {\n\t\t\t\tif (linkedElem.hasClass(oldVal)) {\n\t\t\t\t\tlinkedElem.removeClass(oldVal);\n\t\t\t\t}\n\t\t\t\tlinkedElem.addClass(val);\n\t\t\t\tlinkedElem[0]._jsvCl = val;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (tag.onAfterLink) {\n\t\ttag.onAfterLink(tagCtx, linkCtx, tag.ctx, ev, eventArgs);\n\t\tcopyFromTagCtxToTag();\n\t}\n\n\tif (!tag.flow && !tag._.chg) {\n\t\tif (tag.inline && tag._.unlinked && (tag.linkedElems || tag.bindTo)) {\n\t\t\tdefineBindToDataTargets(bindingStore[tag._tgId], tag);\n\t\t}\n\t\tm = tagCtxs.length;\n\t\twhile (m--) {\n\t\t\tprops = tag.cvtArgs(1, m); // array of bindFrom args/props\n\t\t\tl = props.length;\n\t\t\twhile (l--) {\n\t\t\t\tval = props[l];\n\t\t\t\ttag.setValue(val, l, m);\n\t\t\t}\n\t\t\tif (tag._.unlinked) {\n\t\t\t\ttagCtx = tagCtxs[m];\n\t\t\t\tlinkedElems = tagCtx.linkedElems || tag.linkedElem && [tag.linkedElem];\n\t\t\t\tindexTo = (tag.bindTo || [0]).length;\n\t\t\t\twhile (indexTo--) {\n\t\t\t\t\tif ((linkedElem = linkedElems && linkedElems[indexTo]) && (l = linkedElem.length)) {\n\t\t\t\t\t\twhile (l--) {\n\t\t\t\t\t\t\tlinkedEl = linkedElem[l];\n\t\t\t\t\t\t\tlinkedTag = linkedEl._jsvLkEl;\n\t\t\t\t\t\t\tif (!linkedTag || linkedTag !== tag) {\n\t\t\t\t\t\t\t\t// For data-linked tags, identify the linkedEl with the tag, for \"to\" binding\n\t\t\t\t\t\t\t\t// (For data-linked elements, if not yet bound, we identify later when the linkCtx.elem is bound)\n\t\t\t\t\t\t\t\tlinkedEl._jsvLkEl = tag;\n\t\t\t\t\t\t\t\tlinkedEl._jsvInd = indexTo;\n\t\t\t\t\t\t\t\tlinkedEl._jsvElse = m;\n\t\t\t\t\t\t\t\tbindLinkedElChange(tag, linkedEl);\n\t\t\t\t\t\t\t\tlinkedEl._jsvBnd = \"&\" + tag._tgId + \"+\"; // Add a \"+\" for cloned binding - so removing\n\t\t\t\t\t\t\t\t// elems with cloned bindings will not remove the 'parent' binding from the bindingStore.\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\ttag._.unlinked = undefined;\n\tif (tag._.lt) { // Late tag: Late path: @some.path had not returned @some object, so try again with refresh\n\t\ttag.refresh();\n\t}\n}\n\nfunction asyncOnElemChange(ev) {\n\tvar which = ev.which;\n\tif (!(which > 15 && which < 21 || which > 32 && which < 41 || which > 111 && which < 131 || which === 27 || which === 144)) {\n\t\t// Shift, Ctrl, Alt, Pause, Caplock, Page up/down End, Home, Left, Up, Right, Down, Function keys, Escape, Numlock\n\t\tsetTimeout(function() {\n\t\t\tonElemChange(ev);\n\t\t});\n\t}\n}\n\nfunction bindTriggerEvent($elem, trig, onoff) {\n\t// Bind keydown, or other trigger - (rather than use the default change event bubbled to activeBody)\n\tif (trig === true && useInput && (!isIE || $elem[0].contentEditable !== TRUE)) { // IE oninput event is not raised for contenteditable changes\n\t\t$elem[onoff](\"input.jsv\", onElemChange); // For HTML5 browser with \"oninput\" support - for mouse editing of text\n\t} else {\n\t\ttrig = \"\" + trig === trig ? trig : \"keydown.jsv\"; // Set trigger to (true || truey non-string (e.g. 1) || 'keydown')\n\t\t$elem[onoff](trig, trig.indexOf(\"keydown\") >= 0 ? asyncOnElemChange : onElemChange); // Get 'keydown' with async\n\t}\n}\n\nfunction bindLinkedElChange(tag, linkedElem) {\n\t// Two-way binding for linkedElem - in the case of input, textarea or contentEditable elements.\n\t// Trigger setting may have changed. Unbind previous trigger binding (if any) and bind new one.\n\n\tvar $linkedElem, newTrig,\n\t\toldTrig = linkedElem._jsvTr || false;\n\n\tif (tag) {\n\t\tnewTrig = tag.tagCtx.props.trigger;\n\t\tif (newTrig === undefined) {\n\t\t\tnewTrig = tag.trigger;\n\t\t}\n\t}\n\tif (newTrig === undefined) {\n\t\tnewTrig = $subSettings.trigger;\n\t}\n\t// Trigger is noop except for text box, textarea, contenteditable...\n\tnewTrig = newTrig && (linkedElem.tagName === \"INPUT\" && linkedElem.type !== CHECKBOX && linkedElem.type !== RADIO\n\t\t|| linkedElem.type === \"textarea\" || linkedElem.contentEditable === TRUE) && newTrig || false;\n\n\tif (oldTrig !== newTrig) {\n\t\t$linkedElem = $(linkedElem);\n\t\tbindTriggerEvent($linkedElem, oldTrig, \"off\");\n\t\tbindTriggerEvent($linkedElem, linkedElem._jsvTr = newTrig, \"on\");\n\t}\n}\n\nfunction defineBindToDataTargets(binding, tag, cvtBk) {\n\t// Two-way binding.\n\t// We set the binding.to[1] to be the cvtBack, and binding.to[0] to be either the path to the target, or [object, path] where the target is the\n\t// path on the provided object. So for a computed path with an object call: a.b.getObject().d.e, we set to[0] to be [exprOb, \"d.e\"], and\n\t// we bind to the path on the returned object, exprOb.ob, as target. Otherwise our target is the first path, paths[0], which we will convert\n\t// with contextCb() for paths like ~a.b.c or #x.y.z\n\n\tvar pathIndex, path, lastPath, bindtoOb, to, bindTo, paths, k, obsCtxPrm, linkedCtxParam, contextCb, targetPaths, bindTos, fromIndex,\n\t\ttagElse = 1,\n\t\ttos = [],\n\t\tlinkCtx = binding.linkCtx,\n\t\tsource = linkCtx.data,\n\t\ttargetPathsElses = linkCtx.fn.paths;\n\n\tif (binding && !binding.to) {\n\t\tif (tag) {\n\t\t\tif (!tag.convertBack) {\n\t\t\t\ttag.convertBack = cvtBk;\n\t\t\t}\n\t\t\tbindTo = tag.bindTo;\n\t\t\ttagElse = tag.tagCtxs ? tag.tagCtxs.length : 1;\n\t\t}\n\t\twhile (tagElse--) {\n\t\t\tbindTos = [];\n\t\t\tif (targetPaths = targetPathsElses[tagElse]) {\n\t\t\t\tbindTo = targetPaths._jsvto ? [\"jsvto\"] : (bindTo || [0]);\n\t\t\t\tif (!tagElse && tag && tag._.ths) {\n\t\t\t\t\t// Tag has a this=expr bindign for which we will create an additional 'to' target (at index bindTo.length)\n\t\t\t\t\tbindTo = bindTo.concat(\"this\");\n\t\t\t\t}\n\t\t\t\tk = bindTo.length;\n\t\t\t\twhile (k--) {\n\t\t\t\t\tpath = \"\";\n\t\t\t\t\tcontextCb = linkCtx._ctxCb;\n\t\t\t\t\tpaths = bindTo[k];\n\t\t\t\t\tpaths = targetPaths[+paths === paths ? paths : \"_\" + paths]; // If path is a string, prepend \"_\" to avoid collision (e.g. with array.length if path is \"length\")\n\t\t\t\t\tif (pathIndex = paths && paths.length) {\n\t\t\t\t\t\tlastPath = paths[pathIndex - 1];\n\t\t\t\t\t\tif (lastPath._cpfn) { // Computed property exprOb\n\n\t\t\t\t\t\t\tbindtoOb = lastPath;\n\t\t\t\t\t\t\twhile (lastPath.sb && lastPath.sb._cpfn) {\n\t\t\t\t\t\t\t\tpath = lastPath = lastPath.sb;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tpath = lastPath.sb || path && path.path;\n\t\t\t\t\t\t\tlastPath = path ? path.slice(1) : bindtoOb.path;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tto = path\n\t\t\t\t\t\t\t? [bindtoOb, // 'exprOb' for this expression and view-binding. So bindtoOb.ob is current object returned by expression.\n\t\t\t\t\t\t\t\t\tlastPath]\n\t\t\t\t\t\t\t: resolveDataTargetPath(lastPath, source, contextCb); // Get 'to' for target path: lastPath\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Contextual parameter ~foo with no external binding - has ctx.foo = [{_ocp: xxx}] and binds to ctx.foo._ocp\n\t\t\t\t\t\tlinkedCtxParam = tag.linkedCtxParam;\n\t\t\t\t\t\tto = [];\n\t\t\t\t\t\tfromIndex = tag._.fromIndex;\n\t\t\t\t\t\tif (fromIndex && linkedCtxParam && linkedCtxParam[fromIndex[k]]) {\n\t\t\t\t\t\t\t// This is a tag binding, with linked tag contextual parameters\n\t\t\t\t\t\t\tto = [tag.tagCtxs[tagElse].ctx[linkedCtxParam[fromIndex[k]]][0], _ocp];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ((obsCtxPrm = to._cxp) && obsCtxPrm.tag && lastPath.indexOf(\".\")<0) {\n\t\t\t\t\t\t// This is a binding for a tag contextual parameter (e.g. within a tag block content\n\t\t\t\t\t\tto = obsCtxPrm;\n\t\t\t\t\t}\n\t\t\t\t\tbindTos.unshift(to);\n\t\t\t\t}\n\t\t\t}\n\t\t\ttos.unshift(bindTos);\n\t\t}\n\t\tbinding.to = tos;\n\t}\n}\n\nfunction resolveDataTargetPath(targetPath, source, contextCb) {\n\t// Iteratively process targetPath, resolving ~a.b.c paths for contextual parameters\n\tvar path, bindtoOb, to, l, obsCtxPrm, view, topCp, data;\n\n\twhile (targetPath && targetPath !== _ocp && (to = contextCb(path = targetPath.split(\"^\").join(\".\"), source)) && (l = to.length)) {\n\t\tif (obsCtxPrm = to[0]._cxp) { // Two-way binding to a contextual parameter reference, ~foo (declared as ~foo=expr on a parent tag)\n\t\t\ttopCp = topCp || obsCtxPrm;\n\t\t\tview = to[0][0];\n\t\t\tif (_ocp in view) {\n\t\t\t\tdata = view;\n\t\t\t\tview = view._vw;\n\t\t\t} else {\n\t\t\t\tdata = view.data;\n\t\t\t}\n\t\t\ttopCp.path = targetPath = to[0][1];\n\t\t\tto = [topCp.data = data, targetPath];\n\t\t\t\tcontextCb = $sub._gccb(view);\n\t\t\t\tif (targetPath._cpfn) { // computed property\n\t\t\t\t\tbindtoOb = targetPath;\n\t\t\t\t\tbindtoOb.data = to[0];\n\t\t\t\t\tbindtoOb._cpCtx = contextCb;\n\t\t\t\t\twhile (targetPath.sb && targetPath.sb._cpfn) {\n\t\t\t\t\t\tpath = targetPath = targetPath.sb;\n\t\t\t\t\t}\n\t\t\t\t\tpath = targetPath.sb || path && path.path;\n\t\t\t\t\ttargetPath = path ? path.slice(1) : bindtoOb.path;\n\t\t\t\t\tto = [\n\t\t\t\t\t\tbindtoOb, // 'exprOb' for this expression and view-binding. So bindtoOb.ob is current object returned by expression.\n\t\t\t\t\t\ttargetPath\n\t\t\t\t\t];\n\t\t\t\t} else if (obsCtxPrm.tag && obsCtxPrm.path === _ocp) {\n\t\t\t\t\tto = obsCtxPrm;\n\t\t\t\t}\n\t\t} else { // Two-way binding to a helper - e.g. ~address.street, or computed, e.g. ~fullName(), or view property e.g. #data.foo\n\t\t\tto = l>1\n\t\t\t\t? [to[l-2], to[l-1]] // With path: [object, path]\n\t\t\t\t: [to[l-1]]; // No path, (e.g. [function] for computed with setter)\n\t\t}\n\t\tsource = to[0];\n\t\ttargetPath = to[1];\n\t}\n\tto = to || [source, path];\n\tto._cxp = topCp;\n\treturn to;\n}\n\nfunction mergeCtxs(tag, newCtxs, replace) { // Merge updated tagCtxs into tag.tagCtxs\n\tvar tagCtx, newTagCtx, latePath,\n\t\tview = tag.tagCtx.view,\n\t\ttagCtxs = tag.tagCtxs || [tag.tagCtx],\n\t\tl = tagCtxs.length,\n\t\trefresh = !newCtxs;\n\n\tif (refresh) {\n\t\tnewCtxs = tag._.bnd.call(view.tmpl, (tag.linkCtx || view).data, view, $sub);\n\t\tif (newCtxs.lt) {\n\t\t\treturn; // We are calling tag.refresh() but a late path (@a.b.c) has not yet returned an object (@a) so cancel the refresh()\n\t\t}\n\t\ttag._.lt = undefined; // All late paths are now resolved, so this is no longer a late tag\n\t\tnewCtxs = $isArray(newCtxs) ? newCtxs : [newCtxs];\n\t}\n\n\tif (replace) {\n\t\t// Replace previous tagCtxs by new ones, rather than merging\n\t\ttagCtxs = tag.tagCtxs = newCtxs;\n\t\ttag.tagCtx = tagCtxs[0];\n\t\taddLinkMethods(tag);\n\t} else {\n\t\twhile (l--) {\n\t\t\ttagCtx = tagCtxs[l];\n\t\t\tnewTagCtx = newCtxs[l];\n\t\t\t$observable(tagCtx.props).setProperty(newTagCtx.props);\n\t\t\t$extend(tagCtx.ctx, newTagCtx.ctx); // We don't support propagating ctx variables, ~foo, observably, to nested views. So extend, not setProperty...\n\t\t\ttagCtx.args = newTagCtx.args;\n\t\t\tif (refresh) {\n\t\t\t\ttagCtx.tmpl = newTagCtx.tmpl;\n\t\t\t}\n\t\t}\n\t}\n\t$sub._thp(tag, tagCtxs[0]); // tagHandlersFromProps\n\treturn tagCtxs;\n}\n\n//=========\n// Disposal\n//=========\n\nfunction clean(elems) {\n\t// Remove data-link bindings, or contained views\n\tvar l, elem, bindings,\n\t\telemArray = [],\n\t\tlen = elems.length,\n\t\ti = len;\n\twhile (i--) {\n\t\t// Copy into an array, so that deletion of nodes from DOM will not cause our 'i' counter to get shifted\n\t\t// (Note: This seems as fast or faster than elemArray = [].slice.call(elems); ...)\n\t\telemArray.push(elems[i]);\n\t}\n\ti = len;\n\twhile (i--) {\n\t\telem = elemArray[i];\n\t\tif (elem.parentNode) {\n\t\t\t// Has not already been removed from the DOM\n\t\t\tif (bindings = elem._jsvBnd) {\n\t\t\t\t// Get propertyChange bindings for this element\n\t\t\t\t// This may be an element with data-link, or the opening script marker node for a data-linked tag {^{...}}\n\t\t\t\t// bindings is a string with the syntax: \"(&bindingId)*\"\n\t\t\t\tbindings = bindings.slice(1).split(\"&\");\n\t\t\t\telem._jsvBnd = \"\";\n\t\t\t\tl = bindings.length;\n\t\t\t\twhile (l--) {\n\t\t\t\t\t// Remove associated bindings\n\t\t\t\t\tremoveViewBinding(bindings[l], elem._jsvLkEl, elem); // unbind bindings with this bindingId on this view\n\t\t\t\t}\n\t\t\t}\n\t\t\tdisposeTokens(markerNodeInfo(elem) + (elem._df || \"\"), elem);\n\t\t}\n\t}\n}\n\nfunction removeViewBinding(bindId, linkedElemTag, elem) {\n\t// Unbind\n\tvar objId, linkCtx, tag, object, obsId, tagCtxs, l, map, linkedElem, trigger, view, tagCtx, linkedElems, allLinkedElems,\n\t\tbinding = bindingStore[bindId];\n\n\tif (linkedElemTag) {\n\t\telem._jsvLkEl = undefined;\n\t} else if (binding && (!elem || elem === binding.elem)) { // Test that elem is actually binding.elem, since cloned elements can have inappropriate markerNode info\n\t\tdelete bindingStore[bindId]; // Delete already, so call to onDispose handler below cannot trigger recursive deletion (through recursive call to jQuery cleanData)\n\t\tfor (objId in binding.bnd) {\n\t\t\tobject = binding.bnd[objId];\n\t\t\tobsId = binding.cbId;\n\t\t\tif ($isArray(object)) {\n\t\t\t\t$([object]).off(arrayChangeStr + obsId).off(propertyChangeStr + obsId); // There may be either or both of arrayChange and propertyChange\n\t\t\t} else {\n\t\t\t\t$(object).off(propertyChangeStr + obsId);\n\t\t\t}\n\t\t\tdelete binding.bnd[objId];\n\t\t}\n\n\t\tif (linkCtx = binding.linkCtx) {\n\t\t\tif (tag = linkCtx.tag) {\n\t\t\t\tif (tagCtxs = tag.tagCtxs) {\n\t\t\t\t\tl = tagCtxs.length;\n\t\t\t\t\twhile (l--) {\n\t\t\t\t\t\ttagCtx = tagCtxs[l];\n\t\t\t\t\t\tif (map = tagCtx.map) {\n\t\t\t\t\t\t\tmap.unmap(); //unobserve\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Copy linkedElems in case tag.linkedElem or tag.linkedElems are undefined in onUnbind\n\t\t\t\t\t\tif (linkedElems = tagCtx.linkedElems) {\n\t\t\t\t\t\t\tallLinkedElems = (allLinkedElems || []).concat(linkedElems);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (tag.onUnbind) {\n\t\t\t\t\ttag.onUnbind(tag.tagCtx, linkCtx, tag.ctx);\n\t\t\t\t}\n\t\t\t\tif (tag.onDispose) {\n\t\t\t\t\ttag.onDispose();\n\t\t\t\t}\n\n\t\t\t\tif (!tag._elCnt) {\n\t\t\t\t\tif (tag._prv) {\n\t\t\t\t\t\ttag._prv.parentNode.removeChild(tag._prv);\n\t\t\t\t\t}\n\t\t\t\t\tif (tag._nxt) {\n\t\t\t\t\t\ttag._nxt.parentNode.removeChild(tag._nxt);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlinkedElems = allLinkedElems || [$(linkCtx.elem)];\n\t\t\tl = linkedElems.length;\n\t\t\twhile (l--) {\n\t\t\t\tlinkedElem = linkedElems[l];\n\t\t\t\tif (trigger = linkedElem && linkedElem[0] && linkedElem[0]._jsvTr) {\n\t\t\t\t\tbindTriggerEvent(linkedElem, trigger, \"off\");\n\t\t\t\t\tlinkedElem[0]._jsvTr = undefined;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tview = linkCtx.view;\n\t\t\tif (view.type === \"link\") {\n\t\t\t\tview.parent.removeViews(view._.key, undefined, true); // A \"link\" view is associated with the binding, so should be disposed with binding.\n\t\t\t} else {\n\t\t\t\tdelete view._.bnds[bindId];\n\t\t\t}\n\t\t}\n\t\tdelete binding.s[binding.cbId];\n\t}\n}\n\nfunction $unlink(to) {\n\tif (to) {\n\t\tto = to.jquery ? to : $(to);\n\t\tto.each(function() {\n\t\t\tvar innerView;\n\t\t\t//TODO fix this for better perf. Rather that calling inner view multiple times which does querySelectorAll each time, consider a single querySelectorAll\n\t\t\t// or simply call view.removeViews() on the top-level views under the target 'to' node, then clean(...)\n\t\t\t// And/or replace each() by for() or while()\n\t\t\twhile ((innerView = $view(this, true)) && innerView.parent) {\n\t\t\t\tinnerView.parent.removeViews(innerView._.key, undefined, true);\n\t\t\t}\n\t\t\tclean(this.getElementsByTagName(\"*\"));\n\t\t});\n\t\tclean(to);\n\t} else {\n\t\t// Call to $.unlink() is equivalent to $.unlink(true, \"body\")\n\t\tif (activeBody) {\n\t\t\t$(activeBody)\n\t\t\t\t.off(elementChangeStr, onElemChange)\n\t\t\t\t.off('blur.jsv', '[contenteditable]', onElemChange);\n\t\t\tactiveBody = undefined;\n\t\t}\n\t\ttopView.removeViews();\n\t\tclean(document.body.getElementsByTagName(\"*\"));\n\t}\n}\n\n//========\n// Helpers\n//========\n\nfunction inputAttrib(elem) {\n\treturn elem.type === CHECKBOX ? elem[CHECKED] : elem.value;\n}\n\nfunction changeHandler(view, name, tag) {\n\t// Get onBeforeChange, onAfterChange, onAfterCreate handler - if there is one;\n\treturn tag && tag[name] || view.ctx[name] && view.ctxPrm(name) || $views.helpers[name];\n}\n\n//========================== Initialize ==========================\n\n//=====================\n// JsRender integration\n//=====================\n\naddLinkMethods($sub.View.prototype); // Modify the View prototype to include link methods\n\n$sub.onStore.template = function(name, item, parentTmpl) {\n\tif (item === null) {\n\t\tdelete $.link[name];\n\t\tdelete $.render[name];\n\t} else {\n\t\titem.link = tmplLink;\n\n\t\tif (name && !parentTmpl && name !== \"jsvTmpl\") {\n\t\t\t$.render[name] = item;\n\t\t\t$.link[name] = function() {\n\t\t\t\treturn tmplLink.apply(item, arguments);\n\t\t\t};\n\t\t}\n\t}\n};\n\n$sub.viewInfos = viewInfos; // Expose viewInfos() as public helper method\n\n// Define JsViews version of delimiters(), and initialize\n($viewsSettings.delimiters = function() {\n\t// Run delimiters initialization in context of jsrender.js\n\tvar ret = oldJsvDelimiters.apply(0, arguments),\n\t\t// Now set also delimOpenChar0 etc. in context of jquery.views.js...\n\t\tdelimChars = $subSettings.delimiters;\n\n\tdelimOpenChar0 = delimChars[0].charAt(0);\n\tdelimOpenChar1 = delimChars[0].charAt(1);\n\tdelimCloseChar0 = delimChars[1].charAt(0);\n\tdelimCloseChar1 = delimChars[1].charAt(1);\n\tlinkChar = delimChars[2];\n\n\t// Data-linking must use new delimiters\n\trTagDatalink = new RegExp(\"(?:^|\\\\s*)([\\\\w-]*)(\\\\\" + linkChar + \")?(\\\\\" + delimOpenChar1 + $sub.rTag + \"(:\\\\w*)?\\\\\" + delimCloseChar0 + \")\", \"g\");\n\treturn ret;\n})(); // jshint ignore:line\n\n$sub.addSetting(\"trigger\");\n\n//====================================\n// Additional members for linked views\n//====================================\n\nfunction transferViewTokens(prevNode, nextNode, parentElem, id, viewOrTagChar, refresh) {\n\t// Transfer tokens on prevNode of viewToRemove/viewToRefresh to nextNode or parentElem._df\n\t// view marker tokens: #m_...VIEW.../m_\n\t// tag marker tokens: #m^...TAG..../m^\n\n\tvar i, l, vwInfos, vwInfo, viewOrTag, viewId, tokens,\n\t\tprecedingLength = 0,\n\t\temptyView = prevNode === nextNode;\n\n\tif (prevNode) {\n\t\t// prevNode is either the first node in the viewOrTag, or has been replaced by the vwInfos tokens string\n\t\tvwInfos = viewInfos(prevNode) || [];\n\t\tfor (i = 0, l = vwInfos.length; i < l; i++) {\n\t\t\t// Step through views or tags on the prevNode\n\t\t\tvwInfo = vwInfos[i];\n\t\t\tviewId = vwInfo.id;\n\t\t\tif (viewId === id && vwInfo.ch === viewOrTagChar) {\n\t\t\t\tif (refresh) {\n\t\t\t\t\t// This is viewOrTagToRefresh, this is the last viewOrTag to process...\n\t\t\t\t\tl = 0;\n\t\t\t\t} else {\n\t\t\t\t\t// This is viewOrTagToRemove, so we are done...\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!emptyView) {\n\t\t\t\tviewOrTag = vwInfo.ch === \"_\"\n\t\t\t\t\t? viewStore[viewId] // A view: \"#m_\" or \"/m_\"\n\t\t\t\t\t: bindingStore[viewId].linkCtx.tag; // A tag \"#m^\" or \"/m^\"\n\t\t\t\tif (viewOrTag) {\n\t\t\t\t\tif (vwInfo.open) { // A \"#m_\" or \"#m^\" token\n\t\t\t\t\t\tviewOrTag._prv = nextNode;\n\t\t\t\t\t} else if (vwInfo.close) { // A \"/m_\" or \"/m^\" token\n\t\t\t\t\t\tviewOrTag._nxt = nextNode;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tprecedingLength += viewId.length + 2;\n\t\t}\n\n\t\tif (precedingLength) {\n\t\t\tprevNode.setAttribute(jsvAttrStr, prevNode.getAttribute(jsvAttrStr).slice(precedingLength));\n\t\t}\n\t\ttokens = nextNode ? nextNode.getAttribute(jsvAttrStr) : parentElem._df;\n\t\tif (l = tokens.indexOf(\"/\" + id + viewOrTagChar) + 1) {\n\t\t\ttokens = vwInfos._tkns.slice(0, precedingLength) + tokens.slice(l + (refresh ? -1 : id.length + 1));\n\t\t}\n\t\tif (tokens) {\n\t\t\tif (nextNode) {\n\t\t\t\t// If viewOrTagToRemove was an empty viewOrTag, we will remove both #n and /n\n\t\t\t\t// (and any intervening tokens) from the nextNode (=== prevNode)\n\t\t\t\t// If viewOrTagToRemove was not empty, we will take tokens preceding #n from prevNode,\n\t\t\t\t// and concatenate with tokens following /n on nextNode\n\t\t\t\tnextNode.setAttribute(jsvAttrStr, tokens);\n\t\t\t} else {\n\t\t\t\tsetDefer(parentElem, tokens);\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// !prevNode, so there may be a deferred nodes token on the parentElem. Remove it.\n\t\tsetDefer(parentElem, removeSubStr(parentElem._df, \"#\" + id + viewOrTagChar));\n\t\tif (!refresh && !nextNode) {\n\t\t\t// If this viewOrTag is being removed, and there was no .nxt, remove closing token from deferred tokens\n\t\t\tsetDefer(parentElem, removeSubStr(parentElem._df, \"/\" + id + viewOrTagChar));\n\t\t}\n\t}\n}\n\nfunction disposeTokens(tokens, elem) {\n\tvar i, l, vwItem, vwInfos;\n\tif (vwInfos = viewInfos(tokens, true, rOpenMarkers)) {\n\t\tfor (i = 0, l = vwInfos.length; i < l; i++) {\n\t\t\tvwItem = vwInfos[i];\n\t\t\tif (vwItem.ch === \"_\") {\n\t\t\t\tif ((vwItem = viewStore[vwItem.id]) && vwItem.type && (!elem || vwItem._prv === elem || vwItem.parentElem === elem )) {\n\t\t\t\t\t// If this is the _prv (prevNode) for a view, remove the view\n\t\t\t\t\t// - unless view.type is undefined, in which case it is already being removed\n\t\t\t\t\t// (or unless the elem is not related - e.g. a cloned element which 'accidentally' picked up the data-jsv atttribute of the ._df expando)\n\t\t\t\t\tvwItem.parent.removeViews(vwItem._.key, undefined, true);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tremoveViewBinding(vwItem.id, undefined, elem); // unbind bindings with this bindingId on this view\n\t\t\t}\n\t\t}\n\t}\n}\n\n//============================================\n// Add link methods to data-linked view or tag\n//============================================\n\nfunction updateValue(val, index, tagElse, async, bindId, ev) {\n// Observably update a data value targeted by the binding.to binding of a 2way data-link binding. Called when elem changes\n// Called when linkedElem of a tag control changes: as updateValue(val, index, tagElse, bindId, ev) - this: undefined\n// Called directly as tag.updateValue(val, index, tagElse) - this: tag\n\tvar self = this,\n\t\tvalues = [];\n\tif (self && self._tgId) {\n\t\tbindId = self;\n\t}\n\tvalues[index||0] = val;\n\tif (async) {\n\t\tsetTimeout(function() {\n\t\t\tupdateValues(values, tagElse, bindId, ev);\n\t\t});\n\t} else {\n\t\tupdateValues(values, tagElse, bindId, ev);\n\t}\n\treturn self;\n}\n\nfunction setValues() {\n// tagCtx.setValues() calls tag.setValue() on that tagCtx for each bindTo target\n\tvar m = arguments.length;\n\twhile (m--) {\n\t\tthis.tag.setValue(arguments[m], m, this.index);\n\t}\n}\n\nfunction addLinkMethods(tagOrView) { // tagOrView is View prototype or tag instance\n\n\tvar l, m, tagCtx, boundProps, bindFrom, key, theTag, theView;\n\n\ttagOrView.contents = function(deep, select) {\n\t\t// For a view, a tag or a tagCtx, return jQuery object with the content nodes,\n\t\tif (deep !== !!deep) {\n\t\t\t// deep not boolean, so this is contents(selector)\n\t\t\tselect = deep;\n\t\t\tdeep = undefined;\n\t\t}\n\t\tvar filtered,\n\t\t\tnodes = $(this.nodes());\n\t\tif (nodes[0]) {\n\t\t\tfiltered = select ? nodes.filter(select) : nodes;\n\t\t\tnodes = deep && select ? filtered.add(nodes.find(select)) : filtered;\n\t\t}\n\t\treturn nodes;\n\t};\n\n\ttagOrView.nodes = function(withMarkers, prevNode, nextNode) {\n\t\t// For a view, a tag or a tagCtx, return top-level nodes\n\t\t// Do not return any script marker nodes, unless withMarkers is true\n\t\t// Optionally limit range, by passing in prevNode or nextNode parameters\n\n\t\tvar node,\n\t\t\tself = this.contentView || this, // If tagCtx, use tagCtx.contentView\n\t\t\telCnt = self._elCnt,\n\t\t\tprevIsFirstNode = !prevNode && elCnt,\n\t\t\tnodes = [];\n\n\t\tif (!self.args) { // If tagCtx with no content (so no contentView) self is tagCtx: return empty [];\n\t\t\tprevNode = prevNode || self._prv;\n\t\t\tnextNode = nextNode || self._nxt;\n\n\t\t\tnode = prevIsFirstNode\n\t\t\t\t? (prevNode === self._nxt\n\t\t\t\t\t? self.parentElem.lastSibling\n\t\t\t\t\t: prevNode)\n\t\t\t\t: (self.inline === false\n\t\t\t\t\t? prevNode || self.linkCtx.elem.firstChild\n\t\t\t\t\t: prevNode && prevNode.nextSibling);\n\n\t\t\twhile (node && (!nextNode || node !== nextNode)) {\n\t\t\t\tif (withMarkers || elCnt || node.tagName !== SCRIPT) {\n\t\t\t\t\t// All the top-level nodes in the view\n\t\t\t\t\t// (except script marker nodes, unless withMarkers = true)\n\t\t\t\t\t// (Note: If a script marker node, viewInfo.elCnt undefined)\n\t\t\t\t\tnodes.push(node);\n\t\t\t\t}\n\t\t\t\tnode = node.nextSibling;\n\t\t\t}\n\t\t}\n\t\treturn nodes;\n\t};\n\n\ttagOrView.childTags = function(deep, tagName) {\n\t\t// For a view, a tag or a tagCtx, return child tags - at any depth, or as immediate children only.\n\t\tif (deep !== !!deep) {\n\t\t\t// deep not boolean, so this is childTags(tagName) - which looks for top-level tags of given tagName\n\t\t\ttagName = deep;\n\t\t\tdeep = undefined;\n\t\t}\n\n\t\tvar self = this.contentView || this, // If tagCtx, use tagCtx.contentView\n\t\t\tview = self.link ? self : self.tagCtx.view, // This may be a view or a tag. If a tag, get the view from tag.tagCtx.view\n\t\t\tprevNode = self._prv,\n\t\t\telCnt = self._elCnt,\n\t\t\ttags = [];\n\n\t\tif (!self.args) { // If tagCtx with no content (so no contentView) self is tagCtx: return empty [];\n\t\t\tview.link(\n\t\t\t\tundefined,\n\t\t\t\tself.parentElem,\n\t\t\t\telCnt ? prevNode && prevNode.previousSibling : prevNode,\n\t\t\t\tself._nxt,\n\t\t\t\tundefined,\n\t\t\t\t{get:{\n\t\t\t\t\ttags: tags,\n\t\t\t\t\tdeep: deep,\n\t\t\t\t\tname: tagName,\n\t\t\t\t\tid: self.link ? self._.id + \"_\" : self._tgId + \"^\"\n\t\t\t\t}}\n\t\t\t);\n\t\t}\n\t\treturn tags;\n\t};\n\n\tif (tagOrView._is === \"tag\") {\n\t\t//=======================\n\t\t// This is a TAG instance\n\t\t//=======================\n\n\t\ttheTag = tagOrView;\n\n\t\tm = theTag.tagCtxs.length;\n\t\twhile (m--) {\n\t\t\ttagCtx = theTag.tagCtxs[m];\n\n\t\t\ttagCtx.setValues = setValues;\n\t\t\ttagCtx.contents = tagOrView.contents;\n\t\t\ttagCtx.childTags = tagOrView.childTags;\n\t\t\ttagCtx.nodes = tagOrView.nodes;\n\t\t}\n\n\t\tboundProps = theTag.boundProps = theTag.boundProps || [];\n\t\tif (bindFrom = theTag.bindFrom) {\n\t\t\tl = bindFrom.length;\n\t\t\twhile (l--) {\n\t\t\t\tkey = bindFrom[l];\n\t\t\t\tif (key + \"\" === key) {\n\t\t\t\t\tbindFrom[key] = 1;\n\t\t\t\t\tif ($inArray(key, boundProps) < 0) {\n\t\t\t\t\t\tboundProps.push(key); // Add any 'bindFrom' props to boundProps array. (So two-way binding works without writing ^foo=expression)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttheTag.setValue = $sub._gm( // getMethod\n\t\t\ttheTag.constructor.prototype.setValue || function(val) { // base method\n\t\t\t\treturn val;\n\t\t\t},\n\t\t\tfunction(val, indexFrom, tagElse) {\n\t\t\t\tindexFrom = indexFrom || 0;\n\t\t\t\ttagElse = tagElse || 0;\n\n\t\t\t\tvar linkedElem, linkedEl, linkedCtxParam, linkedCtxPrmKey, indexTo, linkedElems,\n\t\t\t\t\ttagCtx = theTag.tagCtxs[tagElse],\n\t\t\t\t\tnewVal = theTag.base.call(theTag, val, indexFrom, tagElse);\n\n\t\t\t\tif (newVal !== undefined) { // Call tag method tag.setValue(), if implemented\n\t\t\t\t\tval = newVal;\n\t\t\t\t}\n\t\t\t\tif (val !== undefined && (theTag.convert || theTag._.toIndex[indexFrom] === undefined)\n\t\t\t\t\t\t&& (linkedCtxParam = theTag.linkedCtxParam)\n\t\t\t\t\t\t&& linkedCtxParam[indexFrom]\n\t\t\t\t\t\t// If this setValue call corresponds to a tag contextual parameter and the tag has a converter, then we need to set the\n\t\t\t\t\t\t// value of this contextual parameter (since it is not directly bound to the tag argument/property when there is a converter).\n\t\t\t\t\t\t&& (linkedCtxPrmKey = linkedCtxParam[indexFrom])\n\t\t\t\t\t) {\n\t\t\t\t\ttagCtx.ctxPrm(linkedCtxPrmKey, val);\n\t\t\t\t}\n\t\t\t\tindexTo = theTag._.toIndex[indexFrom];\n\t\t\t\tif (indexTo !== undefined) {\n\t\t\t\t\tif (linkedElems = tagCtx.linkedElems || theTag.linkedElem && [theTag.linkedElem]) {\n\t\t\t\t\t\tif ((linkedElem = linkedElems[indexTo]) && (l = linkedElem.length)) {\n\t\t\t\t\t\t\twhile (l--) {\n\t\t\t\t\t\t\t\tlinkedEl = linkedElem[l];\n\t\t\t\t\t\t\t\tif (val !== undefined && !linkedEl._jsvChg && theTag.linkCtx._val !== val) {\n\t\t\t\t\t\t\t\t\tif (linkedEl.value !== undefined) {\n\t\t\t\t\t\t\t\t\t\tif (linkedEl.type === CHECKBOX) {\n\t\t\t\t\t\t\t\t\t\t\tlinkedEl[CHECKED] = val && val !== \"false\";\n\t\t\t\t\t\t\t\t\t\t} else if (linkedEl.type === RADIO) {\n\t\t\t\t\t\t\t\t\t\t\tlinkedEl[CHECKED] = (linkedEl.value === val);\n\t\t\t\t\t\t\t\t\t\t} else if ($isArray(val)) {\n\t\t\t\t\t\t\t\t\t\t\tlinkedEl.value = val; // Don't use jQuery since it replaces array by mapped clone\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t$(linkedEl).val(val); // Use jQuery for attrHooks - can't just set value (on select, for example)\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tlinkedEl[linkedEl.contentEditable === TRUE ? \"innerHTML\" : TEXTCONTENT] = val;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (tagCtx.props.name) {\n\t\t\t\t\t\t\t\t\tlinkedEl.name = linkedEl.name || tagCtx.props.name;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn theTag;\n\t\t\t}\n\t\t);\n\t\ttheTag.updateValue = updateValue;\n\n\t\ttheTag.updateValues = function() {\n\t\t\treturn updateValues(arguments, undefined, this);\n\t\t};\n\n\t\ttheTag.setValues = function() {\n\t\t// tag.setValues(a, b, c) calls tagCtx.setValues(a, b, c) on the first tagCtx\n\t\t\tsetValues.apply(theTag.tagCtx, arguments);\n\t\t\treturn theTag;\n\t\t};\n\n\t\ttheTag.refresh = function() {\n\t\t\tvar attr, sourceValue,\n\t\t\t\tlinkCtx = theTag.linkCtx,\n\t\t\t\tview = theTag.tagCtx.view;\n\n\t\t\tif (!(sourceValue = mergeCtxs(theTag))) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (theTag.onUnbind) {\n\t\t\t\ttheTag.onUnbind(theTag.tagCtx, linkCtx, theTag.ctx);\n\t\t\t\ttheTag._.unlinked = true;\n\t\t\t}\n\t\t\tattr = theTag.inline ? HTML : (linkCtx.attr || defaultAttr(theTag.parentElem, true));\n\t\t\tsourceValue = theTag.tagName === \":\"\n\t\t\t\t? $sub._cnvt(theTag.convert, view, theTag.tagCtx)\n\t\t\t\t: $sub._tag(theTag, view, view.tmpl, sourceValue, true); // Get rendered HTML for tag, based on refreshed tagCtxs\n\n\t\t\tobserveAndBind(linkCtx, linkCtx.data, linkCtx.elem);\n\t\t\tupdateContent(sourceValue, linkCtx, attr, theTag);\n\t\t\tcallAfterLink(theTag);\n\t\t\treturn theTag;\n\t\t};\n\n\t\ttheTag.domChange = function() { // domChange notification support\n\t\t\tvar elem = this.parentElem,\n\t\t\t\thasListener = $._data(elem).events,\n\t\t\t\tdomChangeNotification = \"jsv-domchange\";\n\n\t\t\tif (hasListener && hasListener[domChangeNotification]) {\n\t\t\t\t// Only trigger handler if there is a handler listening for this event. (Note using triggerHandler - so no event bubbling.)\n\t\t\t\t$(elem).triggerHandler(domChangeNotification, arguments);\n\t\t\t}\n\t\t};\n\n\t\t//====================================\n\t\t// End of added link methods for TAG\n\t\t//====================================\n\t} else {\n\t\t//=========================\n\t\t// This is a VIEW prototype\n\t\t//=========================\n\n\t\ttheView = tagOrView;\n\n\t\t// Note: a linked view will also, after linking have nodes[], _prv (prevNode), _nxt (nextNode) ...\n\t\ttheView.addViews = function(index, dataItems) {\n\t\t\t// if view is not an array view, do nothing\n\t\t\tvar i, viewsCount,\n\t\t\t\tview = this,\n\t\t\t\titemsCount = dataItems.length,\n\t\t\t\tviews = view.views;\n\n\t\t\tif (!view._.useKey && itemsCount) {\n\t\t\t\t// view is of type \"array\"\n\t\t\t\tviewsCount = views.length + itemsCount;\n\n\t\t\t\tif (viewsCount === view.data.length // If views not already synced to array (e.g. triggered by array.length propertyChange - jsviews/issues/301)\n\t\t\t\t\t\t&& renderAndLink(view, index, view.tmpl, views, dataItems, view.ctx) !== false) {\n\t\t\t\t\tif (!view._.srt) { // Not part of a 'sort' on refresh\n\t\t\t\t\t\tview.fixIndex(index + itemsCount);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\ttheView.removeViews = function(index, itemsCount, keepNodes, isMove) {\n\t\t\t// view.removeViews() removes all the child views\n\t\t\t// view.removeViews(index) removes the child view with specified index or key\n\t\t\t// view.removeViews(index, count) removes the specified nummber of child views, starting with the specified index\n\t\t\tfunction removeView(index) {\n\t\t\t\tvar id, bindId, parentElem, prevNode, nextNode, nodesToRemove,\n\t\t\t\t\tviewToRemove = views[index];\n\n\t\t\t\tif (viewToRemove && viewToRemove.link) {\n\t\t\t\t\tid = viewToRemove._.id;\n\t\t\t\t\tif (!keepNodes) {\n\t\t\t\t\t\t// Remove the HTML nodes from the DOM, unless they have already been removed, including nodes of child views\n\t\t\t\t\t\tnodesToRemove = viewToRemove.nodes();\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove child views, without removing nodes\n\t\t\t\t\tviewToRemove.removeViews(undefined, undefined, true);\n\n\t\t\t\t\tviewToRemove.type = undefined; // Set type to undefined: used as a flag that this view is being removed\n\t\t\t\t\tprevNode = viewToRemove._prv;\n\t\t\t\t\tnextNode = viewToRemove._nxt;\n\t\t\t\t\tparentElem = viewToRemove.parentElem;\n\t\t\t\t\t// If prevNode and nextNode are the same, the view is empty\n\t\t\t\t\tif (!keepNodes) {\n\t\t\t\t\t\t// Remove the HTML nodes from the DOM, unless they have already been removed, including nodes of child views\n\t\t\t\t\t\tif (viewToRemove._elCnt) {\n\t\t\t\t\t\t\t// if keepNodes is false (and transferring of tokens has not already been done at a higher level)\n\t\t\t\t\t\t\t// then transfer tokens from prevNode which is being removed, to nextNode.\n\t\t\t\t\t\t\ttransferViewTokens(prevNode, nextNode, parentElem, id, \"_\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$(nodesToRemove).remove();\n\t\t\t\t\t}\n\t\t\t\t\tif (!viewToRemove._elCnt) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tprevNode.parentNode.removeChild(prevNode); // (prevNode.parentNode is parentElem, except if jQuery Mobile or similar has inserted an intermediate wrapper\n\t\t\t\t\t\t\tnextNode.parentNode.removeChild(nextNode);\n\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t}\n\t\t\t\t\tsetArrayChangeLink(viewToRemove);\n\t\t\t\t\tfor (bindId in viewToRemove._.bnds) {\n\t\t\t\t\t\tremoveViewBinding(bindId);\n\t\t\t\t\t}\n\t\t\t\t\tdelete viewStore[id];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar current, childView, viewsCount,\n\t\t\t\tview = this,\n\t\t\t\tisArray = !view._.useKey,\n\t\t\t\tviews = view.views;\n\n\t\t\tif (isArray) {\n\t\t\t\tviewsCount = views.length;\n\t\t\t}\n\t\t\tif (index === undefined) {\n\t\t\t\t// Remove all child views\n\t\t\t\tif (isArray) {\n\t\t\t\t\t// views and data are arrays\n\t\t\t\t\tcurrent = viewsCount;\n\t\t\t\t\twhile (current--) {\n\t\t\t\t\t\tremoveView(current);\n\t\t\t\t\t}\n\t\t\t\t\tview.views = [];\n\t\t\t\t} else {\n\t\t\t\t\t// views and data are objects\n\t\t\t\t\tfor (childView in views) {\n\t\t\t\t\t\t// Remove by key\n\t\t\t\t\t\tremoveView(childView);\n\t\t\t\t\t}\n\t\t\t\t\tview.views = {};\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (itemsCount === undefined) {\n\t\t\t\t\tif (isArray) {\n\t\t\t\t\t\t// The parentView is data array view.\n\t\t\t\t\t\t// Set itemsCount to 1, to remove this item\n\t\t\t\t\t\titemsCount = 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Remove child view with key 'index'\n\t\t\t\t\t\tremoveView(index);\n\t\t\t\t\t\tdelete views[index];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (isArray && itemsCount\n\t\t\t\t\t&& (isMove || viewsCount - itemsCount === view.data.length)) { // If views not already synced to array (e.g. triggered by array.length propertyChange - jsviews/issues/301)\n\t\t\t\t\tcurrent = index + itemsCount;\n\t\t\t\t\t// Remove indexed items (parentView is data array view);\n\t\t\t\t\twhile (current-- > index) {\n\t\t\t\t\t\tremoveView(current);\n\t\t\t\t\t}\n\t\t\t\t\tviews.splice(index, itemsCount);\n\t\t\t\t\tif (!view._.srt) {\n\t\t\t\t\t\tview.fixIndex(index);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\ttheView.moveViews = function(oldIndex, index, itemsCount) {\n\t\t\tfunction parts(itemView, str) { // Get the totkens preceding the 'open' token for this view, #n_, and the tokens following (and including) the 'open' token\n\t\t\t\treturn RegExp(\"^(.*)(\" + (str ? \"\\\\/\" : \"#\") + itemView._.id + \"_.*)$\").exec(str || itemView._prv.getAttribute(jsvAttrStr));\n\t\t\t}\n\t\t\tfunction setPrv(itemView, tokens) {\n\t\t\t\tvar prv = itemView._prv;\n\t\t\t\tprv.setAttribute(jsvAttrStr, tokens);\n\t\t\t\ttokens.replace(rTagMarkers, function(all, open, close, id) {\n\t\t\t\t\tbindingStore[id].linkCtx.tag[open ? \"_prv\" : \"_nxt\"] = prv;\n\t\t\t\t});\n\t\t\t\ttokens.replace(rViewMarkers, function(all, open, close, id) {\n\t\t\t\t\tviewStore[id][open ? \"_prv\" : \"_nxt\"] = prv;\n\t\t\t\t});\n\t\t\t}\n\t\t\tvar nodes, childView, nxtView, insertBefore, viewId,\n\t\t\t\tview = this,\n\t\t\t\tselfNxt = view._nxt,\n\t\t\t\tviews = view.views,\n\t\t\t\tbackwards = index < oldIndex,\n\t\t\t\tfirstChange = backwards ? index : oldIndex,\n\t\t\t\tlastChange = backwards ? oldIndex : index,\n\t\t\t\ti = index,\n\t\t\t\tmovedNodes = [],\n\n\t\t\t\tviewsToMove = views.splice(oldIndex, itemsCount); // remove\n\n\t\t\tif (index > views.length) {\n\t\t\t\tindex = views.length;\n\t\t\t}\n\t\t\tviews.splice.apply(views, [index, 0].concat(viewsToMove)); //re-insert\n\n\t\t\titemsCount = viewsToMove.length;\n\t\t\tinsertBefore = index + itemsCount;\n\t\t\tlastChange += itemsCount;\n\n\t\t\tfor (i; i < insertBefore; i++) {\n\t\t\t\tchildView = views[i];\n\t\t\t\tnodes = childView.nodes(true);\n\t\t\t\tmovedNodes = view._elCnt ? movedNodes.concat(nodes) : movedNodes.concat(childView._prv, nodes, childView._nxt);\n\t\t\t}\n\t\t\tmovedNodes = $(movedNodes);\n\n\t\t\tif (insertBefore < views.length) {\n\t\t\t\tmovedNodes.insertBefore(views[insertBefore]._prv);\n\t\t\t} else if (selfNxt) {\n\t\t\t\tmovedNodes.insertBefore(selfNxt);\n\t\t\t} else {\n\t\t\t\tmovedNodes.appendTo(view.parentElem);\n\t\t\t}\n\n\t\t\tif (view._elCnt) {\n\t\t\t\tvar afterParts,\n\t\t\t\t\tendChange = backwards ? firstChange + itemsCount : lastChange - itemsCount,\n\t\t\t\t\tbeforeView = views[firstChange-1],\n\t\t\t\t\tstartView = views[firstChange],\n\t\t\t\t\tendView = views[endChange],\n\t\t\t\t\tafterView = views[lastChange],\n\t\t\t\t\tstartParts = parts(startView),\n\t\t\t\t\tendParts = parts(endView);\n\n\t\t\t\tsetPrv(startView, endParts[1] + startParts[2]);\n\t\t\t\tif (afterView) {\n\t\t\t\t\tafterParts = parts(afterView);\n\t\t\t\t\tsetPrv(afterView, startParts[1] + afterParts[2]);\n\t\t\t\t} else {\n\t\t\t\t\tviews[lastChange-1]._nxt = selfNxt;\n\t\t\t\t\tif (selfNxt) {\n\t\t\t\t\t\tafterParts = parts(view, selfNxt.getAttribute(jsvAttrStr));\n\t\t\t\t\t\tselfNxt.setAttribute(jsvAttrStr, startParts[1] + afterParts[2]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tafterParts = parts(view, view.parentElem._df);\n\n\t\t\t\t\t\tsetDefer(view.parentElem, startParts[1] + afterParts[2]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsetPrv(endView, afterParts[1] + endParts[2]);\n\t\t\t}\n\t\t\tview.fixIndex(firstChange);\n\t\t};\n\n\t\ttheView.refresh = function() {\n\t\t\tvar view = this,\n\t\t\t\tparent = view.parent;\n\n\t\t\tif (parent) {\n\t\t\t\trenderAndLink(view, view.index, view.tmpl, parent.views, view.data, undefined, true);\n\t\t\t\tsetArrayChangeLink(view);\n\t\t\t}\n\t\t};\n\n\t\ttheView.fixIndex = function(fromIndex) {\n\t\t\t// Fixup index on following view items...\n\t\t\tvar views = this.views,\n\t\t\t\tindex = views.length;\n\t\t\twhile (fromIndex < index--) {\n\t\t\t\tif (views[index].index !== index) {\n\t\t\t\t\t$observable(views[index]).setProperty(\"index\", index);\n\t\t\t\t\t// This is fixing up index, but not key, and not index on child views. From child views, use view.getIndex()\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\ttheView.link = viewLink;\n\n\t\t//====================================\n\t\t// End of added link methods for VIEW\n\t\t//====================================\n\t}\n}\n\n//========================\n// JsViews-specific converters\n//========================\n\n$converters.merge = function(val) {\n\t// Special converter used in data-linking to space-separated lists, such as className:\n\t// Currently only supports toggle semantics - and has no effect if toggle string is not specified\n\t// data-link=\"class{merge:boolExpr toggle=className}\"\n\tvar regularExpression,\n\t\tcurrentValue = this.linkCtx.elem.className,\n\t\ttoggle = this.tagCtx.props.toggle;\n\n\tif (toggle) {\n\t\t// We are toggling the class specified by the toggle property,\n\t\t// and the boolean val binding is driving the insert/remove toggle\n\n\t\tregularExpression = toggle.replace(/[\\\\^$.|?*+()[{]/g, \"\\\\$&\");\n\t\t// Escape any regular expression special characters (metacharacters) within the toggle string\n\t\tregularExpression = \"(\\\\s(?=\" + regularExpression + \"$)|(\\\\s)|^)(\" + regularExpression + \"(\\\\s|$))\";\n\t\t// Example: /(\\s(?=myclass$)|(\\s)|^)?(myclass(\\s|$))/ - so matches (\" myclass\" or \" \" or ^ ) followed by (\"myclass \" or \"myclass$\") where ^/$ are beginning/end of string\n\t\tcurrentValue = currentValue.replace(new RegExp(regularExpression), \"$2\");\n\t\tval = currentValue + (val ? (currentValue && \" \") + toggle : \"\");\n\t}\n\treturn val;\n};\n\n//========================\n// JsViews-specific tags\n//========================\n\n$tags({\n\ton: {\n\t\tattr: NONE,\n\t\tbindTo: [], // Don't need to bind to first arg, so prevent the default [0] binding\n\t\tinit: function(tagCtx) {\n\t\t\tvar content,\n\t\t\t\ttag = this,\n\t\t\t\ti = 0,\n\t\t\t\targs = tagCtx.args, // [events,] [selector,] handler\n\t\t\t\tl = args.length;\n\n\t\t\tfor (; ii && i+1; // handler index\n\t\t\tif (tag.inline) {\n\t\t\t\tif (!$sub.rTmpl.exec(content = $.trim(tagCtx.tmpl.markup))) {\n\t\t\t\t\t// Inline {^{on}} tag with no content (or external template content) or with content containing\n\t\t\t\t\t// no HTML or JsRender tags: We will wrap the (text) content, or the operation name in a \";\n\t\t\t\t}\n\t\t\t\ttag.attr = HTML;\n\t\t\t}\n\t\t},\n\t\tonBind: function() {\n\t\t\tif (this.template) { // {^{on/}} with no content has template rendering
\", \"
\"],\n\t\ttr: [2, \"\", \"
\"],\n\t\ttd: [3, \"\", \"
\"],\n\t\tcol: [2, \"\", \"
\"],\n\t\tsvg_ns: [1, \"\", \"\"],\n\t\t// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,\n\t\t// unless wrapped in a div with non-breaking characters in front of it.\n\t\tdiv: $.support.htmlSerialize ? [0, \"\", \"\"] : [1, \"X
\", \"
\"]\n\t},\n\t_fe: {\n\t\tinput: {\n\t\t\tfrom: inputAttrib, to: VALUE\n\t\t},\n\t\ttextarea: valueBinding,\n\t\tselect: valueBinding,\n\t\toptgroup: {\n\t\t\tto: \"label\"\n\t\t}\n\t}\n});\n\n\treturn $;\n}, window));\n"]} \ No newline at end of file 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 ',Bn='',Hn='',\n\topenScript = ' - data-linked tag, close marker\n\t\t\t// We validate with inTag so no script markers are inserted in attribute context e.g. for:\n\t\t\t// \"\" or \"
...{{/if}}...\"\n\t\t\tpreceding = id\n\t\t\t\t? (preceding + endOfElCnt + spaceBefore + (inTag ? \"\" : openScript + id + closeScript)+ spaceAfter + tag)\n\t\t\t\t: endOfElCnt || all;\n\t\t}\n\n\t\tif (validate && boundId) {\n\t\t\tif (inTag) {\n\t\t\t\t// JsViews data-linking tags are not allowed within element markup.\n\t\t\t\t// See jsviews/issues/303\n\t\t\t\tsyntaxError('{^{ within elem markup (' + inTag + ' ). Use data-link=\"...\"');\n\t\t\t}\n\t\t\tif (id.charAt(0) === \"#\") {\n\t\t\t\ttagStack.unshift(id.slice(1));\n\t\t\t} else if (id.slice(1) !== (bndId = tagStack.shift())) {\n\t\t\t\t// See jsviews/issues/213\n\t\t\t\tsyntaxError('Closing tag for {^{...}} under different elem: <' + bndId + '>');\n\t\t\t}\n\t\t}\n\t\tif (tag) {\n\t\t\tinTag = tag;\n\t\t\t// If there are ids (markers since the last tag), move them to the defer string\n\t\t\ttagStack.unshift(parentTag);\n\t\t\tparentTag = tag.slice(1);\n\t\t\tif (validate && tagStack[0] && tagStack[0] === badParent[parentTag]) {\n\t\t\t\t// Missing \n\t\t\t\t// TODO: replace this by smart insertion of tags\n\t\t\t\terror('Parent of must be ');\n\t\t\t}\n\t\t\tisVoid = voidElems[parentTag];\n\t\t\tif ((elCnt = elContent[parentTag]) && !prevElCnt) {\n\t\t\t\tdeferStack.unshift(defer);\n\t\t\t\tdefer = \"\";\n\t\t\t}\n\t\t\tprevElCnt = elCnt;\n//TODO Consider providing validation which throws if you place as child of , etc. - since if not caught,\n//this can cause errors subsequently which are difficult to debug.\n//\t\t\t\tif (elContent[tagStack[0]]>2 && !elCnt) {\n//\t\t\t\t\terror(parentTag + \" in \" + tagStack[0]);\n//\t\t\t\t}\n\t\t\tif (defer && elCnt) {\n\t\t\t\tdefer += \"+\"; // Will be used for stepping back through deferred tokens\n\t\t\t}\n\t\t}\n\t\treturn preceding;\n\t}\n\n\tfunction processViewInfos(vwInfos, targetParent) {\n\t\t// If targetParent, we are processing viewInfos (which may include navigation through '+-' paths) and hooking up to the right parentElem etc.\n\t\t// (and elem may also be defined - the next node)\n\t\t// If no targetParent, then we are processing viewInfos on newly inserted content\n\t\tvar deferPath, deferChar, bindChar, parentElem, id, onAftCr, deep,\n\t\t\taddedBindEls = [];\n\n\t\t// In elCnt context (element-only content model), prevNode is the first node after the open, nextNode is the first node after the close.\n\t\t// If both are null/undefined, then open and close are at end of parent content, so the view is empty, and its placeholder is the\n\t\t// 'lastChild' of the parentNode. If there is a prevNode, then it is either the first node in the view, or the view is empty and\n\t\t// its placeholder is the 'previousSibling' of the prevNode, which is also the nextNode.\n\t\tif (vwInfos) {\n\t\t\tif (vwInfos._tkns.charAt(0) === \"@\") {\n\t\t\t\t// We are processing newly inserted content. This is a special script element that was created in convertMarkers() to process deferred bindings,\n\t\t\t\t// and inserted following the target parent element - because no element tags (outside elCnt) were encountered to carry those binding tokens.\n\t\t\t\t// We will step back from the preceding sibling of this element, looking at targetParent elements until we find the one that the current binding\n\t\t\t\t// token belongs to. Set elem to null (the special script element), and remove it from the DOM.\n\t\t\t\ttargetParent = elem.previousSibling;\n\t\t\t\telem.parentNode.removeChild(elem);\n\t\t\t\telem = undefined;\n\t\t\t}\n\t\t\tlen = vwInfos.length;\n\t\t\twhile (len--) {\n\t\t\t\tvwInfo = vwInfos[len];\n//if (prevIds.indexOf(vwInfo.token) < 0) { // This token is a newly created view or tag binding\n\t\t\t\tbindChar = vwInfo.ch;\n\t\t\t\tif (deferPath = vwInfo.path) {\n\t\t\t\t\t// We have a 'deferred path'\n\t\t\t\t\tj = deferPath.length - 1;\n\t\t\t\t\twhile (deferChar = deferPath.charAt(j--)) {\n\t\t\t\t\t\t// Use the \"+\" and\"-\" characters to navigate the path back to the original parent node where the deferred bindings ocurred\n\t\t\t\t\t\tif (deferChar === \"+\") {\n\t\t\t\t\t\t\tif (deferPath.charAt(j) === \"-\") {\n\t\t\t\t\t\t\t\tj--;\n\t\t\t\t\t\t\t\ttargetParent = targetParent.previousSibling;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttargetParent = targetParent.parentNode;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttargetParent = targetParent.lastChild;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Note: Can use previousSibling and lastChild, not previousElementSibling and lastElementChild,\n\t\t\t\t\t\t// since we have removed white space within elCnt. Hence support IE < 9\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (bindChar === \"^\") {\n\t\t\t\t\tif (tag = bindingStore[id = vwInfo.id]) {\n\t\t\t\t\t\t// The binding may have been deleted, for example in a different handler to an array collectionChange event\n\t\t\t\t\t\t// This is a tag binding\n\t\t\t\t\t\tdeep = targetParent && (!elem || elem.parentNode !== targetParent); // We are stepping back looking for the right targetParent,\n\t\t\t\t\t\t// or we are linking existing content and this element is in elCnt, not an immediate child of the targetParent.\n\t\t\t\t\t\tif (!elem || deep) {\n\t\t\t\t\t\t\ttag.parentElem = targetParent;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (vwInfo.elCnt && deep) {\n\t\t\t\t\t\t\t// With element only content, if there is no following element, or if the binding is deeper than the following element\n\t\t\t\t\t\t\t// then we need to set the open or close token as a deferred binding annotation on the parent\n\t\t\t\t\t\t\tsetDefer(targetParent, (vwInfo.open ? \"#\" : \"/\") + id + bindChar + (targetParent._df || \"\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// This is an open or close marker for a data-linked tag {^{...}}. Add it to bindEls.\n\t\t\t\t\t\taddedBindEls.push([deep ? null : elem, vwInfo]);\n\t\t\t\t\t}\n\t\t\t\t} else if (view = viewStore[id = vwInfo.id]) {\n\t\t\t\t\t// The view may have been deleted, for example in a different handler to an array collectionChange event\n\t\t\t\t\tif (!view.parentElem) {\n\t\t\t\t\t\t// If view is not already extended for JsViews, extend and initialize the view object created in JsRender, as a JsViews view\n\t\t\t\t\t\tview.parentElem = targetParent || elem && elem.parentNode || parentNode;\n\t\t\t\t\t\tview._.onRender = addBindingMarkers;\n\t\t\t\t\t\tview._.onArrayChange = arrayChangeHandler;\n\t\t\t\t\t\tsetArrayChangeLink(view);\n\t\t\t\t\t}\n\t\t\t\t\tparentElem = view.parentElem;\n\t\t\t\t\tif (vwInfo.open) {\n\t\t\t\t\t\t// This is an 'open view' node (preceding script marker node,\n\t\t\t\t\t\t// or if elCnt, the first element in the view, with a data-jsv annotation) for binding\n\t\t\t\t\t\tview._elCnt = vwInfo.elCnt;\n\t\t\t\t\t\tif (targetParent && !elem) {\n\t\t\t\t\t\t\tsetDefer(targetParent, \"#\" + id + bindChar + (targetParent._df || \"\"));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// No targetParent, so there is a ._nxt elem (and this is processing tokens on the elem)\n\t\t\t\t\t\t\tif (!view._prv) {\n\t\t\t\t\t\t\t\tsetDefer(parentElem, removeSubStr(parentElem._df, \"#\" + id + bindChar));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tview._prv = elem;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// This is a 'close view' marker node for binding\n\t\t\t\t\t\tif (targetParent && (!elem || elem.parentNode !== targetParent)) {\n\t\t\t\t\t\t\t// There is no ._nxt so add token to _df. It is deferred.\n\t\t\t\t\t\t\tsetDefer(targetParent, \"/\" + id + bindChar + (targetParent._df || \"\"));\n\t\t\t\t\t\t\tview._nxt = undefined;\n\t\t\t\t\t\t} else if (elem) {\n\t\t\t\t\t\t\t// This view did not have a ._nxt, but has one now, so token may be in _df, and must be removed. (No longer deferred)\n\t\t\t\t\t\t\tif (!view._nxt) {\n\t\t\t\t\t\t\t\tsetDefer(parentElem, removeSubStr(parentElem._df, \"/\" + id + bindChar));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tview._nxt = elem;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (onAftCr = view.ctx && view.ctx[onAfterCreateStr] || onAfterCreate) {\n\t\t\t\t\t\t\tonAftCr.call(view.ctx.tag, view);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n//}\n\t\t\t\t}\n\t\t\t}\n\t\t\tlen = addedBindEls.length;\n\t\t\twhile (len--) {\n\t\t\t\t// These were added in reverse order to addedBindEls. We push them in BindEls in the correct order.\n\t\t\t\tbindEls.push(addedBindEls[len]);\n\t\t\t}\n\t\t}\n\t\treturn !vwInfos || vwInfos.elCnt;\n\t}\n\n\tfunction getViewInfos(vwInfos) {\n\t\t// Used by view.childTags() and tag.childTags()\n\t\t// Similar to processViewInfos in how it steps through bindings to find tags. Only finds data-linked tags.\n\t\tvar level, parentTag, named;\n\n\t\tif (vwInfos) {\n\t\t\tlen = vwInfos.length;\n\t\t\tfor (j = 0; j < len; j++) {\n\t\t\t\tvwInfo = vwInfos[j];\n\t\t\t\t// This is an open marker for a data-linked tag {^{...}}, within the content of the tag whose id is get.id. Add it to bindEls.\n\t\t\t\t// Note - if bindingStore[vwInfo.id]._is === \"tag\" then getViewInfos is being called too soon - during first linking pass\n\t\t\t\ttag = bindingStore[vwInfo.id];\n\t\t\t\tif (!tag._is && tag.linkCtx) {\n\t\t\t\t\tparentTag = tag = tag.linkCtx.tag;\n\t\t\t\t\tnamed = tag.tagName === tagName;\n\t\t\t\t\tif (!tag.flow || named) {\n\t\t\t\t\t\tif (!deep) {\n\t\t\t\t\t\t\tlevel = 1;\n\t\t\t\t\t\t\twhile (parentTag = parentTag.parent) {\n\t\t\t\t\t\t\t\tlevel++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttagDepth = tagDepth || level; // The level of the first tag encountered.\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ((deep || level === tagDepth) && (!tagName || named)) {\n\t\t\t\t\t\t\t// Filter on top-level or tagName as appropriate\n\t\t\t\t\t\t\ttags.push(tag);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction dataLink() {\n\t\t//================ Data-link and fixup of data-jsv annotations ================\n\t\tvar j, index,\n\t\t\ttokens = \"\",\n\t\t\twrap = {},\n\t\t\tselector = linkViewsSel + (get ? \",[\" + deferAttr + \"]\" : \"\");\n\t\t\t// If a childTags() call, get = \",[\" + deferAttr + \"]\" - since we need to include elements that have a ._df expando for deferred tokens\n\n\t\telems = qsa ? parentNode.querySelectorAll(selector) : $(selector, parentNode).get();\n\t\tl = elems.length;\n\n\t\t// The prevNode will be in the returned query, since we called markPrevOrNextNode() on it.\n\t\t// But it may have contained nodes that satisfy the selector also.\n\t\tif (prevNode && prevNode.innerHTML) {\n\t\t\t// Find the last contained node of prevNode, to use as the prevNode - so we only link subsequent elems in the query\n\t\t\tprevNodes = qsa ? prevNode.querySelectorAll(selector) : $(selector, prevNode).get();\n\t\t\tprevNode = prevNodes.length ? prevNodes[prevNodes.length - 1] : prevNode;\n\t\t}\n\n\t\ttagDepth = 0;\n\t\tfor (i = 0; i < l; i++) {\n\t\t\telem = elems[i];\n\t\t\tif (prevNode && !found) {\n\t\t\t\t// If prevNode is set, not false, skip linking. If this element is the prevNode, set to false so subsequent elements will link.\n\t\t\t\tfound = (elem === prevNode);\n\t\t\t} else if (nextNode && elem === nextNode) {\n\t\t\t\t// If nextNode is set then break when we get to nextNode\n\t\t\t\tif (get) {\n\t\t\t\t\ttokens += markerNodeInfo(elem);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t} else if (elem.parentNode) {\n\t\t\t\t// elem has not been removed from DOM\n\t\t\t\tif (get) {\n\t\t\t\t\ttokens += markerNodeInfo(elem);\n\t\t\t\t\tif (elem._df) {\n\t\t\t\t\t\tj = i + 1;\n\t\t\t\t\t\twhile (j < l && elem.contains(elems[j])) {\n\t\t\t\t\t\t\tj++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Add deferred tokens after any tokens on descendant elements of this one\n\t\t\t\t\t\twrap[j-1] = elem._df;\n\t\t\t\t\t}\n\t\t\t\t\tif (wrap[i]) {\n\t\t\t\t\t\ttokens += wrap[i] || \"\";\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (isLink && (vwInfo = viewInfos(elem, undefined, rViewMarkers)) && (vwInfo = vwInfo[0])) {\n\t\t\t\t\t\t// If this is a link(trueOrString ...) call we will avoid re-binding to elems that are within template-rendered views\n\t\t\t\t\t\tskip = skip ? (vwInfo.id !== skip && skip) : vwInfo.open && vwInfo.id;\n\t\t\t\t\t}\n\t\t\t\t\tif (!skip && processInfos(viewInfos(elem))\n\t\t\t\t\t\t// If a link() call, processViewInfos() adds bindings to bindEls, and returns true for non-script nodes, for adding data-link bindings\n\t\t\t\t\t\t// If a childTags() call, getViewInfos returns array of tag bindings.\n\t\t\t\t\t\t\t&& elem.getAttribute($viewsLinkAttr)) {\n\t\t\t\t\t\tbindEls.push([elem]); // A data-linked element so add to bindEls too\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (get) {\n\t\t\ttokens += parentNode._df || \"\";\n\t\t\tif (index = tokens.indexOf(\"#\" + get.id) + 1) {\n\t\t\t\t// We are looking for view.childTags() or tag.childTags() - so start after the open token of the parent view or tag.\n\t\t\t\ttokens = tokens.slice(index + get.id.length);\n\t\t\t}\n\t\t\tindex = tokens.indexOf(\"/\" + get.id);\n\t\t\tif (index + 1) {\n\t\t\t\t// We are looking for view.childTags() or tag.childTags() - so don't look beyond the close token of the parent view or tag.\n\t\t\t\ttokens = tokens.slice(0, index);\n\t\t\t}\n\t\t\t// Call getViewInfos to add the found childTags to the tags array\n\t\t\tgetViewInfos(viewInfos(tokens, undefined, rOpenTagMarkers));\n\t\t}\n\n\t\tif (html === undefined && parentNode.getAttribute($viewsLinkAttr)) {\n\t\t\tbindEls.push([parentNode]); // Support data-linking top-level element directly (not within a data-linked container)\n\t\t}\n\n\t\t// Remove temporary marker script nodes they were added by markPrevOrNextNode\n\t\tunmarkPrevOrNextNode(prevNode, elCnt);\n\t\tunmarkPrevOrNextNode(nextNode, elCnt);\n\n\t\tif (get) {\n\t\t\treturn; // We have added childTags to the tags array, so we are done\n\t\t}\n\n\t\tif (elCnt && defer + ids) {\n\t\t\t// There are some views with elCnt, for which the open or close did not precede any HTML tag - so they have not been processed yet\n\t\t\telem = nextNode;\n\t\t\tif (defer) {\n\t\t\t\tif (nextNode) {\n\t\t\t\t\tprocessViewInfos(viewInfos(defer + \"+\", true), nextNode);\n\t\t\t\t} else {\n\t\t\t\t\tprocessViewInfos(viewInfos(defer, true), parentNode);\n\t\t\t\t}\n\t\t\t}\n\t\t\tprocessViewInfos(viewInfos(ids, true), parentNode);\n\t\t\t// If there were any tokens on nextNode which have now been associated with inserted HTML tags, remove them from nextNode\n\t\t\tif (nextNode) {\n\t\t\t\ttokens = nextNode.getAttribute(jsvAttrStr);\n\t\t\t\tif (l = tokens.indexOf(prevIds) + 1) {\n\t\t\t\t\ttokens = tokens.slice(l + prevIds.length - 1);\n\t\t\t\t}\n\t\t\t\tnextNode.setAttribute(jsvAttrStr, ids + tokens);\n\t\t\t}\n\t\t}\n\n// if (context.lazyLink) {\n// setTimeout(doLinking) (doLinking is function wrapper of following lines)\n// See Future tasks, and https://github.com/BorisMoore/jsviews/issues/368.\n// Could call context.lazyLink as callback, on async completion - or return promise.\n\t\t//================ Bind the data-linked elements and tags ================\n\t\tl = bindEls.length;\n\t\tfor (i = 0; i < l; i++) {\n\t\t\telem = bindEls[i];\n\t\t\tlinkInfo = elem[1];\n\t\t\telem = elem[0];\n\t\t\tif (linkInfo) {\n\t\t\t\tif (tag = bindingStore[linkInfo.id]) {\n\t\t\t\t\tif (linkCtx = tag.linkCtx) {\n\t\t\t\t\t\t// The tag may have been stored temporarily on the bindingStore - or may have already been replaced by the actual binding\n\t\t\t\t\t\ttag = linkCtx.tag;\n\t\t\t\t\t\ttag.linkCtx = linkCtx;\n\t\t\t\t\t}\n\t\t\t\t\tif (linkInfo.open) {\n\t\t\t\t\t\t// This is an 'open linked tag' binding annotation for a data-linked tag {^{...}}\n\t\t\t\t\t\tif (elem) {\n\t\t\t\t\t\t\ttag.parentElem = elem.parentNode;\n\t\t\t\t\t\t\ttag._prv = elem;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttag._elCnt = linkInfo.elCnt;\n\t\t\t\t\t\t// We data-link depth-first (\"on the way in\"), which is better for perf - and allows setting parent tags etc.\n\t\t\t\t\t\tview = tag.tagCtx.view;\n\n\t\t\t\t\t\t// Add data binding (unless skipped due to lateRender)\n\t\t\t\t\t\taddDataBinding(late, undefined, tag._prv, view, linkInfo.id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttag._nxt = elem;\n\t\t\t\t\t\tif (tag._.unlinked && !tag._toLk) {\n\t\t\t\t\t\t\t// This is a 'close linked tag' binding annotation (and data-binding was not skipped due to lateRender)\n\t\t\t\t\t\t\ttagCtx = tag.tagCtx;\n\t\t\t\t\t\t\tview = tagCtx.view;\n\t\t\t\t\t\t\tcallAfterLink(tag);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Add data binding for a data-linked element (with data-link attribute)\n\t\t\t\taddDataBinding(late, elem.getAttribute($viewsLinkAttr), elem, $view(elem), undefined, isLink, outerData, context);\n\t\t\t}\n\t\t}\n//});\n\t}\n\t//==== /end of nested functions ====\n\n\tvar inTag, linkCtx, tag, i, l, j, len, elems, elem, view, vwInfo, linkInfo, prevNodes, token, prevView, nextView,\n\t\tnode, tags, deep, tagName, tagCtx, validate, tagDepth, depth, fragment, copiedNode, firstTag, parentTag,\n\t\tisVoid, wrapper, div, tokens, elCnt, prevElCnt, htmlTag, ids, prevIds, found, skip, isLink, get,\n\t\tself = this,\n\t\tthisId = self._.id + \"_\",\n\t\tdefer = \"\",\n\t\t// The marker ids for which no tag was encountered (empty views or final closing markers) which we carry over to container tag\n\t\tbindEls = [],\n\t\ttagStack = [],\n\t\tdeferStack = [],\n\t\tlate = [],\n\t\tonAfterCreate = changeHandler(self, onAfterCreateStr),\n\t\tprocessInfos = processViewInfos;\n\n\tif (refresh) {\n\t\tif (refresh.tmpl) {\n\t\t\t// refresh is the prevView, passed in from addViews()\n\t\t\tprevView = \"/\" + refresh._.id + \"_\";\n\t\t} else {\n\t\t\tisLink = refresh.lnk; // Top-level linking\n\t\t\tif (refresh.tag) {\n\t\t\t\tthisId = refresh.tag + \"^\";\n\t\t\t\trefresh = true;\n\t\t\t}\n\t\t\tif (get = refresh.get) {\n\t\t\t\tprocessInfos = getViewInfos;\n\t\t\t\ttags = get.tags;\n\t\t\t\tdeep = get.deep;\n\t\t\t\ttagName = get.name;\n\t\t\t}\n\t\t}\n\t\trefresh = refresh === true;\n\t}\n\n\tparentNode = parentNode\n\t\t? (\"\" + parentNode === parentNode\n\t\t\t? $(parentNode)[0] // It is a string, so treat as selector\n\t\t\t: parentNode.jquery\n\t\t\t\t? parentNode[0] // A jQuery object - take first element.\n\t\t\t\t: parentNode)\n\t\t: (self.parentElem // view.link()\n\t\t\t|| document.body); // link(null, data) to link the whole document\n\n\tvalidate = !$subSettingsAdvanced.noValidate && parentNode.contentEditable !== TRUE;\n\tparentTag = parentNode.tagName.toLowerCase();\n\telCnt = !!elContent[parentTag];\n\n\tprevNode = prevNode && markPrevOrNextNode(prevNode, elCnt);\n\tnextNode = nextNode && markPrevOrNextNode(nextNode, elCnt) || null;\n\n\tif (html != undefined) {\n\t\t//================ Insert html into DOM using documentFragments (and wrapping HTML appropriately). ================\n\t\t// Also convert markers to DOM annotations, based on content model.\n\t\t// Corresponds to nextNode ? $(nextNode).before(html) : $(parentNode).html(html);\n\t\t// but allows insertion to wrap correctly even with inserted script nodes. jQuery version will fail e.g. under tbody or select.\n\t\t// This version should also be slightly faster\n\t\tdiv = document.createElement(\"div\");\n\t\twrapper = div;\n\t\tprevIds = ids = \"\";\n\t\thtmlTag = parentNode.namespaceURI === \"http://www.w3.org/2000/svg\" ? \"svg_ns\" : (firstTag = rFirstElem.exec(html)) && firstTag[1] || \"\";\n\t\tif (elCnt) {\n\t\t\t// Now look for following view, and find its tokens, or if not found, get the parentNode._df tokens\n\t\t\tnode = nextNode;\n\t\t\twhile (node && !(nextView = viewInfos(node))) {\n\t\t\t\tnode = node.nextSibling;\n\t\t\t}\n\t\t\tif (tokens = nextView ? nextView._tkns : parentNode._df) {\n\t\t\t\ttoken = prevView || \"\";\n\t\t\t\tif (refresh || !prevView) {\n\t\t\t\t\ttoken += \"#\" + thisId;\n\t\t\t\t}\n\t\t\t\tj = tokens.indexOf(token);\n\t\t\t\tif (j + 1) {\n\t\t\t\t\tj += token.length;\n\t\t\t\t\t// Transfer the initial tokens to inserted nodes, by setting them as the ids variable, picked up in convertMarkers\n\t\t\t\t\tprevIds = ids = tokens.slice(0, j);\n\t\t\t\t\ttokens = tokens.slice(j);\n\t\t\t\t\tif (nextView) {\n\t\t\t\t\t\tnode.setAttribute(jsvAttrStr, tokens);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetDefer(parentNode, tokens);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//================ Convert the markers to DOM annotations, based on content model. ================\n//\t\t\toldElCnt = elCnt;\n\t\tisVoid = undefined;\n\t\thtml = (\"\" + html).replace(rConvertMarkers, convertMarkers);\n//\t\t\tif (!!oldElCnt !== !!elCnt) {\n//\t\t\t\terror(\"Parse: \" + html); // Parse error. Content not well-formed?\n//\t\t\t}\n\t\tif (validate && tagStack.length) {\n\t\t\tsyntaxError(\"Mismatched '<\" + parentTag + \"...>' in:\\n\" + html); // Unmatched tag\n\t\t}\n\t\tif (validateOnly) {\n\t\t\treturn;\n\t\t}\n\t\t// Append wrapper element to doc fragment\n\t\tsafeFragment.appendChild(div);\n\n\t\t// Go to html and back, then peel off extra wrappers\n\t\t// Corresponds to jQuery $(nextNode).before(html) or $(parentNode).html(html);\n\t\t// but supports svg elements, and other features missing from jQuery version (and this version should also be slightly faster)\n\t\thtmlTag = wrapMap[htmlTag] || wrapMap.div;\n\t\tdepth = htmlTag[0];\n\t\twrapper.innerHTML = htmlTag[1] + html + htmlTag[2];\n\t\twhile (depth--) {\n\t\t\twrapper = wrapper.lastChild;\n\t\t}\n\t\tsafeFragment.removeChild(div);\n\t\tfragment = document.createDocumentFragment();\n\t\twhile (copiedNode = wrapper.firstChild) {\n\t\t\tfragment.appendChild(copiedNode);\n\t\t}\n\t\t// Insert into the DOM\n\t\tparentNode.insertBefore(fragment, nextNode);\n\t}\n\tdataLink();\n\n\treturn late;\n}\n\nfunction addDataBinding(late, linkMarkup, node, currentView, boundTagId, isLink, data, context) {\n\t// Add data binding for data-linked elements or {^{...}} data-linked tags\n\tvar tmpl, tokens, attr, convertBack, tagExpr, linkFn, linkCtx, tag, rTagIndex, hasElse, lastIndex,\n\t\tlinkExpressions = [];\n\n\tif (boundTagId) {\n\t\t// boundTagId is a string for {^{...}} data-linked tag. So only one linkTag in linkMarkup\n\t\t// data and context arguments are undefined\n\t\ttag = bindingStore[boundTagId];\n\t\ttag = tag.linkCtx ? tag.linkCtx.tag : tag;\n\n\t\tlinkCtx = tag.linkCtx || {\n\t\t\ttype: \"inline\",\n\t\t\tdata: currentView.data, // source\n\t\t\telem: tag._elCnt ? tag.parentElem : node, // target\n\t\t\tview: currentView,\n\t\t\tctx: currentView.ctx,\n\t\t\tattr: HTML, // Script marker nodes are associated with {^{ and always target HTML.\n\t\t\tfn: tag._.bnd,\n\t\t\ttag: tag,\n\t\t\t// Pass the boundTagId in the linkCtx, so that it can be picked up in observeAndBind\n\t\t\t_bndId: boundTagId\n\t\t};\n\t\ttag.linkCtx = linkCtx;\n\t\tbindDataLinkTarget(linkCtx, late);\n\t\ttag._toLk = linkCtx._bndId; // If data binding happened, remove _toLk flag from tag\n\t} else if (linkMarkup && node) {\n\t\t// Data-linked element\n\n\t\t// If isLink then this is a top-level linking: .link(expression, target, data, ....) or\n\t\t// .link(true, target, data, ....) scenario - and data and context are passed in separately from the view\n\t\tdata = isLink ? data : currentView.data;\n\n\t\t// Compiled linkFn expressions could be stored in the tmpl.links array of the template\n\t\t// TODO - consider also caching globally so that if {{:foo}} or data-link=\"foo\" occurs in different places,\n\t\t// the compiled template for this is cached and only compiled once...\n\t\t//links = currentView.links || currentView.tmpl.links;\n\n\t\ttmpl = currentView.tmpl;\n\n//\t\t\tif (!(linkTags = links[linkMarkup])) {\n\t\t// This is the first time this view template has been linked, so we compile the data-link expressions, and store them on the template.\n\n\t\tlinkMarkup = normalizeLinkTag(linkMarkup, defaultAttr(node));\n\t\tlastIndex = rTagDatalink.lastIndex = 0;\n\t\twhile (tokens = rTagDatalink.exec(linkMarkup)) { // TODO require } to be followed by whitespace or $, and remove the \\}(!\\}) option.\n\t\t\tlinkExpressions.push(tokens);\n\t\t\tlastIndex = rTagDatalink.lastIndex;\n\t\t}\n\t\tif (lastIndex < linkMarkup.length) {\n\t\t\tsyntaxError(linkMarkup);\n\t\t}\n\t\twhile (tokens = linkExpressions.shift()) {\n\t\t\t// Iterate over the data-link expressions, for different target attrs,\n\t\t\t// e.g. ~description(firstName, lastName)}\"\n\t\t\t// tokens: [all, attr, bindOnly, tagExpr, tagName, converter, colon, html, comment, code, params]\n\t\t\trTagIndex = rTagDatalink.lastIndex;\n\t\t\tattr = tokens[1];\n\t\t\ttagExpr = tokens[3];\n\t\t\twhile (linkExpressions[0] && linkExpressions[0][4] === \"else\") { // If this is {sometag...} and is followed by an {else...} add to tagExpr\n\t\t\t\ttagExpr += delimCloseChar1 + delimOpenChar0 + linkExpressions.shift()[3];\n\t\t\t\thasElse = true;\n\t\t\t}\n\t\t\tif (hasElse) { // If an {else} has been added, need also to add closing {{/sometag}}\n\t\t\t\ttagExpr += delimCloseChar1 + delimOpenChar0 + delimOpenChar1 + \"/\" + tokens[4] + delimCloseChar0;\n\t\t\t}\n\t\t\tlinkCtx = {\n\t\t\t\ttype: isLink ? \"top\" : \"link\",\n\t\t\t\tdata: data, // source\n\t\t\t\telem: node, // target\n\t\t\t\tview: currentView,\n\t\t\t\tctx: context,\n\t\t\t\tattr: attr,\n\t\t\t\tisLk: isLink, // top-level linking?\n\t\t\t\t_toLk : 1, // Flag to data-link on initial data-link call rendering call\n\t\t\t\t_noUpd : tokens[2] // Flag for data-link=\"^{...}\" so on initial data-link call will bind, but not render)\n\t\t\t};\n\n\t\t\tconvertBack = undefined;\n\t\t\tif (tokens[6]) {\n\t\t\t\tconvertBack = tokens[10] || undefined;\n\t\t\t\tlinkCtx.convert = tokens[5] || \"\";\n\t\t\t\tif (convertBack !== undefined && defaultAttr(node)) {\n\t\t\t\t\tif (attr) {\n\t\t\t\t\t\tsyntaxError(tagExpr + \"- Remove target: \" + attr);\n\t\t\t\t\t}\n\t\t\t\t\t// Default target, so allow 2 way binding\n\t\t\t\t\tlinkCtx.convertBack = convertBack = convertBack.slice(1);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Compile the linkFn expression which evaluates and binds a data-link expression\n\t\t\t// TODO - optimize for the case of simple data path with no conversion, helpers, etc.:\n\t\t\t// i.e. data-link=\"a.b.c\". Avoid creating new instances of Function every time. Can use a default function for all of these...\n\n\t\t\tlinkCtx.expr = attr + tagExpr;\n\t\t\tlinkFn = tmpl.links[tagExpr];\n\t\t\tif (!linkFn) {\n\t\t\t\ttmpl.links[tagExpr] = linkFn = $sub.tmplFn(tagExpr, tmpl, true, convertBack, hasElse);\n\t\t\t}\n\t\t\tlinkCtx.fn = linkFn;\n\t\t\tbindDataLinkTarget(linkCtx, late);\n\t\t\t// We store rTagIndex in local scope, since this addDataBinding method can sometimes be called recursively,\n\t\t\t// and each is using the same rTagDatalink instance.\n\t\t\trTagDatalink.lastIndex = rTagIndex;\n\t\t}\n//\t\t}\n\t}\n}\n\nfunction bindDataLinkTarget(linkCtx, late) {\n\t// Add data link bindings for a link expression in data-link attribute markup\n\tfunction handler(ev, eventArgs) {\n\t\tonDataLinkedTagChange.call(linkCtx, ev, eventArgs);\n\t\t// If the link expression uses a custom tag, the onDataLinkedTagChange call will call renderTag, which will set tagCtx on linkCtx\n\t}\n\tif (linkCtx.isLk) {\n\t\t// Top-level linking: .link(expressionOrTrue, data, context) - so we need to create a view for the linking, with the data and ctx\n\t\t// which may be different than the current context of the target. Note that this view is not a standard data-linked view, so it will\n\t\t// be disposed only when its parent view is disposed.\n\t\tlinkCtx.view = new $sub.View(\n\t\t\t$sub.extendCtx(linkCtx.ctx, linkCtx.view.ctx),\n\t\t\t\"link\", linkCtx.view, linkCtx.data, linkCtx.expr, undefined, addBindingMarkers);\n\t}\n\tlinkCtx._ctxCb = $sub._gccb(linkCtx.view); // getContextCallback: _ctxCb, for filtering/appending to dependency paths: function(path, object) { return [(object|path)*]}\n\tlinkCtx._hdl = handler;\n\t// handler._ctx = linkCtx; Could pass linkCtx for use in a depends = function() {} call, so depends is different for different linkCtx's\n\tif (linkCtx.fn._lr) {\n\t\tlinkCtx._toLk = 1;\n\t\tlate.push(linkCtx); // lateRender - defer rendering and linking (sync but after first linking pass)\n\t} else {\n\t\thandler(true);\n\t}\n}\n\n//=====================\n// Data-linking helpers\n//=====================\n\nfunction removeSubStr(str, substr) {\n\tvar k;\n\treturn str\n\t\t? (k = str.indexOf(substr),\n\t\t\t(k + 1\n\t\t\t\t? str.slice(0, k) + str.slice(k + substr.length)\n\t\t\t\t: str))\n\t\t: \"\";\n}\n\nfunction markerNodeInfo(node) {\n\treturn node &&\n\t\t(\"\" + node === node\n\t\t\t? node\n\t\t\t: node.tagName === SCRIPT\n\t\t\t\t? node.type.slice(3)\n\t\t\t\t: node.nodeType === 1 && node.getAttribute(jsvAttrStr) || \"\");\n}\n\nfunction viewInfos(node, isVal, rBinding) {\n\t// Test whether node is a script marker node, and if so, return metadata\n\tfunction getInfos(all, open, close, id, ch, elPath) {\n\t\tinfos.push({\n\t\t\telCnt: elCnt,\n\t\t\tid: id,\n\t\t\tch: ch,\n\t\t\topen: open,\n\t\t\tclose: close,\n\t\t\tpath: elPath,\n\t\t\ttoken: all\n\t\t});\n\t}\n\tvar elCnt, tokens,\n\t\tinfos = [];\n\tif (tokens = isVal ? node : markerNodeInfo(node)) {\n\t\telCnt = infos.elCnt = node.tagName !== SCRIPT;\n\t\telCnt = tokens.charAt(0) === \"@\" || elCnt;\n\t\tinfos._tkns = tokens;\n\t\t// rMarkerTokens = /(?:(#)|(\\/))(\\d+)([_^])([-+@\\d]+)?/g;\n\t\ttokens.replace(rBinding || rMarkerTokens, getInfos);\n\t\treturn infos;\n\t}\n}\n\nfunction unmarkPrevOrNextNode(node, elCnt) {\n\tif (node) {\n\t\tif (node.type === \"jsv\") {\n\t\t\tnode.parentNode.removeChild(node);\n\t\t} else if (elCnt && node.getAttribute($viewsLinkAttr) === \"\") {\n\t\t\tnode.removeAttribute($viewsLinkAttr);\n\t\t}\n\t}\n}\n\nfunction markPrevOrNextNode(node, elCnt) {\n\tvar marker = node;\n\twhile (elCnt && marker && marker.nodeType !== 1) {\n\t\tmarker = marker.previousSibling;\n\t}\n\tif (marker) {\n\t\tif (marker.nodeType !== 1) {\n\t\t\t// For text nodes, we will add a script node before\n\t\t\tmarker = document.createElement(SCRIPT);\n\t\t\tmarker.type = \"jsv\";\n\t\t\tnode.parentNode.insertBefore(marker, node);\n\t\t} else if (!markerNodeInfo(marker) && !marker.getAttribute($viewsLinkAttr)) {\n\t\t\t// For element nodes, we will add a data-link attribute (unless there is already one)\n\t\t\t// so that this node gets included in the node linking process.\n\t\t\tmarker.setAttribute($viewsLinkAttr, \"\");\n\t\t}\n\t}\n\treturn marker;\n}\n\nfunction normalizeLinkTag(linkMarkup, twoway) {\n\tlinkMarkup = $.trim(linkMarkup).replace(rEscapeQuotes, \"\\\\$&\");\n\treturn linkMarkup.slice(-1) !== delimCloseChar0\n\t// If simplified syntax is used: data-link=\"expression\", convert to data-link=\"{:expression}\",\n\t// or for inputs, data-link=\"{:expression:}\" for (default) two-way binding\n\t\t? linkMarkup = delimOpenChar1 + \":\" + linkMarkup + (twoway ? \":\" : \"\") + delimCloseChar0\n\t\t: linkMarkup;\n}\n\n//===========================\n// Methods for views and tags\n//===========================\n\nfunction callAfterLink(tag, ev, eventArgs) {\n\tfunction copyFromTagCtxToTag() {\n\t\tlinkedElems = tagCtx.linkedElems || tag.linkedElems || tag.linkedElem && [tag.linkedElem];\n\t\tif (linkedElems) {\n\t\t\ttag.linkedElems = tagCtx.linkedElems = linkedElems;\n\t\t\ttag.linkedElem = linkedElems[0] = tag.linkedElem || linkedElems[0];\n\t\t}\n\t\tif (linkedElem = tagCtx.mainElem || tag.mainElem) {\n\t\t\ttagCtx.mainElem = tag.mainElem = linkedElem;\n\t\t}\n\t\tif (linkedElem = tagCtx.displayElem || tag.displayElem) {\n\t\t\ttagCtx.displayElem = tag.displayElem = linkedElem;\n\t\t}\n\t}\n\n\tvar linkedElems, linkedElements, linkedElem, l, m, $linkCtxElem, linkCtxElem, tagCtxElse, props, val, oldVal,\n\t\ttagCtx = tag.tagCtx,\n\t\ttagCtxs = tag.tagCtxs,\n\t\ttagCtxslength = tagCtxs && tagCtxs.length,\n\t\tlinkCtx = tag.linkCtx,\n\t\tbindTo = tag.bindTo || {};\n\n\tif (tag._.unlinked) { // First call to onAfterLink, or first call after onUpdate: updateContent. Initialize and call onBind and set properties\n\t\t$linkCtxElem = $(linkCtx.elem);\n\t\tif (tag.linkedElement || tag.mainElement || tag.displayElement) {\n\t\t\tif (linkedElements = tag.linkedElement) {\n\t\t\t\t// tag.linkedElement: - selector, or array of selectors, for identifying linked elements in template/rendered content.\n\t\t\t\t// (But for tag bindings on data-linked elements, defaults to data-linked element)\n\t\t\t\ttag.linkedElem = undefined;\n\t\t\t\tl = linkedElements.length;\n\t\t\t\twhile (l--) {\n\t\t\t\t\tif (linkedElements[l]) {\n\t\t\t\t\t\tm = tagCtxslength;\n\t\t\t\t\t\twhile (m--) {\n\t\t\t\t\t\t\tlinkCtxElem = !m && !tag.inline && $linkCtxElem.filter(linkedElements[l]);\n\t\t\t\t\t\t\ttagCtxElse = tagCtxs[m];\n\t\t\t\t\t\t\tlinkedElems = tagCtxElse.linkedElems = tagCtxElse.linkedElems || new Array(l);\n\t\t\t\t\t\t\tlinkedElem = linkCtxElem[0] ? linkCtxElem : tagCtxElse.contents(true, linkedElements[l]);\n\t\t\t\t\t\t\tif (linkedElem[0] && linkedElem[0].type !== RADIO) {\n\t\t\t\t\t\t\t\tlinkedElems[l] = linkedElem.eq(0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (linkedElements = tag.mainElement) {\n\t\t\t\t// tag.mainElement: - selector for identifying mainElem in template/rendered content\n\t\t\t\t// (But for tag bindings on data-linked elements, defaults to data-linked element)\n\t\t\t\tm = tagCtxslength;\n\t\t\t\twhile (m--) {\n\t\t\t\t\tlinkCtxElem = !m && !tag.inline && $linkCtxElem.filter(linkedElements);\n\t\t\t\t\ttagCtxElse = tagCtxs[m];\n\t\t\t\t\tlinkedElem = linkCtxElem[0] ? linkCtxElem : tagCtxElse.contents(true, linkedElements).eq(0);\n\t\t\t\t\tif (linkedElem[0]) {\n\t\t\t\t\t\ttagCtxElse.mainElem = linkedElem;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (linkedElements = tag.displayElement) {\n\t\t\t\t// tag.mainElement: - selector for identifying mainElem in template/rendered content\n\t\t\t\t// (But for tag bindings on data-linked elements, defaults to data-linked element)\n\t\t\t\tm = tagCtxslength;\n\t\t\t\twhile (m--) {\n\t\t\t\t\tlinkCtxElem = !m && !tag.inline && $linkCtxElem.filter(linkedElements);\n\t\t\t\t\ttagCtxElse = tagCtxs[m];\n\t\t\t\t\tlinkedElem = linkCtxElem[0] ? linkCtxElem : tagCtxElse.contents(true, linkedElements).eq(0);\n\t\t\t\t\tif (linkedElem[0]) {\n\t\t\t\t\t\ttagCtxElse.displayElem = linkedElem;\n\t\t\t\t\t\tif (!m) {\n\t\t\t\t\t\t\ttag.displayElem = linkedElem;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcopyFromTagCtxToTag();\n\t\t}\n\t\tif (tag.onBind) {\n\t\t\ttag.onBind(tagCtx, linkCtx, tag.ctx, ev, eventArgs);\n\t\t\tcopyFromTagCtxToTag();\n\t\t}\n\t}\n\n\tm = tagCtxslength;\n\twhile (m--) {\n\t\ttagCtxElse = tagCtxs[m];\n\t\tprops = tagCtxElse.props;\n\n\t\tif (linkedElem = tagCtxElse.mainElem || !tag.mainElement && tagCtxElse.linkedElems && tagCtxElse.linkedElems[0]) {\n\t\t\t// linkedElem is the mainElem (defaulting to linkedElem)\n\t\t\tif (linkedElem[0] && props.id && !linkedElem[0].id) {\n\t\t\t\tlinkedElem[0].id = props.id;\n\t\t\t}\n\t\t\tif (tag.setSize) {\n\t\t\t\tif (val = !bindTo.height && props.height || tag.height) {\n\t\t\t\t\tlinkedElem.height(val);\n\t\t\t\t}\n\t\t\t\tif (val = !bindTo.width && props.width || tag.width) {\n\t\t\t\t\tlinkedElem.width(val);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (val = (linkedElem = tagCtxElse.displayElem || linkedElem) && (!bindTo[\"class\"] && props[\"class\"] || tag.className)) {\n\t\t\t// This code supports dynamic binding to class - where it adds the class if absent, and removes/adds if a previous value is present\n\t\t\toldVal = linkedElem[0]._jsvCl;\n\t\t\tif (val !== oldVal) {\n\t\t\t\tif (linkedElem.hasClass(oldVal)) {\n\t\t\t\t\tlinkedElem.removeClass(oldVal);\n\t\t\t\t}\n\t\t\t\tlinkedElem.addClass(val);\n\t\t\t\tlinkedElem[0]._jsvCl = val;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (tag.onAfterLink) {\n\t\ttag.onAfterLink(tagCtx, linkCtx, tag.ctx, ev, eventArgs);\n\t\tcopyFromTagCtxToTag();\n\t}\n\n\tif (!tag.flow && !tag._.chg) {\n\t\tif (tag.inline && tag._.unlinked && (tag.linkedElems || bindTo)) {\n\t\t\tdefineBindToDataTargets(bindingStore[tag._tgId], tag);\n\t\t}\n\t\ttag.setValue();\n\t}\n\ttag._.unlinked = undefined;\n}\n\nfunction asyncOnElemChange(ev) {\n\tvar which = ev.which;\n\tif (!(which > 15 && which < 21 || which > 32 && which < 41 || which > 111 && which < 131 || which === 27 || which === 144)) {\n\t\t// Shift, Ctrl, Alt, Pause, Caplock, Page up/down End, Home, Left, Up, Right, Down, Function keys, Escape, Numlock\n\t\tsetTimeout(function() {\n\t\t\tonElemChange(ev);\n\t\t});\n\t}\n}\n\nfunction bindTriggerEvent($elem, trig, onoff) {\n\t// Bind keydown, or other trigger - (rather than use the default change event bubbled to activeBody)\n\tif (trig === true && useInput) {\n\t\t$elem[onoff](\"input.jsv\", onElemChange); // For HTML5 browser with \"oninput\" support - for mouse editing of text\n\t} else {\n\t\ttrig = \"\" + trig === trig ? trig : \"keydown.jsv\"; // Set trigger to (true || truey non-string (e.g. 1) || 'keydown')\n\t\t$elem[onoff](trig, trig.indexOf(\"keydown\") >= 0 ? asyncOnElemChange : onElemChange); // Get 'keydown' with async\n\t}\n}\n\nfunction bindLinkedElChange(tag, linkedElem) {\n\t// Two-way binding for linkedElem - in the case of input, textarea or contentEditable elements.\n\t// Trigger setting may have changed. Unbind previous trigger binding (if any) and bind new one.\n\n\tvar $linkedElem, newTrig,\n\t\toldTrig = linkedElem._jsvTr || false;\n\n\tif (tag) {\n\t\tnewTrig = tag.tagCtx.props.trigger;\n\t\tif (newTrig === undefined) {\n\t\t\tnewTrig = tag.trigger;\n\t\t}\n\t}\n\tif (newTrig === undefined) {\n\t\tnewTrig = $subSettings.trigger;\n\t}\n\t// Trigger is noop except for text box, textarea, contenteditable...\n\tnewTrig = newTrig && (linkedElem.tagName === \"INPUT\" && linkedElem.type !== CHECKBOX && linkedElem.type !== RADIO\n\t\t|| linkedElem.type === \"textarea\" || linkedElem.contentEditable === TRUE) && newTrig || false;\n\n\tif (oldTrig !== newTrig) {\n\t\t$linkedElem = $(linkedElem);\n\t\tbindTriggerEvent($linkedElem, oldTrig, \"off\");\n\t\tbindTriggerEvent($linkedElem, linkedElem._jsvTr = newTrig, \"on\");\n\t}\n}\n\nfunction defineBindToDataTargets(binding, tag, cvtBk) {\n\t// Two-way binding.\n\t// We set the binding.to[1] to be the cvtBack, and binding.to[0] to be either the path to the target, or [object, path] where the target is the\n\t// path on the provided object. So for a computed path with an object call: a.b.getObject().d.e, we set to[0] to be [exprOb, \"d.e\"], and\n\t// we bind to the path on the returned object, exprOb.ob, as target. Otherwise our target is the first path, paths[0], which we will convert\n\t// with contextCb() for paths like ~a.b.c or #x.y.z\n\n\tvar pathIndex, path, lastPath, bindtoOb, to, bindTo, paths, k, l, obsCtxPrm, linkedCtxParam, contextCb, targetPaths, bindTos,\n\t\ttagElse = 1,\n\t\ttos = [],\n\t\tlinkCtx = binding.linkCtx,\n\t\tsource = linkCtx.data,\n\t\ttargetPathsElses = linkCtx.fn.paths;\n\n\tif (binding && !binding.to) {\n\t\tif (tag) {\n\t\t\ttag.convertBack = tag.convertBack || cvtBk;\n\t\t\tbindTo = tag.bindTo;\n\t\t\ttagElse = tag.tagCtxs ? tag.tagCtxs.length : 1;\n\t\t}\n\t\twhile (tagElse--) {\n\t\t\tbindTos = [];\n\t\t\tif (targetPaths = targetPathsElses[tagElse]) {\n\t\t\t\tbindTo = targetPaths._jsvto ? [\"_jsvto\"] : (bindTo || [0]);\n\t\t\t\tk = bindTo.length;\n\t\t\t\twhile (k--) {\n\t\t\t\t\tpath = \"\";\n\t\t\t\t\tcontextCb = linkCtx._ctxCb;\n\t\t\t\t\tpaths = targetPaths[bindTo[k]];\n\t\t\t\t\tif (pathIndex = paths && paths.length) {\n\t\t\t\t\t\tlastPath = paths[pathIndex - 1];\n\t\t\t\t\t\tif (lastPath._cpfn) { // Computed property exprOb\n\n\t\t\t\t\t\t\tbindtoOb = lastPath;\n\t\t\t\t\t\t\twhile (lastPath.sb && lastPath.sb._cpfn) {\n\t\t\t\t\t\t\t\tpath = lastPath = lastPath.sb;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tpath = lastPath.sb || path && path.path;\n\t\t\t\t\t\t\tlastPath = path ? path.slice(1) : bindtoOb.path;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tto = path\n\t\t\t\t\t\t\t? [bindtoOb, // 'exprOb' for this expression and view-binding. So bindtoOb.ob is current object returned by expression.\n\t\t\t\t\t\t\t\t\tlastPath]\n\t\t\t\t\t\t\t: resolveDataTargetPath(lastPath, source, contextCb); // Get 'to' for target path: lastPath\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Contextual parameter ~foo with no external binding - has ctx.foo = [{_ocp: xxx}] and binds to ctx.foo._ocp\n\t\t\t\t\t\tlinkedCtxParam = tag.linkedCtxParam;\n\t\t\t\t\t\tto = [];\n\t\t\t\t\t\tif (linkedCtxParam && linkedCtxParam[k]) {\n\t\t\t\t\t\t\t// This is a tag binding, with linked tag contextual parameters\n\t\t\t\t\t\t\tto = [tag.tagCtxs[tagElse].ctx[linkedCtxParam[k]][0], _ocp];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ((obsCtxPrm = to._cxp) && obsCtxPrm.tag && lastPath.indexOf(\".\")<0) {\n\t\t\t\t\t\t// This is a binding for a tag contextual parameter (e.g. within a tag block content\n\t\t\t\t\t\tto = obsCtxPrm;\n\t\t\t\t\t}\n\t\t\t\t\tbindTos.unshift(to);\n\t\t\t\t}\n\t\t\t}\n\t\t\ttos.unshift(bindTos);\n\t\t}\n\t\tbinding.to = tos;\n\t}\n}\n\nfunction resolveDataTargetPath(targetPath, source, contextCb) {\n\t// Iteratively process targetPath, resolving ~a.b.c paths for contextual parameters\n\tvar path, bindtoOb, to, l, obsCtxPrm, view, topCp, data;\n\n\twhile (targetPath && targetPath !== _ocp && (to = contextCb(path = targetPath.split(\"^\").join(\".\"), source)) && (l = to.length)) {\n\t\tif (obsCtxPrm = to[0]._cxp) { // Two-way binding to a contextual parameter reference, ~foo (declared as ~foo=expr on a parent tag)\n\t\t\ttopCp = topCp || obsCtxPrm;\n\t\t\tview = to[0][0];\n\t\t\tif (_ocp in view) {\n\t\t\t\tdata = view;\n\t\t\t\tview = view._vw;\n\t\t\t} else {\n\t\t\t\tdata = view.data;\n\t\t\t}\n\t\t\ttopCp.path = targetPath = to[0][1];\n\t\t\tto = [topCp.data = data, targetPath];\n\t\t\t\tcontextCb = $sub._gccb(view);\n\t\t\t\tif (targetPath._cpfn) { // computed property\n\t\t\t\t\tbindtoOb = targetPath;\n\t\t\t\t\tbindtoOb.data = to[0];\n\t\t\t\t\tbindtoOb._cpCtx = contextCb;\n\t\t\t\t\twhile (targetPath.sb && targetPath.sb._cpfn) {\n\t\t\t\t\t\tpath = targetPath = targetPath.sb;\n\t\t\t\t\t}\n\t\t\t\t\tpath = targetPath.sb || path && path.path;\n\t\t\t\t\ttargetPath = path ? path.slice(1) : bindtoOb.path;\n\t\t\t\t\tto = [\n\t\t\t\t\t\tbindtoOb, // 'exprOb' for this expression and view-binding. So bindtoOb.ob is current object returned by expression.\n\t\t\t\t\t\ttargetPath\n\t\t\t\t\t];\n\t\t\t\t} else if (obsCtxPrm.tag && obsCtxPrm.path === _ocp) {\n\t\t\t\t\tto = obsCtxPrm;\n\t\t\t\t}\n\t\t} else { // Two-way binding to a helper - e.g. ~address.street, or computed, e.g. ~fullName(), or view property e.g. #data.foo\n\t\t\tto = l>2\n\t\t\t\t? [to[l-3], to[l-2]] // With path: [object, path]\n\t\t\t\t: [to[l-2]]; // No path, (e.g. [function] for computed with setter)\n\t\t}\n\t\tsource = to[0];\n\t\ttargetPath = to[1];\n\t}\n\tto = to || [source, path];\n\tto._cxp = topCp;\n\treturn to;\n}\n\nfunction mergeCtxs(tag, newCtxs, replace) { // Merge updated tagCtxs into tag.tagCtxs\n\tvar tagCtx, newTagCtx,\n\t\tview = tag.tagCtx.view,\n\t\ttagCtxs = tag.tagCtxs || [tag.tagCtx],\n\t\tl = tagCtxs.length,\n\t\trefresh = !newCtxs;\n\n\tnewCtxs = newCtxs || tag._.bnd.call(view.tmpl, (tag.linkCtx || view).data, view, $sub);\n\n\tif (replace) {\n\t\t// Replace previous tagCtxs by new ones, rather than merging\n\t\ttagCtxs = tag.tagCtxs = newCtxs;\n\t\ttag.tagCtx = tagCtxs[0];\n\t\taddLinkMethods(tag);\n\t} else {\n\t\twhile (l--) {\n\t\t\ttagCtx = tagCtxs[l];\n\t\t\tnewTagCtx = newCtxs[l];\n\t\t\t$observable(tagCtx.props).setProperty(newTagCtx.props);\n\t\t\t$extend(tagCtx.ctx, newTagCtx.ctx); // We don't support propagating ctx variables, ~foo, observably, to nested views. So extend, not setProperty...\n\t\t\ttagCtx.args = newTagCtx.args;\n\t\t\tif (refresh) {\n\t\t\t\ttagCtx.tmpl = newTagCtx.tmpl;\n\t\t\t}\n\t\t}\n\t}\n\t$sub._ths(tag, tagCtxs[0]); // tagHandlersFromProps\n\treturn tagCtxs;\n}\n\n//=========\n// Disposal\n//=========\n\nfunction clean(elems) {\n\t// Remove data-link bindings, or contained views\n\tvar l, elem, bindings,\n\t\telemArray = [],\n\t\tlen = elems.length,\n\t\ti = len;\n\twhile (i--) {\n\t\t// Copy into an array, so that deletion of nodes from DOM will not cause our 'i' counter to get shifted\n\t\t// (Note: This seems as fast or faster than elemArray = [].slice.call(elems); ...)\n\t\telemArray.push(elems[i]);\n\t}\n\ti = len;\n\twhile (i--) {\n\t\telem = elemArray[i];\n\t\tif (elem.parentNode) {\n\t\t\t// Has not already been removed from the DOM\n\t\t\tif (bindings = elem._jsvBnd) {\n\t\t\t\t// Get propertyChange bindings for this element\n\t\t\t\t// This may be an element with data-link, or the opening script marker node for a data-linked tag {^{...}}\n\t\t\t\t// bindings is a string with the syntax: \"(&bindingId)*\"\n\t\t\t\tbindings = bindings.slice(1).split(\"&\");\n\t\t\t\telem._jsvBnd = \"\";\n\t\t\t\tl = bindings.length;\n\t\t\t\twhile (l--) {\n\t\t\t\t\t// Remove associated bindings\n\t\t\t\t\tremoveViewBinding(bindings[l], elem._jsvLkEl, elem); // unbind bindings with this bindingId on this view\n\t\t\t\t}\n\t\t\t}\n\t\t\tdisposeTokens(markerNodeInfo(elem) + (elem._df || \"\"), elem);\n\t\t}\n\t}\n}\n\nfunction removeViewBinding(bindId, linkedElemTag, elem) {\n\t// Unbind\n\tvar objId, linkCtx, tag, object, obsId, tagCtxs, l, map, linkedElem, trigger, view, tagCtx, linkedElems, allLinkedElems,\n\t\tbinding = bindingStore[bindId];\n\n\tif (linkedElemTag) {\n\t\telem._jsvLkEl = undefined;\n\t} else if (binding && (!elem || elem === binding.elem)) { // Test that elem is actually binding.elem, since cloned elements can have inappropriate markerNode info\n\t\tdelete bindingStore[bindId]; // Delete already, so call to onDispose handler below cannot trigger recursive deletion (through recursive call to jQuery cleanData)\n\t\tfor (objId in binding.bnd) {\n\t\t\tobject = binding.bnd[objId];\n\t\t\tobsId = binding.cbId;\n\t\t\tif ($isArray(object)) {\n\t\t\t\t$([object]).off(arrayChangeStr + obsId).off(propertyChangeStr + obsId); // There may be either or both of arrayChange and propertyChange\n\t\t\t} else {\n\t\t\t\t$(object).off(propertyChangeStr + obsId);\n\t\t\t}\n\t\t\tdelete binding.bnd[objId];\n\t\t}\n\n\t\tif (linkCtx = binding.linkCtx) {\n\t\t\tif (tag = linkCtx.tag) {\n\t\t\t\tif (tagCtxs = tag.tagCtxs) {\n\t\t\t\t\tl = tagCtxs.length;\n\t\t\t\t\twhile (l--) {\n\t\t\t\t\t\ttagCtx = tagCtxs[l];\n\t\t\t\t\t\tif (map = tagCtx.map) {\n\t\t\t\t\t\t\tmap.unmap(); //unobserve\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Copy linkedElems in case tag.linkedElem or tag.linkedElems are undefined in onUnbind\n\t\t\t\t\t\tif (linkedElems = tagCtx.linkedElems) {\n\t\t\t\t\t\t\tallLinkedElems = (allLinkedElems || []).concat(linkedElems);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (tag.onUnbind) {\n\t\t\t\t\ttag.onUnbind(tag.tagCtx, linkCtx, tag.ctx, true);\n\t\t\t\t}\n\t\t\t\tif (tag.onDispose) {\n\t\t\t\t\ttag.onDispose();\n\t\t\t\t}\n\n\t\t\t\tif (!tag._elCnt) {\n\t\t\t\t\tif (tag._prv) {\n\t\t\t\t\t\ttag._prv.parentNode.removeChild(tag._prv);\n\t\t\t\t\t}\n\t\t\t\t\tif (tag._nxt) {\n\t\t\t\t\t\ttag._nxt.parentNode.removeChild(tag._nxt);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlinkedElems = allLinkedElems || [$(linkCtx.elem)];\n\t\t\tl = linkedElems.length;\n\t\t\twhile (l--) {\n\t\t\t\tlinkedElem = linkedElems[l];\n\t\t\t\tif (trigger = linkedElem && linkedElem[0] && linkedElem[0]._jsvTr) {\n\t\t\t\t\tbindTriggerEvent(linkedElem, trigger, \"off\");\n\t\t\t\t\tlinkedElem[0]._jsvTr = undefined;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tview = linkCtx.view;\n\t\t\tif (view.type === \"link\") {\n\t\t\t\tview.parent.removeViews(view._.key, undefined, true); // A \"link\" view is associated with the binding, so should be disposed with binding.\n\t\t\t} else {\n\t\t\t\tdelete view._.bnds[bindId];\n\t\t\t}\n\t\t}\n\t\tdelete cbBindingsStore[binding.cbId];\n\t}\n}\n\nfunction $unlink(to) {\n\tif (to) {\n\t\tto = to.jquery ? to : $(to);\n\t\tto.each(function() {\n\t\t\tvar innerView;\n\t\t\t//TODO fix this for better perf. Rather that calling inner view multiple times which does querySelectorAll each time, consider a single querySelectorAll\n\t\t\t// or simply call view.removeViews() on the top-level views under the target 'to' node, then clean(...)\n\t\t\twhile ((innerView = $view(this, true)) && innerView.parent) {\n\t\t\t\tinnerView.parent.removeViews(innerView._.key, undefined, true);\n\t\t\t}\n\t\t\tclean(this.getElementsByTagName(\"*\"));\n\t\t});\n\t\tclean(to);\n\t} else {\n\t\t// Call to $.unlink() is equivalent to $.unlink(true, \"body\")\n\t\tif (activeBody) {\n\t\t\t$(activeBody)\n\t\t\t\t.off(elementChangeStr, onElemChange)\n\t\t\t\t.off('blur.jsv', '[contenteditable]', onElemChange);\n\t\t\tactiveBody = undefined;\n\t\t}\n\t\ttopView.removeViews();\n\t\tclean(document.body.getElementsByTagName(\"*\"));\n\t}\n}\n\n//========\n// Helpers\n//========\n\nfunction inputAttrib(elem) {\n\treturn elem.type === CHECKBOX ? elem[CHECKED] : elem.value;\n}\n\nfunction changeHandler(view, name, tag) {\n\t// Get onBeforeChange, onAfterChange, onAfterCreate handler - if there is one;\n\treturn tag && tag[name] || view.ctx[name] && view.ctxPrm(name) || $views.helpers[name];\n}\n\n//========================== Initialize ==========================\n\n//=====================\n// JsRender integration\n//=====================\n\naddLinkMethods($sub.View.prototype); // Modify the View prototype to include link methods\n\n$sub.onStore.template = function(name, item, parentTmpl) {\n\tif (item === null) {\n\t\tdelete $.link[name];\n\t\tdelete $.render[name];\n\t} else {\n\t\titem.link = tmplLink;\n\n\t\tif (name && !parentTmpl && name !== \"jsvTmpl\") {\n\t\t\t$.render[name] = item;\n\t\t\t$.link[name] = function() {\n\t\t\t\treturn tmplLink.apply(item, arguments);\n\t\t\t};\n\t\t}\n\t}\n};\n\n$sub.viewInfos = viewInfos; // Expose viewInfos() as public helper method\n\n// Define JsViews version of delimiters(), and initialize\n($viewsSettings.delimiters = function() {\n\t// Run delimiters initialization in context of jsrender.js\n\tvar ret = oldJsvDelimiters.apply(0, arguments);\n\n\tif (oldJsvDelimiters !== $viewsDelimiters) {\n\t\t// If JsRender was loaded before JsViews, then need also to initialize and set globals in that JsRender instance\n\t\tret = $viewsDelimiters.apply(0, arguments);\n\t}\n\n\t// Data-linking must use new delimiters\n\trTagDatalink = new RegExp(\"(?:^|\\\\s*)([\\\\w-]*)(\\\\\" + linkChar + \")?(\\\\\" + delimOpenChar1 + $sub.rTag + \"(:\\\\w*)?\\\\\" + delimCloseChar0 + \")\", \"g\");\n\treturn ret;\n})(); // jshint ignore:line\n\n$sub.addSetting(\"trigger\");\n\n//====================================\n// Additional members for linked views\n//====================================\n\nfunction transferViewTokens(prevNode, nextNode, parentElem, id, viewOrTagChar, refresh) {\n\t// Transfer tokens on prevNode of viewToRemove/viewToRefresh to nextNode or parentElem._df\n\t// view marker tokens: #m_...VIEW.../m_\n\t// tag marker tokens: #m^...TAG..../m^\n\n\tvar i, l, vwInfos, vwInfo, viewOrTag, viewId, tokens,\n\t\tprecedingLength = 0,\n\t\temptyView = prevNode === nextNode;\n\n\tif (prevNode) {\n\t\t// prevNode is either the first node in the viewOrTag, or has been replaced by the vwInfos tokens string\n\t\tvwInfos = viewInfos(prevNode) || [];\n\t\tfor (i = 0, l = vwInfos.length; i < l; i++) {\n\t\t\t// Step through views or tags on the prevNode\n\t\t\tvwInfo = vwInfos[i];\n\t\t\tviewId = vwInfo.id;\n\t\t\tif (viewId === id && vwInfo.ch === viewOrTagChar) {\n\t\t\t\tif (refresh) {\n\t\t\t\t\t// This is viewOrTagToRefresh, this is the last viewOrTag to process...\n\t\t\t\t\tl = 0;\n\t\t\t\t} else {\n\t\t\t\t\t// This is viewOrTagToRemove, so we are done...\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!emptyView) {\n\t\t\t\tviewOrTag = vwInfo.ch === \"_\"\n\t\t\t\t\t? viewStore[viewId] // A view: \"#m_\" or \"/m_\"\n\t\t\t\t\t: bindingStore[viewId].linkCtx.tag; // A tag \"#m^\" or \"/m^\"\n\t\t\t\tif (vwInfo.open) { // A \"#m_\" or \"#m^\" token\n\t\t\t\t\tviewOrTag._prv = nextNode;\n\t\t\t\t} else if (vwInfo.close) { // A \"/m_\" or \"/m^\" token\n\t\t\t\t\tviewOrTag._nxt = nextNode;\n\t\t\t\t}\n\t\t\t}\n\t\t\tprecedingLength += viewId.length + 2;\n\t\t}\n\n\t\tif (precedingLength) {\n\t\t\tprevNode.setAttribute(jsvAttrStr, prevNode.getAttribute(jsvAttrStr).slice(precedingLength));\n\t\t}\n\t\ttokens = nextNode ? nextNode.getAttribute(jsvAttrStr) : parentElem._df;\n\t\tif (l = tokens.indexOf(\"/\" + id + viewOrTagChar) + 1) {\n\t\t\ttokens = vwInfos._tkns.slice(0, precedingLength) + tokens.slice(l + (refresh ? -1 : id.length + 1));\n\t\t}\n\t\tif (tokens) {\n\t\t\tif (nextNode) {\n\t\t\t\t// If viewOrTagToRemove was an empty viewOrTag, we will remove both #n and /n\n\t\t\t\t// (and any intervening tokens) from the nextNode (=== prevNode)\n\t\t\t\t// If viewOrTagToRemove was not empty, we will take tokens preceding #n from prevNode,\n\t\t\t\t// and concatenate with tokens following /n on nextNode\n\t\t\t\tnextNode.setAttribute(jsvAttrStr, tokens);\n\t\t\t} else {\n\t\t\t\tsetDefer(parentElem, tokens);\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// !prevNode, so there may be a deferred nodes token on the parentElem. Remove it.\n\t\tsetDefer(parentElem, removeSubStr(parentElem._df, \"#\" + id + viewOrTagChar));\n\t\tif (!refresh && !nextNode) {\n\t\t\t// If this viewOrTag is being removed, and there was no .nxt, remove closing token from deferred tokens\n\t\t\tsetDefer(parentElem, removeSubStr(parentElem._df, \"/\" + id + viewOrTagChar));\n\t\t}\n\t}\n}\n\nfunction disposeTokens(tokens, elem) {\n\tvar i, l, vwItem, vwInfos;\n\tif (vwInfos = viewInfos(tokens, true, rOpenMarkers)) {\n\t\tfor (i = 0, l = vwInfos.length; i < l; i++) {\n\t\t\tvwItem = vwInfos[i];\n\t\t\tif (vwItem.ch === \"_\") {\n\t\t\t\tif ((vwItem = viewStore[vwItem.id]) && vwItem.type && (!elem || vwItem._prv === elem || vwItem.parentElem === elem )) {\n\t\t\t\t\t// If this is the _prv (prevNode) for a view, remove the view\n\t\t\t\t\t// - unless view.type is undefined, in which case it is already being removed\n\t\t\t\t\t// (or unless the elem is not related - e.g. a cloned element which 'accidentally' picked up the data-jsv atttribute of the ._df expando)\n\t\t\t\t\tvwItem.parent.removeViews(vwItem._.key, undefined, true);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tremoveViewBinding(vwItem.id, undefined, elem); // unbind bindings with this bindingId on this view\n\t\t\t}\n\t\t}\n\t}\n}\n\n//============================================\n// Add link methods to data-linked view or tag\n//============================================\n\nfunction updateValue(val, index, tagElse, bindId, ev) {\n// Observably update a data value targeted by bindTo\n// Called when linkedElem changes: called as updateValue(val, index, tagElse, bindId, ev) - this: undefined\n// Called directly as tag.updateValue(val, index, tagElse) - this: tag\n\tvar values = [];\n\tif (this && this._tgId) {\n\t\tbindId = this;\n\t}\n\tvalues[index||0] = val;\n\tupdateValues(values, tagElse, bindId, ev);\n\treturn this;\n}\n\nfunction setValues() {\n\tvar args = arguments,\n\t\tm = args.length;\n\n\tif (!m) {\n\t\targs = this.tag.cvtArgs(true, this.index); // setValues() with no arguments calls setValue with boundArgs values\n\t\tm = args.length;\n\t}\n\twhile (m--) {\n\t\tthis.tag.setValue(args[m], m, this.index);\n\t}\n}\n\nfunction addLinkMethods(tagOrView) { // tagOrView is View prototype or tag instance\n\n\tvar l, m, tagCtx, boundProps, bindTo, key, theTag, theView;\n\n\ttagOrView.contents = function(deep, select) {\n\t\t// For a view, a tag or a tagCtx, return jQuery object with the content nodes,\n\t\tif (deep !== !!deep) {\n\t\t\t// deep not boolean, so this is contents(selector)\n\t\t\tselect = deep;\n\t\t\tdeep = undefined;\n\t\t}\n\t\tvar filtered,\n\t\t\tnodes = $(this.nodes());\n\t\tif (nodes[0]) {\n\t\t\tfiltered = select ? nodes.filter(select) : nodes;\n\t\t\tnodes = deep && select ? filtered.add(nodes.find(select)) : filtered;\n\t\t}\n\t\treturn nodes;\n\t};\n\n\ttagOrView.nodes = function(withMarkers, prevNode, nextNode) {\n\t\t// For a view, a tag or a tagCtx, return top-level nodes\n\t\t// Do not return any script marker nodes, unless withMarkers is true\n\t\t// Optionally limit range, by passing in prevNode or nextNode parameters\n\n\t\tvar node,\n\t\t\tself = this.contentView || this, // If tagCtx, use tagCtx.contentView\n\t\t\telCnt = self._elCnt,\n\t\t\tprevIsFirstNode = !prevNode && elCnt,\n\t\t\tnodes = [];\n\n\t\tif (!self.args) { // If tagCtx with no content (so no contentView) self is tagCtx: return empty [];\n\t\t\tprevNode = prevNode || self._prv;\n\t\t\tnextNode = nextNode || self._nxt;\n\n\t\t\tnode = prevIsFirstNode\n\t\t\t\t? (prevNode === self._nxt\n\t\t\t\t\t? self.parentElem.lastSibling\n\t\t\t\t\t: prevNode)\n\t\t\t\t: (self.inline === false\n\t\t\t\t\t? prevNode || self.linkCtx.elem.firstChild\n\t\t\t\t\t: prevNode && prevNode.nextSibling);\n\n\t\t\twhile (node && (!nextNode || node !== nextNode)) {\n\t\t\t\tif (withMarkers || elCnt || node.tagName !== SCRIPT) {\n\t\t\t\t\t// All the top-level nodes in the view\n\t\t\t\t\t// (except script marker nodes, unless withMarkers = true)\n\t\t\t\t\t// (Note: If a script marker node, viewInfo.elCnt undefined)\n\t\t\t\t\tnodes.push(node);\n\t\t\t\t}\n\t\t\t\tnode = node.nextSibling;\n\t\t\t}\n\t\t}\n\t\treturn nodes;\n\t};\n\n\ttagOrView.childTags = function(deep, tagName) {\n\t\t// For a view, a tagor a tagCtx, return child tags - at any depth, or as immediate children only.\n\t\tif (deep !== !!deep) {\n\t\t\t// deep not boolean, so this is childTags(tagName) - which looks for top-level tags of given tagName\n\t\t\ttagName = deep;\n\t\t\tdeep = undefined;\n\t\t}\n\n\t\tvar self = this.contentView || this, // If tagCtx, use tagCtx.contentView\n\t\t\tview = self.link ? self : self.tagCtx.view, // This may be a view or a tag. If a tag, get the view from tag.tagCtx.view\n\t\t\tprevNode = self._prv,\n\t\t\telCnt = self._elCnt,\n\t\t\ttags = [];\n\n\t\tif (!self.args) { // If tagCtx with no content (so no contentView) self is tagCtx: return empty [];\n\t\t\tview.link(\n\t\t\t\tundefined,\n\t\t\t\tself.parentElem,\n\t\t\t\telCnt ? prevNode && prevNode.previousSibling : prevNode,\n\t\t\t\tself._nxt,\n\t\t\t\tundefined,\n\t\t\t\t{get:{\n\t\t\t\t\ttags: tags,\n\t\t\t\t\tdeep: deep,\n\t\t\t\t\tname: tagName,\n\t\t\t\t\tid: self.link ? self._.id + \"_\" : self._tgId + \"^\"\n\t\t\t\t}}\n\t\t\t);\n\t\t}\n\t\treturn tags;\n\t};\n\n\tif (tagOrView._is === \"tag\") {\n\t\t//=======================\n\t\t// This is a TAG instance\n\t\t//=======================\n\n\t\ttheTag = tagOrView;\n\n\t\tm = theTag.tagCtxs.length;\n\t\twhile (m--) {\n\t\t\ttagCtx = theTag.tagCtxs[m];\n\n\t\t\ttagCtx.setValues = setValues;\n\t\t\ttagCtx.cvtArgs = convertArgs;\n\t\t\ttagCtx.bndArgs = convertBoundArgs;\n\t\t\ttagCtx.contents = tagOrView.contents;\n\t\t\ttagCtx.childTags = tagOrView.childTags;\n\t\t\ttagCtx.nodes = tagOrView.nodes;\n\t\t}\n\n\t\tboundProps = theTag.boundProps = theTag.boundProps || [];\n\t\tif (bindTo = theTag.linkTo ? [\"linkTo\"] : theTag.bindTo) {\n\t\t\tl = bindTo.length;\n\t\t\twhile (l--) {\n\t\t\t\tkey = bindTo[l];\n\t\t\t\tif (key + \"\" === key) {\n\t\t\t\t\tbindTo[key] = 1;\n\t\t\t\t\tif ($.inArray(key, boundProps) < 0) {\n\t\t\t\t\t\tboundProps.push(key); // Add any 'bindTo' props to boundProps array. (So two-way binding works without writing ^foo=expression)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttheTag.setValue = $sub._gm(theTag.constructor.prototype.setValue, function(val, index, tagElse) {\n\t\t\tif (!arguments.length) { // tag.setValue() calls setValue(val, index) for each parameter in bindTo array\n\t\t\t\ttheTag.setValues(); // = theTag.bndArgs()\n\t\t\t\treturn theTag;\n\t\t\t}\n\t\t\tvar linkedElem, linkedEl, linkedTag,\n\t\t\t\tlinkedCtxParam = theTag.linkedCtxParam,\n\t\t\t\ttagCtx = theTag.tagCtxs[tagElse || 0],\n\t\t\t\tprops = tagCtx.props,\n\t\t\t\tlinkCtx = theTag.linkCtx,\n\t\t\t\tlinkedElems = tagCtx.linkedElems || theTag.linkedElem && [theTag.linkedElem];\n\n\t\t\tif (val !== undefined) {\n\t\t\t\ttheTag.base.call(theTag , val, index, tagElse);\n\t\t\t} else if (theTag.getValue && (val = theTag.getValue(tagElse)) && val !== undefined) {\n\t\t\t\t// If bound args are not initialized, and getValue is defined, use getValue to initialize\n\t\t\t\tif (theTag.bindTo.length > 1) {\n\t\t\t\t\tval = val[index]; // getVal returns value if tag.bndArgs() (and bindTo) length is 1, or array of values if bindTo.length > 1\n\t\t\t\t}\n\t\t\t\tif (linkedCtxParam && linkedCtxParam[index]) {\n\t\t\t\t\t// Values of tag contextual param were already intialized (during rendering) so need to observably update to values from tag.getValue()\n\t\t\t\t\t$.observable(tagCtx.ctx[linkedCtxParam[index]][0]).setProperty(_ocp, val);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ((linkedElem = linkedElems && linkedElems[index]) && linkedElem[0]) {\n\t\t\t\tl = linkedElem.length;\n\t\t\t\twhile (l--) {\n\t\t\t\t\tlinkedEl = linkedElem[l];\n\t\t\t\t\tif (theTag._.unlinked) {\n\t\t\t\t\t\tlinkedTag = linkedEl._jsvLkEl;\n\t\t\t\t\t\tif (!linkedTag || linkedTag !== theTag) {\n\t\t\t\t\t\t\tif (linkedTag) {\n\t\t\t\t\t\t\t\tval = linkedTag.cvtArgs(true, tagElse)[index]; // Need to use converter of linked tag\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// For data-linked tags, identify the linkedEl with the tag, for \"to\" binding\n\t\t\t\t\t\t\t// (For data-linked elements, if not yet bound, we identify later when the linkCtx.elem is bound)\n\t\t\t\t\t\t\tlinkedEl._jsvLkEl = theTag;\n\t\t\t\t\t\t\tlinkedEl._jsvInd = index;\n\t\t\t\t\t\t\tlinkedEl._jsvElse = tagElse;\n\t\t\t\t\t\t\tbindLinkedElChange(theTag, linkedEl);\n\t\t\t\t\t\t\tlinkedEl._jsvBnd = \"&\" + theTag._tgId + \"+\"; // Add a \"+\" for cloned binding - so removing\n\t\t\t\t\t\t\t// elems with cloned bindings will not remove the 'parent' binding from the bindingStore.\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (val !== undefined && !linkedEl._jsvChg && linkCtx._val !== val) {\n\t\t\t\t\t\tif (linkedEl.value !== undefined) {\n\t\t\t\t\t\t\tif (linkedEl.type === CHECKBOX) {\n\t\t\t\t\t\t\t\tlinkedEl[CHECKED] = val && val !== \"false\";\n\t\t\t\t\t\t\t} else if (linkedEl.type === RADIO) {\n\t\t\t\t\t\t\t\tlinkedEl[CHECKED] = (linkedEl.value === val);\n\t\t\t\t\t\t\t} else if ($isArray(val)) {\n\t\t\t\t\t\t\t\tlinkedEl.value = val; // Don't use jQuery since it replaces array by mapped clone\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t$(linkedEl).val(val); // Use jQuery for attrHooks - can't just set value (on select, for example)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (linkedEl.contentEditable === TRUE) {\n\t\t\t\t\t\t\tlinkedEl.innerHTML = val;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (props.name) {\n\t\t\t\t\t\tlinkedEl.name = linkedEl.name || props.name;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn theTag;\n\t\t});\n\n\t\ttheTag.updateValue = updateValue;\n\n\t\ttheTag.updateValues = function() {\n\t\t\treturn updateValues(arguments, undefined, this);\n\t\t};\n\n\t\ttheTag.setValues = function() {\n\t\t\tvar m = arguments.length ? 1 : theTag.tagCtxs.length;\n\t\t\twhile (m--) {\n\t\t\t\tsetValues.apply(theTag.tagCtxs[m], arguments);\n\t\t\t}\n\t\t};\n\n\t\ttheTag.refresh = function(sourceValue) {\n\t\t\tvar attr,\n\t\t\t\tlinkCtx = theTag.linkCtx,\n\t\t\t\tview = theTag.tagCtx.view;\n\n\t\t\tif (theTag.onUnbind) {\n\t\t\t\ttheTag.onUnbind(theTag.tagCtx, linkCtx, theTag.ctx);\n\t\t\t}\n\t\t\tattr = theTag.inline ? HTML : (linkCtx.attr || defaultAttr(theTag.parentElem, true));\n\t\t\tsourceValue = $sub._tag(theTag, view, view.tmpl, mergeCtxs(theTag), true); // Get rendered HTML for tag, based on refreshed tagCtxs\n\t\t\tupdateContent(sourceValue, linkCtx, attr, theTag);\n\t\t\tcallAfterLink(theTag);\n\t\t\treturn theTag;\n\t\t};\n\n\t\ttheTag.domChange = function() { // domChange notification support\n\t\t\tvar elem = this.parentElem,\n\t\t\t\thasListener = $.hasData(elem) && $._data(elem).events,\n\t\t\t\tdomChangeNotification = \"jsv-domchange\";\n\n\t\t\tif (hasListener && hasListener[domChangeNotification]) {\n\t\t\t\t// Only trigger handler if there is a handler listening for this event. (Note using triggerHandler - so no event bubbling.)\n\t\t\t\t$(elem).triggerHandler(domChangeNotification, arguments);\n\t\t\t}\n\t\t};\n\n\t\t//====================================\n\t\t// End of added link methods for TAG\n\t\t//====================================\n\t} else {\n\t\t//=========================\n\t\t// This is a VIEW prototype\n\t\t//=========================\n\n\t\ttheView = tagOrView;\n\n\t\t// Note: a linked view will also, after linking have nodes[], _prv (prevNode), _nxt (nextNode) ...\n\t\ttheView.addViews = function(index, dataItems) {\n\t\t\t// if view is not an array view, do nothing\n\t\t\tvar i, viewsCount,\n\t\t\t\tview = this,\n\t\t\t\titemsCount = dataItems.length,\n\t\t\t\tviews = view.views;\n\n\t\t\tif (!view._.useKey && itemsCount) {\n\t\t\t\t// view is of type \"array\"\n\t\t\t\tviewsCount = views.length + itemsCount;\n\n\t\t\t\tif (viewsCount === view.data.length // If views not already synced to array (e.g. triggered by array.length propertyChange - jsviews/issues/301)\n\t\t\t\t\t\t&& renderAndLink(view, index, view.tmpl, views, dataItems, view.ctx) !== false) {\n\t\t\t\t\tif (!view._.srt) { // Not part of a 'sort' on refresh\n\t\t\t\t\t\tview.fixIndex(index + itemsCount);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\ttheView.removeViews = function(index, itemsCount, keepNodes, isMove) {\n\t\t\t// view.removeViews() removes all the child views\n\t\t\t// view.removeViews(index) removes the child view with specified index or key\n\t\t\t// view.removeViews(index, count) removes the specified nummber of child views, starting with the specified index\n\t\t\tfunction removeView(index) {\n\t\t\t\tvar id, bindId, parentElem, prevNode, nextNode, nodesToRemove,\n\t\t\t\t\tviewToRemove = views[index];\n\n\t\t\t\tif (viewToRemove && viewToRemove.link) {\n\t\t\t\t\tid = viewToRemove._.id;\n\t\t\t\t\tif (!keepNodes) {\n\t\t\t\t\t\t// Remove the HTML nodes from the DOM, unless they have already been removed, including nodes of child views\n\t\t\t\t\t\tnodesToRemove = viewToRemove.nodes();\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove child views, without removing nodes\n\t\t\t\t\tviewToRemove.removeViews(undefined, undefined, true);\n\n\t\t\t\t\tviewToRemove.type = undefined; // Set type to undefined: used as a flag that this view is being removed\n\t\t\t\t\tprevNode = viewToRemove._prv;\n\t\t\t\t\tnextNode = viewToRemove._nxt;\n\t\t\t\t\tparentElem = viewToRemove.parentElem;\n\t\t\t\t\t// If prevNode and nextNode are the same, the view is empty\n\t\t\t\t\tif (!keepNodes) {\n\t\t\t\t\t\t// Remove the HTML nodes from the DOM, unless they have already been removed, including nodes of child views\n\t\t\t\t\t\tif (viewToRemove._elCnt) {\n\t\t\t\t\t\t\t// if keepNodes is false (and transferring of tokens has not already been done at a higher level)\n\t\t\t\t\t\t\t// then transfer tokens from prevNode which is being removed, to nextNode.\n\t\t\t\t\t\t\ttransferViewTokens(prevNode, nextNode, parentElem, id, \"_\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$(nodesToRemove).remove();\n\t\t\t\t\t}\n\t\t\t\t\tif (!viewToRemove._elCnt) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tprevNode.parentNode.removeChild(prevNode); // (prevNode.parentNode is parentElem, except if jQuery Mobile or similar has inserted an intermediate wrapper\n\t\t\t\t\t\t\tnextNode.parentNode.removeChild(nextNode);\n\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t}\n\t\t\t\t\tsetArrayChangeLink(viewToRemove);\n\t\t\t\t\tfor (bindId in viewToRemove._.bnds) {\n\t\t\t\t\t\tremoveViewBinding(bindId);\n\t\t\t\t\t}\n\t\t\t\t\tdelete viewStore[id];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar current, childView, viewsCount,\n\t\t\t\tview = this,\n\t\t\t\tisArray = !view._.useKey,\n\t\t\t\tviews = view.views;\n\n\t\t\tif (isArray) {\n\t\t\t\tviewsCount = views.length;\n\t\t\t}\n\t\t\tif (index === undefined) {\n\t\t\t\t// Remove all child views\n\t\t\t\tif (isArray) {\n\t\t\t\t\t// views and data are arrays\n\t\t\t\t\tcurrent = viewsCount;\n\t\t\t\t\twhile (current--) {\n\t\t\t\t\t\tremoveView(current);\n\t\t\t\t\t}\n\t\t\t\t\tview.views = [];\n\t\t\t\t} else {\n\t\t\t\t\t// views and data are objects\n\t\t\t\t\tfor (childView in views) {\n\t\t\t\t\t\t// Remove by key\n\t\t\t\t\t\tremoveView(childView);\n\t\t\t\t\t}\n\t\t\t\t\tview.views = {};\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (itemsCount === undefined) {\n\t\t\t\t\tif (isArray) {\n\t\t\t\t\t\t// The parentView is data array view.\n\t\t\t\t\t\t// Set itemsCount to 1, to remove this item\n\t\t\t\t\t\titemsCount = 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Remove child view with key 'index'\n\t\t\t\t\t\tremoveView(index);\n\t\t\t\t\t\tdelete views[index];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (isArray && itemsCount\n\t\t\t\t\t&& (isMove || viewsCount - itemsCount === view.data.length)) { // If views not already synced to array (e.g. triggered by array.length propertyChange - jsviews/issues/301)\n\t\t\t\t\tcurrent = index + itemsCount;\n\t\t\t\t\t// Remove indexed items (parentView is data array view);\n\t\t\t\t\twhile (current-- > index) {\n\t\t\t\t\t\tremoveView(current);\n\t\t\t\t\t}\n\t\t\t\t\tviews.splice(index, itemsCount);\n\t\t\t\t\tif (!view._.srt) {\n\t\t\t\t\t\tview.fixIndex(index);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\ttheView.moveViews = function(oldIndex, index, itemsCount) {\n\t\t\tfunction parts(itemView, str) {\n\t\t\t\treturn RegExp(\"^(.*)(\" + (str ? \"\\\\/\" : \"#\") + itemView._.id + \"_.*)$\").exec(str || itemView._prv.getAttribute(jsvAttrStr));\n\t\t\t}\n\t\t\tfunction setPrv(itemView, tokens) {\n\t\t\t\titemView._prv.setAttribute(jsvAttrStr, tokens);\n\t\t\t}\n\t\t\tvar nodes, childView, nxtView, insertBefore, viewId,\n\t\t\t\tview = this,\n\t\t\t\tselfNxt = view._nxt,\n\t\t\t\tviews = view.views,\n\t\t\t\tbackwards = index < oldIndex,\n\t\t\t\tfirstChange = backwards ? index : oldIndex,\n\t\t\t\tlastChange = backwards ? oldIndex : index,\n\t\t\t\ti = index,\n\t\t\t\tmovedNodes = [],\n\n\t\t\t\tviewsToMove = views.splice(oldIndex, itemsCount); // remove\n\n\t\t\tif (index > views.length) {\n\t\t\t\tindex = views.length;\n\t\t\t}\n\t\t\tviews.splice.apply(views, [index, 0].concat(viewsToMove)); //re-insert\n\n\t\t\titemsCount = viewsToMove.length;\n\t\t\tinsertBefore = index + itemsCount;\n\t\t\tlastChange += itemsCount;\n\n\t\t\tfor (i; i < insertBefore; i++) {\n\t\t\t\tchildView = views[i];\n\t\t\t\tnodes = childView.nodes(true);\n\t\t\t\tmovedNodes = view._elCnt ? movedNodes.concat(nodes) : movedNodes.concat(childView._prv, nodes, childView._nxt);\n\t\t\t}\n\t\t\tmovedNodes = $(movedNodes);\n\n\t\t\tif (insertBefore < views.length) {\n\t\t\t\tmovedNodes.insertBefore(views[insertBefore]._prv);\n\t\t\t} else if (selfNxt) {\n\t\t\t\tmovedNodes.insertBefore(selfNxt);\n\t\t\t} else {\n\t\t\t\tmovedNodes.appendTo(view.parentElem);\n\t\t\t}\n\n\t\t\tif (view._elCnt) {\n\t\t\t\tvar afterParts,\n\t\t\t\t\tendChange = backwards ? firstChange + itemsCount : lastChange - itemsCount,\n\t\t\t\t\tbeforeView = views[firstChange-1],\n\t\t\t\t\tstartView = views[firstChange],\n\t\t\t\t\tendView = views[endChange],\n\t\t\t\t\tafterView = views[lastChange],\n\t\t\t\t\tstartParts = parts(startView),\n\t\t\t\t\tendParts = parts(endView);\n\n\t\t\t\tsetPrv(startView, endParts[1] + startParts[2]);\n\t\t\t\tif (afterView) {\n\t\t\t\t\tafterParts = parts(afterView);\n\t\t\t\t\tsetPrv(afterView, startParts[1] + afterParts[2]);\n\t\t\t\t} else {\n\t\t\t\t\tif (selfNxt) {\n\t\t\t\t\t\tafterParts = parts(view, selfNxt.getAttribute(jsvAttrStr));\n\t\t\t\t\t\tselfNxt.setAttribute(jsvAttrStr, startParts[1] + afterParts[2]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tafterParts = parts(view, view.parentElem._df);\n\t\t\t\t\t\tsetDefer(view.parentElem, startParts[1] + afterParts[2]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsetPrv(endView, afterParts[1] + endParts[2]);\n\t\t\t\tif (beforeView) {\n\t\t\t\t\tbeforeView._nxt = startView._prv;\n\t\t\t\t} else {\n\t\t\t\t\tview._prv = startView._prv;\n\t\t\t\t}\n\t\t\t\tviews[endChange-1]._nxt = endView._prv;\n\t\t\t\tviews[lastChange-1]._nxt = afterView ? afterView._prv : selfNxt;\n\t\t\t}\n\t\t\tview.fixIndex(firstChange);\n\t\t};\n\n\t\ttheView.refresh = function() {\n\t\t\tvar view = this,\n\t\t\t\tparent = view.parent;\n\n\t\t\tif (parent) {\n\t\t\t\trenderAndLink(view, view.index, view.tmpl, parent.views, view.data, undefined, true);\n\t\t\t\tsetArrayChangeLink(view);\n\t\t\t}\n\t\t};\n\n\t\ttheView.fixIndex = function(fromIndex) {\n\t\t\t// Fixup index on following view items...\n\t\t\tvar views = this.views,\n\t\t\t\tindex = views.length;\n\t\t\twhile (fromIndex < index--) {\n\t\t\t\tif (views[index].index !== index) {\n\t\t\t\t\t$observable(views[index]).setProperty(\"index\", index);\n\t\t\t\t\t// This is fixing up index, but not key, and not index on child views. From child views, use view.getIndex()\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\ttheView.link = viewLink;\n\n\t\t//====================================\n\t\t// End of added link methods for VIEW\n\t\t//====================================\n\t}\n}\n\n//========================\n// JsViews-specific converters\n//========================\n\n$converters.merge = function(val) {\n\t// Special converter used in data-linking to space-separated lists, such as className:\n\t// Currently only supports toggle semantics - and has no effect if toggle string is not specified\n\t// data-link=\"class{merge:boolExpr toggle=className}\"\n\tvar regularExpression,\n\t\tcurrentValue = this.linkCtx.elem.className,\n\t\ttoggle = this.tagCtx.props.toggle;\n\n\tif (toggle) {\n\t\t// We are toggling the class specified by the toggle property,\n\t\t// and the boolean val binding is driving the insert/remove toggle\n\n\t\tregularExpression = toggle.replace(/[\\\\^$.|?*+()[{]/g, \"\\\\$&\");\n\t\t// Escape any regular expression special characters (metacharacters) within the toggle string\n\t\tregularExpression = \"(\\\\s(?=\" + regularExpression + \"$)|(\\\\s)|^)(\" + regularExpression + \"(\\\\s|$))\";\n\t\t// Example: /(\\s(?=myclass$)|(\\s)|^)?(myclass(\\s|$))/ - so matches (\" myclass\" or \" \" or ^ ) followed by (\"myclass \" or \"myclass$\") where ^/$ are beginning/end of string\n\t\tcurrentValue = currentValue.replace(new RegExp(regularExpression), \"$2\");\n\t\tval = currentValue + (val ? (currentValue && \" \") + toggle : \"\");\n\t}\n\treturn val;\n};\n\n//========================\n// JsViews-specific tags\n//========================\n\n$tags({\n\ton: {\n\t\tattr: NONE,\n\t\tinit: function(tagCtx) {\n\t\t\tvar content,\n\t\t\t\ttag = this,\n\t\t\t\ti = 0,\n\t\t\t\targs = tagCtx.args, // [events,] [selector,] handler\n\t\t\t\tl = args.length;\n\n\t\t\tfor (; ii && i+1; // handler index\n\t\t\tif (tag.inline) {\n\t\t\t\tif (!$sub.rTmpl.exec(content = $.trim(tagCtx.tmpl.markup))) {\n\t\t\t\t\t// Inline {^{on}} tag with no content (or external template content) or with content containing\n\t\t\t\t\t// no HTML or JsRender tags: We will wrap the (text) content, or the operation name in a \";\n\t\t\t\t}\n\t\t\t\ttag.attr = HTML;\n\t\t\t}\n\t\t},\n\t\tonBind: function() {\n\t\t\tif (this.template) { // {^{on/}} with no content has template rendering
\", \"
\"],\n\t\ttr: [2, \"\", \"
\"],\n\t\ttd: [3, \"\", \"
\"],\n\t\tcol: [2, \"\", \"
\"],\n\t\tsvg_ns: [1, \"\", \"\"],\n\t\t// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,\n\t\t// unless wrapped in a div with non-breaking characters in front of it.\n\t\tdiv: $.support.htmlSerialize ? [0, \"\", \"\"] : [1, \"X
\", \"
\"]\n\t},\n\t_fe: {\n\t\tinput: {\n\t\t\tfrom: inputAttrib, to: VALUE\n\t\t},\n\t\ttextarea: valueBinding,\n\t\tselect: valueBinding,\n\t\toptgroup: {\n\t\t\tto: \"label\"\n\t\t}\n\t}\n});\n\nreturn $;\n}, window));\n"]} \ No newline at end of file +{"version":3,"sources":["jsviews.js"],"names":["factory","global","$","jQuery","exports","module","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","getPathObject","ob","path","ltOb","fn","prevOb","tokens","split","lt","contextParameter","key","value","wrapped","deps","res","obsCtxPrm","tagElse","callView","newRes","storeView","isUpdate","isRenderCall","store","ctx","hasOwnProperty","$helpers","it","linked","_cxp","scope","isTop","_ocps","_ocp","_vw","_key","ind","updateValue","observable","setProperty","_ceo","unshift","cvtArgs","data","_ucp","getTemplate","tmpl","getRsc","$templates","convertVal","converter","onError","argsLen","bindTo","boundTag","bnds","linkCtx","_lr","args","_bd","_tg","bnd","unlinked","inline","tagName","convert","flow","tagCtxs","_is","extendCtx","_er","onRender","convertArgs","bound","boundArgs","bindFrom","error","slice","argOrProp","context","convertBoundArgs","getResource","resourceType","itemName","renderTag","parentView","bindToOrBindFrom","bindArray","m","isNaN","parseInt","topView","tagDef","template","tags","attr","parentTag","n","itemRet","tagCtxCtx","ctxPrm","initVal","content","callInit","mapDef","thisMap","bdArgs","tagDataMap","contentCtx","bindFromLength","bindToLength","linkedElement","defaultCtx","parentTmpl","lateRender","params","tmpls","render","renderContent","bndArgs","getTmpl","init","_ctr","ths","arrVws","dataBoundOnly","dataMap","map","parents","parentTags","rendering","rndr","argDefault","linkedCtxParam","fromIndex","toIndex","_dfAt","noVws","HTML","_cp","cvt","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","j","g","getters","getter","viewModels","JSON","parse","merge","viewModel","$expando","getterNames","mod","assigned","newModArr","k","model","$observable","refresh","concat","extend","proto","body","privField","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","noLinking","_wrp","syntaxError","nl","helpers","contentView","onRenderError","fallback","Err","isLinkExpr","convertBack","hasElse","pushprecedingContent","shift","loc","substr","rNewLine","blockTagCheck","block","parseTag","all","bind","colon","codeTag","slash","bind2","closeBlock","late","openTagName","isLateOb","pathBindings","ctxProps","paramsArgs","paramsProps","paramsCtxProps","useTrigger","allowCode","rUnescapeQuotes","rTestElseIf","current","substring","stack","pop","parseParams","rBuildHash","onerror","isCtxPrm","keyToken","keyValue","arg","param","hasHandlers","newNode","parsedParam","bindings","astTop","buildCode","setPaths","pathsArr","paths","skp","paramStructure","parts","parseTokens","lftPrn0","lftPrn","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","join","expr","exprFn","newOb","rtSq","aposed","quoted","boundName","bndStack","prm","tmplLinks","indexOf","paramIndex","rPath","fnCall","0","rBracketQuote","rParams","ast","node","hasTag","hasEncoder","getsVal","hasCnvt","useCnvt","tmplBindings","boundOnErrStart","boundOnErrEnd","tagRender","nestedTmpls","nestedTmpl","tagAndElses","nextIsElse","oldCode","isElse","isGetVal","tagCtxFn","tagStart","trigger","retStrOpen","retStrClose","tmplBindingKey","templates","converters","code","tmplOptions","debug","debugMode","_tag","parentContext","getTargetProps","noFunctions","isFunction","getTargetSorted","mapped","start","end","propParams","filter","sort","directSort","step","reverse","v","a","b","onFilter","sorted","paged","$fnRender","tmplElem","jquery","getCharEntity","ch","charEntities","charCodeAt","getCharFromEntity","match","token","charsFromEntities","htmlEncode","text","rIsHtml","rHtmlEncode","dataEncode","rDataEncode","dataUnencode","rDataUnencode","updateValues","sourceValues","bindId","ev","cvtBack","cnvtName","binding","sourceValue","origVals","sourceElem","sourceEl","oldLinkCtx","tos","to","tcpTag","exprOb","contextCb","_tgId","defineBindToDataTargets","bindingStore","chg","nodeName","multiple","_jsvSel","onBeforeUpdateVal","change","setValue","_jsvInd","_jsvLkEl","_jsvElse","_ctxCb","_cpCtx","onElemChange","fromAttr","defaultAttr","setter","fnSetters","_jsvTr","delegateTarget","activeBody","_jsvChg","rSplitBindings","lastIndex","_jsvBnd","onDataLinkedTagChange","eventArgs","noUpdate","forceUpdate","hasError","bindEarly","linkFn","parentElem","parentNode","onEvent","changeHandler","onBeforeChangeStr","_toLk","VALUE","CHECKBOX","CHECKED","onUpdate","mergeCtxs","NONE","callAfterLink","observeAndBind","onAfterChangeStr","onUnbind","_cnvt","TRUE","addLinkMethods","updateContent","_noUpd","setDefer","_df","deferAttr","prevNode","nextNode","nodesToRemove","useProp","openIndex","closeIndex","testElem","cStyle","jsvSel","renders","targetParent","$target","targetVal","_val","_elCnt","_prv","_nxt","currentStyle","getComputedStyle","display","_jsvd","displayStyles","createElement","appendChild","removeChild","style","RADIO","nodes","transferViewTokens","jsvAttrStr","disposeTokens","previousSibling","lastChild","remove","empty","children","TEXTCONTENT","selected","$inArray","lateLink","arrayChangeHandler","onBeforeChange","onAfterChange","items","srt","addViews","removeViews","moveViews","oldIndex","fixIndex","setArrayChangeLink","handler","arrayBinding","bndArr","off","arrayChangeStr","on","linkGetVal","_fe","contentEditable","from","renderAndLink","linkToNode","prevView","elCnt","removeViewBinding","nextSibling","addBindingMarkers","bindingKey","viewStore","linkedElem","exprFnDeps","propDeps","tagDepends","linkedElems","cvtBk","_hdl","_dp","_depends","bdId","_apply","boundProps","_bndId","bindLinkedElChange","lnkCtx","tmplLink","$link","tmplOrLinkExpr","useInput","elementChangeStr","vwInfos","placeholderParent","targetEl","topLevelCall","replaceMode","$view","addDataBinding","cleanData","lnk","viewInfos","rOpenViewMarkers","viewLink","outerData","validateOnly","convertMarkers","preceding","selfClose","closeTag","spaceBefore","boundId","spaceAfter","tag1","tag2","closeTag2","spaceAfterClose","selfClose2","endOpenTag","errorMsg","bndId","endOfElCnt","inTag","isVoid","tagStack","validate","voidElems","prevElCnt","elContent","defer","ids","openScript","closeScript","deferStack","badParent","processViewInfos","deferPath","deferChar","bindChar","onAftCr","deep","addedBindEls","_tkns","len","vwInfo","open","onArrayChange","removeSubStr","onAfterCreateStr","onAfterCreate","bindEls","getViewInfos","level","tagDepth","dataLink","wrap","selector","linkViewsSel","elems","qsa","querySelectorAll","prevNodes","markerNodeInfo","contains","isLink","rViewMarkers","skip","processInfos","$viewsLinkAttr","rOpenTagMarkers","unmarkPrevOrNextNode","prevIds","linkInfo","nextView","depth","fragment","copiedNode","firstTag","wrapper","thisId","noValidate","markPrevOrNextNode","namespaceURI","rConvertMarkers","safeFragment","createDocumentFragment","firstChild","insertBefore","linkMarkup","currentView","boundTagId","tagExpr","rTagIndex","linkExpressions","bindDataLinkTarget","normalizeLinkTag","rTagDatalink","isLk","_gccb","$elem","str","SCRIPT","isVal","rBinding","getInfos","close","elPath","infos","rMarkerTokens","removeAttribute","marker","twoway","copyFromTagCtxToTag","mainElem","displayElem","linkedElements","$linkCtxElem","linkCtxElem","linkedEl","linkedTag","tagCtxElse","oldVal","indexTo","tagCtxslength","mainElement","displayElement","Array","contents","onBind","setSize","height","width","className","_jsvCl","hasClass","removeClass","addClass","onAfterLink","asyncOnElemChange","which","setTimeout","bindTriggerEvent","trig","onoff","isIE","$linkedElem","newTrig","oldTrig","pathIndex","lastPath","bindtoOb","targetPaths","bindTos","targetPathsElses","resolveDataTargetPath","targetPath","topCp","newCtxs","newTagCtx","_thp","clean","elemArray","linkedElemTag","objId","obsId","allLinkedElems","cbId","propertyChangeStr","onDispose","cbBindingsStore","$unlink","each","innerView","getElementsByTagName","inputAttrib","viewOrTagChar","viewOrTag","precedingLength","emptyView","vwItem","rOpenMarkers","async","values","setValues","tagOrView","theTag","theView","select","filtered","add","find","withMarkers","prevIsFirstNode","lastSibling","childTags","_gm","indexFrom","linkedCtxPrmKey","newVal","domChange","hasListener","_data","events","domChangeNotification","triggerHandler","dataItems","viewsCount","itemsCount","keepNodes","isMove","removeView","viewToRemove","itemView","setPrv","prv","rTagMarkers","selfNxt","backwards","firstChange","lastChange","movedNodes","viewsToMove","appendTo","afterParts","endChange","startView","endView","afterView","startParts","endParts","observeProps","update","insert","observeMappedProps","removeProperty","oldValue","shallowArrayFilter","rShallowArrayPath","setGlobals","jsvStoreName","$observe","setting","versionNumber","rAttrEncode","&","<",">","\u0000","'","\"","`","=","amp","gt","$render","jsr","jsrender","jsrToJq","jsviews","sub","syntaxErr","settings","advSet","_err","_sq","advanced","Error","getOb","expando","renderFile","__express","obj","_jq","jq","_jsv","if","done","for","sortDataMap","cloned","range","include","*",":*","dbg","encode","unencode","url","encodeURI","observe","$eventSpecial","event","special","PARSEINT","rNotWhite","rShallowPath","propChng","arrChng","observeStr","observeObjKey","observeCbKey","observeInnerCbKey","$data","getCbKey","cb","_cId","ObjectObservable","ns","_ns","ArrayObservable","wrapArray","dependsPaths","callback","rt","nextObj","out","_ar","removeCbBindings","cbBindings","cbBindingsId","onDataChange","isOb","noArray","parentObs","observeAll","arOk","array","_path","observe_apply","$observeAll","unobserve","$unobserveAll","namespace","objMap","observeArrayItems","unobs","newAllPath","filterAndObserveAll","nestedArray","newObject","newParentObs","_fltr","nextParentObs","updatedTgt","wrappedCb","isObject","obId","notRemoving","un","hasData","shallowFilter","$unobserve","innerObserve","unobserveBinding","observeOnOff","fullPath","pathStr","isArrayBinding","evData","boundObOrArr","prntObs","allPth","initialNs","el","allowArray","inArray","unbind","relPath","prevAllPath","observeObjects","observeObjectPaths","pths","getInnerCb","newObj","observePath","prts","obArrAddRemove","arrIndex","dep","obArr","prt","_inId","pth","innerCb","p","inId","initNsArr","initNsArrLen","lastArg","Object","unobserveAll","nonStrict","pair","multi","_setProperty","leaf","removeProp","property","Date","_trigger","_insert","oldLength","numToRemove","_remove","move","newIndex","numToMove","_move","excess","newItems","insertAdded","addedItems","dataLength","newItem","num","oldItems","newLength","_srt","$_data","handleObj","oldMapOrTarget","unbound","changing","updatedMap","obsSrc","obs","srcFlt","obsTgt","obt","_updt","tgtFlt","oldMap","newMap","_def","_gck","_obs","oldAdvSet","window","navigator","userAgent","textContent","bindElsSel","input","valueBinding","isCleanCall","oldCleanData","oldJsvDelimiters","querySelector","ol","ul","table","tbody","thead","tfoot","tr","colgroup","dl","optgroup","svg","svg_ns","br","img","hr","area","col","meta","command","embed","keygen","track","wbr","rViewPath","requiresStr","regularExpression","currentValue","toggle","_hi","activeElem","contextOb","_sel","_evs","_hlr","radiogroup","Math","random","domChngCntnr","useDisable","disabled","forOrIfTagCtx","checked","arrayView","targetLength","arrayBindings","_ars","tagCt","newTagCtxs","prevArg","different","tci","getInnerView","nd","isVl","unlink","oldFn","_glt","regEx","linkCtxs","last","nextPath","addedTagCpDep","paramVal","paramExpr","tagCtxPrm","cloneExprObjects","clones","linkAttr","option","caption","th","td","legend","support","htmlSerialize","textarea"],"mappings":"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","file":"jsviews.min.js","sourcesContent":["/*! jsviews.js v0.9.91 (Beta) single-file version: http://jsviews.com/ */\n/*! includes JsRender, JsObservable and JsViews - see: http://jsviews.com/#download */\n\n/* Interactive data-driven views using JsRender templates */\n\n//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< JsRender >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n/* JsRender:\n * See http://jsviews.com/#jsrender and http://github.com/BorisMoore/jsrender\n * Copyright 2018, 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 jQuery passed as parameter: require(\"jsviews\")(jQuery)\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([\"jquery\"], function($) {\n\t\t\treturn factory(global, $);\n\t\t}); // Require jQuery\n\t} else { // Browser using plain ',\n\topenScript = ' - data-linked tag, close marker\n\t\t\t// We validate with inTag so no script markers are inserted in attribute context e.g. for:\n\t\t\t// \"\" or \"
...{{/if}}...\"\n\t\t\tpreceding = id\n\t\t\t\t? (preceding + endOfElCnt + spaceBefore + (inTag ? \"\" : openScript + id + closeScript)+ spaceAfter + tag)\n\t\t\t\t: endOfElCnt || all;\n\t\t}\n\n\t\tif (validate && boundId) {\n\t\t\tif (inTag) {\n\t\t\t\t// JsViews data-linking tags are not allowed within element markup.\n\t\t\t\t// See jsviews/issues/303\n\t\t\t\tsyntaxError('{^{ within elem markup (' + inTag + ' ). Use data-link=\"...\"');\n\t\t\t}\n\t\t\tif (id.charAt(0) === \"#\") {\n\t\t\t\ttagStack.unshift(id.slice(1));\n\t\t\t} else if (id.slice(1) !== (bndId = tagStack.shift())) {\n\t\t\t\t// See jsviews/issues/213\n\t\t\t\tsyntaxError('Closing tag for {^{...}} under different elem: <' + bndId + '>');\n\t\t\t}\n\t\t}\n\t\tif (tag) {\n\t\t\tinTag = tag;\n\t\t\t// If there are ids (markers since the last tag), move them to the defer string\n\t\t\ttagStack.unshift(parentTag);\n\t\t\tparentTag = tag.slice(1);\n\t\t\tif (validate && tagStack[0] && tagStack[0] === badParent[parentTag]) {\n\t\t\t\t// Missing \n\t\t\t\t// TODO: replace this by smart insertion of tags\n\t\t\t\terror('Parent of must be ');\n\t\t\t}\n\t\t\tisVoid = voidElems[parentTag];\n\t\t\tif ((elCnt = elContent[parentTag]) && !prevElCnt) {\n\t\t\t\tdeferStack.unshift(defer);\n\t\t\t\tdefer = \"\";\n\t\t\t}\n\t\t\tprevElCnt = elCnt;\n//TODO Consider providing validation which throws if you place as child of , etc. - since if not caught,\n//this can cause errors subsequently which are difficult to debug.\n//\t\t\t\tif (elContent[tagStack[0]]>2 && !elCnt) {\n//\t\t\t\t\terror(parentTag + \" in \" + tagStack[0]);\n//\t\t\t\t}\n\t\t\tif (defer && elCnt) {\n\t\t\t\tdefer += \"+\"; // Will be used for stepping back through deferred tokens\n\t\t\t}\n\t\t}\n\t\treturn preceding;\n\t}\n\n\tfunction processViewInfos(vwInfos, targetParent) {\n\t\t// If targetParent, we are processing viewInfos (which may include navigation through '+-' paths) and hooking up to the right parentElem etc.\n\t\t// (and elem may also be defined - the next node)\n\t\t// If no targetParent, then we are processing viewInfos on newly inserted content\n\t\tvar deferPath, deferChar, bindChar, parentElem, id, onAftCr, deep,\n\t\t\taddedBindEls = [];\n\n\t\t// In elCnt context (element-only content model), prevNode is the first node after the open, nextNode is the first node after the close.\n\t\t// If both are null/undefined, then open and close are at end of parent content, so the view is empty, and its placeholder is the\n\t\t// 'lastChild' of the parentNode. If there is a prevNode, then it is either the first node in the view, or the view is empty and\n\t\t// its placeholder is the 'previousSibling' of the prevNode, which is also the nextNode.\n\t\tif (vwInfos) {\n\t\t\tif (vwInfos._tkns.charAt(0) === \"@\") {\n\t\t\t\t// We are processing newly inserted content. This is a special script element that was created in convertMarkers() to process deferred bindings,\n\t\t\t\t// and inserted following the target parent element - because no element tags (outside elCnt) were encountered to carry those binding tokens.\n\t\t\t\t// We will step back from the preceding sibling of this element, looking at targetParent elements until we find the one that the current binding\n\t\t\t\t// token belongs to. Set elem to null (the special script element), and remove it from the DOM.\n\t\t\t\ttargetParent = elem.previousSibling;\n\t\t\t\telem.parentNode.removeChild(elem);\n\t\t\t\telem = undefined;\n\t\t\t}\n\t\t\tlen = vwInfos.length;\n\t\t\twhile (len--) {\n\t\t\t\tvwInfo = vwInfos[len];\n//if (prevIds.indexOf(vwInfo.token) < 0) { // This token is a newly created view or tag binding\n\t\t\t\tbindChar = vwInfo.ch;\n\t\t\t\tif (deferPath = vwInfo.path) {\n\t\t\t\t\t// We have a 'deferred path'\n\t\t\t\t\tj = deferPath.length - 1;\n\t\t\t\t\twhile (deferChar = deferPath.charAt(j--)) {\n\t\t\t\t\t\t// Use the \"+\" and\"-\" characters to navigate the path back to the original parent node where the deferred bindings ocurred\n\t\t\t\t\t\tif (deferChar === \"+\") {\n\t\t\t\t\t\t\tif (deferPath.charAt(j) === \"-\") {\n\t\t\t\t\t\t\t\tj--;\n\t\t\t\t\t\t\t\ttargetParent = targetParent.previousSibling;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttargetParent = targetParent.parentNode;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttargetParent = targetParent.lastChild;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Note: Can use previousSibling and lastChild, not previousElementSibling and lastElementChild,\n\t\t\t\t\t\t// since we have removed white space within elCnt. Hence support IE < 9\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (bindChar === \"^\") {\n\t\t\t\t\tif (tag = bindingStore[id = vwInfo.id]) {\n\t\t\t\t\t\t// The binding may have been deleted, for example in a different handler to an array collectionChange event\n\t\t\t\t\t\t// This is a tag binding\n\t\t\t\t\t\tdeep = targetParent && (!elem || elem.parentNode !== targetParent); // We are stepping back looking for the right targetParent,\n\t\t\t\t\t\t// or we are linking existing content and this element is in elCnt, not an immediate child of the targetParent.\n\t\t\t\t\t\tif (!elem || deep) {\n\t\t\t\t\t\t\ttag.parentElem = targetParent;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (vwInfo.elCnt && deep) {\n\t\t\t\t\t\t\t// With element only content, if there is no following element, or if the binding is deeper than the following element\n\t\t\t\t\t\t\t// then we need to set the open or close token as a deferred binding annotation on the parent\n\t\t\t\t\t\t\tsetDefer(targetParent, (vwInfo.open ? \"#\" : \"/\") + id + bindChar + (targetParent._df || \"\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// This is an open or close marker for a data-linked tag {^{...}}. Add it to bindEls.\n\t\t\t\t\t\taddedBindEls.push([deep ? null : elem, vwInfo]);\n\t\t\t\t\t}\n\t\t\t\t} else if (view = viewStore[id = vwInfo.id]) {\n\t\t\t\t\t// The view may have been deleted, for example in a different handler to an array collectionChange event\n\t\t\t\t\tif (!view.parentElem) {\n\t\t\t\t\t\t// If view is not already extended for JsViews, extend and initialize the view object created in JsRender, as a JsViews view\n\t\t\t\t\t\tview.parentElem = targetParent || elem && elem.parentNode || parentNode;\n\t\t\t\t\t\tview._.onRender = addBindingMarkers;\n\t\t\t\t\t\tview._.onArrayChange = arrayChangeHandler;\n\t\t\t\t\t\tsetArrayChangeLink(view);\n\t\t\t\t\t}\n\t\t\t\t\tparentElem = view.parentElem;\n\t\t\t\t\tif (vwInfo.open) {\n\t\t\t\t\t\t// This is an 'open view' node (preceding script marker node,\n\t\t\t\t\t\t// or if elCnt, the first element in the view, with a data-jsv annotation) for binding\n\t\t\t\t\t\tview._elCnt = vwInfo.elCnt;\n\t\t\t\t\t\tif (targetParent && !elem) {\n\t\t\t\t\t\t\tsetDefer(targetParent, \"#\" + id + bindChar + (targetParent._df || \"\"));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// No targetParent, so there is a ._nxt elem (and this is processing tokens on the elem)\n\t\t\t\t\t\t\tif (!view._prv) {\n\t\t\t\t\t\t\t\tsetDefer(parentElem, removeSubStr(parentElem._df, \"#\" + id + bindChar));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tview._prv = elem;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// This is a 'close view' marker node for binding\n\t\t\t\t\t\tif (targetParent && (!elem || elem.parentNode !== targetParent)) {\n\t\t\t\t\t\t\t// There is no ._nxt so add token to _df. It is deferred.\n\t\t\t\t\t\t\tsetDefer(targetParent, \"/\" + id + bindChar + (targetParent._df || \"\"));\n\t\t\t\t\t\t\tview._nxt = undefined;\n\t\t\t\t\t\t} else if (elem) {\n\t\t\t\t\t\t\t// This view did not have a ._nxt, but has one now, so token may be in _df, and must be removed. (No longer deferred)\n\t\t\t\t\t\t\tif (!view._nxt) {\n\t\t\t\t\t\t\t\tsetDefer(parentElem, removeSubStr(parentElem._df, \"/\" + id + bindChar));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tview._nxt = elem;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (onAftCr = changeHandler(view, onAfterCreateStr) || onAfterCreate) {\n\t\t\t\t\t\t\tonAftCr.call(view.ctx.tag, view);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n//}\n\t\t\t\t}\n\t\t\t}\n\t\t\tlen = addedBindEls.length;\n\t\t\twhile (len--) {\n\t\t\t\t// These were added in reverse order to addedBindEls. We push them in BindEls in the correct order.\n\t\t\t\tbindEls.push(addedBindEls[len]);\n\t\t\t}\n\t\t}\n\t\treturn !vwInfos || vwInfos.elCnt;\n\t}\n\n\tfunction getViewInfos(vwInfos) {\n\t\t// Used by view.childTags() and tag.childTags()\n\t\t// Similar to processViewInfos in how it steps through bindings to find tags. Only finds data-linked tags.\n\t\tvar level, parentTag, named;\n\n\t\tif (vwInfos) {\n\t\t\tlen = vwInfos.length;\n\t\t\tfor (j = 0; j < len; j++) {\n\t\t\t\tvwInfo = vwInfos[j];\n\t\t\t\t// This is an open marker for a data-linked tag {^{...}}, within the content of the tag whose id is get.id. Add it to bindEls.\n\t\t\t\t// Note - if bindingStore[vwInfo.id]._is === \"tag\" then getViewInfos is being called too soon - during first linking pass\n\t\t\t\ttag = bindingStore[vwInfo.id];\n\t\t\t\tif (!tag._is && tag.linkCtx) {\n\t\t\t\t\tparentTag = tag = tag.linkCtx.tag;\n\t\t\t\t\tnamed = tag.tagName === tagName;\n\t\t\t\t\tif (!tag.flow || named) {\n\t\t\t\t\t\tif (!deep) {\n\t\t\t\t\t\t\tlevel = 1;\n\t\t\t\t\t\t\twhile (parentTag = parentTag.parent) {\n\t\t\t\t\t\t\t\tlevel++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttagDepth = tagDepth || level; // The level of the first tag encountered.\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ((deep || level === tagDepth) && (!tagName || named)) {\n\t\t\t\t\t\t\t// Filter on top-level or tagName as appropriate\n\t\t\t\t\t\t\ttags.push(tag);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction dataLink() {\n\t\t//================ Data-link and fixup of data-jsv annotations ================\n\t\tvar j, index,\n\t\t\ttokens = \"\",\n\t\t\twrap = {},\n\t\t\tselector = linkViewsSel + (get ? \",[\" + deferAttr + \"]\" : \"\");\n\t\t\t// If a childTags() call, get = \",[\" + deferAttr + \"]\" - since we need to include elements that have a ._df expando for deferred tokens\n\n\t\telems = qsa ? parentNode.querySelectorAll(selector) : $(selector, parentNode).get();\n\t\tl = elems.length;\n\n\t\t// The prevNode will be in the returned query, since we called markPrevOrNextNode() on it.\n\t\t// But it may have contained nodes that satisfy the selector also.\n\t\tif (prevNode && prevNode.innerHTML) {\n\t\t\t// Find the last contained node of prevNode, to use as the prevNode - so we only link subsequent elems in the query\n\t\t\tprevNodes = qsa ? prevNode.querySelectorAll(selector) : $(selector, prevNode).get();\n\t\t\tprevNode = prevNodes.length ? prevNodes[prevNodes.length - 1] : prevNode;\n\t\t}\n\n\t\ttagDepth = 0;\n\t\tfor (i = 0; i < l; i++) {\n\t\t\telem = elems[i];\n\t\t\tif (prevNode && !found) {\n\t\t\t\t// If prevNode is set, not false, skip linking. If this element is the prevNode, set to false so subsequent elements will link.\n\t\t\t\tfound = (elem === prevNode);\n\t\t\t} else if (nextNode && elem === nextNode) {\n\t\t\t\t// If nextNode is set then break when we get to nextNode\n\t\t\t\tif (get) {\n\t\t\t\t\ttokens += markerNodeInfo(elem);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t} else if (elem.parentNode) {\n\t\t\t\t// elem has not been removed from DOM\n\t\t\t\tif (get) {\n\t\t\t\t\ttokens += markerNodeInfo(elem);\n\t\t\t\t\tif (elem._df) {\n\t\t\t\t\t\tj = i + 1;\n\t\t\t\t\t\twhile (j < l && elem.contains(elems[j])) {\n\t\t\t\t\t\t\tj++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Add deferred tokens after any tokens on descendant elements of this one\n\t\t\t\t\t\twrap[j-1] = elem._df;\n\t\t\t\t\t}\n\t\t\t\t\tif (wrap[i]) {\n\t\t\t\t\t\ttokens += wrap[i] || \"\";\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (isLink && (vwInfo = viewInfos(elem, undefined, rViewMarkers)) && (vwInfo = vwInfo[0])) {\n\t\t\t\t\t\t// If this is a link(trueOrString ...) call we will avoid re-binding to elems that are within template-rendered views\n\t\t\t\t\t\tskip = skip ? (vwInfo.id !== skip && skip) : vwInfo.open && vwInfo.id;\n\t\t\t\t\t}\n\t\t\t\t\tif (!skip && processInfos(viewInfos(elem))\n\t\t\t\t\t\t// If a link() call, processViewInfos() adds bindings to bindEls, and returns true for non-script nodes, for adding data-link bindings\n\t\t\t\t\t\t// If a childTags() call, getViewInfos returns array of tag bindings.\n\t\t\t\t\t\t\t&& elem.getAttribute($viewsLinkAttr)) {\n\t\t\t\t\t\tbindEls.push([elem]); // A data-linked element so add to bindEls too\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (get) {\n\t\t\ttokens += parentNode._df || \"\";\n\t\t\tif (index = tokens.indexOf(\"#\" + get.id) + 1) {\n\t\t\t\t// We are looking for view.childTags() or tag.childTags() - so start after the open token of the parent view or tag.\n\t\t\t\ttokens = tokens.slice(index + get.id.length);\n\t\t\t}\n\t\t\tindex = tokens.indexOf(\"/\" + get.id);\n\t\t\tif (index + 1) {\n\t\t\t\t// We are looking for view.childTags() or tag.childTags() - so don't look beyond the close token of the parent view or tag.\n\t\t\t\ttokens = tokens.slice(0, index);\n\t\t\t}\n\t\t\t// Call getViewInfos to add the found childTags to the tags array\n\t\t\tgetViewInfos(viewInfos(tokens, undefined, rOpenTagMarkers));\n\t\t}\n\n\t\tif (html === undefined && parentNode.getAttribute($viewsLinkAttr)) {\n\t\t\tbindEls.push([parentNode]); // Support data-linking top-level element directly (not within a data-linked container)\n\t\t}\n\n\t\t// Remove temporary marker script nodes they were added by markPrevOrNextNode\n\t\tunmarkPrevOrNextNode(prevNode, elCnt);\n\t\tunmarkPrevOrNextNode(nextNode, elCnt);\n\n\t\tif (get) {\n\t\t\treturn; // We have added childTags to the tags array, so we are done\n\t\t}\n\n\t\tif (elCnt && defer + ids) {\n\t\t\t// There are some views with elCnt, for which the open or close did not precede any HTML tag - so they have not been processed yet\n\t\t\telem = nextNode;\n\t\t\tif (defer) {\n\t\t\t\tif (nextNode) {\n\t\t\t\t\tprocessViewInfos(viewInfos(defer + \"+\", true), nextNode);\n\t\t\t\t} else {\n\t\t\t\t\tprocessViewInfos(viewInfos(defer, true), parentNode);\n\t\t\t\t}\n\t\t\t}\n\t\t\tprocessViewInfos(viewInfos(ids, true), parentNode);\n\t\t\t// If there were any tokens on nextNode which have now been associated with inserted HTML tags, remove them from nextNode\n\t\t\tif (nextNode) {\n\t\t\t\ttokens = nextNode.getAttribute(jsvAttrStr);\n\t\t\t\tif (l = tokens.indexOf(prevIds) + 1) {\n\t\t\t\t\ttokens = tokens.slice(l + prevIds.length - 1);\n\t\t\t\t}\n\t\t\t\tnextNode.setAttribute(jsvAttrStr, ids + tokens);\n\t\t\t}\n\t\t}\n\n// if (context.lazyLink) {\n// setTimeout(doLinking) (doLinking is function wrapper of following lines)\n// See Future tasks, and https://github.com/BorisMoore/jsviews/issues/368.\n// Could call context.lazyLink as callback, on async completion - or return promise.\n\t\t//================ Bind the data-linked elements and tags ================\n\t\tl = bindEls.length;\n\t\tfor (i = 0; i < l; i++) {\n\t\t\telem = bindEls[i];\n\t\t\tlinkInfo = elem[1];\n\t\t\telem = elem[0];\n\t\t\tif (linkInfo) {\n\t\t\t\tif (tag = bindingStore[linkInfo.id]) {\n\t\t\t\t\tif (linkCtx = tag.linkCtx) {\n\t\t\t\t\t\t// The tag may have been stored temporarily on the bindingStore - or may have already been replaced by the actual binding\n\t\t\t\t\t\ttag = linkCtx.tag;\n\t\t\t\t\t\ttag.linkCtx = linkCtx;\n\t\t\t\t\t}\n\t\t\t\t\tif (linkInfo.open) {\n\t\t\t\t\t\t// This is an 'open linked tag' binding annotation for a data-linked tag {^{...}}\n\t\t\t\t\t\tif (elem) {\n\t\t\t\t\t\t\ttag.parentElem = elem.parentNode;\n\t\t\t\t\t\t\ttag._prv = elem;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttag._elCnt = linkInfo.elCnt;\n\t\t\t\t\t\t// We data-link depth-first (\"on the way in\"), which is better for perf - and allows setting parent tags etc.\n\t\t\t\t\t\tview = tag.tagCtx.view;\n\n\t\t\t\t\t\t// Add data binding (unless skipped due to lateRender)\n\t\t\t\t\t\taddDataBinding(late, undefined, tag._prv, view, linkInfo.id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttag._nxt = elem;\n\t\t\t\t\t\tif (tag._.unlinked && !tag._toLk) {\n\t\t\t\t\t\t\t// This is a 'close linked tag' binding annotation (and data-binding was not skipped due to lateRender)\n\t\t\t\t\t\t\ttagCtx = tag.tagCtx;\n\t\t\t\t\t\t\tview = tagCtx.view;\n\t\t\t\t\t\t\tcallAfterLink(tag);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Add data binding for a data-linked element (with data-link attribute)\n\t\t\t\taddDataBinding(late, elem.getAttribute($viewsLinkAttr), elem, $view(elem), undefined, isLink, outerData, context);\n\t\t\t}\n\t\t}\n//});\n\t}\n\t//==== /end of nested functions ====\n\n\tvar inTag, linkCtx, tag, i, l, j, len, elems, elem, view, vwInfo, linkInfo, prevNodes, token, prevView, nextView,\n\t\tnode, tags, deep, tagName, tagCtx, validate, tagDepth, depth, fragment, copiedNode, firstTag, parentTag,\n\t\tisVoid, wrapper, div, tokens, elCnt, prevElCnt, htmlTag, ids, prevIds, found, skip, isLink, get,\n\t\tself = this,\n\t\tthisId = self._.id + \"_\",\n\t\tdefer = \"\",\n\t\t// The marker ids for which no tag was encountered (empty views or final closing markers) which we carry over to container tag\n\t\tbindEls = [],\n\t\ttagStack = [],\n\t\tdeferStack = [],\n\t\tlate = [],\n\t\tonAfterCreate = changeHandler(self, onAfterCreateStr),\n\t\tprocessInfos = processViewInfos;\n\n\tif (refresh) {\n\t\tif (refresh.tmpl) {\n\t\t\t// refresh is the prevView, passed in from addViews()\n\t\t\tprevView = \"/\" + refresh._.id + \"_\";\n\t\t} else {\n\t\t\tisLink = refresh.lnk; // Top-level linking\n\t\t\tif (refresh.tag) {\n\t\t\t\tthisId = refresh.tag + \"^\";\n\t\t\t\trefresh = true;\n\t\t\t}\n\t\t\tif (get = refresh.get) {\n\t\t\t\tprocessInfos = getViewInfos;\n\t\t\t\ttags = get.tags;\n\t\t\t\tdeep = get.deep;\n\t\t\t\ttagName = get.name;\n\t\t\t}\n\t\t}\n\t\trefresh = refresh === true;\n\t}\n\n\tparentNode = parentNode\n\t\t? (\"\" + parentNode === parentNode\n\t\t\t? $(parentNode)[0] // It is a string, so treat as selector\n\t\t\t: parentNode.jquery\n\t\t\t\t? parentNode[0] // A jQuery object - take first element.\n\t\t\t\t: parentNode)\n\t\t: (self.parentElem // view.link()\n\t\t\t|| document.body); // link(null, data) to link the whole document\n\n\tvalidate = !$subSettingsAdvanced.noValidate && parentNode.contentEditable !== TRUE;\n\tparentTag = parentNode.tagName.toLowerCase();\n\telCnt = !!elContent[parentTag];\n\n\tprevNode = prevNode && markPrevOrNextNode(prevNode, elCnt);\n\tnextNode = nextNode && markPrevOrNextNode(nextNode, elCnt) || null;\n\n\tif (html != undefined) {\n\t\t//================ Insert html into DOM using documentFragments (and wrapping HTML appropriately). ================\n\t\t// Also convert markers to DOM annotations, based on content model.\n\t\t// Corresponds to nextNode ? $(nextNode).before(html) : $(parentNode).html(html);\n\t\t// but allows insertion to wrap correctly even with inserted script nodes. jQuery version will fail e.g. under tbody or select.\n\t\t// This version should also be slightly faster\n\t\tdiv = document.createElement(\"div\");\n\t\twrapper = div;\n\t\tprevIds = ids = \"\";\n\t\thtmlTag = parentNode.namespaceURI === \"http://www.w3.org/2000/svg\" ? \"svg_ns\" : (firstTag = rFirstElem.exec(html)) && firstTag[1] || \"\";\n\t\tif (elCnt) {\n\t\t\t// Now look for following view, and find its tokens, or if not found, get the parentNode._df tokens\n\t\t\tnode = nextNode;\n\t\t\twhile (node && !(nextView = viewInfos(node))) {\n\t\t\t\tnode = node.nextSibling;\n\t\t\t}\n\t\t\tif (tokens = nextView ? nextView._tkns : parentNode._df) {\n\t\t\t\ttoken = prevView || \"\";\n\t\t\t\tif (refresh || !prevView) {\n\t\t\t\t\ttoken += \"#\" + thisId;\n\t\t\t\t}\n\t\t\t\tj = tokens.indexOf(token);\n\t\t\t\tif (j + 1) {\n\t\t\t\t\tj += token.length;\n\t\t\t\t\t// Transfer the initial tokens to inserted nodes, by setting them as the ids variable, picked up in convertMarkers\n\t\t\t\t\tprevIds = ids = tokens.slice(0, j);\n\t\t\t\t\ttokens = tokens.slice(j);\n\t\t\t\t\tif (nextView) {\n\t\t\t\t\t\tnode.setAttribute(jsvAttrStr, tokens);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetDefer(parentNode, tokens);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//================ Convert the markers to DOM annotations, based on content model. ================\n//\t\t\toldElCnt = elCnt;\n\t\tisVoid = undefined;\n\t\thtml = (\"\" + html).replace(rConvertMarkers, convertMarkers);\n//\t\t\tif (!!oldElCnt !== !!elCnt) {\n//\t\t\t\terror(\"Parse: \" + html); // Parse error. Content not well-formed?\n//\t\t\t}\n\t\tif (validate && tagStack.length) {\n\t\t\tsyntaxError(\"Mismatched '<\" + parentTag + \"...>' in:\\n\" + html); // Unmatched tag\n\t\t}\n\t\tif (validateOnly) {\n\t\t\treturn;\n\t\t}\n\t\t// Append wrapper element to doc fragment\n\t\tsafeFragment.appendChild(div);\n\n\t\t// Go to html and back, then peel off extra wrappers\n\t\t// Corresponds to jQuery $(nextNode).before(html) or $(parentNode).html(html);\n\t\t// but supports svg elements, and other features missing from jQuery version (and this version should also be slightly faster)\n\t\thtmlTag = wrapMap[htmlTag] || wrapMap.div;\n\t\tdepth = htmlTag[0];\n\t\twrapper.innerHTML = htmlTag[1] + html + htmlTag[2];\n\t\twhile (depth--) {\n\t\t\twrapper = wrapper.lastChild;\n\t\t}\n\t\tsafeFragment.removeChild(div);\n\t\tfragment = document.createDocumentFragment();\n\t\twhile (copiedNode = wrapper.firstChild) {\n\t\t\tfragment.appendChild(copiedNode);\n\t\t}\n\t\t// Insert into the DOM\n\t\tparentNode.insertBefore(fragment, nextNode);\n\t}\n\tdataLink();\n\n\treturn late;\n}\n\nfunction addDataBinding(late, linkMarkup, node, currentView, boundTagId, isLink, data, context) {\n\t// Add data binding for data-linked elements or {^{...}} data-linked tags\n\tvar tmpl, tokens, attr, convertBack, tagExpr, linkFn, linkCtx, tag, rTagIndex, hasElse, lastIndex,\n\t\tlinkExpressions = [];\n\n\tif (boundTagId) {\n\t\t// boundTagId is a string for {^{...}} data-linked tag. So only one linkTag in linkMarkup\n\t\t// data and context arguments are undefined\n\t\ttag = bindingStore[boundTagId];\n\t\ttag = tag.linkCtx ? tag.linkCtx.tag : tag;\n\n\t\tlinkCtx = tag.linkCtx || {\n\t\t\ttype: \"inline\",\n\t\t\tdata: currentView.data, // source\n\t\t\telem: tag._elCnt ? tag.parentElem : node, // target\n\t\t\tview: currentView,\n\t\t\tctx: currentView.ctx,\n\t\t\tattr: HTML, // Script marker nodes are associated with {^{ and always target HTML.\n\t\t\tfn: tag._.bnd,\n\t\t\ttag: tag,\n\t\t\t// Pass the boundTagId in the linkCtx, so that it can be picked up in observeAndBind\n\t\t\t_bndId: boundTagId\n\t\t};\n\t\ttag.linkCtx = linkCtx;\n\t\tbindDataLinkTarget(linkCtx, late);\n\t\ttag._toLk = linkCtx._bndId; // If data binding happened, remove _toLk flag from tag\n\t} else if (linkMarkup && node) {\n\t\t// Data-linked element\n\n\t\t// If isLink then this is a top-level linking: .link(expression, target, data, ....) or\n\t\t// .link(true, target, data, ....) scenario - and data and context are passed in separately from the view\n\t\tdata = isLink ? data : currentView.data;\n\n\t\t// Compiled linkFn expressions could be stored in the tmpl.links array of the template\n\t\t// TODO - consider also caching globally so that if {{:foo}} or data-link=\"foo\" occurs in different places,\n\t\t// the compiled template for this is cached and only compiled once...\n\t\t//links = currentView.links || currentView.tmpl.links;\n\n\t\ttmpl = currentView.tmpl;\n\n//\t\t\tif (!(linkTags = links[linkMarkup])) {\n\t\t// This is the first time this view template has been linked, so we compile the data-link expressions, and store them on the template.\n\n\t\tlinkMarkup = normalizeLinkTag(linkMarkup, defaultAttr(node));\n\t\tlastIndex = rTagDatalink.lastIndex = 0;\n\t\twhile (tokens = rTagDatalink.exec(linkMarkup)) { // TODO require } to be followed by whitespace or $, and remove the \\}(!\\}) option.\n\t\t\tlinkExpressions.push(tokens);\n\t\t\tlastIndex = rTagDatalink.lastIndex;\n\t\t}\n\t\tif (lastIndex < linkMarkup.length) {\n\t\t\tsyntaxError(linkMarkup);\n\t\t}\n\t\twhile (tokens = linkExpressions.shift()) {\n\t\t\t// Iterate over the data-link expressions, for different target attrs,\n\t\t\t// e.g. ~description(firstName, lastName)}\"\n\t\t\t// tokens: [all, attr, bindOnly, tagExpr, tagName, converter, colon, html, comment, code, params]\n\t\t\trTagIndex = rTagDatalink.lastIndex;\n\t\t\tattr = tokens[1];\n\t\t\ttagExpr = tokens[3];\n\t\t\twhile (linkExpressions[0] && linkExpressions[0][4] === \"else\") { // If this is {sometag...} and is followed by an {else...} add to tagExpr\n\t\t\t\ttagExpr += delimCloseChar1 + delimOpenChar0 + linkExpressions.shift()[3];\n\t\t\t\thasElse = true;\n\t\t\t}\n\t\t\tif (hasElse) { // If an {else} has been added, need also to add closing {{/sometag}}\n\t\t\t\ttagExpr += delimCloseChar1 + delimOpenChar0 + delimOpenChar1 + \"/\" + tokens[4] + delimCloseChar0;\n\t\t\t}\n\t\t\tlinkCtx = {\n\t\t\t\ttype: isLink ? \"top\" : \"link\",\n\t\t\t\tdata: data, // source\n\t\t\t\telem: node, // target\n\t\t\t\tview: currentView,\n\t\t\t\tctx: context,\n\t\t\t\tattr: attr,\n\t\t\t\tisLk: isLink, // top-level linking?\n\t\t\t\t_toLk : 1, // Flag to data-link on initial data-link call rendering call\n\t\t\t\t_noUpd : tokens[2] // Flag for data-link=\"^{...}\" so on initial data-link call will bind, but not render)\n\t\t\t};\n\n\t\t\tconvertBack = undefined;\n\t\t\tif (tokens[6]) {\n\t\t\t\tconvertBack = tokens[10] || undefined;\n\t\t\t\tlinkCtx.convert = tokens[5] || \"\";\n\t\t\t\tif (convertBack !== undefined && defaultAttr(node)) {\n\t\t\t\t\tif (attr) {\n\t\t\t\t\t\tsyntaxError(tagExpr + \"- Remove target: \" + attr);\n\t\t\t\t\t}\n\t\t\t\t\t// Default target, so allow 2 way binding\n\t\t\t\t\tlinkCtx.convertBack = convertBack = convertBack.slice(1);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Compile the linkFn expression which evaluates and binds a data-link expression\n\t\t\t// TODO - optimize for the case of simple data path with no conversion, helpers, etc.:\n\t\t\t// i.e. data-link=\"a.b.c\". Avoid creating new instances of Function every time. Can use a default function for all of these...\n\n\t\t\tlinkCtx.expr = attr + tagExpr;\n\t\t\tlinkFn = tmpl.links[tagExpr];\n\t\t\tif (!linkFn) {\n\t\t\t\ttmpl.links[tagExpr] = linkFn = $sub.tmplFn(tagExpr.replace(rEscapeQuotes, \"\\\\$&\"), tmpl, true, convertBack, hasElse);\n\t\t\t}\n\t\t\tlinkCtx.fn = linkFn;\n\t\t\tbindDataLinkTarget(linkCtx, late);\n\t\t\t// We store rTagIndex in local scope, since this addDataBinding method can sometimes be called recursively,\n\t\t\t// and each is using the same rTagDatalink instance.\n\t\t\trTagDatalink.lastIndex = rTagIndex;\n\t\t}\n//\t\t}\n\t}\n}\n\nfunction bindDataLinkTarget(linkCtx, late) {\n\t// Add data link bindings for a link expression in data-link attribute markup\n\tfunction handler(ev, eventArgs) {\n\t\tonDataLinkedTagChange.call(linkCtx, ev, eventArgs);\n\t\t// If the link expression uses a custom tag, the onDataLinkedTagChange call will call renderTag, which will set tagCtx on linkCtx\n\t}\n\tvar view;\n\tif (linkCtx.isLk) {\n\t\t// Top-level linking: .link(expressionOrTrue, data, context) - so we need to create a view for the linking, with the data and ctx\n\t\t// which may be different than the current context of the target. Note that this view is not a standard data-linked view, so it will\n\t\t// be disposed only when its parent view is disposed.\n\t\tlinkCtx.view = new $sub.View(\n\t\t\t$sub.extendCtx(linkCtx.ctx, linkCtx.view.ctx),\n\t\t\t\"link\", linkCtx.view, linkCtx.data, linkCtx.expr, undefined, addBindingMarkers);\n\t}\n\tlinkCtx._ctxCb = $sub._gccb(view = linkCtx.view); // getContextCallback: _ctxCb, for filtering/appending to dependency paths: function(path, object) { return [(object|path)*]}\n\tlinkCtx._hdl = handler;\n\t// handler._ctx = linkCtx; Could pass linkCtx for use in a depends = function() {} call, so depends is different for different linkCtx's\n\tif (linkCtx.elem.nodeName === \"SELECT\" && linkCtx.type === \"link\" && !linkCtx.attr) {\n\t\tvar $elem = $(linkCtx.elem);\n\t\t$elem.on(\"jsv-domchange\", function() {\n\t\t\t// If the options have changed dynamically under the select, we need to refresh the data-linked selection, using the new options\n\t\t\tif (!arguments[3].refresh) { // eventArgs.refresh !== true - so a refresh action will only set the selection once\n\t\t\t\tvar source = linkCtx.fn(view.data, view, $sub);\n\t\t\t\t$elem.val(linkCtx.convert || linkCtx.convertBack ? $sub._cnvt(linkCtx.convert, view, source) : source);\n\t\t\t}\n\t\t});\n\t}\n\n\tif (linkCtx.fn._lr) {\n\t\tlinkCtx._toLk = 1;\n\t\tlate.push(linkCtx); // lateRender - defer rendering and linking (sync but after first linking pass)\n\t} else {\n\t\thandler(true);\n\t}\n}\n\n//=====================\n// Data-linking helpers\n//=====================\n\nfunction removeSubStr(str, substr) {\n\tvar k;\n\treturn str\n\t\t? (k = str.indexOf(substr),\n\t\t\t(k + 1\n\t\t\t\t? str.slice(0, k) + str.slice(k + substr.length)\n\t\t\t\t: str))\n\t\t: \"\";\n}\n\nfunction markerNodeInfo(node) {\n\treturn node &&\n\t\t(\"\" + node === node\n\t\t\t? node\n\t\t\t: node.tagName === SCRIPT\n\t\t\t\t? node.type.slice(3)\n\t\t\t\t: node.nodeType === 1 && node.getAttribute(jsvAttrStr) || \"\");\n}\n\nfunction viewInfos(node, isVal, rBinding) {\n\t// Test whether node is a script marker node, and if so, return metadata\n\tfunction getInfos(all, open, close, id, ch, elPath) {\n\t\tinfos.push({\n\t\t\telCnt: elCnt,\n\t\t\tid: id,\n\t\t\tch: ch,\n\t\t\topen: open,\n\t\t\tclose: close,\n\t\t\tpath: elPath,\n\t\t\ttoken: all\n\t\t});\n\t}\n\tvar elCnt, tokens,\n\t\tinfos = [];\n\tif (tokens = isVal ? node : markerNodeInfo(node)) {\n\t\telCnt = infos.elCnt = node.tagName !== SCRIPT;\n\t\telCnt = tokens.charAt(0) === \"@\" || elCnt;\n\t\tinfos._tkns = tokens;\n\t\t// rMarkerTokens = /(?:(#)|(\\/))(\\d+)([_^])([-+@\\d]+)?/g;\n\t\ttokens.replace(rBinding || rMarkerTokens, getInfos);\n\t\treturn infos;\n\t}\n}\n\nfunction unmarkPrevOrNextNode(node, elCnt) {\n\tif (node) {\n\t\tif (node.type === \"jsv\") {\n\t\t\tnode.parentNode.removeChild(node);\n\t\t} else if (elCnt && node.getAttribute($viewsLinkAttr) === \"\") {\n\t\t\tnode.removeAttribute($viewsLinkAttr);\n\t\t}\n\t}\n}\n\nfunction markPrevOrNextNode(node, elCnt) {\n\tvar marker = node;\n\twhile (elCnt && marker && marker.nodeType !== 1) {\n\t\tmarker = marker.previousSibling;\n\t}\n\tif (marker) {\n\t\tif (marker.nodeType !== 1) {\n\t\t\t// For text nodes, we will add a script node before\n\t\t\tmarker = document.createElement(SCRIPT);\n\t\t\tmarker.type = \"jsv\";\n\t\t\tnode.parentNode.insertBefore(marker, node);\n\t\t} else if (!markerNodeInfo(marker) && !marker.getAttribute($viewsLinkAttr)) {\n\t\t\t// For element nodes, we will add a data-link attribute (unless there is already one)\n\t\t\t// so that this node gets included in the node linking process.\n\t\t\tmarker.setAttribute($viewsLinkAttr, \"\");\n\t\t}\n\t}\n\treturn marker;\n}\n\nfunction normalizeLinkTag(linkMarkup, twoway) {\n\tlinkMarkup = $.trim(linkMarkup);\n\treturn linkMarkup.slice(-1) !== delimCloseChar0\n\t// If simplified syntax is used: data-link=\"expression\", convert to data-link=\"{:expression}\",\n\t// or for inputs, data-link=\"{:expression:}\" for (default) two-way binding\n\t\t? linkMarkup = delimOpenChar1 + \":\" + linkMarkup + (twoway ? \":\" : \"\") + delimCloseChar0\n\t\t: linkMarkup;\n}\n\n//===========================\n// Methods for views and tags\n//===========================\n\nfunction callAfterLink(tag, ev, eventArgs) {\n\tfunction copyFromTagCtxToTag() {\n\t\tlinkedElems = tagCtx.linkedElems || tag.linkedElems || tag.linkedElem && [tag.linkedElem];\n\t\tif (linkedElems) {\n\t\t\ttag.linkedElems = tagCtx.linkedElems = linkedElems;\n\t\t\ttag.linkedElem = linkedElems[0] = tag.linkedElem || linkedElems[0];\n\t\t}\n\t\tif (linkedElem = tagCtx.mainElem || tag.mainElem) {\n\t\t\ttagCtx.mainElem = tag.mainElem = linkedElem;\n\t\t}\n\t\tif (linkedElem = tagCtx.displayElem || tag.displayElem) {\n\t\t\ttagCtx.displayElem = tag.displayElem = linkedElem;\n\t\t}\n\t}\n\n\tvar linkedElems, linkedElements, linkedElem, l, m, $linkCtxElem, linkCtxElem, linkedEl, linkedTag, tagCtxElse, props, val, oldVal, indexTo,\n\t\ttagCtx = tag.tagCtx,\n\t\ttagCtxs = tag.tagCtxs,\n\t\ttagCtxslength = tagCtxs && tagCtxs.length,\n\t\tlinkCtx = tag.linkCtx,\n\t\tbindTo = tag.bindTo || {};\n\n\tif (tag._.unlinked) { // First call to onAfterLink, or first call after onUpdate: updateContent. Initialize and call onBind and set properties\n\t\t$linkCtxElem = $(linkCtx.elem);\n\t\tif (tag.linkedElement || tag.mainElement || tag.displayElement) {\n\t\t\tif (linkedElements = tag.linkedElement) {\n\t\t\t\t// tag.linkedElement: - selector, or array of selectors, for identifying linked elements in template/rendered content.\n\t\t\t\t// (But for tag bindings on data-linked elements, defaults to data-linked element)\n\t\t\t\ttag.linkedElem = undefined;\n\t\t\t\tl = linkedElements.length;\n\t\t\t\twhile (l--) {\n\t\t\t\t\tif (linkedElements[l]) {\n\t\t\t\t\t\tm = tagCtxslength;\n\t\t\t\t\t\twhile (m--) {\n\t\t\t\t\t\t\tlinkCtxElem = !m && !tag.inline && $linkCtxElem.filter(linkedElements[l]);\n\t\t\t\t\t\t\ttagCtxElse = tagCtxs[m];\n\t\t\t\t\t\t\tlinkedElems = tagCtxElse.linkedElems = tagCtxElse.linkedElems || new Array(l);\n\t\t\t\t\t\t\tlinkedElem = linkCtxElem[0] ? linkCtxElem : tagCtxElse.contents(true, linkedElements[l]);\n\t\t\t\t\t\t\tif (linkedElem[0] && linkedElem[0].type !== RADIO) {\n\t\t\t\t\t\t\t\tlinkedElems[l] = linkedElem.eq(0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (linkedElements = tag.mainElement) {\n\t\t\t\t// tag.mainElement: - selector for identifying mainElem in template/rendered content\n\t\t\t\t// (But for tag bindings on data-linked elements, defaults to data-linked element)\n\t\t\t\tm = tagCtxslength;\n\t\t\t\twhile (m--) {\n\t\t\t\t\tlinkCtxElem = !m && !tag.inline && $linkCtxElem.filter(linkedElements);\n\t\t\t\t\ttagCtxElse = tagCtxs[m];\n\t\t\t\t\tlinkedElem = linkCtxElem[0] ? linkCtxElem : tagCtxElse.contents(true, linkedElements).eq(0);\n\t\t\t\t\tif (linkedElem[0]) {\n\t\t\t\t\t\ttagCtxElse.mainElem = linkedElem;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (linkedElements = tag.displayElement) {\n\t\t\t\t// tag.displayElement: - selector for identifying displayElem in template/rendered content\n\t\t\t\t// (But for tag bindings on data-linked elements, defaults to data-linked element)\n\t\t\t\tm = tagCtxslength;\n\t\t\t\twhile (m--) {\n\t\t\t\t\tlinkCtxElem = !m && !tag.inline && $linkCtxElem.filter(linkedElements);\n\t\t\t\t\ttagCtxElse = tagCtxs[m];\n\t\t\t\t\tlinkedElem = linkCtxElem[0] ? linkCtxElem : tagCtxElse.contents(true, linkedElements).eq(0);\n\t\t\t\t\tif (linkedElem[0]) {\n\t\t\t\t\t\ttagCtxElse.displayElem = linkedElem;\n\t\t\t\t\t\tif (!m) {\n\t\t\t\t\t\t\ttag.displayElem = linkedElem;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcopyFromTagCtxToTag();\n\t\t}\n\t\tif (tag.onBind) {\n\t\t\ttag.onBind(tagCtx, linkCtx, tag.ctx, ev, eventArgs);\n\t\t\tcopyFromTagCtxToTag();\n\t\t}\n\t}\n\n\tm = tagCtxslength;\n\twhile (m--) {\n\t\ttagCtxElse = tagCtxs[m];\n\t\tprops = tagCtxElse.props;\n\n\t\tif (linkedElem = tagCtxElse.mainElem || !tag.mainElement && tagCtxElse.linkedElems && tagCtxElse.linkedElems[0]) {\n\t\t\t// linkedElem is the mainElem (defaulting to linkedElem)\n\t\t\tif (linkedElem[0] && props.id && !linkedElem[0].id) {\n\t\t\t\tlinkedElem[0].id = props.id;\n\t\t\t}\n\t\t\tif (tag.setSize) {\n\t\t\t\tif (val = !bindTo.height && props.height || tag.height) {\n\t\t\t\t\tlinkedElem.height(val);\n\t\t\t\t}\n\t\t\t\tif (val = !bindTo.width && props.width || tag.width) {\n\t\t\t\t\tlinkedElem.width(val);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (val = (linkedElem = tagCtxElse.displayElem || linkedElem) && (!bindTo[\"class\"] && props[\"class\"] || tag.className)) {\n\t\t\t// This code supports dynamic binding to class - where it adds the class if absent, and removes/adds if a previous value is present\n\t\t\toldVal = linkedElem[0]._jsvCl;\n\t\t\tif (val !== oldVal) {\n\t\t\t\tif (linkedElem.hasClass(oldVal)) {\n\t\t\t\t\tlinkedElem.removeClass(oldVal);\n\t\t\t\t}\n\t\t\t\tlinkedElem.addClass(val);\n\t\t\t\tlinkedElem[0]._jsvCl = val;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (tag.onAfterLink) {\n\t\ttag.onAfterLink(tagCtx, linkCtx, tag.ctx, ev, eventArgs);\n\t\tcopyFromTagCtxToTag();\n\t}\n\n\tif (!tag.flow && !tag._.chg) {\n\t\tif (tag.inline && tag._.unlinked && (tag.linkedElems || tag.bindTo)) {\n\t\t\tdefineBindToDataTargets(bindingStore[tag._tgId], tag);\n\t\t}\n\t\tm = tagCtxs.length;\n\t\twhile (m--) {\n\t\t\tprops = tag.cvtArgs(1, m); // array of bindFrom args/props\n\t\t\tl = props.length;\n\t\t\twhile (l--) {\n\t\t\t\tval = props[l];\n\t\t\t\ttag.setValue(val, l, m);\n\t\t\t}\n\t\t\tif (tag._.unlinked) {\n\t\t\t\ttagCtx = tagCtxs[m];\n\t\t\t\tlinkedElems = tagCtx.linkedElems || tag.linkedElem && [tag.linkedElem];\n\t\t\t\tindexTo = (tag.bindTo || [0]).length;\n\t\t\t\twhile (indexTo--) {\n\t\t\t\t\tif ((linkedElem = linkedElems && linkedElems[indexTo]) && (l = linkedElem.length)) {\n\t\t\t\t\t\twhile (l--) {\n\t\t\t\t\t\t\tlinkedEl = linkedElem[l];\n\t\t\t\t\t\t\tlinkedTag = linkedEl._jsvLkEl;\n\t\t\t\t\t\t\tif (!linkedTag || linkedTag !== tag) {\n\t\t\t\t\t\t\t\t// For data-linked tags, identify the linkedEl with the tag, for \"to\" binding\n\t\t\t\t\t\t\t\t// (For data-linked elements, if not yet bound, we identify later when the linkCtx.elem is bound)\n\t\t\t\t\t\t\t\tlinkedEl._jsvLkEl = tag;\n\t\t\t\t\t\t\t\tlinkedEl._jsvInd = indexTo;\n\t\t\t\t\t\t\t\tlinkedEl._jsvElse = m;\n\t\t\t\t\t\t\t\tbindLinkedElChange(tag, linkedEl);\n\t\t\t\t\t\t\t\tlinkedEl._jsvBnd = \"&\" + tag._tgId + \"+\"; // Add a \"+\" for cloned binding - so removing\n\t\t\t\t\t\t\t\t// elems with cloned bindings will not remove the 'parent' binding from the bindingStore.\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\ttag._.unlinked = undefined;\n\tif (tag._.lt) { // Late tag: Late path: @some.path had not returned @some object, so try again with refresh\n\t\ttag.refresh();\n\t}\n}\n\nfunction asyncOnElemChange(ev) {\n\tvar which = ev.which;\n\tif (!(which > 15 && which < 21 || which > 32 && which < 41 || which > 111 && which < 131 || which === 27 || which === 144)) {\n\t\t// Shift, Ctrl, Alt, Pause, Caplock, Page up/down End, Home, Left, Up, Right, Down, Function keys, Escape, Numlock\n\t\tsetTimeout(function() {\n\t\t\tonElemChange(ev);\n\t\t});\n\t}\n}\n\nfunction bindTriggerEvent($elem, trig, onoff) {\n\t// Bind keydown, or other trigger - (rather than use the default change event bubbled to activeBody)\n\tif (trig === true && useInput && (!isIE || $elem[0].contentEditable !== TRUE)) { // IE oninput event is not raised for contenteditable changes\n\t\t$elem[onoff](\"input.jsv\", onElemChange); // For HTML5 browser with \"oninput\" support - for mouse editing of text\n\t} else {\n\t\ttrig = \"\" + trig === trig ? trig : \"keydown.jsv\"; // Set trigger to (true || truey non-string (e.g. 1) || 'keydown')\n\t\t$elem[onoff](trig, trig.indexOf(\"keydown\") >= 0 ? asyncOnElemChange : onElemChange); // Get 'keydown' with async\n\t}\n}\n\nfunction bindLinkedElChange(tag, linkedElem) {\n\t// Two-way binding for linkedElem - in the case of input, textarea or contentEditable elements.\n\t// Trigger setting may have changed. Unbind previous trigger binding (if any) and bind new one.\n\n\tvar $linkedElem, newTrig,\n\t\toldTrig = linkedElem._jsvTr || false;\n\n\tif (tag) {\n\t\tnewTrig = tag.tagCtx.props.trigger;\n\t\tif (newTrig === undefined) {\n\t\t\tnewTrig = tag.trigger;\n\t\t}\n\t}\n\tif (newTrig === undefined) {\n\t\tnewTrig = $subSettings.trigger;\n\t}\n\t// Trigger is noop except for text box, textarea, contenteditable...\n\tnewTrig = newTrig && (linkedElem.tagName === \"INPUT\" && linkedElem.type !== CHECKBOX && linkedElem.type !== RADIO\n\t\t|| linkedElem.type === \"textarea\" || linkedElem.contentEditable === TRUE) && newTrig || false;\n\n\tif (oldTrig !== newTrig) {\n\t\t$linkedElem = $(linkedElem);\n\t\tbindTriggerEvent($linkedElem, oldTrig, \"off\");\n\t\tbindTriggerEvent($linkedElem, linkedElem._jsvTr = newTrig, \"on\");\n\t}\n}\n\nfunction defineBindToDataTargets(binding, tag, cvtBk) {\n\t// Two-way binding.\n\t// We set the binding.to[1] to be the cvtBack, and binding.to[0] to be either the path to the target, or [object, path] where the target is the\n\t// path on the provided object. So for a computed path with an object call: a.b.getObject().d.e, we set to[0] to be [exprOb, \"d.e\"], and\n\t// we bind to the path on the returned object, exprOb.ob, as target. Otherwise our target is the first path, paths[0], which we will convert\n\t// with contextCb() for paths like ~a.b.c or #x.y.z\n\n\tvar pathIndex, path, lastPath, bindtoOb, to, bindTo, paths, k, obsCtxPrm, linkedCtxParam, contextCb, targetPaths, bindTos, fromIndex,\n\t\ttagElse = 1,\n\t\ttos = [],\n\t\tlinkCtx = binding.linkCtx,\n\t\tsource = linkCtx.data,\n\t\ttargetPathsElses = linkCtx.fn.paths;\n\n\tif (binding && !binding.to) {\n\t\tif (tag) {\n\t\t\tif (!tag.convertBack) {\n\t\t\t\ttag.convertBack = cvtBk;\n\t\t\t}\n\t\t\tbindTo = tag.bindTo;\n\t\t\ttagElse = tag.tagCtxs ? tag.tagCtxs.length : 1;\n\t\t}\n\t\twhile (tagElse--) {\n\t\t\tbindTos = [];\n\t\t\tif (targetPaths = targetPathsElses[tagElse]) {\n\t\t\t\tbindTo = targetPaths._jsvto ? [\"jsvto\"] : (bindTo || [0]);\n\t\t\t\tif (!tagElse && tag && tag._.ths) {\n\t\t\t\t\t// Tag has a this=expr bindign for which we will create an additional 'to' target (at index bindTo.length)\n\t\t\t\t\tbindTo = bindTo.concat(\"this\");\n\t\t\t\t}\n\t\t\t\tk = bindTo.length;\n\t\t\t\twhile (k--) {\n\t\t\t\t\tpath = \"\";\n\t\t\t\t\tcontextCb = linkCtx._ctxCb;\n\t\t\t\t\tpaths = bindTo[k];\n\t\t\t\t\tpaths = targetPaths[+paths === paths ? paths : \"_\" + paths]; // If path is a string, prepend \"_\" to avoid collision (e.g. with array.length if path is \"length\")\n\t\t\t\t\tif (pathIndex = paths && paths.length) {\n\t\t\t\t\t\tlastPath = paths[pathIndex - 1];\n\t\t\t\t\t\tif (lastPath._cpfn) { // Computed property exprOb\n\n\t\t\t\t\t\t\tbindtoOb = lastPath;\n\t\t\t\t\t\t\twhile (lastPath.sb && lastPath.sb._cpfn) {\n\t\t\t\t\t\t\t\tpath = lastPath = lastPath.sb;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tpath = lastPath.sb || path && path.path;\n\t\t\t\t\t\t\tlastPath = path ? path.slice(1) : bindtoOb.path;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tto = path\n\t\t\t\t\t\t\t? [bindtoOb, // 'exprOb' for this expression and view-binding. So bindtoOb.ob is current object returned by expression.\n\t\t\t\t\t\t\t\t\tlastPath]\n\t\t\t\t\t\t\t: resolveDataTargetPath(lastPath, source, contextCb); // Get 'to' for target path: lastPath\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Contextual parameter ~foo with no external binding - has ctx.foo = [{_ocp: xxx}] and binds to ctx.foo._ocp\n\t\t\t\t\t\tlinkedCtxParam = tag.linkedCtxParam;\n\t\t\t\t\t\tto = [];\n\t\t\t\t\t\tfromIndex = tag._.fromIndex;\n\t\t\t\t\t\tif (fromIndex && linkedCtxParam && linkedCtxParam[fromIndex[k]]) {\n\t\t\t\t\t\t\t// This is a tag binding, with linked tag contextual parameters\n\t\t\t\t\t\t\tto = [tag.tagCtxs[tagElse].ctx[linkedCtxParam[fromIndex[k]]][0], _ocp];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ((obsCtxPrm = to._cxp) && obsCtxPrm.tag && lastPath.indexOf(\".\")<0) {\n\t\t\t\t\t\t// This is a binding for a tag contextual parameter (e.g. within a tag block content\n\t\t\t\t\t\tto = obsCtxPrm;\n\t\t\t\t\t}\n\t\t\t\t\tbindTos.unshift(to);\n\t\t\t\t}\n\t\t\t}\n\t\t\ttos.unshift(bindTos);\n\t\t}\n\t\tbinding.to = tos;\n\t}\n}\n\nfunction resolveDataTargetPath(targetPath, source, contextCb) {\n\t// Iteratively process targetPath, resolving ~a.b.c paths for contextual parameters\n\tvar path, bindtoOb, to, l, obsCtxPrm, view, topCp, data;\n\n\twhile (targetPath && targetPath !== _ocp && (to = contextCb(path = targetPath.split(\"^\").join(\".\"), source)) && (l = to.length)) {\n\t\tif (obsCtxPrm = to[0]._cxp) { // Two-way binding to a contextual parameter reference, ~foo (declared as ~foo=expr on a parent tag)\n\t\t\ttopCp = topCp || obsCtxPrm;\n\t\t\tview = to[0][0];\n\t\t\tif (_ocp in view) {\n\t\t\t\tdata = view;\n\t\t\t\tview = view._vw;\n\t\t\t} else {\n\t\t\t\tdata = view.data;\n\t\t\t}\n\t\t\ttopCp.path = targetPath = to[0][1];\n\t\t\tto = [topCp.data = data, targetPath];\n\t\t\t\tcontextCb = $sub._gccb(view);\n\t\t\t\tif (targetPath._cpfn) { // computed property\n\t\t\t\t\tbindtoOb = targetPath;\n\t\t\t\t\tbindtoOb.data = to[0];\n\t\t\t\t\tbindtoOb._cpCtx = contextCb;\n\t\t\t\t\twhile (targetPath.sb && targetPath.sb._cpfn) {\n\t\t\t\t\t\tpath = targetPath = targetPath.sb;\n\t\t\t\t\t}\n\t\t\t\t\tpath = targetPath.sb || path && path.path;\n\t\t\t\t\ttargetPath = path ? path.slice(1) : bindtoOb.path;\n\t\t\t\t\tto = [\n\t\t\t\t\t\tbindtoOb, // 'exprOb' for this expression and view-binding. So bindtoOb.ob is current object returned by expression.\n\t\t\t\t\t\ttargetPath\n\t\t\t\t\t];\n\t\t\t\t} else if (obsCtxPrm.tag && obsCtxPrm.path === _ocp) {\n\t\t\t\t\tto = obsCtxPrm;\n\t\t\t\t}\n\t\t} else { // Two-way binding to a helper - e.g. ~address.street, or computed, e.g. ~fullName(), or view property e.g. #data.foo\n\t\t\tto = l>1\n\t\t\t\t? [to[l-2], to[l-1]] // With path: [object, path]\n\t\t\t\t: [to[l-1]]; // No path, (e.g. [function] for computed with setter)\n\t\t}\n\t\tsource = to[0];\n\t\ttargetPath = to[1];\n\t}\n\tto = to || [source, path];\n\tto._cxp = topCp;\n\treturn to;\n}\n\nfunction mergeCtxs(tag, newCtxs, replace) { // Merge updated tagCtxs into tag.tagCtxs\n\tvar tagCtx, newTagCtx, latePath,\n\t\tview = tag.tagCtx.view,\n\t\ttagCtxs = tag.tagCtxs || [tag.tagCtx],\n\t\tl = tagCtxs.length,\n\t\trefresh = !newCtxs;\n\n\tif (refresh) {\n\t\tnewCtxs = tag._.bnd.call(view.tmpl, (tag.linkCtx || view).data, view, $sub);\n\t\tif (newCtxs.lt) {\n\t\t\treturn; // We are calling tag.refresh() but a late path (@a.b.c) has not yet returned an object (@a) so cancel the refresh()\n\t\t}\n\t\ttag._.lt = undefined; // All late paths are now resolved, so this is no longer a late tag\n\t\tnewCtxs = $isArray(newCtxs) ? newCtxs : [newCtxs];\n\t}\n\n\tif (replace) {\n\t\t// Replace previous tagCtxs by new ones, rather than merging\n\t\ttagCtxs = tag.tagCtxs = newCtxs;\n\t\ttag.tagCtx = tagCtxs[0];\n\t\taddLinkMethods(tag);\n\t} else {\n\t\twhile (l--) {\n\t\t\ttagCtx = tagCtxs[l];\n\t\t\tnewTagCtx = newCtxs[l];\n\t\t\t$observable(tagCtx.props).setProperty(newTagCtx.props);\n\t\t\t$extend(tagCtx.ctx, newTagCtx.ctx); // We don't support propagating ctx variables, ~foo, observably, to nested views. So extend, not setProperty...\n\t\t\ttagCtx.args = newTagCtx.args;\n\t\t\tif (refresh) {\n\t\t\t\ttagCtx.tmpl = newTagCtx.tmpl;\n\t\t\t}\n\t\t}\n\t}\n\t$sub._thp(tag, tagCtxs[0]); // tagHandlersFromProps\n\treturn tagCtxs;\n}\n\n//=========\n// Disposal\n//=========\n\nfunction clean(elems) {\n\t// Remove data-link bindings, or contained views\n\tvar l, elem, bindings,\n\t\telemArray = [],\n\t\tlen = elems.length,\n\t\ti = len;\n\twhile (i--) {\n\t\t// Copy into an array, so that deletion of nodes from DOM will not cause our 'i' counter to get shifted\n\t\t// (Note: This seems as fast or faster than elemArray = [].slice.call(elems); ...)\n\t\telemArray.push(elems[i]);\n\t}\n\ti = len;\n\twhile (i--) {\n\t\telem = elemArray[i];\n\t\tif (elem.parentNode) {\n\t\t\t// Has not already been removed from the DOM\n\t\t\tif (bindings = elem._jsvBnd) {\n\t\t\t\t// Get propertyChange bindings for this element\n\t\t\t\t// This may be an element with data-link, or the opening script marker node for a data-linked tag {^{...}}\n\t\t\t\t// bindings is a string with the syntax: \"(&bindingId)*\"\n\t\t\t\tbindings = bindings.slice(1).split(\"&\");\n\t\t\t\telem._jsvBnd = \"\";\n\t\t\t\tl = bindings.length;\n\t\t\t\twhile (l--) {\n\t\t\t\t\t// Remove associated bindings\n\t\t\t\t\tremoveViewBinding(bindings[l], elem._jsvLkEl, elem); // unbind bindings with this bindingId on this view\n\t\t\t\t}\n\t\t\t}\n\t\t\tdisposeTokens(markerNodeInfo(elem) + (elem._df || \"\"), elem);\n\t\t}\n\t}\n}\n\nfunction removeViewBinding(bindId, linkedElemTag, elem) {\n\t// Unbind\n\tvar objId, linkCtx, tag, object, obsId, tagCtxs, l, map, linkedElem, trigger, view, tagCtx, linkedElems, allLinkedElems,\n\t\tbinding = bindingStore[bindId];\n\n\tif (linkedElemTag) {\n\t\telem._jsvLkEl = undefined;\n\t} else if (binding && (!elem || elem === binding.elem)) { // Test that elem is actually binding.elem, since cloned elements can have inappropriate markerNode info\n\t\tdelete bindingStore[bindId]; // Delete already, so call to onDispose handler below cannot trigger recursive deletion (through recursive call to jQuery cleanData)\n\t\tfor (objId in binding.bnd) {\n\t\t\tobject = binding.bnd[objId];\n\t\t\tobsId = binding.cbId;\n\t\t\tif ($isArray(object)) {\n\t\t\t\t$([object]).off(arrayChangeStr + obsId).off(propertyChangeStr + obsId); // There may be either or both of arrayChange and propertyChange\n\t\t\t} else {\n\t\t\t\t$(object).off(propertyChangeStr + obsId);\n\t\t\t}\n\t\t\tdelete binding.bnd[objId];\n\t\t}\n\n\t\tif (linkCtx = binding.linkCtx) {\n\t\t\tif (tag = linkCtx.tag) {\n\t\t\t\tif (tagCtxs = tag.tagCtxs) {\n\t\t\t\t\tl = tagCtxs.length;\n\t\t\t\t\twhile (l--) {\n\t\t\t\t\t\ttagCtx = tagCtxs[l];\n\t\t\t\t\t\tif (map = tagCtx.map) {\n\t\t\t\t\t\t\tmap.unmap(); //unobserve\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Copy linkedElems in case tag.linkedElem or tag.linkedElems are undefined in onUnbind\n\t\t\t\t\t\tif (linkedElems = tagCtx.linkedElems) {\n\t\t\t\t\t\t\tallLinkedElems = (allLinkedElems || []).concat(linkedElems);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (tag.onUnbind) {\n\t\t\t\t\ttag.onUnbind(tag.tagCtx, linkCtx, tag.ctx);\n\t\t\t\t}\n\t\t\t\tif (tag.onDispose) {\n\t\t\t\t\ttag.onDispose();\n\t\t\t\t}\n\n\t\t\t\tif (!tag._elCnt) {\n\t\t\t\t\tif (tag._prv) {\n\t\t\t\t\t\ttag._prv.parentNode.removeChild(tag._prv);\n\t\t\t\t\t}\n\t\t\t\t\tif (tag._nxt) {\n\t\t\t\t\t\ttag._nxt.parentNode.removeChild(tag._nxt);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlinkedElems = allLinkedElems || [$(linkCtx.elem)];\n\t\t\tl = linkedElems.length;\n\t\t\twhile (l--) {\n\t\t\t\tlinkedElem = linkedElems[l];\n\t\t\t\tif (trigger = linkedElem && linkedElem[0] && linkedElem[0]._jsvTr) {\n\t\t\t\t\tbindTriggerEvent(linkedElem, trigger, \"off\");\n\t\t\t\t\tlinkedElem[0]._jsvTr = undefined;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tview = linkCtx.view;\n\t\t\tif (view.type === \"link\") {\n\t\t\t\tview.parent.removeViews(view._.key, undefined, true); // A \"link\" view is associated with the binding, so should be disposed with binding.\n\t\t\t} else {\n\t\t\t\tdelete view._.bnds[bindId];\n\t\t\t}\n\t\t}\n\t\tdelete cbBindingsStore[binding.cbId];\n\t}\n}\n\nfunction $unlink(to) {\n\tif (to) {\n\t\tto = to.jquery ? to : $(to);\n\t\tto.each(function() {\n\t\t\tvar innerView;\n\t\t\t//TODO fix this for better perf. Rather that calling inner view multiple times which does querySelectorAll each time, consider a single querySelectorAll\n\t\t\t// or simply call view.removeViews() on the top-level views under the target 'to' node, then clean(...)\n\t\t\t// And/or replace each() by for() or while()\n\t\t\twhile ((innerView = $view(this, true)) && innerView.parent) {\n\t\t\t\tinnerView.parent.removeViews(innerView._.key, undefined, true);\n\t\t\t}\n\t\t\tclean(this.getElementsByTagName(\"*\"));\n\t\t});\n\t\tclean(to);\n\t} else {\n\t\t// Call to $.unlink() is equivalent to $.unlink(true, \"body\")\n\t\tif (activeBody) {\n\t\t\t$(activeBody)\n\t\t\t\t.off(elementChangeStr, onElemChange)\n\t\t\t\t.off('blur.jsv', '[contenteditable]', onElemChange);\n\t\t\tactiveBody = undefined;\n\t\t}\n\t\ttopView.removeViews();\n\t\tclean(document.body.getElementsByTagName(\"*\"));\n\t}\n}\n\n//========\n// Helpers\n//========\n\nfunction inputAttrib(elem) {\n\treturn elem.type === CHECKBOX ? elem[CHECKED] : elem.value;\n}\n\nfunction changeHandler(view, name, tag) {\n\t// Get onBeforeChange, onAfterChange, onAfterCreate handler - if there is one;\n\treturn tag && tag[name] || view.ctx[name] && view.ctxPrm(name) || $views.helpers[name];\n}\n\n//========================== Initialize ==========================\n\n//=====================\n// JsRender integration\n//=====================\n\naddLinkMethods($sub.View.prototype); // Modify the View prototype to include link methods\n\n$sub.onStore.template = function(name, item, parentTmpl) {\n\tif (item === null) {\n\t\tdelete $.link[name];\n\t\tdelete $.render[name];\n\t} else {\n\t\titem.link = tmplLink;\n\n\t\tif (name && !parentTmpl && name !== \"jsvTmpl\") {\n\t\t\t$.render[name] = item;\n\t\t\t$.link[name] = function() {\n\t\t\t\treturn tmplLink.apply(item, arguments);\n\t\t\t};\n\t\t}\n\t}\n};\n\n$sub.viewInfos = viewInfos; // Expose viewInfos() as public helper method\n\n// Define JsViews version of delimiters(), and initialize\n($viewsSettings.delimiters = function() {\n\t// Run delimiters initialization in context of jsrender.js\n\tvar ret = oldJsvDelimiters.apply(0, arguments);\n\n\tif (oldJsvDelimiters !== $viewsDelimiters) {\n\t\t// If JsRender was loaded before JsViews, then need also to initialize and set globals in that JsRender instance\n\t\tret = $viewsDelimiters.apply(0, arguments);\n\t}\n\n\t// Data-linking must use new delimiters\n\trTagDatalink = new RegExp(\"(?:^|\\\\s*)([\\\\w-]*)(\\\\\" + linkChar + \")?(\\\\\" + delimOpenChar1 + $sub.rTag + \"(:\\\\w*)?\\\\\" + delimCloseChar0 + \")\", \"g\");\n\treturn ret;\n})(); // jshint ignore:line\n\n$sub.addSetting(\"trigger\");\n\n//====================================\n// Additional members for linked views\n//====================================\n\nfunction transferViewTokens(prevNode, nextNode, parentElem, id, viewOrTagChar, refresh) {\n\t// Transfer tokens on prevNode of viewToRemove/viewToRefresh to nextNode or parentElem._df\n\t// view marker tokens: #m_...VIEW.../m_\n\t// tag marker tokens: #m^...TAG..../m^\n\n\tvar i, l, vwInfos, vwInfo, viewOrTag, viewId, tokens,\n\t\tprecedingLength = 0,\n\t\temptyView = prevNode === nextNode;\n\n\tif (prevNode) {\n\t\t// prevNode is either the first node in the viewOrTag, or has been replaced by the vwInfos tokens string\n\t\tvwInfos = viewInfos(prevNode) || [];\n\t\tfor (i = 0, l = vwInfos.length; i < l; i++) {\n\t\t\t// Step through views or tags on the prevNode\n\t\t\tvwInfo = vwInfos[i];\n\t\t\tviewId = vwInfo.id;\n\t\t\tif (viewId === id && vwInfo.ch === viewOrTagChar) {\n\t\t\t\tif (refresh) {\n\t\t\t\t\t// This is viewOrTagToRefresh, this is the last viewOrTag to process...\n\t\t\t\t\tl = 0;\n\t\t\t\t} else {\n\t\t\t\t\t// This is viewOrTagToRemove, so we are done...\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!emptyView) {\n\t\t\t\tviewOrTag = vwInfo.ch === \"_\"\n\t\t\t\t\t? viewStore[viewId] // A view: \"#m_\" or \"/m_\"\n\t\t\t\t\t: bindingStore[viewId].linkCtx.tag; // A tag \"#m^\" or \"/m^\"\n\t\t\t\tif (viewOrTag) {\n\t\t\t\t\tif (vwInfo.open) { // A \"#m_\" or \"#m^\" token\n\t\t\t\t\t\tviewOrTag._prv = nextNode;\n\t\t\t\t\t} else if (vwInfo.close) { // A \"/m_\" or \"/m^\" token\n\t\t\t\t\t\tviewOrTag._nxt = nextNode;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tprecedingLength += viewId.length + 2;\n\t\t}\n\n\t\tif (precedingLength) {\n\t\t\tprevNode.setAttribute(jsvAttrStr, prevNode.getAttribute(jsvAttrStr).slice(precedingLength));\n\t\t}\n\t\ttokens = nextNode ? nextNode.getAttribute(jsvAttrStr) : parentElem._df;\n\t\tif (l = tokens.indexOf(\"/\" + id + viewOrTagChar) + 1) {\n\t\t\ttokens = vwInfos._tkns.slice(0, precedingLength) + tokens.slice(l + (refresh ? -1 : id.length + 1));\n\t\t}\n\t\tif (tokens) {\n\t\t\tif (nextNode) {\n\t\t\t\t// If viewOrTagToRemove was an empty viewOrTag, we will remove both #n and /n\n\t\t\t\t// (and any intervening tokens) from the nextNode (=== prevNode)\n\t\t\t\t// If viewOrTagToRemove was not empty, we will take tokens preceding #n from prevNode,\n\t\t\t\t// and concatenate with tokens following /n on nextNode\n\t\t\t\tnextNode.setAttribute(jsvAttrStr, tokens);\n\t\t\t} else {\n\t\t\t\tsetDefer(parentElem, tokens);\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// !prevNode, so there may be a deferred nodes token on the parentElem. Remove it.\n\t\tsetDefer(parentElem, removeSubStr(parentElem._df, \"#\" + id + viewOrTagChar));\n\t\tif (!refresh && !nextNode) {\n\t\t\t// If this viewOrTag is being removed, and there was no .nxt, remove closing token from deferred tokens\n\t\t\tsetDefer(parentElem, removeSubStr(parentElem._df, \"/\" + id + viewOrTagChar));\n\t\t}\n\t}\n}\n\nfunction disposeTokens(tokens, elem) {\n\tvar i, l, vwItem, vwInfos;\n\tif (vwInfos = viewInfos(tokens, true, rOpenMarkers)) {\n\t\tfor (i = 0, l = vwInfos.length; i < l; i++) {\n\t\t\tvwItem = vwInfos[i];\n\t\t\tif (vwItem.ch === \"_\") {\n\t\t\t\tif ((vwItem = viewStore[vwItem.id]) && vwItem.type && (!elem || vwItem._prv === elem || vwItem.parentElem === elem )) {\n\t\t\t\t\t// If this is the _prv (prevNode) for a view, remove the view\n\t\t\t\t\t// - unless view.type is undefined, in which case it is already being removed\n\t\t\t\t\t// (or unless the elem is not related - e.g. a cloned element which 'accidentally' picked up the data-jsv atttribute of the ._df expando)\n\t\t\t\t\tvwItem.parent.removeViews(vwItem._.key, undefined, true);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tremoveViewBinding(vwItem.id, undefined, elem); // unbind bindings with this bindingId on this view\n\t\t\t}\n\t\t}\n\t}\n}\n\n//============================================\n// Add link methods to data-linked view or tag\n//============================================\n\nfunction updateValue(val, index, tagElse, async, bindId, ev) {\n// Observably update a data value targeted by the binding.to binding of a 2way data-link binding. Called when elem changes\n// Called when linkedElem of a tag control changes: as updateValue(val, index, tagElse, bindId, ev) - this: undefined\n// Called directly as tag.updateValue(val, index, tagElse) - this: tag\n\tvar self = this,\n\t\tvalues = [];\n\tif (self && self._tgId) {\n\t\tbindId = self;\n\t}\n\tvalues[index||0] = val;\n\tif (async) {\n\t\tsetTimeout(function() {\n\t\t\tupdateValues(values, tagElse, bindId, ev);\n\t\t});\n\t} else {\n\t\tupdateValues(values, tagElse, bindId, ev);\n\t}\n\treturn self;\n}\n\nfunction setValues() {\n// tagCtx.setValues() calls tag.setValue() on that tagCtx for each bindTo target\n\tvar m = arguments.length;\n\twhile (m--) {\n\t\tthis.tag.setValue(arguments[m], m, this.index);\n\t}\n}\n\nfunction addLinkMethods(tagOrView) { // tagOrView is View prototype or tag instance\n\n\tvar l, m, tagCtx, boundProps, bindFrom, key, theTag, theView;\n\n\ttagOrView.contents = function(deep, select) {\n\t\t// For a view, a tag or a tagCtx, return jQuery object with the content nodes,\n\t\tif (deep !== !!deep) {\n\t\t\t// deep not boolean, so this is contents(selector)\n\t\t\tselect = deep;\n\t\t\tdeep = undefined;\n\t\t}\n\t\tvar filtered,\n\t\t\tnodes = $(this.nodes());\n\t\tif (nodes[0]) {\n\t\t\tfiltered = select ? nodes.filter(select) : nodes;\n\t\t\tnodes = deep && select ? filtered.add(nodes.find(select)) : filtered;\n\t\t}\n\t\treturn nodes;\n\t};\n\n\ttagOrView.nodes = function(withMarkers, prevNode, nextNode) {\n\t\t// For a view, a tag or a tagCtx, return top-level nodes\n\t\t// Do not return any script marker nodes, unless withMarkers is true\n\t\t// Optionally limit range, by passing in prevNode or nextNode parameters\n\n\t\tvar node,\n\t\t\tself = this.contentView || this, // If tagCtx, use tagCtx.contentView\n\t\t\telCnt = self._elCnt,\n\t\t\tprevIsFirstNode = !prevNode && elCnt,\n\t\t\tnodes = [];\n\n\t\tif (!self.args) { // If tagCtx with no content (so no contentView) self is tagCtx: return empty [];\n\t\t\tprevNode = prevNode || self._prv;\n\t\t\tnextNode = nextNode || self._nxt;\n\n\t\t\tnode = prevIsFirstNode\n\t\t\t\t? (prevNode === self._nxt\n\t\t\t\t\t? self.parentElem.lastSibling\n\t\t\t\t\t: prevNode)\n\t\t\t\t: (self.inline === false\n\t\t\t\t\t? prevNode || self.linkCtx.elem.firstChild\n\t\t\t\t\t: prevNode && prevNode.nextSibling);\n\n\t\t\twhile (node && (!nextNode || node !== nextNode)) {\n\t\t\t\tif (withMarkers || elCnt || node.tagName !== SCRIPT) {\n\t\t\t\t\t// All the top-level nodes in the view\n\t\t\t\t\t// (except script marker nodes, unless withMarkers = true)\n\t\t\t\t\t// (Note: If a script marker node, viewInfo.elCnt undefined)\n\t\t\t\t\tnodes.push(node);\n\t\t\t\t}\n\t\t\t\tnode = node.nextSibling;\n\t\t\t}\n\t\t}\n\t\treturn nodes;\n\t};\n\n\ttagOrView.childTags = function(deep, tagName) {\n\t\t// For a view, a tag or a tagCtx, return child tags - at any depth, or as immediate children only.\n\t\tif (deep !== !!deep) {\n\t\t\t// deep not boolean, so this is childTags(tagName) - which looks for top-level tags of given tagName\n\t\t\ttagName = deep;\n\t\t\tdeep = undefined;\n\t\t}\n\n\t\tvar self = this.contentView || this, // If tagCtx, use tagCtx.contentView\n\t\t\tview = self.link ? self : self.tagCtx.view, // This may be a view or a tag. If a tag, get the view from tag.tagCtx.view\n\t\t\tprevNode = self._prv,\n\t\t\telCnt = self._elCnt,\n\t\t\ttags = [];\n\n\t\tif (!self.args) { // If tagCtx with no content (so no contentView) self is tagCtx: return empty [];\n\t\t\tview.link(\n\t\t\t\tundefined,\n\t\t\t\tself.parentElem,\n\t\t\t\telCnt ? prevNode && prevNode.previousSibling : prevNode,\n\t\t\t\tself._nxt,\n\t\t\t\tundefined,\n\t\t\t\t{get:{\n\t\t\t\t\ttags: tags,\n\t\t\t\t\tdeep: deep,\n\t\t\t\t\tname: tagName,\n\t\t\t\t\tid: self.link ? self._.id + \"_\" : self._tgId + \"^\"\n\t\t\t\t}}\n\t\t\t);\n\t\t}\n\t\treturn tags;\n\t};\n\n\tif (tagOrView._is === \"tag\") {\n\t\t//=======================\n\t\t// This is a TAG instance\n\t\t//=======================\n\n\t\ttheTag = tagOrView;\n\n\t\tm = theTag.tagCtxs.length;\n\t\twhile (m--) {\n\t\t\ttagCtx = theTag.tagCtxs[m];\n\n\t\t\ttagCtx.setValues = setValues;\n\t\t\ttagCtx.contents = tagOrView.contents;\n\t\t\ttagCtx.childTags = tagOrView.childTags;\n\t\t\ttagCtx.nodes = tagOrView.nodes;\n\t\t}\n\n\t\tboundProps = theTag.boundProps = theTag.boundProps || [];\n\t\tif (bindFrom = theTag.bindFrom) {\n\t\t\tl = bindFrom.length;\n\t\t\twhile (l--) {\n\t\t\t\tkey = bindFrom[l];\n\t\t\t\tif (key + \"\" === key) {\n\t\t\t\t\tbindFrom[key] = 1;\n\t\t\t\t\tif ($inArray(key, boundProps) < 0) {\n\t\t\t\t\t\tboundProps.push(key); // Add any 'bindFrom' props to boundProps array. (So two-way binding works without writing ^foo=expression)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttheTag.setValue = $sub._gm( // getMethod\n\t\t\ttheTag.constructor.prototype.setValue || function(val) { // base method\n\t\t\t\treturn val;\n\t\t\t},\n\t\t\tfunction(val, indexFrom, tagElse) {\n\t\t\t\tindexFrom = indexFrom || 0;\n\t\t\t\ttagElse = tagElse || 0;\n\n\t\t\t\tvar linkedElem, linkedEl, linkedCtxParam, linkedCtxPrmKey, indexTo, linkedElems,\n\t\t\t\t\ttagCtx = theTag.tagCtxs[tagElse],\n\t\t\t\t\tnewVal = theTag.base.call(theTag, val, indexFrom, tagElse);\n\n\t\t\t\tif (newVal !== undefined) { // Call tag method tag.setValue(), if implemented\n\t\t\t\t\tval = newVal;\n\t\t\t\t}\n\t\t\t\tif (val !== undefined && (theTag.convert || theTag._.toIndex[indexFrom] === undefined)\n\t\t\t\t\t\t&& (linkedCtxParam = theTag.linkedCtxParam)\n\t\t\t\t\t\t&& linkedCtxParam[indexFrom]\n\t\t\t\t\t\t// If this setValue call corresponds to a tag contextual parameter and the tag has a converter, then we need to set the\n\t\t\t\t\t\t// value of this contextual parameter (since it is not directly bound to the tag argument/property when there is a converter).\n\t\t\t\t\t\t&& (linkedCtxPrmKey = linkedCtxParam[indexFrom])\n\t\t\t\t\t) {\n\t\t\t\t\ttagCtx.ctxPrm(linkedCtxPrmKey, val);\n\t\t\t\t}\n\t\t\t\tindexTo = theTag._.toIndex[indexFrom];\n\t\t\t\tif (indexTo !== undefined) {\n\t\t\t\t\tif (linkedElems = tagCtx.linkedElems || theTag.linkedElem && [theTag.linkedElem]) {\n\t\t\t\t\t\tif ((linkedElem = linkedElems[indexTo]) && (l = linkedElem.length)) {\n\t\t\t\t\t\t\twhile (l--) {\n\t\t\t\t\t\t\t\tlinkedEl = linkedElem[l];\n\t\t\t\t\t\t\t\tif (val !== undefined && !linkedEl._jsvChg && theTag.linkCtx._val !== val) {\n\t\t\t\t\t\t\t\t\tif (linkedEl.value !== undefined) {\n\t\t\t\t\t\t\t\t\t\tif (linkedEl.type === CHECKBOX) {\n\t\t\t\t\t\t\t\t\t\t\tlinkedEl[CHECKED] = val && val !== \"false\";\n\t\t\t\t\t\t\t\t\t\t} else if (linkedEl.type === RADIO) {\n\t\t\t\t\t\t\t\t\t\t\tlinkedEl[CHECKED] = (linkedEl.value === val);\n\t\t\t\t\t\t\t\t\t\t} else if ($isArray(val)) {\n\t\t\t\t\t\t\t\t\t\t\tlinkedEl.value = val; // Don't use jQuery since it replaces array by mapped clone\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t$(linkedEl).val(val); // Use jQuery for attrHooks - can't just set value (on select, for example)\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tlinkedEl[linkedEl.contentEditable === TRUE ? \"innerHTML\" : TEXTCONTENT] = val;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (tagCtx.props.name) {\n\t\t\t\t\t\t\t\t\tlinkedEl.name = linkedEl.name || tagCtx.props.name;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn theTag;\n\t\t\t}\n\t\t);\n\t\ttheTag.updateValue = updateValue;\n\n\t\ttheTag.updateValues = function() {\n\t\t\treturn updateValues(arguments, undefined, this);\n\t\t};\n\n\t\ttheTag.setValues = function() {\n\t\t// tag.setValues(a, b, c) calls tagCtx.setValues(a, b, c) on the first tagCtx\n\t\t\tsetValues.apply(theTag.tagCtx, arguments);\n\t\t\treturn theTag;\n\t\t};\n\n\t\ttheTag.refresh = function() {\n\t\t\tvar attr, sourceValue,\n\t\t\t\tlinkCtx = theTag.linkCtx,\n\t\t\t\tview = theTag.tagCtx.view;\n\n\t\t\tif (!(sourceValue = mergeCtxs(theTag))) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (theTag.onUnbind) {\n\t\t\t\ttheTag.onUnbind(theTag.tagCtx, linkCtx, theTag.ctx);\n\t\t\t\ttheTag._.unlinked = true;\n\t\t\t}\n\t\t\tattr = theTag.inline ? HTML : (linkCtx.attr || defaultAttr(theTag.parentElem, true));\n\t\t\tsourceValue = theTag.tagName === \":\"\n\t\t\t\t? $sub._cnvt(theTag.convert, view, theTag.tagCtx)\n\t\t\t\t: $sub._tag(theTag, view, view.tmpl, sourceValue, true); // Get rendered HTML for tag, based on refreshed tagCtxs\n\n\t\t\tobserveAndBind(linkCtx, linkCtx.data, linkCtx.elem);\n\t\t\tupdateContent(sourceValue, linkCtx, attr, theTag);\n\t\t\tcallAfterLink(theTag);\n\t\t\treturn theTag;\n\t\t};\n\n\t\ttheTag.domChange = function() { // domChange notification support\n\t\t\tvar elem = this.parentElem,\n\t\t\t\thasListener = $._data(elem).events,\n\t\t\t\tdomChangeNotification = \"jsv-domchange\";\n\n\t\t\tif (hasListener && hasListener[domChangeNotification]) {\n\t\t\t\t// Only trigger handler if there is a handler listening for this event. (Note using triggerHandler - so no event bubbling.)\n\t\t\t\t$(elem).triggerHandler(domChangeNotification, arguments);\n\t\t\t}\n\t\t};\n\n\t\t//====================================\n\t\t// End of added link methods for TAG\n\t\t//====================================\n\t} else {\n\t\t//=========================\n\t\t// This is a VIEW prototype\n\t\t//=========================\n\n\t\ttheView = tagOrView;\n\n\t\t// Note: a linked view will also, after linking have nodes[], _prv (prevNode), _nxt (nextNode) ...\n\t\ttheView.addViews = function(index, dataItems) {\n\t\t\t// if view is not an array view, do nothing\n\t\t\tvar i, viewsCount,\n\t\t\t\tview = this,\n\t\t\t\titemsCount = dataItems.length,\n\t\t\t\tviews = view.views;\n\n\t\t\tif (!view._.useKey && itemsCount) {\n\t\t\t\t// view is of type \"array\"\n\t\t\t\tviewsCount = views.length + itemsCount;\n\n\t\t\t\tif (viewsCount === view.data.length // If views not already synced to array (e.g. triggered by array.length propertyChange - jsviews/issues/301)\n\t\t\t\t\t\t&& renderAndLink(view, index, view.tmpl, views, dataItems, view.ctx) !== false) {\n\t\t\t\t\tif (!view._.srt) { // Not part of a 'sort' on refresh\n\t\t\t\t\t\tview.fixIndex(index + itemsCount);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\ttheView.removeViews = function(index, itemsCount, keepNodes, isMove) {\n\t\t\t// view.removeViews() removes all the child views\n\t\t\t// view.removeViews(index) removes the child view with specified index or key\n\t\t\t// view.removeViews(index, count) removes the specified nummber of child views, starting with the specified index\n\t\t\tfunction removeView(index) {\n\t\t\t\tvar id, bindId, parentElem, prevNode, nextNode, nodesToRemove,\n\t\t\t\t\tviewToRemove = views[index];\n\n\t\t\t\tif (viewToRemove && viewToRemove.link) {\n\t\t\t\t\tid = viewToRemove._.id;\n\t\t\t\t\tif (!keepNodes) {\n\t\t\t\t\t\t// Remove the HTML nodes from the DOM, unless they have already been removed, including nodes of child views\n\t\t\t\t\t\tnodesToRemove = viewToRemove.nodes();\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove child views, without removing nodes\n\t\t\t\t\tviewToRemove.removeViews(undefined, undefined, true);\n\n\t\t\t\t\tviewToRemove.type = undefined; // Set type to undefined: used as a flag that this view is being removed\n\t\t\t\t\tprevNode = viewToRemove._prv;\n\t\t\t\t\tnextNode = viewToRemove._nxt;\n\t\t\t\t\tparentElem = viewToRemove.parentElem;\n\t\t\t\t\t// If prevNode and nextNode are the same, the view is empty\n\t\t\t\t\tif (!keepNodes) {\n\t\t\t\t\t\t// Remove the HTML nodes from the DOM, unless they have already been removed, including nodes of child views\n\t\t\t\t\t\tif (viewToRemove._elCnt) {\n\t\t\t\t\t\t\t// if keepNodes is false (and transferring of tokens has not already been done at a higher level)\n\t\t\t\t\t\t\t// then transfer tokens from prevNode which is being removed, to nextNode.\n\t\t\t\t\t\t\ttransferViewTokens(prevNode, nextNode, parentElem, id, \"_\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$(nodesToRemove).remove();\n\t\t\t\t\t}\n\t\t\t\t\tif (!viewToRemove._elCnt) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tprevNode.parentNode.removeChild(prevNode); // (prevNode.parentNode is parentElem, except if jQuery Mobile or similar has inserted an intermediate wrapper\n\t\t\t\t\t\t\tnextNode.parentNode.removeChild(nextNode);\n\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t}\n\t\t\t\t\tsetArrayChangeLink(viewToRemove);\n\t\t\t\t\tfor (bindId in viewToRemove._.bnds) {\n\t\t\t\t\t\tremoveViewBinding(bindId);\n\t\t\t\t\t}\n\t\t\t\t\tdelete viewStore[id];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar current, childView, viewsCount,\n\t\t\t\tview = this,\n\t\t\t\tisArray = !view._.useKey,\n\t\t\t\tviews = view.views;\n\n\t\t\tif (isArray) {\n\t\t\t\tviewsCount = views.length;\n\t\t\t}\n\t\t\tif (index === undefined) {\n\t\t\t\t// Remove all child views\n\t\t\t\tif (isArray) {\n\t\t\t\t\t// views and data are arrays\n\t\t\t\t\tcurrent = viewsCount;\n\t\t\t\t\twhile (current--) {\n\t\t\t\t\t\tremoveView(current);\n\t\t\t\t\t}\n\t\t\t\t\tview.views = [];\n\t\t\t\t} else {\n\t\t\t\t\t// views and data are objects\n\t\t\t\t\tfor (childView in views) {\n\t\t\t\t\t\t// Remove by key\n\t\t\t\t\t\tremoveView(childView);\n\t\t\t\t\t}\n\t\t\t\t\tview.views = {};\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (itemsCount === undefined) {\n\t\t\t\t\tif (isArray) {\n\t\t\t\t\t\t// The parentView is data array view.\n\t\t\t\t\t\t// Set itemsCount to 1, to remove this item\n\t\t\t\t\t\titemsCount = 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Remove child view with key 'index'\n\t\t\t\t\t\tremoveView(index);\n\t\t\t\t\t\tdelete views[index];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (isArray && itemsCount\n\t\t\t\t\t&& (isMove || viewsCount - itemsCount === view.data.length)) { // If views not already synced to array (e.g. triggered by array.length propertyChange - jsviews/issues/301)\n\t\t\t\t\tcurrent = index + itemsCount;\n\t\t\t\t\t// Remove indexed items (parentView is data array view);\n\t\t\t\t\twhile (current-- > index) {\n\t\t\t\t\t\tremoveView(current);\n\t\t\t\t\t}\n\t\t\t\t\tviews.splice(index, itemsCount);\n\t\t\t\t\tif (!view._.srt) {\n\t\t\t\t\t\tview.fixIndex(index);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\ttheView.moveViews = function(oldIndex, index, itemsCount) {\n\t\t\tfunction parts(itemView, str) { // Get the totkens preceding the 'open' token for this view, #n_, and the tokens following (and including) the 'open' token\n\t\t\t\treturn RegExp(\"^(.*)(\" + (str ? \"\\\\/\" : \"#\") + itemView._.id + \"_.*)$\").exec(str || itemView._prv.getAttribute(jsvAttrStr));\n\t\t\t}\n\t\t\tfunction setPrv(itemView, tokens) {\n\t\t\t\tvar prv = itemView._prv;\n\t\t\t\tprv.setAttribute(jsvAttrStr, tokens);\n\t\t\t\ttokens.replace(rTagMarkers, function(all, open, close, id) {\n\t\t\t\t\tbindingStore[id].linkCtx.tag[open ? \"_prv\" : \"_nxt\"] = prv;\n\t\t\t\t});\n\t\t\t\ttokens.replace(rViewMarkers, function(all, open, close, id) {\n\t\t\t\t\tviewStore[id][open ? \"_prv\" : \"_nxt\"] = prv;\n\t\t\t\t});\n\t\t\t}\n\t\t\tvar nodes, childView, nxtView, insertBefore, viewId,\n\t\t\t\tview = this,\n\t\t\t\tselfNxt = view._nxt,\n\t\t\t\tviews = view.views,\n\t\t\t\tbackwards = index < oldIndex,\n\t\t\t\tfirstChange = backwards ? index : oldIndex,\n\t\t\t\tlastChange = backwards ? oldIndex : index,\n\t\t\t\ti = index,\n\t\t\t\tmovedNodes = [],\n\n\t\t\t\tviewsToMove = views.splice(oldIndex, itemsCount); // remove\n\n\t\t\tif (index > views.length) {\n\t\t\t\tindex = views.length;\n\t\t\t}\n\t\t\tviews.splice.apply(views, [index, 0].concat(viewsToMove)); //re-insert\n\n\t\t\titemsCount = viewsToMove.length;\n\t\t\tinsertBefore = index + itemsCount;\n\t\t\tlastChange += itemsCount;\n\n\t\t\tfor (i; i < insertBefore; i++) {\n\t\t\t\tchildView = views[i];\n\t\t\t\tnodes = childView.nodes(true);\n\t\t\t\tmovedNodes = view._elCnt ? movedNodes.concat(nodes) : movedNodes.concat(childView._prv, nodes, childView._nxt);\n\t\t\t}\n\t\t\tmovedNodes = $(movedNodes);\n\n\t\t\tif (insertBefore < views.length) {\n\t\t\t\tmovedNodes.insertBefore(views[insertBefore]._prv);\n\t\t\t} else if (selfNxt) {\n\t\t\t\tmovedNodes.insertBefore(selfNxt);\n\t\t\t} else {\n\t\t\t\tmovedNodes.appendTo(view.parentElem);\n\t\t\t}\n\n\t\t\tif (view._elCnt) {\n\t\t\t\tvar afterParts,\n\t\t\t\t\tendChange = backwards ? firstChange + itemsCount : lastChange - itemsCount,\n\t\t\t\t\tbeforeView = views[firstChange-1],\n\t\t\t\t\tstartView = views[firstChange],\n\t\t\t\t\tendView = views[endChange],\n\t\t\t\t\tafterView = views[lastChange],\n\t\t\t\t\tstartParts = parts(startView),\n\t\t\t\t\tendParts = parts(endView);\n\n\t\t\t\tsetPrv(startView, endParts[1] + startParts[2]);\n\t\t\t\tif (afterView) {\n\t\t\t\t\tafterParts = parts(afterView);\n\t\t\t\t\tsetPrv(afterView, startParts[1] + afterParts[2]);\n\t\t\t\t} else {\n\t\t\t\t\tviews[lastChange-1]._nxt = selfNxt;\n\t\t\t\t\tif (selfNxt) {\n\t\t\t\t\t\tafterParts = parts(view, selfNxt.getAttribute(jsvAttrStr));\n\t\t\t\t\t\tselfNxt.setAttribute(jsvAttrStr, startParts[1] + afterParts[2]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tafterParts = parts(view, view.parentElem._df);\n\n\t\t\t\t\t\tsetDefer(view.parentElem, startParts[1] + afterParts[2]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsetPrv(endView, afterParts[1] + endParts[2]);\n\t\t\t}\n\t\t\tview.fixIndex(firstChange);\n\t\t};\n\n\t\ttheView.refresh = function() {\n\t\t\tvar view = this,\n\t\t\t\tparent = view.parent;\n\n\t\t\tif (parent) {\n\t\t\t\trenderAndLink(view, view.index, view.tmpl, parent.views, view.data, undefined, true);\n\t\t\t\tsetArrayChangeLink(view);\n\t\t\t}\n\t\t};\n\n\t\ttheView.fixIndex = function(fromIndex) {\n\t\t\t// Fixup index on following view items...\n\t\t\tvar views = this.views,\n\t\t\t\tindex = views.length;\n\t\t\twhile (fromIndex < index--) {\n\t\t\t\tif (views[index].index !== index) {\n\t\t\t\t\t$observable(views[index]).setProperty(\"index\", index);\n\t\t\t\t\t// This is fixing up index, but not key, and not index on child views. From child views, use view.getIndex()\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\ttheView.link = viewLink;\n\n\t\t//====================================\n\t\t// End of added link methods for VIEW\n\t\t//====================================\n\t}\n}\n\n//========================\n// JsViews-specific converters\n//========================\n\n$converters.merge = function(val) {\n\t// Special converter used in data-linking to space-separated lists, such as className:\n\t// Currently only supports toggle semantics - and has no effect if toggle string is not specified\n\t// data-link=\"class{merge:boolExpr toggle=className}\"\n\tvar regularExpression,\n\t\tcurrentValue = this.linkCtx.elem.className,\n\t\ttoggle = this.tagCtx.props.toggle;\n\n\tif (toggle) {\n\t\t// We are toggling the class specified by the toggle property,\n\t\t// and the boolean val binding is driving the insert/remove toggle\n\n\t\tregularExpression = toggle.replace(/[\\\\^$.|?*+()[{]/g, \"\\\\$&\");\n\t\t// Escape any regular expression special characters (metacharacters) within the toggle string\n\t\tregularExpression = \"(\\\\s(?=\" + regularExpression + \"$)|(\\\\s)|^)(\" + regularExpression + \"(\\\\s|$))\";\n\t\t// Example: /(\\s(?=myclass$)|(\\s)|^)?(myclass(\\s|$))/ - so matches (\" myclass\" or \" \" or ^ ) followed by (\"myclass \" or \"myclass$\") where ^/$ are beginning/end of string\n\t\tcurrentValue = currentValue.replace(new RegExp(regularExpression), \"$2\");\n\t\tval = currentValue + (val ? (currentValue && \" \") + toggle : \"\");\n\t}\n\treturn val;\n};\n\n//========================\n// JsViews-specific tags\n//========================\n\n$tags({\n\ton: {\n\t\tattr: NONE,\n\t\tbindTo: [], // Don't need to bind to first arg, so prevent the default [0] binding\n\t\tinit: function(tagCtx) {\n\t\t\tvar content,\n\t\t\t\ttag = this,\n\t\t\t\ti = 0,\n\t\t\t\targs = tagCtx.args, // [events,] [selector,] handler\n\t\t\t\tl = args.length;\n\n\t\t\tfor (; ii && i+1; // handler index\n\t\t\tif (tag.inline) {\n\t\t\t\tif (!$sub.rTmpl.exec(content = $.trim(tagCtx.tmpl.markup))) {\n\t\t\t\t\t// Inline {^{on}} tag with no content (or external template content) or with content containing\n\t\t\t\t\t// no HTML or JsRender tags: We will wrap the (text) content, or the operation name in a \";\n\t\t\t\t}\n\t\t\t\ttag.attr = HTML;\n\t\t\t}\n\t\t},\n\t\tonBind: function() {\n\t\t\tif (this.template) { // {^{on/}} with no content has template rendering
\", \"
\"],\n\t\ttr: [2, \"\", \"
\"],\n\t\ttd: [3, \"\", \"
\"],\n\t\tcol: [2, \"\", \"
\"],\n\t\tsvg_ns: [1, \"\", \"\"],\n\t\t// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,\n\t\t// unless wrapped in a div with non-breaking characters in front of it.\n\t\tdiv: $.support.htmlSerialize ? [0, \"\", \"\"] : [1, \"X
\", \"
\"]\n\t},\n\t_fe: {\n\t\tinput: {\n\t\t\tfrom: inputAttrib, to: VALUE\n\t\t},\n\t\ttextarea: valueBinding,\n\t\tselect: valueBinding,\n\t\toptgroup: {\n\t\t\tto: \"label\"\n\t\t}\n\t}\n});\n\nreturn $;\n}, window));\n"]} \ No newline at end of file diff --git a/package.json b/package.json index 7b065d9..402a4bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jsviews", - "version": "v0.9.90", + "version": "v0.9.91", "description": "Next-generation MVVM and MVP framework - built on top of JsRender templates. Bringing templates to life...", "main": "./jsviews.js", "author": { @@ -16,7 +16,7 @@ "bugs": { "url": "https://github.com/borismoore/jsviews/issues" }, - "scripts": {}, + "scripts": { }, "keywords": [ "jsviews", "jsrender", @@ -34,9 +34,10 @@ "browserify": "^11.0.1", "glob-stream": "^5.0.0", "gulp": "^3.9.0", - "jquery": "^2.1.4", - "jsrender": "^0.9.90", + "jsrender": "^0.9.91", "qunit": "^0.7.6" }, - "dependencies": {} + "dependencies": { + "jquery": "^3.0.0" + } } diff --git a/test/unit-tests/requirejs-config.js b/test/unit-tests/requirejs-config.js index 2963744..31031b8 100644 --- a/test/unit-tests/requirejs-config.js +++ b/test/unit-tests/requirejs-config.js @@ -3,7 +3,7 @@ requirejs.config({ "baseUrl": "//www.jsviews.com/download", // Or point to correct local path on your system: "baseUrl": "/download", // "baseUrl": "../../download", // Or point to correct local path on your system: "baseUrl": "/download", "paths": { - "jquery": "//code.jquery.com/jquery-1.12.4", + "jquery": "//code.jquery.com/jquery-3.3.1", "jsrender": "./jsrender", "jquery.observable": "./jquery.observable", "jquery.views": "./jquery.views", diff --git a/test/unit-tests/tests-jsobservable.js b/test/unit-tests/tests-jsobservable.js index 0e8fbcc..f7c2b14 100644 --- a/test/unit-tests/tests-jsobservable.js +++ b/test/unit-tests/tests-jsobservable.js @@ -50,7 +50,6 @@ function myListener(ev, eventArgs) { } } - // =============== Model =============== function fullName(reverse, upper) { var name = reverse ? (this.lastName + " " + this.firstName()) : this.firstName() + " " + this.lastName; @@ -906,7 +905,7 @@ test("JsObservable: move()", function() { $.views.settings.advanced({_jsv: false}); }); -module("API - $.observe()"); +module("API - $.observe() (jso)"); test("depends, for computed observables", function() { @@ -1054,8 +1053,8 @@ test("Array", function() { // ............................... Assert ................................. equal(result + !$._data(myArray).events.arrayChange + " " + $._data(myArray).events.propertyChange.length, - "calls: 1, ev.data: prop: length, eventArgs: oldValue: 5 value: 6, eventArgs.path: length|true 1", - '$.observe(myArray, myArray, "length", myListener) listens to length propertyChange on the array, but not to array change on the array'); + "calls: 1, ev.data: prop: length, eventArgs: oldValue: 5 value: 6, eventArgs.path: length|regularCallbackCalls: 2, eventArgs: change: insert|false 1", + '$.observe(myArray, myArray, "length", myListener) listens to length propertyChange on the array, and to array change on the array'); // ................................ Reset .................................. reset(); @@ -1069,8 +1068,8 @@ test("Array", function() { $.observable(myArray).insert(15); // ............................... Assert ................................. - equal(result + !$._data(myArray).events, "regularCallbackCalls: 1, eventArgs: change: insert|false", - '$.unobserve(myArray, myArray, "length", myListener) removes the propertychange handler, but not the array handler'); + equal(result + !$._data(myArray).events, "true", + '$.unobserve(myArray, myArray, "length", myListener) removes the propertychange handler and the array handler'); // ................................ Reset .................................. reset(); @@ -1514,12 +1513,11 @@ test("observe/unobserve alternative signatures", function() { // ................................ Act .................................. $.observe(person, "name", "address^street", "phones", myListener); - var bindingsData = JSON.stringify([_jsv.cbBindings, $._data(person).events, $._data(person.address).events, $._data(person.phones).events]); $.unobserve(person, person.address, person.phones); // ............................... Assert ................................. - equal(JSON.stringify([_jsv.cbBindings, $._data(person).events, $._data(person.address).events, $._data(person.phones).events]), bindingsData, - "unobserve(object1, object2) does nothing"); + equal(JSON.stringify([_jsv.cbBindings, $._data(person).events, $._data(person.address).events, $._data(person.phones).events]), "[{},null,null,null]", + "unobserve(object1, object2) removes handlers from each object"); // ................................ Act .................................. $.unobserve(person); @@ -2297,7 +2295,7 @@ test("observe context helper", function() { function observeCtxHelper(val, currentRoot) { if (val) { if (val.charAt(0) === "%") { - return [obj, val.slice(1), currentRoot || {}]; + return [obj, val.slice(1)]; } } } @@ -2541,29 +2539,29 @@ test("dataMap", function() { } // ................................ Act .................................. - var map = sortMap.map(data.rows, {sortby: "name"}); + var map1 = sortMap.map(data.rows, {sortby: "name"}); // ............................... Assert ................................. - equal(viewSrcTgt(map, "name"), "Jeff,Ariel,Pete|ARIEL,JEFF,PETE", + equal(viewSrcTgt(map1, "name"), "Jeff,Ariel,Pete|ARIEL,JEFF,PETE", 'map = sortMap.map(data.rows, {sortby: "name"}) creates a map with sorted target'); // ............................... Assert ................................. - equal(map.options.sortby, "name", + equal(map1.options.sortby, "name", 'map.options is the initial options passed to .map(source, options)'); // ............................... Assert ................................. - ok(map.src === data.rows, + ok(map1.src === data.rows, 'map.src is the source'); // ................................ Act .................................. - map.update({sortby: "role"}); + map1.update({sortby: "role"}); // ............................... Assert ................................. - equal(viewSrcTgt(map, "role"), "Goalie,Consultant,Assistant|ASSISTANT,CONSULTANT,GOALIE", + equal(viewSrcTgt(map1, "role"), "Goalie,Consultant,Assistant|ASSISTANT,CONSULTANT,GOALIE", 'map.update({sortby: "role"}) re-sorts target'); // ............................... Assert ................................. - equal(map.options.sortby, "role", + equal(map1.options.sortby, "role", 'map.options is the current options - as passed to .update(options)'); // ................................ Act .................................. @@ -2574,14 +2572,14 @@ test("dataMap", function() { }); // ............................... Assert ................................. - equal(viewSrcTgt(map, "role"), "Goalie,Consultant,Assistant,Broker|ASSISTANT,CONSULTANT,GOALIE", + equal(viewSrcTgt(map1, "role"), "Goalie,Consultant,Assistant,Broker|ASSISTANT,CONSULTANT,GOALIE", 'If map has no obsSrc method, target does not update observably'); // ................................ Act .................................. - map.update({sortby: "role"}); + map1.update({sortby: "role"}); // ............................... Assert ................................. - equal(viewSrcTgt(map, "role"), "Goalie,Consultant,Assistant,Broker|ASSISTANT,BROKER,CONSULTANT,GOALIE", + equal(viewSrcTgt(map1, "role"), "Goalie,Consultant,Assistant,Broker|ASSISTANT,BROKER,CONSULTANT,GOALIE", 'map.update({sortby: "role"}) re-sorts target based on current source'); // ................................ Act .................................. @@ -2600,43 +2598,43 @@ test("dataMap", function() { $.observable(data.rows).remove(); // ............................... Assert ................................. - equal(viewSrcTgt(map, "role") + "/" + viewSrcTgt(map2, "name"), + equal(viewSrcTgt(map1, "role") + "/" + viewSrcTgt(map2, "name"), "Goalie,Consultant,Assistant|ASSISTANT,BROKER,CONSULTANT,GOALIE/Jeff,Ariel,Pete|ARIEL,JEFF,MARY,PETE", 'If map has no obsSrc method, target does not update observably'); - map.update(); + map1.update(); // ............................... Assert ................................. - equal(viewSrcTgt(map, "role") + "/" + viewSrcTgt(map2, "name"), + equal(viewSrcTgt(map1, "role") + "/" + viewSrcTgt(map2, "name"), "Goalie,Consultant,Assistant|ASSISTANT,CONSULTANT,GOALIE/Jeff,Ariel,Pete|ARIEL,JEFF,MARY,PETE", 'map.update() will update target to current source using current options (sortby is now "role")'); // ............................... Assert ................................. - equal(map.options.sortby, "role", + equal(map1.options.sortby, "role", 'map.options is still the current options - as passed previously to .map(source, options) or .update(options)'); - var tgt = map.tgt; + var tgt = map1.tgt; // ................................ Act .................................. - map.unmap(); + map1.unmap(); // ............................... Assert ................................. - ok(map.src === undefined, 'map.unmap() removes src'); + ok(map1.src === undefined, 'map.unmap() removes src'); // ................................ Act .................................. - map.map(data.rows, {sortby: "id"}, tgt); + map1.map(data.rows, {sortby: "id"}, tgt); // ............................... Assert ................................. - equal(viewSrcTgt(map, "id"), "id1,id2,id3|ID1,ID2,ID3", + equal(viewSrcTgt(map1, "id"), "id1,id2,id3|ID1,ID2,ID3", 'map.map(source, options, target) will remap to chosen source, options, and target'); // ................................ Act .................................. - map.map(data.rows, {sortby: "name"}); + map1.map(data.rows, {sortby: "name"}); - after = (map.tgt === tgt); + after = (map1.tgt === tgt); // ............................... Assert ................................. - equal(viewSrcTgt(map, "name") + " " + after, "Jeff,Ariel,Pete|ARIEL,JEFF,PETE true", + equal(viewSrcTgt(map1, "name") + " " + after, "Jeff,Ariel,Pete|ARIEL,JEFF,PETE true", 'map.map(source, options) will remap to chosen source and options, and keep target'); // ................................ Act .................................. @@ -2653,18 +2651,18 @@ test("dataMap", function() { } ]; - tgt = map.tgt; + tgt = map1.tgt; - map.map(otherRows); + map1.map(otherRows); - after = (tgt === map.tgt); + after = (tgt === map1.tgt); // ............................... Assert ................................. - equal(viewSrcTgt(map, "name") + " " + after, "OtherGuy,Abel|ABEL,OTHERGUY true", + equal(viewSrcTgt(map1, "name") + " " + after, "OtherGuy,Abel|ABEL,OTHERGUY true", 'map.map(newSource) will remap new source, using current options and target'); // ................................ Act .................................. - map.unmap(); + map1.unmap(); map2.unmap(); // =============================== Arrange =============================== @@ -2692,29 +2690,29 @@ test("dataMap", function() { }); // ................................ Act .................................. - map = observableSortMap.map(data.rows, {sortby: "name"}); + var map1 = observableSortMap.map(data.rows, {sortby: "name"}); // ............................... Assert ................................. - equal(viewSrcTgt(map, "name"), "Jeff,Ariel,Pete|ARIEL,JEFF,PETE", + equal(viewSrcTgt(map1, "name"), "Jeff,Ariel,Pete|ARIEL,JEFF,PETE", 'map = observableSortMap.map(data.rows, {sortby: "name"}) creates a map with sorted target'); // ............................... Assert ................................. - equal(map.options.sortby, "name", + equal(map1.options.sortby, "name", 'map.options is the initial options passed to .map(source, options)'); // ............................... Assert ................................. - ok(map.src === data.rows, + ok(map1.src === data.rows, 'map.src is the source'); // ................................ Act .................................. - map.update({sortby: "role"}); + map1.update({sortby: "role"}); // ............................... Assert ................................. - equal(viewSrcTgt(map, "role"), "Goalie,Consultant,Assistant|ASSISTANT,CONSULTANT,GOALIE", + equal(viewSrcTgt(map1, "role"), "Goalie,Consultant,Assistant|ASSISTANT,CONSULTANT,GOALIE", 'map.update({sortby: "role"}) re-sorts target'); // ............................... Assert ................................. - equal(map.options.sortby, "role", + equal(map1.options.sortby, "role", 'map.options is the current options - as passed to .update(options)'); // ................................ Act .................................. @@ -2725,14 +2723,14 @@ test("dataMap", function() { }); // ............................... Assert ................................. - equal(viewSrcTgt(map, "role"), "Goalie,Consultant,Assistant,Broker|ASSISTANT,BROKER,CONSULTANT,GOALIE", + equal(viewSrcTgt(map1, "role"), "Goalie,Consultant,Assistant,Broker|ASSISTANT,BROKER,CONSULTANT,GOALIE", 'If map has an obsSrc method, observable changes to source trigger observable target updates too'); // ................................ Act .................................. - map.update({sortby: "role"}); + map1.update({sortby: "role"}); // ............................... Assert ................................. - equal(viewSrcTgt(map, "role"), "Goalie,Consultant,Assistant,Broker|ASSISTANT,BROKER,CONSULTANT,GOALIE", + equal(viewSrcTgt(map1, "role"), "Goalie,Consultant,Assistant,Broker|ASSISTANT,BROKER,CONSULTANT,GOALIE", 'map.update({sortby: "role"}) re-sorts target based on current source'); // ................................ Act .................................. @@ -2751,7 +2749,7 @@ test("dataMap", function() { $.observable(data.rows).remove(2, 2); // ............................... Assert ................................. - equal(viewSrcTgt(map, "role") + "/" + viewSrcTgt(map2, "name"), + equal(viewSrcTgt(map1, "role") + "/" + viewSrcTgt(map2, "name"), "Goalie,Consultant|CONSULTANT,GOALIE/Jeff,Ariel|ARIEL,JEFF", 'If map has an obsSrc method, observable changes to source trigger observable target updates too'); @@ -2761,10 +2759,10 @@ test("dataMap", function() { name: "Amadeus", role: "Musician" }); - map.update(); + map1.update(); // ............................... Assert ................................. - equal(viewSrcTgt(map, "role"), + equal(viewSrcTgt(map1, "role"), "Goalie,Musician,Consultant|CONSULTANT,GOALIE,MUSICIAN", 'map.update() will update target to current source using current options (sortby is now "role")'); @@ -2779,19 +2777,19 @@ test("dataMap", function() { 'map2.update() will update target to current source using current options (sortby is now "name")'); // ............................... Assert ................................. - equal(map.options.sortby, "role", + equal(map1.options.sortby, "role", 'map.options is still the current options - as passed previously to .map(source, options) or .update(options)'); - tgt = map.tgt; - before = $._data(data.rows).events.arrayChange.length + "-" + ($._data(map.tgt).events === undefined); + tgt = map1.tgt; + before = $._data(data.rows).events.arrayChange.length + "-" + ($._data(map1.tgt).events === undefined); // ................................ Act .................................. - map.unmap(); + map1.unmap(); - after = $._data(data.rows).events.arrayChange.length + "-" + ($._data(map.tgt).events === undefined); + after = $._data(data.rows).events.arrayChange.length + "-" + ($._data(map1.tgt).events === undefined); // ............................... Assert ................................. - ok(map.src === undefined, + ok(map1.src === undefined, 'map.unmap() removes src'); // ............................... Assert ................................. @@ -2799,22 +2797,22 @@ test("dataMap", function() { 'map.unmap() removes dataMap observe bindings from src. (Note: map.tgt has no bindings since obsTgt not defined for this dataMap)'); // ................................ Act .................................. - map.map(data.rows, {sortby: "id"}, tgt); + map1.map(data.rows, {sortby: "id"}, tgt); after = $._data(data.rows).events.arrayChange.length; // ............................... Assert ................................. - equal(viewSrcTgt(map, "id") + " events: " + after, "id1,inserted,id2|ID1,ID2,INSERTED events: 2", + equal(viewSrcTgt(map1, "id") + " events: " + after, "id1,inserted,id2|ID1,ID2,INSERTED events: 2", 'map.map(source, options, target) will remap to chosen source, options, and target'); // ................................ Act .................................. - map.map(data.rows, {sortby: "name"}); + map1.map(data.rows, {sortby: "name"}); - after = $._data(data.rows).events.arrayChange.length + "-" + (map.tgt === tgt); + after = $._data(data.rows).events.arrayChange.length + "-" + (map1.tgt === tgt); // ............................... Assert ................................. - equal(viewSrcTgt(map, "name") + " events: " + after, "Jeff,Amadeus,Ariel|AMADEUS,ARIEL,JEFF events: 2-true", + equal(viewSrcTgt(map1, "name") + " events: " + after, "Jeff,Amadeus,Ariel|AMADEUS,ARIEL,JEFF events: 2-true", 'map.map(source, options) will remap to chosen source and options, keep target - and remove previous bindings'); // ................................ Act .................................. @@ -2831,9 +2829,9 @@ test("dataMap", function() { } ]; - tgt = map.tgt; + tgt = map1.tgt; - map.map(otherRows); + map1.map(otherRows); $.observable(otherRows).insert(1, [ { @@ -2849,11 +2847,11 @@ test("dataMap", function() { ]); // ............................... Assert ................................. - equal(viewSrcTgt(map, "name") + " " + after, "OtherGuy,Isabel,Xavier,Abel|ABEL,ISABEL,OTHERGUY,XAVIER 2-true", + equal(viewSrcTgt(map1, "name") + " " + after, "OtherGuy,Isabel,Xavier,Abel|ABEL,ISABEL,OTHERGUY,XAVIER 2-true", 'map.map(newSource) will remap new source, using current options and target'); // ................................ Act .................................. - map.unmap(); + map1.unmap(); map2.unmap(); // =============================== Arrange =============================== @@ -2882,13 +2880,13 @@ test("dataMap", function() { }); // ................................ Act .................................. - map = observableSortMap2.map(data.rows, {sortby: "name"}); + map1 = observableSortMap2.map(data.rows, {sortby: "name"}); // ............................... Assert ................................. - equal(viewSrcTgt(map, "name"), "Jeff,Amadeus,Ariel|AMADEUS,ARIEL,JEFF", + equal(viewSrcTgt(map1, "name"), "Jeff,Amadeus,Ariel|AMADEUS,ARIEL,JEFF", 'map = observableSortMap2.map(data.rows, {sortby: "name"}) with obsTgt creates a map with sorted target'); - $.observable(map.tgt).insert(1, [ + $.observable(map1.tgt).insert(1, [ { id: "new", name: "Mary", @@ -2901,15 +2899,15 @@ test("dataMap", function() { } ]); - equal(viewSrcTgt(map, "name"), "Jeff,Amadeus,Ariel,Mary,Jane|AMADEUS,ARIEL,JANE,JEFF,MARY", + equal(viewSrcTgt(map1, "name"), "Jeff,Amadeus,Ariel,Mary,Jane|AMADEUS,ARIEL,JANE,JEFF,MARY", 'If map has an obsTgt method, observable changes to target trigger observable source updates too'); - $.observable(map.tgt).remove(1, 2); + $.observable(map1.tgt).remove(1, 2); - equal(viewSrcTgt(map, "name"), "Jeff,Amadeus,Mary|AMADEUS,JEFF,MARY", + equal(viewSrcTgt(map1, "name"), "Jeff,Amadeus,Mary|AMADEUS,JEFF,MARY", 'If map has an obsTgt method, observable changes to target trigger observable source updates too'); - map.unmap(); + map1.unmap(); }); test("observeAll", function() { @@ -3659,6 +3657,440 @@ test('observe(... "**" ...)', function() { }); +test('observe(... "[]" ...)', function() { + $.views.settings.advanced({_jsv: true}); + + // =============================== Arrange =============================== + var cb = function cb(ev, eventArgs) { + var val = eventArgs.value; + result += eventArgs.path + ": " + ($.isArray(val) ? val.length : val) + ", "; + }, + + reset = function() { + result = "", + data = { + list: [ + {a: "0a", b: "0b"}, + {a: "1a", b: "1b"} + ] + }; + }, + + observablyChange = function(list) { + result += "|Set01| "; + $.observable(list[0]).setProperty({a: "0a2", b: "0b2"}); + $.observable(list[1]).setProperty({a: "1a2", b: "1b2"}); + result += "|Insert23| "; + $.observable(list).insert([{a: "2a", b: "2b"}, {a: "3a", b: "3b"}]); + result += "|Set0123| "; + $.observable(list[0]).setProperty({a: "0a3", b: "0b3"}); + $.observable(list[1]).setProperty({a: "1a3", b: "1b3"}); + $.observable(list[2]).setProperty({a: "2a3", b: "2b3"}); + $.observable(list[3]).setProperty({a: "3a3", b: "3b3"}); + }, + + result = "", + data; + + // ................................ Act .................................. + reset(); + $.observe(data, 'list.[].*', cb); + + observablyChange(data.list); + result += !!$._data(data.list).events; + + $.unobserve(data, 'list.[].*', cb); + + result += JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|Set01| a: 0a2, b: 0b2, a: 1a2, b: 1b2, |Insert23| |Set0123| a: 0a3, b: 0b3, a: 1a3, b: 1b3, false{}", + "observe '[].*' unobserve '[].*' works correctly"); + + // ................................ Act .................................. + reset(); + + $.observe(data, 'list.[]^*', cb); + + observablyChange(data.list); + result += $._data(data.list).events.arrayChange.length; + + $.unobserve(data, 'list.[]^*', cb); + + result += !!$._data(data.list).events + JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|Set01| a: 0a2, b: 0b2, a: 1a2, b: 1b2, |Insert23| |Set0123| a: 0a3, b: 0b3, a: 1a3, b: 1b3, a: 2a3, b: 2b3, a: 3a3, b: 3b3, 1false{}", + "observe '[]^*' unobserve '[]^*' works correctly"); + + // ................................ Act .................................. + reset(); + + $.observe(data, 'list.[]^a', cb); + + observablyChange(data.list); + result += $._data(data.list).events.arrayChange.length; + + $.unobserve(data, 'list.[]^*', cb); + + result += !!$._data(data.list).events + JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|Set01| a: 0a2, a: 1a2, |Insert23| |Set0123| a: 0a3, a: 1a3, a: 2a3, a: 3a3, 1false{}", + "observe '[]^a' unobserve '[]^*' works correctly"); + + // ................................ Act .................................. + reset(); + $.observe(data, 'list.[].a', cb); + + observablyChange(data.list); + result += !!$._data(data.list).events; + + $.unobserve(data, 'list.[]^*', cb); + + result += JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|Set01| a: 0a2, a: 1a2, |Insert23| |Set0123| a: 0a3, a: 1a3, false{}", + "observe '[].a' unobserve '[]^*' works correctly"); + + // ................................ Act .................................. + reset(); + + $.observe(data, 'list.[]^a', cb); + + observablyChange(data.list); + result += $._data(data.list).events.arrayChange.length; + + $.unobserve(data, 'list.[].*', cb); + + result += $._data(data.list).events.arrayChange.length; + + $.unobserve(data, 'list.[]', cb); + + result += !!$._data(data.list).events + JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|Set01| a: 0a2, a: 1a2, |Insert23| |Set0123| a: 0a3, a: 1a3, a: 2a3, a: 3a3, 11false{}", + "observe '[]^a' unobserve '[].*' unobserve '[]' works correctly"); + + // ................................ Act .................................. + reset(); + + $.observe(data, 'list^[].a', cb); + + result += "|setList| "; + + $.observable(data).setProperty({list: [{a: "2a4", b: "2b4"}, {a: "3a4", b: "3b4"}]}); + observablyChange(data.list); + result += $._data(data.list).events.arrayChange.length + $._data(data).events.propertyChange.length; + + $.unobserve(data, 'list^[].*', cb); + + result += !!$._data(data.list).events + "" + !!$._data(data).events + JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|setList| list: 2, |Set01| a: 0a2, a: 1a2, |Insert23| |Set0123| a: 0a3, a: 1a3, a: 2a3, a: 3a3, 2falsefalse{}", + "observe 'list^[].a' unobserve 'list^[].*' works correctly"); + + // =============================== Arrange =============================== + reset = function() { + result = "", + data = { + deeplist: [ + {sublist:[ + {a: "0a", b: "0b"}, + {a: "1a", b: "1b"} + ]} + ] + }; + }; + + observablyChange = function(list) { + result += "|Set01| "; + $.observable(list[0]).setProperty({a: "0a2", b: "0b2"}); + $.observable(list[1]).setProperty({a: "1a2", b: "1b2"}); + result += "|Insert23| "; + $.observable(list).insert([{a: "2a", b: "2b"}, {a: "3a", b: "3b"}]); + result += "|Set0123| "; + $.observable(list[0]).setProperty({a: "0a3", b: "0b3"}); + $.observable(list[1]).setProperty({a: "1a3", b: "1b3"}); + $.observable(list[2]).setProperty({a: "2a3", b: "2b3"}); + $.observable(list[3]).setProperty({a: "3a3", b: "3b3"}); + }; + + // ................................ Act .................................. + reset(); + $.observe(data.deeplist, '[].sublist.[].*', cb); + + observablyChange(data.deeplist[0].sublist); + result += !!$._data(data.deeplist[0].sublist).events; + + $.unobserve(data.deeplist, '[].sublist.[].*', cb); + + result += JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|Set01| a: 0a2, b: 0b2, a: 1a2, b: 1b2, |Insert23| |Set0123| a: 0a3, b: 0b3, a: 1a3, b: 1b3, false{}", + "observe '[].sublist.[].*' unobserve '[].sublist.[].*' works correctly"); + + // ................................ Act .................................. + reset(); + + $.observe(data.deeplist, '[].sublist.[]^*', cb); + + observablyChange(data.deeplist[0].sublist); + result += $._data(data.deeplist[0].sublist).events.arrayChange.length; + + $.unobserve(data.deeplist, '[].sublist.[]^*', cb); + + result += !!$._data(data.deeplist[0].sublist).events + JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|Set01| a: 0a2, b: 0b2, a: 1a2, b: 1b2, |Insert23| |Set0123| a: 0a3, b: 0b3, a: 1a3, b: 1b3, a: 2a3, b: 2b3, a: 3a3, b: 3b3, 1false{}", + "observe '[].sublist.[]^*' unobserve '[].sublist.[]^*' works correctly"); + + // ................................ Act .................................. + reset(); + + $.observe(data, 'deeplist.[].sublist.[]^a', cb); + + observablyChange(data.deeplist[0].sublist); + result += $._data(data.deeplist[0].sublist).events.arrayChange.length; + + $.unobserve(data, 'deeplist.[].sublist.[]^*', cb); + + result += !!$._data(data.deeplist[0].sublist).events + JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|Set01| a: 0a2, a: 1a2, |Insert23| |Set0123| a: 0a3, a: 1a3, a: 2a3, a: 3a3, 1false{}", + "observe '[].sublist.[].a' unobserve '[].sublist.[]^*' works correctly"); + + // ................................ Act .................................. + reset(); + $.observe(data.deeplist, '[].sublist.[].a', cb); + + observablyChange(data.deeplist[0].sublist); + result += !!$._data(data.deeplist[0].sublist).events; + + $.unobserve(data.deeplist, '[].sublist.[]^*', cb); + + result += JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|Set01| a: 0a2, a: 1a2, |Insert23| |Set0123| a: 0a3, a: 1a3, false{}", + "observe '[].sublist.[].a' unobserve '[].sublist.[]^*' works correctly"); + + // ................................ Act .................................. + reset(); + + $.observe(data.deeplist, '[].sublist.[]^a', cb); + + observablyChange(data.deeplist[0].sublist); + result += $._data(data.deeplist[0].sublist).events.arrayChange.length; + + $.unobserve(data.deeplist, '[].sublist.[].*', cb); + + result += $._data(data.deeplist[0].sublist).events.arrayChange.length; + + $.unobserve(data.deeplist, '[].sublist.[]', cb); + + result += !!$._data(data.deeplist[0].sublist).events + JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|Set01| a: 0a2, a: 1a2, |Insert23| |Set0123| a: 0a3, a: 1a3, a: 2a3, a: 3a3, 11false{}", + "observe '[].sublist.[]^a' unobserve '[].sublist.[].*' unobserve '[].sublist.[]' works correctly"); + + // ................................ Act .................................. + reset(); + + $.observe(data.deeplist, '[].sublist^[].a', cb); + + result += "|setList| "; + + $.observable(data.deeplist[0]).setProperty({sublist: [{a: "2a4", b: "2b4"}, {a: "3a4", b: "3b4"}]}); + observablyChange(data.deeplist[0].sublist); + result += $._data(data.deeplist[0].sublist).events.arrayChange.length + $._data(data.deeplist[0]).events.propertyChange.length; + + $.unobserve(data.deeplist, '[].sublist^[].*', cb); + + result += !!$._data(data.deeplist[0].sublist).events + "" + !!$._data(data.deeplist[0]).events + JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|setList| sublist: 2, |Set01| a: 0a2, a: 1a2, |Insert23| |Set0123| a: 0a3, a: 1a3, a: 2a3, a: 3a3, 2falsefalse{}", + "observe '[].sublist^[].a' unobserve '[].sublist^[].*' works correctly"); + + // ................................ Act .................................. + + reset(); + $.observe(data.deeplist, '[]^sublist.[].a', cb); + + result += "|insertDeepList| "; + + $.observable(data.deeplist).insert(0, {sublist: [{a: "00a", b: "00b"}, {a: "01a", b: "01b"}]}); + observablyChange(data.deeplist[0].sublist); + observablyChange(data.deeplist[1].sublist); + result += $._data(data.deeplist).events.arrayChange.length + $._data(data.deeplist[0].sublist).events.arrayChange.length + $._data(data.deeplist[0]).events.propertyChange.length; + + $.unobserve(data.deeplist, '[]^sublist.[].a', cb); + + result += !!$._data(data.deeplist).events + "" + !!$._data(data.deeplist[0]).events + "" + !!$._data(data.deeplist[0].sublist).events + JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|insertDeepList| |Set01| a: 0a2, a: 1a2, |Insert23| |Set0123| a: 0a3, a: 1a3, a: 2a3, a: 3a3, |Set01| a: 0a2, a: 1a2, |Insert23| |Set0123| a: 0a3, a: 1a3, a: 2a3, a: 3a3, 3falsefalsefalse{}", + "observe '[]^sublist.[].a'' unobserve '[]^sublist.[].a'' works correctly"); + + // =============================== Arrange =============================== + + reset = function() { + result = "", + data = { + listoflist: [ + [ + {a: "0a", b: "0b"}, + {a: "1a", b: "1b"} + ] + ] + }; + }; + + observablyChange = function(list) { + result += "|Set01| "; + $.observable(list[0]).setProperty({a: "0a2", b: "0b2"}); + $.observable(list[1]).setProperty({a: "1a2", b: "1b2"}); + result += "|Insert23| "; + $.observable(list).insert([{a: "2a", b: "2b"}, {a: "3a", b: "3b"}]); + result += "|Set0123| "; + $.observable(list[0]).setProperty({a: "0a3", b: "0b3"}); + $.observable(list[1]).setProperty({a: "1a3", b: "1b3"}); + $.observable(list[2]).setProperty({a: "2a3", b: "2b3"}); + $.observable(list[3]).setProperty({a: "3a3", b: "3b3"}); + }; + + // ................................ Act .................................. + reset(); + $.observe(data.listoflist, '[].[].*', cb); + + observablyChange(data.listoflist[0]); + result += !!$._data(data.listoflist[0]).events; + + $.unobserve(data.listoflist, '[].[].*', cb); + + result += JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|Set01| a: 0a2, b: 0b2, a: 1a2, b: 1b2, |Insert23| |Set0123| a: 0a3, b: 0b3, a: 1a3, b: 1b3, false{}", + "observe '[].[].*' unobserve '[].[].*' works correctly"); + + // ................................ Act .................................. + reset(); + + $.observe(data.listoflist, '[].[]^*', cb); + + observablyChange(data.listoflist[0]); + result += $._data(data.listoflist[0]).events.arrayChange.length; + + $.unobserve(data.listoflist, '[].[]^*', cb); + + result += !!$._data(data.listoflist[0]).events + JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|Set01| a: 0a2, b: 0b2, a: 1a2, b: 1b2, |Insert23| |Set0123| a: 0a3, b: 0b3, a: 1a3, b: 1b3, a: 2a3, b: 2b3, a: 3a3, b: 3b3, 1false{}", + "observe '[].[]^*' unobserve '[].[]^*' works correctly"); + + // ................................ Act .................................. + reset(); + + $.observe(data, 'listoflist.[].[]^a', cb); + + observablyChange(data.listoflist[0]); + result += $._data(data.listoflist[0]).events.arrayChange.length; + + $.unobserve(data, 'listoflist.[].[]^*', cb); + + result += !!$._data(data.listoflist[0]).events + JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|Set01| a: 0a2, a: 1a2, |Insert23| |Set0123| a: 0a3, a: 1a3, a: 2a3, a: 3a3, 1false{}", + "observe '[].[].a' unobserve '[].[].*' works correctly"); + + // ................................ Act .................................. + reset(); + $.observe(data.listoflist, '[].[].a', cb); + + observablyChange(data.listoflist[0]); + result += !!$._data(data.listoflist[0]).events; + + $.unobserve(data.listoflist, '[].[]^*', cb); + + result += JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|Set01| a: 0a2, a: 1a2, |Insert23| |Set0123| a: 0a3, a: 1a3, false{}", + "observe '[].[].a' unobserve '[].[].*' works correctly"); + + // ................................ Act .................................. + reset(); + + $.observe(data.listoflist, '[].[]^a', cb); + + observablyChange(data.listoflist[0]); + result += $._data(data.listoflist[0]).events.arrayChange.length; + + $.unobserve(data.listoflist, '[].[].*', cb); + + result += $._data(data.listoflist[0]).events.arrayChange.length; + + $.unobserve(data.listoflist, '[].[]', cb); + + result += !!$._data(data.listoflist[0]).events + JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|Set01| a: 0a2, a: 1a2, |Insert23| |Set0123| a: 0a3, a: 1a3, a: 2a3, a: 3a3, 11false{}", + "observe '[].[]^a' unobserve '[].[].*' unobserve '[].[]' works correctly"); + + // ................................ Act .................................. + reset(); + + $.observe(data.listoflist, '[]^[].a', cb); + + result += "|setList| "; + + $.observable(data.listoflist[0]).refresh([{a: "2a4", b: "2b4"}, {a: "3a4", b: "3b4"}]); + observablyChange(data.listoflist[0]); + result += $._data(data.listoflist[0]).events.arrayChange.length; + + $.unobserve(data.listoflist, '[]^[].*', cb); + + result += !!$._data(data.listoflist[0]).events + JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|setList| |Set01| a: 0a2, a: 1a2, |Insert23| |Set0123| a: 0a3, a: 1a3, a: 2a3, a: 3a3, 1false{}", + "observe '[]^[].a' unobserve '[]^[].*' works correctly"); + + // ................................ Act .................................. + reset(); + + $.observe(data.listoflist, '[]^[].a', cb); + + result += "|insertDeepList| "; + + $.observable(data.listoflist).insert(0, [[{a: "00a", b: "00b"}, {a: "01a", b: "01b"}]]); + observablyChange(data.listoflist[0]); + observablyChange(data.listoflist[1]); + result += $._data(data.listoflist).events.arrayChange.length + $._data(data.listoflist[0]).events.arrayChange.length + $._data(data.listoflist[1]).events.arrayChange.length; + + $.unobserve(data.listoflist, '[]^[].a', cb); + + result += !!$._data(data.listoflist).events + "" + !!$._data(data.listoflist[0]).events + "" + !!$._data(data.listoflist[1]).events + JSON.stringify(_jsv.cbBindings); + + // ............................... Assert ................................. + equal(result, "|insertDeepList| |Set01| a: 0a2, a: 1a2, |Insert23| |Set0123| a: 0a3, a: 1a3, a: 2a3, a: 3a3, |Set01| a: 0a2, a: 1a2, |Insert23| |Set0123| a: 0a3, a: 1a3, a: 2a3, a: 3a3, 3falsefalsefalse{}", + "observe '[]^[].a' unobserve '[]^[].a' works correctly"); + + $.views.settings.advanced({_jsv: false}); +}); + test("observeAll - cyclic graphs", function() { reset(); @@ -4325,7 +4757,7 @@ test("observeAll/unobserveAll using namespaces", function() { + "myListener3 change: 'set' Caller ns: 'b' Handler ns: 'a.b.c' Handler fullPath: '*' Handler paths: '' Handler prop: '*' " + "Handler observeAll._path : 'root.person.friend' Handler observeAll.path() : 'root.person.friend' Handler observeAll.parents() : '3' calls: 2|" + "myListener3 change: 'insert' Caller ns: 'c' Handler ns: 'a.b.c' calls: 3|", - "call observeAll namesspaces"); + "call observeAll namespaces"); $.unobserve("a.b.c"); @@ -4355,7 +4787,7 @@ $.unobserve("a.b.c"); + "myListener3 change: 'set' Caller ns: 'b' Handler ns: 'a.b.c' Handler fullPath: '*' Handler paths: '' Handler prop: '*' " + "Handler observeAll._path : 'root.person.friend' Handler observeAll.path() : 'root.person.friend' Handler observeAll.parents() : '3' calls: 2|" + "myListener3 change: 'insert' Caller ns: 'c' Handler ns: 'a.b.c' calls: 3|", - 'call observe with "**" - namesspaces'); + 'call observe with "**" - namespaces'); $.unobserve("a.b.c"); @@ -4384,7 +4816,7 @@ $.unobserve("a.b.c"); "myListener3 change: 'set' Caller ns: 'a' Handler ns: 'a.b.c' Handler fullPath: 'person.phones' Handler paths: 'phones,friend.name' Handler prop: 'person' calls: 1|" + "myListener3 change: 'set' Caller ns: 'b' Handler ns: 'a.b.c' Handler fullPath: 'friend.name' Handler paths: '' Handler prop: 'name' calls: 2|" + "myListener3 change: 'insert' Caller ns: 'c' Handler ns: 'a.b.c' calls: 3|", - "call observe deep paths, with namesspaces"); + "call observe deep paths, with namespaces"); $.unobserve("a.b.c"); diff --git a/test/unit-tests/tests-jsrender-no-jquery.js b/test/unit-tests/tests-jsrender-no-jquery.js index e5097b6..02959eb 100644 --- a/test/unit-tests/tests-jsrender-no-jquery.js +++ b/test/unit-tests/tests-jsrender-no-jquery.js @@ -311,7 +311,7 @@ test("Fallbacks for missing or undefined paths:\nusing {{:some.path onError = 'f equal($.templates({ markup: "{{mytag foo='a'/}} {{mytag foo=missing.willThrow.path onError='Missing Object'/}} {{mytag foo='c' bar=missing.willThrow.path onError='Missing Object'/}} {{mytag foo='c' missing.willThrow.path onError='Missing Object'/}} {{mytag foo='b'/}}", tags: { - mytag: {template: "MyTag: {{:~tag.tagCtx.props.foo}} end"} + mytag: {template: "MyTag: {{:~tagCtx.props.foo}} end"} } }).render({a:1}), "MyTag: a end Missing Object Missing Object Missing Object MyTag: b end", 'onError=... for custom tags: e.g. {{mytag foo=missing.willThrow.path onError="Missing Object"/}}'); @@ -331,7 +331,7 @@ test("Fallbacks for missing or undefined paths:\nusing {{:some.path onError = 'f } }, tags: { - mytag: {template: "MyTag: {{:~tag.tagCtx.props.foo}} end"} + mytag: {template: "MyTag: {{:~tagCtx.props.foo}} end"} } }).render( { @@ -508,6 +508,123 @@ test("{{for}}", 17, function() { equal($.render.simpleFor({}), "ab", 'if #data is undefined, renders empty string'); equal($.render.forPrimitiveDataTypes({people:[0, 1, "abc", "", ,null ,true ,false]}), "a|0|1|abc||||true|falseb", 'Primitive types render correctly, even if falsey'); }); +test("{{for start end sort filter reverse}}", function() { + // =============================== Arrange =============================== + function level(aField, bField) { + return aField > bField ? 1 : aField < bField ? -1 : 0; + } + + var oddValue = function(item, index, items) { return item%2; }; + var oddIndex = function(item, index, items) { return index%2; }; + var sortAgeName = function(a, b) { + return level(a.details.role.toLowerCase(), b.details.role.toLowerCase()) // First level sort: by role + || level(b.details.age, a.details.age) // 2nd level sort: reverse sort by age + || level(a.name.toLowerCase(), b.name.toLowerCase()); // 3rd level sort: sort by name + }; + var under20 = function(item, index, items) { + return item.details.age < 20; + }; + + // ................................ Assert .................................. + + equal($.templates("{{for start=0 end=10}}{{:}} {{/for}}").render(), "0 1 2 3 4 5 6 7 8 9 ", "{{for start=0 end=10}}: Auto-create array"); + equal($.templates("{{for start=5 end=9 reverse=1}}{{:}} {{/for}}").render(), "8 7 6 5 ", "{{for start=5 end=9 reverse=1}}: Auto-create array"); + equal($.templates("{{for start=8 end=4 step=-1}}{{:}} {{/for}}").render(), "8 7 6 5 ", "{{for start=8 end=4 step=-1}}: Auto-create array"); + equal($.templates("{{for start=8 end=4 step=-1 reverse=true}}{{:}} {{/for}}").render(), "5 6 7 8 ", "{{for start=8 end=4 step=-1 reverse=true}}: Auto-create array, with reverse"); + equal($.templates("{{for start=20 end='10' step=-2}}{{:}} {{/for}}").render(), "20 18 16 14 12 ", "{{for start=20 end='10' step=-2}}: Auto-create array"); + equal($.templates("{{for start=20 end='10' step=2}}{{:}} {{/for}}").render(), "", "{{for start=20 end='10' step=2}}: Auto-create array (outputs nothing)"); + equal($.templates("{{for start=2 end=-1.5 step=-.5}}{{:}} {{/for}}").render(), "2 1.5 1 0.5 0 -0.5 -1 ", "{{for start=0 end='10' step=-1}}: Auto-create array"); + equal($.templates("{{for start=2}}{{:}} {{/for}}").render(), "", "{{for start=2}}: (outputs nothing)"); + equal($.templates("{{for end=4}}{{:}} {{/for}}").render(), "0 1 2 3 ", "{{for end=4}}: (start defaults to 0)"); + equal($.templates("{{for start=8 end=4 step=-1 reverse=true sort=true filter=~oddIndex}}{{:}} {{/for}}").render({}, {oddIndex: oddIndex}), "5 6 7 8 ", "{{for start=8 end=4 step=-1 reverse=true sort=true}}: Auto-create array, sort and filter not supported with auto-create arrays - do nothing"); + + // =============================== Arrange =============================== + + var myarray = [1, 9, 2, 8, 3, 7, 4, 6, 5]; + + equal($.templates("{{for #data sort=''}}{{:}} {{/for}}").render(myarray, true), "1 9 2 8 3 7 4 6 5 ", "{{for #data sort=''}}"); + equal($.templates("{{for #data sort=true}}{{:}} {{/for}}").render(myarray, true), "1 2 3 4 5 6 7 8 9 ", "{{for #data sort=true}}"); + equal($.templates("{{for myarray reverse=true}}{{:}} {{/for}}").render({myarray: myarray}), "5 6 4 7 3 8 2 9 1 ", "{{for myarray reverse=true}}"); + equal($.templates("{{for myarray start=1 end=-1}}{{:}} {{/for}}").render({myarray: myarray}), "9 2 8 3 7 4 6 ", "{{for myarray start=1 end=-1}}"); + equal($.templates("{{for myarray start=1}}{{:}} {{/for}}").render({myarray: myarray}), "9 2 8 3 7 4 6 5 ", "{{for myarray start=1}}"); + equal($.templates("{{for myarray end=-1}}{{:}} {{/for}}").render({myarray: myarray}), "1 9 2 8 3 7 4 6 ", "{{for myarray end=-1}}"); + equal($.templates("{{for myarray sort=true}}{{:}} {{/for}}").render({myarray: myarray}), "1 2 3 4 5 6 7 8 9 ", "{{for myarray sort=true}}"); + equal($.templates("{{for myarray sort=true reverse=true}}{{:}} {{/for}}").render({myarray: myarray}), "9 8 7 6 5 4 3 2 1 ", "{{for myarray sort=true reverse=true}}"); + +if (!isIE8) { // IE8 does not support filter. Need to add polyfill on sites that want this support + equal($.templates("{{for myarray filter=~oddValue}}{{:}} {{/for}}").render({myarray: myarray}, {oddValue: oddValue}), "1 9 3 7 5 ", "{{for myarray filter=~oddValue}}"); + equal($.templates("{{for myarray filter=~oddIndex}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "9 8 7 6 ", "{{for myarray filter=~oddIndex}}"); + equal($.templates("{{for myarray sort=true filter=~oddValue}}{{:}} {{/for}}").render({myarray: myarray}, {oddValue: oddValue}), "1 3 5 7 9 ", "{{for myarray sort=true filter=~oddValue}}"); + equal($.templates("{{for myarray sort=true filter=~oddIndex}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "2 4 6 8 ", "{{for myarray sort=true filter=~oddIndex}}"); + equal($.templates("{{for myarray sort=true filter=~oddIndex start=1 end=3}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "4 6 ", "{{for myarray sort=true filter=~oddIndex start=1 end=3}}"); + equal($.templates("{{for myarray sort=true filter=~oddIndex start=-3 end=-1}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "4 6 ", "{{for myarray sort=true filter=~oddIndex start=-3 end=-1}} Negative start or end count from the end"); + equal($.templates("{{for myarray sort=true filter=~oddIndex start=3 end=3}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "", "{{for myarray sort=true filter=~oddIndex start=3 end=3}} (outputs nothing)"); +} + equal($.templates("{{for myarray step=2 start=1}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "9 8 7 6 ", "{{for myarray step=2 start=1}}"); + equal($.templates("{{for myarray sort=true step=2 start=1}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "2 4 6 8 ", "{{for myarray sort=true step=2 start=1}}"); + equal($.templates("{{for myarray sort=true step=2 start=3 end=6}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "4 6 ", "{{for myarray sort=true step=2 start=3 end=6}}"); + equal($.templates("{{for myarray sort=true step=2 start=-6 end=-3}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "4 6 ", "{{for myarray sort=true step=2 start=-6 end=-3}} Negative start or end count from the end"); + equal($.templates("{{for myarray sort=true step=2 start=3 end=3}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "", "{{for myarray sort=true step=2 start=3 end=3}} (outputs nothing)"); + equal($.templates("{{for myarray step=3.5}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "1 8 4 ", "{{for myarray step=3.5}} - equivalent to step=3"); + equal($.templates("{{for myarray step=-2}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "1 9 2 8 3 7 4 6 5 ", "{{for myarray step=-2}} equivalent to no step"); + equal($.templates("{{for myarray step=1}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "1 9 2 8 3 7 4 6 5 ", "{{for myarray step=1}} equivalent to no step"); + // =============================== Arrange =============================== + + var mypeople = [ + {name: "Jo", details: {age: 22}}, + {name: "Bob", details: {age: 2}}, + {name: "Emma", details: {age: 12}}, + {name: "Jeff", details: {age: 13.5}}, + {name: "Julia", details: {age: 0.6}}, + {name: "Xavier", details: {age: 0}} + ]; + + // ................................ Assert .................................. + + equal($.templates("{{for mypeople sort='name'}}{{:name}}: age {{:details.age}} - {{/for}}").render({mypeople: mypeople}), "Bob: age 2 - Emma: age 12 - Jeff: age 13.5 - Jo: age 22 - Julia: age 0.6 - Xavier: age 0 - ", + "{{for mypeople sort='name'}}"); + equal($.templates("{{for mypeople sort='details.age'}}{{:name}}: age {{:details.age}} - {{/for}}").render({mypeople: mypeople}), "Xavier: age 0 - Julia: age 0.6 - Bob: age 2 - Emma: age 12 - Jeff: age 13.5 - Jo: age 22 - ", + "{{for mypeople sort='details.age'}}"); + +if (!isIE8) { // IE8 does not support filter. Need to add polyfill on sites that want this support + equal($.templates("{{for mypeople sort='details.age' reverse=true filter=~under20}}{{:name}}: age {{:details.age}} - {{/for}}").render({mypeople: mypeople}, {under20: under20}), "Jeff: age 13.5 - Emma: age 12 - Bob: age 2 - Julia: age 0.6 - Xavier: age 0 - ", + "{{for mypeople sort='details.age' reverse=true filter=~under20}}"); + equal($.templates("{{for mypeople sort='details.age' reverse=true filter=~under20 start=1 end=-1}}{{:name}}: age {{:details.age}} - {{/for}}").render({mypeople: mypeople}, {under20: under20}), "Emma: age 12 - Bob: age 2 - Julia: age 0.6 - ", + "{{for mypeople sort='details.age' reverse=true filter=~under20 start=1 end=-1}}"); + equal($.templates("{{for mypeople sort='details.age' reverse=true filter=~under20 start=1 end=-1}}{{:name}}: age {{:details.age}} - {{/for}}").render({mypeople: mypeople}, {under20: under20}), "Emma: age 12 - Bob: age 2 - Julia: age 0.6 - ", + "{{for mypeople sort='details.age' reverse=true filter=~under20 start=1 end=-1}}"); +} + // =============================== Arrange =============================== + + var mypeople2 = [ + {name: "Bill", details: {age: 22, role: "Lead"}}, + {name: "Anne", details: {age: 32, role: "Assistant"}}, + {name: "Emma", details: {age: 19.1, role: "Team member"}}, + {name: "Jeff", details: {age: 33.5, role: "Lead"}}, + {name: "Xavier", details: {age: 32, role: "Team member"}}, + {name: "Julia", details: {age: 18, role: "Assistant"}}, + {name: "Bill", details: {age: 32, role: "Team member"}} + ]; + + // ................................ Assert .................................. + + equal($.templates("{{for mypeople sort=~sortAgeName}}{{:name}}: ({{:details.role}}) age {{:details.age}} -{{/for}}").render({mypeople: mypeople2}, {sortAgeName: sortAgeName}), + "Anne: (Assistant) age 32 -Julia: (Assistant) age 18 -Jeff: (Lead) age 33.5 -Bill: (Lead) age 22 -Bill: (Team member) age 32 -Xavier: (Team member) age 32 -Emma: (Team member) age 19.1 -", + "{{for mypeople sort=~sortAgeName}}: custom sort function"); + + // =============================== Arrange =============================== + + $.views.tags("for2", { + baseTag: "for" + }); + + // ................................ Assert .................................. + +if (!isIE8) { // IE8 does not support filter. Need to add polyfill on sites that want this support + equal($.templates("{{for2 mypeople sort='details.age' reverse=true filter=~under20 start=1 end=-1}}{{:name}}: age {{:details.age}} - {{/for2}}").render({mypeople: mypeople}, {under20: under20}), "Emma: age 12 - Bob: age 2 - Julia: age 0.6 - ", + "{{for2 mypeople sort='details.age' reverse=true filter=~under20 start=1 end=-1}} Derived tag"); +} +}); QUnit.module("{{props}}"); test("{{props}}", 15, function() { @@ -546,6 +663,103 @@ test("{{props}}", 15, function() { 'Primitive types render correctly, even if falsey'); }); +test("{{props start end sort filter reverse}}", function() { + // =============================== Arrange =============================== + function level(aField, bField) { + return aField > bField ? 1 : aField < bField ? -1 : 0; + } + + var oddValue = function(item, index, items) { return item.prop%2; }; + var oddIndex = function(item, index, items) { return index%2; }; + var sortAgeName = function(a, b) { + return level(a.prop.details.role.toLowerCase(), b.prop.details.role.toLowerCase()) // First level sort: by role + || level(b.prop.details.age, a.prop.details.age) // 2nd level sort: reverse sort by age + || level(a.prop.name.toLowerCase(), b.prop.name.toLowerCase()); // 3rd level sort: sort by name + }; + + var under20 = function(item, index, items) { + return item.prop.details.age < 20; + }; + + var myobject = {a: 1, b: 9, c: 2, d:8, A:3, B:7, C:4, D:6, e:5}; + + equal($.templates("{{props myobject}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}), "a 1 - b 9 - c 2 - d 8 - A 3 - B 7 - C 4 - D 6 - e 5 - ", "{{props myobject}} (original order)"); + equal($.templates("{{props #data sort='prop'}}{{:key}} {{:prop}} - {{/props}}").render(myobject, true), "a 1 - c 2 - A 3 - C 4 - e 5 - D 6 - B 7 - d 8 - b 9 - ", "{{props #data sort='prop'}}"); + equal($.templates("{{props #data sort='key'}}{{:key}} {{:prop}} - {{/props}}").render(myobject, true), "a 1 - A 3 - b 9 - B 7 - c 2 - C 4 - d 8 - D 6 - e 5 - ", "{{props #data sort='key'}}"); + equal($.templates("{{props #data sort='prop' reverse=true}}{{:key}} {{:prop}} - {{/props}}").render(myobject, true), "b 9 - d 8 - B 7 - D 6 - e 5 - C 4 - A 3 - c 2 - a 1 - ", "{{props #data sort='prop' reverse=true}}"); + equal($.templates("{{props #data sort='key' reverse=true}}{{:key}} {{:prop}} - {{/props}}").render(myobject, true), "e 5 - d 8 - D 6 - c 2 - C 4 - b 9 - B 7 - a 1 - A 3 - ", "{{props #data sort='key' reverse=true}}"); + equal($.templates("{{props myobject reverse=true}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}), "e 5 - D 6 - C 4 - B 7 - A 3 - d 8 - c 2 - b 9 - a 1 - ", "{{props myobject reverse=true}}") + equal($.templates("{{props myobject sort='key' reverse=true}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}), "e 5 - d 8 - D 6 - c 2 - C 4 - b 9 - B 7 - a 1 - A 3 - ", "{{props myobject sort='key' reverse=true}}") + equal($.templates("{{props myobject start=1 end=-1}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}, {oddIndex: oddIndex}), "b 9 - c 2 - d 8 - A 3 - B 7 - C 4 - D 6 - ", "{{props myobject start=1 end=-1}}"); + equal($.templates("{{props myobject start=1}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}, {oddIndex: oddIndex}), "b 9 - c 2 - d 8 - A 3 - B 7 - C 4 - D 6 - e 5 - ", "{{props myobject start=1}}"); + equal($.templates("{{props myobject end=-1}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}, {oddIndex: oddIndex}), "a 1 - b 9 - c 2 - d 8 - A 3 - B 7 - C 4 - D 6 - ", "{{props myobject end=-1}}"); + +if (!isIE8) { // IE8 does not support filter. Need to add polyfill on sites that want this support + equal($.templates("{{props myobject filter=~oddValue}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}, {oddValue: oddValue}), "a 1 - b 9 - A 3 - B 7 - e 5 - ", "{{props myobject filter=~oddValue}}"); + equal($.templates("{{props myobject filter=~oddIndex}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}, {oddIndex: oddIndex}), "b 9 - d 8 - B 7 - D 6 - ", "{{props myobject filter=~oddIndex}}"); + equal($.templates("{{props myobject sort='prop' filter=~oddValue}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}, {oddValue: oddValue}), "a 1 - A 3 - e 5 - B 7 - b 9 - ", "{{props myobject sort='prop' filter=~oddValue}}"); + equal($.templates("{{props myobject sort='prop' filter=~oddIndex}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}, {oddIndex: oddIndex}), "c 2 - C 4 - D 6 - d 8 - ", "{{props myobject sort='prop' filter=~oddIndex}}"); + equal($.templates("{{props myobject sort='prop' filter=~oddIndex start=1 end=3}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}, {oddIndex: oddIndex}), "C 4 - D 6 - ", "{{props myobject sort='prop' filter=~oddIndex start=1 end=3}}"); + equal($.templates("{{props myobject sort='prop' filter=~oddIndex start=-3 end=-1}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}, {oddIndex: oddIndex}), "C 4 - D 6 - ", "{{props myobject sort='prop' filter=~oddIndex start=-3 end=-1}} Negative start or end count from the end"); + equal($.templates("{{props myobject sort='prop' filter=~oddIndex start=3 end=3}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}, {oddIndex: oddIndex}), "", "{{props myobject sort='key' filter=~oddIndex start=3 end=3}} (outputs nothing)"); +} + equal($.templates("{{props myobject step=2 start=1}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}, {oddIndex: oddIndex}), "b 9 - d 8 - B 7 - D 6 - ", "{{props myobject step=2 start=1}}"); + equal($.templates("{{props myobject sort='prop' step=2 start=1}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}, {oddIndex: oddIndex}), "c 2 - C 4 - D 6 - d 8 - ", "{{props myobject sort='prop' step=2 start=1}}"); + equal($.templates("{{props myobject sort='prop' step=2 start=3 end=6}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}, {oddIndex: oddIndex}), "C 4 - D 6 - ", "{{props myobject sort='prop' step=2 start=3 end=6}}"); + equal($.templates("{{props myobject sort='prop' step=2 start=-6 end=-3}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}, {oddIndex: oddIndex}), "C 4 - D 6 - ", "{{props myobject sort='prop' step=2 start=-6 end=-3}} Negative start or end count from the end"); + equal($.templates("{{props myobject sort='prop' step=2 start=3 end=3}}{{:key}} {{:prop}} - {{/props}}").render({myobject: myobject}, {oddIndex: oddIndex}), "", "{{props myobject sort='key' step=2 start=3 end=3}} (outputs nothing)"); + // =============================== Arrange =============================== + + var mypeople = { + p1: {name: "Jo", details: {age: 22}}, + p2: {name: "Bob", details: {age: 2}}, + p3: {name: "Emma", details: {age: 12}}, + p7: {name: "Jeff", details: {age: 13.5}}, + p6: {name: "Julia", details: {age: 0.6}}, + p5: {name: "Xavier", details: {age: 0}} + }; + + // ................................ Assert .................................. + + equal($.templates("{{props mypeople sort='prop.name'}}{{:prop.name}}: age {{:prop.details.age}} - {{/props}}").render({mypeople: mypeople}), "Bob: age 2 - Emma: age 12 - Jeff: age 13.5 - Jo: age 22 - Julia: age 0.6 - Xavier: age 0 - ", "{{props mypeople sort='name'}}"); + equal($.templates("{{props mypeople sort='prop.details.age'}}{{:prop.name}}: age {{:prop.details.age}} - {{/props}}").render({mypeople: mypeople}), "Xavier: age 0 - Julia: age 0.6 - Bob: age 2 - Emma: age 12 - Jeff: age 13.5 - Jo: age 22 - ", "{{props mypeople sort='details.age'}}"); + +if (!isIE8) { // IE8 does not support filter. Need to add polyfill on sites that want this support + equal($.templates("{{props mypeople sort='prop.details.age' reverse=true filter=~under20}}{{:prop.name}}: age {{:prop.details.age}} - {{/props}}").render({mypeople: mypeople}, {under20: under20}), "Jeff: age 13.5 - Emma: age 12 - Bob: age 2 - Julia: age 0.6 - Xavier: age 0 - ", "{{props mypeople sort='details.age' reverse=true filter=~under20}}"); + equal($.templates("{{props mypeople sort='prop.details.age' reverse=true filter=~under20 start=1 end=-1}}{{:prop.name}}: age {{:prop.details.age}} - {{/props}}").render({mypeople: mypeople}, {under20: under20}), "Emma: age 12 - Bob: age 2 - Julia: age 0.6 - ", "{{props mypeople sort='details.age' reverse=true filter=~under20 start=1 end=-1}}"); + equal($.templates("{{props mypeople sort='prop.details.age' reverse=true filter=~under20 start=1 end=-1}}{{:prop.name}}: age {{:prop.details.age}} - {{/props}}").render({mypeople: mypeople}, {under20: under20}), "Emma: age 12 - Bob: age 2 - Julia: age 0.6 - ", "{{props mypeople sort='details.age' reverse=true filter=~under20 start=1 end=-1}}"); +} + // =============================== Arrange =============================== + + var mypeople2 = { + p1: {name: "Bill", details: {age: 22, role: "Lead"}}, + p2: {name: "Anne", details: {age: 32, role: "Assistant"}}, + p3: {name: "Emma", details: {age: 19.1, role: "Team member"}}, + p7: {name: "Jeff", details: {age: 33.5, role: "Lead"}}, + p6: {name: "Xavier", details: {age: 32, role: "Team member"}}, + p5: {name: "Julia", details: {age: 18, role: "Assistant"}}, + p4: {name: "Bill", details: {age: 32, role: "Team member"}} + }; + + // ................................ Assert .................................. + + equal($.templates("{{props mypeople sort=~sortAgeName}}{{:prop.name}}: ({{:prop.details.role}}) age {{:prop.details.age}} - {{/props}}").render({mypeople: mypeople2}, {sortAgeName: sortAgeName}), + "Anne: (Assistant) age 32 - Julia: (Assistant) age 18 - Jeff: (Lead) age 33.5 - Bill: (Lead) age 22 - Bill: (Team member) age 32 - Xavier: (Team member) age 32 - Emma: (Team member) age 19.1 - ", + "{{props mypeople sort=~sortAgeName}}: custom sort function"); + + // =============================== Arrange =============================== + + $.views.tags("props2", { + baseTag: "props" + }); + + // ................................ Assert .................................. + +if (!isIE8) { // IE8 does not support filter. Need to add polyfill on sites that want this support + equal($.templates("{{props2 mypeople sort='prop.details.age' reverse=true filter=~under20 start=1 end=-1}}{{:prop.name}}: age {{:prop.details.age}} - {{/props2}}").render({mypeople: mypeople}, {under20: under20}), "Emma: age 12 - Bob: age 2 - Julia: age 0.6 - ", "{{for2 mypeople sort='details.age' reverse=true filter=~under20 start=1 end=-1}} Derived tag"); +} +}); + QUnit.module("{{!-- --}}"); test("{{!-- --}}", function() { // =============================== Arrange =============================== diff --git a/test/unit-tests/tests-jsrender-with-jquery.js b/test/unit-tests/tests-jsrender-with-jquery.js index 45aa82b..1890474 100644 --- a/test/unit-tests/tests-jsrender-with-jquery.js +++ b/test/unit-tests/tests-jsrender-with-jquery.js @@ -157,11 +157,16 @@ test("templates", function() { debug:true }, "tmplFromString": { - markup: "testDebug", + markup: "X_{{:name}}_Y", debug:true } }); - equal($.templates.tmplFromString.fn.toString().indexOf("debugger;") > 0 && $.templates.scriptTmpl.fn.toString().indexOf("debugger;") > 0, true, 'Debug a template: set debug:true on object'); + equal($.templates.tmplFromString.fn.toString().indexOf("debugger;") > 0 + && $.templates.scriptTmpl.fn.toString().indexOf("debugger;") > 0 + && $.templates.scriptTmpl({name: "Jo"}) + $.templates.tmplFromString({name: "Jo"}), isIE8 + ? "\nA_Jo_BX_Jo_Y" + : "A_Jo_BX_Jo_Y", + 'Debug a template: set debug:true on object'); // reset $("#my_tmpl")[0].removeAttribute("data-jsv-tmpl"); diff --git a/test/unit-tests/tests-jsviews.js b/test/unit-tests/tests-jsviews.js index 99c6ec0..dc9f2c1 100644 --- a/test/unit-tests/tests-jsviews.js +++ b/test/unit-tests/tests-jsviews.js @@ -3,12 +3,17 @@ "use strict"; /* Setup */ -var isIE8 = window.attachEvent && !window.addEventListener; -var useinput = "oninput" in document; -var inputOrKeydown = useinput ? "input" : "keydown"; +var inputOrKeydownContentEditable, + isIE8 = window.attachEvent && !window.addEventListener, + isIE = window.navigator.userAgent, + useInput = "oninput" in document, + inputOrKeydown = useInput ? "input" : "keydown"; + + isIE = isIE.indexOf('MSIE ') > 0 || isIE.indexOf('Trident/') > 0; + inputOrKeydownContentEditable = isIE ? "keydown" : "input"; function keydown(elem) { - if (useinput) { + if (useInput) { elem.trigger("input"); } else { elem.keydown(); @@ -1126,6 +1131,7 @@ test("Top-level linking", function() { res += "|" + $("#result select option:selected").text() + "-" + $("#result ul").text(); + $("#result").link(true, model); // ............................... Assert ................................. equal(res, "Jim-BobJim|new0-BobJimnew0", "Top level bindings with multiple targets on the same element work correctly: html{for people tmpl='selectTmpl'} {:selected:}"); @@ -1168,7 +1174,7 @@ test("Top-level linking", function() { // ............................... Assert ................................. equal(res, (isIE8 ? "Bob lead:Jim - Jim lead:Jim - |Bob lead:newName - Jim lead:newName -newName lead:newName - " - : "Bob lead:Jim - Jim lead:Jim - |Bob lead:newName - Jim lead:newName - newName lead:newName - "), + : "Bob lead:Jim - Jim lead:Jim - |Bob lead:newName - Jim lead:newName - newName lead:newName - "), "Top level bindings allow passing in new contextual parameters to template: data-link=\"{for people ~team=#data tmpl=..."); // ................................ Reset ................................ @@ -1216,7 +1222,9 @@ test("$.link() and $().link() variants", function(assert) { $("#result").empty(); // ............................... Assert ................................. - +if (!(!viewsAndBindings() && !$._data(person1).events && !$._data(person1.home).events && !$._data(help.options).events)) { +debugger; +} ok(!viewsAndBindings() && !$._data(person1).events && !$._data(person1.home).events && !$._data(help.options).events, "$(container).empty removes current listeners from that content"); @@ -3396,6 +3404,10 @@ setTimeout(function() { $("#result").empty(); // =============================== Arrange =============================== + function getSelection() { + return model.selected + ":" + ($("#result select option:selected").text()||"-") + "(" + $("#result select")[0].selectedIndex + ")|"; + } + tmpl = $.templates(''); model = { @@ -3410,7 +3422,7 @@ setTimeout(function() { // ............................... Act ................................. tmpl.link("#result", model); - res = $("#result select option:selected").text() + "-" + $("#result select")[0].selectedIndex + "|"; + res = getSelection(); $.observable(model.people).insert({ name: newName @@ -3418,18 +3430,18 @@ setTimeout(function() { $.observable(model).setProperty("selected", newName); - res += $("#result select option:selected").text() + "-" + $("#result select")[0].selectedIndex + "|"; + res += getSelection(); $.observable(model.people).remove(2); - res += $("#result select option:selected").text() + "-" + $("#result select")[0].selectedIndex + "|"; + res += getSelection(); $("#result select").val('Jim').change(); - res += model.selected + $("#result select option:selected").text() + "-" + $("#result select")[0].selectedIndex + "|"; + res += getSelection(); // ............................... Assert ................................. - equal(res, "Jim-1|new-2|Bob-0|JimJim-1|", + equal(res, "Jim:Jim(1)|new:new(2)|new:-(-1)|Jim:Jim(1)|", '...{{/for}}', + converters: { + cvt: function (value) { + return value + } + } + }); + + model = { + selected: 4, + items: [] + }; + + // ............................... Act ................................. + tmpl.link("#result", model); + + res = getSelection(); + + $.observable(model.items).insert(0, [4,5,6]); + + res += getSelection(); + + // ............................... Assert ................................. + equal(res, "4:-(-1)|4:4(0)|", + '{^{for items}}{{/for}}', + converters: { + cvt: function (value) { + return value + } + } + }); + + model = { + selected: 4, + items: [] + }; + + // ............................... Act ................................. + tmpl.link("#result", model); + + res = getSelection(); + + $.observable(model.items).insert(0, [4,5,6]); + + res += getSelection(); + + // ............................... Assert ................................. + equal(res, "4:-(-1)|4:4(0)|", + '{^{for items}}{{/for}}', + converters: { + cvt: function (value) { + return value + } + } + }); + + model = { + selected: 4, + items: [] + }; + + // ............................... Act ................................. + tmpl.link("#result", model); + + res = getSelection(); + + $.observable(model.items).insert(0, [4,5,6]); + + res += getSelection(); + + // ............................... Assert ................................. + equal(res, "4:-(-1)|4:4(0)|", + '{^{for items}}{{/for}}', + converters: { + cvt: function (value) { + return value + } + } + }); + + model = { + selected: 4, + items: [] + }; + + // ............................... Act ................................. + tmpl.link("#result", model); + + res = getSelection(); + + $.observable(model.items).insert(0, [4,5,6]); + + res += getSelection(); + + // ............................... Assert ................................. + equal(res, "4:-(-1)|4:4(0)|", + '{^{for items}}{{/for}}'); + + model = { + selected: 4, + items: [1,2,3], + items2: [4,5,6] +}; + + // ............................... Act ................................. + tmpl.link("#result", model); + + res = getSelection(); + + $.observable(model).setProperty('items', model.items2); + + res += getSelection(); + + // ............................... Assert ................................. + equal(res, "4:-(-1)|4:4(0)|", + '{^{for people}}{{/for}}'); @@ -3605,7 +3760,7 @@ setTimeout(function() { // ............................... Act ................................. tmpl.link("#result", model); - res = $("#result select")[0].multiple + $("#result select option:selected").text() + "-" + $("#result select")[0].selectedIndex + "|"; + res = $("#result select")[0].multiple + getSelection(); $.observable(model.people).insert({ name: newName @@ -3613,11 +3768,11 @@ setTimeout(function() { $.observable(model).setProperty("selected", [newName, "Bob"]); - res += $("#result select option:selected").text() + "-" + $("#result select")[0].selectedIndex + "|"; + res += getSelection(); $.observable(model.people).remove(2); - res += $("#result select option:selected").text() + "-" + $("#result select")[0].selectedIndex + "|"; + res += getSelection(); $.observable(model.people).insert([ { @@ -3630,22 +3785,22 @@ setTimeout(function() { $("#result select").val(['Jo']).change(); - res += model.selected + $("#result select option:selected").text() + "-" + $("#result select")[0].selectedIndex + "|"; + res += getSelection(); $("#result select").val([]).change(); - res += model.selected + $("#result select option:selected").text() + "-" + $("#result select")[0].selectedIndex + "|"; + res += getSelection(); $("#result select").val(["Bob", "Pete", "Jim"]).change(); - res += model.selected + $("#result select option:selected").text() + "-" + $("#result select")[0].selectedIndex + "|"; + res += getSelection(); $.observable(model).setProperty("selected", "Bob"); - res += $("#result select")[0].multiple + $("#result select option:selected").text() + "-" + $("#result select")[0].selectedIndex + "|"; + res += getSelection(); // ............................... Assert ................................. - equal(res, "trueBOBJIM-0|BOBNEW-0|BOB-0|JoJO-3|--1|Bob,Jim,PeteBOBJIMPETE-0|trueBOB-0|", + equal(res, "trueJim,Bob:BOBJIM(0)|new,Bob:BOBNEW(0)|new,Bob:BOB(0)|Jo:JO(3)|:-(-1)|Bob,Jim,Pete:BOBJIMPETE(0)|Bob:BOB(0)|", 'Multiselect with
" + template: "{^{:~tagCtx.props.label}}
" } }); @@ -8353,7 +8660,7 @@ test("{^{tag}}", function() { // =============================== Arrange =============================== $.views.tags({ mytag: { - template: "{{:~tag.tagCtx.args[0]}}", + template: "{{:~tagCtx.args[0]}}", attr: "html" } }); @@ -8437,6 +8744,9 @@ test("{^{for}}", function() { $("#result").empty(); model.things = []; // reset Prop + equal(JSON.stringify(_jsv.cbBindings), "{}", + "Bindings all removed when content removed from DOM"); + // =============================== Arrange =============================== var things1 = [{thing: "box"}], @@ -8589,6 +8899,52 @@ test("{^{for}}", function() { $("#result").empty(); model.things = []; // reset Prop + equal(JSON.stringify(_jsv.cbBindings), "{}", + "Bindings all removed when content removed from DOM"); + + // =============================== Arrange =============================== + +var ret = ""; + +var listData = {nodes: {list: ["A "]}}; + +$.templates('Plain: {^{for nodes^list}}{{:}}{{/for}}\ +|SpanWithNext: {^{for nodes^list}}{{:}}{{/for}}nextElem\ +|UlWithNext:
    {^{for nodes^list}}
  • {{:}}
  • {{/for}}
  • nextElem
\ +|Ul:
    {^{for nodes^list}}
  • {{:}}
  • {{/for}}
') + .link('#result', listData); //"Plain: A |SpanWithNext: A nextElem|UlWithNext: A nextElem|Ul: A " + + // ................................ Act .................................. +ret += "|1 " + $("#result").text() + " " + $._data(listData.nodes.list).events.arrayChange.length; + +$.observable(listData).setProperty("nodes", {list: []}); + +ret += "|2 " + $("#result").text() + " " + $._data(listData.nodes.list).events.arrayChange.length; + +$.observable(listData.nodes.list).insert("C "); + +ret += "|3 " + $("#result").text() + " " + $._data(listData.nodes.list).events.arrayChange.length; + +$.observable(listData.nodes).setProperty("list", []); +ret += "|4 " + $("#result").text() + " " + $._data(listData.nodes.list).events.arrayChange.length; + +$.observable(listData.nodes.list).insert("C2 "); + +ret += "|5 " + $("#result").text() + " " + $._data(listData.nodes.list).events.arrayChange.length; + + // ............................... Assert ................................. + equal(ret, isIE8 + ? "|1 Plain: A |SpanWithNext: A nextElem|UlWithNext: AnextElem|Ul: A 4" + + "|2 Plain: |SpanWithNext:nextElem|UlWithNext: nextElem|Ul: 4" + + "|3 Plain:C |SpanWithNext:C nextElem|UlWithNext: CnextElem|Ul: C 4" + + "|4 Plain: |SpanWithNext:nextElem|UlWithNext: nextElem|Ul: 4|" + + "5 Plain:C2 |SpanWithNext:C2 nextElem|UlWithNext: C2nextElem|Ul: C2 4" + : "|1 Plain: A |SpanWithNext: A nextElem|UlWithNext: AnextElem|Ul: A 4" + + "|2 Plain: |SpanWithNext: nextElem|UlWithNext: nextElem|Ul: 4" + + "|3 Plain: C |SpanWithNext: C nextElem|UlWithNext: CnextElem|Ul: C 4" + + "|4 Plain: |SpanWithNext: nextElem|UlWithNext: nextElem|Ul: 4" + + "|5 Plain: C2 |SpanWithNext: C2 nextElem|UlWithNext: C2nextElem|Ul: C2 4", + "Deep observable updates of array path on {^{for}} does not create additional array bindings"); // =============================== Arrange =============================== model.things = []; // reset Prop @@ -8725,7 +9081,7 @@ test("{^{for}}", function() { // =============================== Arrange =============================== - model.things = [{thing: "box"}]; // reset Prop + model.things = [{thing: "box"}]; $.templates('{^{for things}}{{:thing}}{{else}}None{{/for}}') .link("#result", model); @@ -8785,7 +9141,7 @@ test("{^{for}}", function() { // =============================== Arrange =============================== - model.things = [{thing: "box"}]; // reset Prop + model.things = [{thing: "box"}]; $.templates('
    {^{for things}}
  • {{:thing}}
  • {{else}}
  • None
  • {{/for}}
') .link("#result", model); @@ -8845,7 +9201,6 @@ test("{^{for}}", function() { // =============================== Arrange =============================== - model.things = []; // reset Prop $.templates('{^{for things}}{{:thing}}{{else}}None{{/for}}{^{if true}}_yes{{/if}}') .link("#result", model); @@ -8859,6 +9214,7 @@ test("{^{for}}", function() { equal(before + "|" + after, 'None_yes|boxtree_yes', '{^{for things}}{{else}}{{/for}}{^{if ...}} starting with empty array binds to array inserts'); // See https://github.com/BorisMoore/jsviews/issues/326 + // ................................ Reset ................................ $("#result").empty(); model.things = []; // reset Prop @@ -8900,6 +9256,9 @@ test("{^{for}}", function() { $("#result").empty(); model.things = []; // reset Prop + equal(JSON.stringify(_jsv.cbBindings), "{}", + "Bindings all removed when content removed from DOM"); + // =============================== Arrange =============================== // ................................ Act .................................. @@ -8937,6 +9296,9 @@ test("{^{for}}", function() { $("#result").empty(); model.things = []; // reset Prop + equal(JSON.stringify(_jsv.cbBindings), "{}", + "Bindings all removed when content removed from DOM"); + // =============================== Arrange =============================== // ................................ Act .................................. $.templates('{^{for things}}{^{if expanded}}{{/if}}{{/for}}
{{:thing}}
') @@ -8957,6 +9319,9 @@ test("{^{for}}", function() { $("#result").empty(); model.things = []; // reset Prop + equal(JSON.stringify(_jsv.cbBindings), "{}", + "Bindings all removed when content removed from DOM"); + // =============================== Arrange =============================== // ................................ Act .................................. @@ -8978,6 +9343,9 @@ test("{^{for}}", function() { $("#result").empty(); model.things = []; // reset Prop + equal(JSON.stringify(_jsv.cbBindings), "{}", + "Bindings all removed when content removed from DOM"); + // =============================== Arrange =============================== // ................................ Act .................................. @@ -8995,6 +9363,9 @@ test("{^{for}}", function() { $("#result").empty(); model.things = []; // reset Prop + equal(JSON.stringify(_jsv.cbBindings), "{}", + "Bindings all removed when content removed from DOM"); + // =============================== Arrange =============================== // ................................ Act .................................. @@ -9038,6 +9409,9 @@ test("{^{for}}", function() { $("#result").empty(); model.things = []; // reset Prop + equal(JSON.stringify(_jsv.cbBindings), "{}", + "Bindings all removed when content removed from DOM"); + // =============================== Arrange =============================== // ................................ Act .................................. @@ -9080,6 +9454,9 @@ test("{^{for}}", function() { $("#result").empty(); model.things = []; // reset Prop + equal(JSON.stringify(_jsv.cbBindings), "{}", + "Bindings all removed when content removed from DOM"); + // =============================== Arrange =============================== $.templates("
    {{for}}
  • Name: {{:firstName()}}. Width: {{:~settings.width}}
  • {{/for}}
") @@ -9197,42 +9574,560 @@ test("{^{for}}", function() { // ................................ Reset ................................ $("#result").empty(); + + equal(JSON.stringify(_jsv.cbBindings), "{}", + "Bindings all removed when content removed from DOM"); + + $.views.settings.advanced({_jsv: false}); + }); -test("{^{if}}...{{else}}...{{/if}}", function() { +test("{^{for start end sort filter reverse}}", function() { $.views.settings.advanced({_jsv: true}); // For using cbBindings store + equal($.templates("{{for start=0 end=10}}{{:}} {{/for}}").render(), "0 1 2 3 4 5 6 7 8 9 ", "{{for start=0 end=10}}: Auto-create array"); + equal($.templates("{{for start=5 end=9 reverse=1}}{{:}} {{/for}}").render(), "8 7 6 5 ", "{{for start=5 end=9 reverse=1}}: Auto-create array"); + equal($.templates("{{for start=8 end=4 step=-1}}{{:}} {{/for}}").render(), "8 7 6 5 ", "{{for start=8 end=4 step=-1}}: Auto-create array"); + equal($.templates("{{for start=8 end=4 step=-1 reverse=true}}{{:}} {{/for}}").render(), "5 6 7 8 ", "{{for start=8 end=4 step=-1 reverse=true}}: Auto-create array"); + equal($.templates("{{for start=20 end='10' step=-2}}{{:}} {{/for}}").render(), "20 18 16 14 12 ", "{{for start=20 end='10' step=-2}}: Auto-create array"); + equal($.templates("{{for start=20 end='10' step=2}}{{:}} {{/for}}").render(), "", "{{for start=20 end='10' step=2}}: Auto-create array (outputs nothing)"); + equal($.templates("{{for start=2 end=-1.5 step=-.5}}{{:}} {{/for}}").render(), "2 1.5 1 0.5 0 -0.5 -1 ", "{{for start=0 end='10' step=-1}}: Auto-create array"); + equal($.templates("{{for start=2}}{{:}} {{/for}}").render(), "", "{{for start=2}}: (outputs nothing)"); + equal($.templates("{{for end=4}}{{:}} {{/for}}").render(), "0 1 2 3 ", "{{for end=4}}: (start defaults to 0)"); + + var myarray = [1, 9, 2, 8, 3, 7, 4, 6, 5, -100, 20, 100, -1]; + var mypeople = [ + {name: "Jo", details: {age: 22}}, + {name: "Bob", details: {age: 2}}, + {name: "Emma", details: {age: 12}}, + {name: "Jeff", details: {age: 13.5}}, + {name: "Julia", details: {age: 0.6}}, + {name: "Xavier", details: {age: 0}} + ]; + var oddValue = function(item, index, items) { return item%2; }; + var oddIndex = function(item, index, items) { return index%2; }; + var under20 = function(item, index, items) { + return item.details.age < 20; + }; + + equal($.templates("{{for #data sort=''}}{{:}} {{/for}}").render(myarray, true), "1 9 2 8 3 7 4 6 5 -100 20 100 -1 ", "{{for #data sort=''}}"); + equal($.templates("{{for #data sort=true}}{{:}} {{/for}}").render(myarray, true), "-100 -1 1 2 3 4 5 6 7 8 9 20 100 ", "{{for #data sort=true}}"); + equal($.templates("{{for myarray reverse=true}}{{:}} {{/for}}").render({myarray: myarray}), "-1 100 20 -100 5 6 4 7 3 8 2 9 1 ", "{{for myarray reverse=true}}"); + equal($.templates("{{for myarray start=1 end=-1}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "9 2 8 3 7 4 6 5 -100 20 100 ", "{{for myarray start=1 end=-1}}"); + equal($.templates("{{for myarray start=1}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "9 2 8 3 7 4 6 5 -100 20 100 -1 ", "{{for myarray start=1}}"); + equal($.templates("{{for myarray end=-1}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "1 9 2 8 3 7 4 6 5 -100 20 100 ", "{{for myarray end=-1}}"); + equal($.templates("{{for myarray sort=''}}{{:}} {{/for}}").render({myarray: myarray}), "1 9 2 8 3 7 4 6 5 -100 20 100 -1 ", "{{for myarray sort=''}}"); + equal($.templates("{{for myarray sort='' reverse=true}}{{:}} {{/for}}").render({myarray: myarray}), "-1 100 20 -100 5 6 4 7 3 8 2 9 1 ", "{{for myarray sort='' reverse=true}}"); + equal($.templates("{{for myarray sort=true}}{{:}} {{/for}}").render({myarray: myarray}), "-100 -1 1 2 3 4 5 6 7 8 9 20 100 ", "{{for myarray sort=true}}"); + equal($.templates("{{for myarray sort=true reverse=true}}{{:}} {{/for}}").render({myarray: myarray}), "100 20 9 8 7 6 5 4 3 2 1 -1 -100 ", "{{for myarray sort=true reverse=true}}"); + +if (!isIE8) { // IE8 does not support filter. Need to add polyfill on sites that want this support + equal($.templates("{{for myarray filter=~oddValue}}{{:}} {{/for}}").render({myarray: myarray}, {oddValue: oddValue}), "1 9 3 7 5 -1 ", "{{for myarray filter=~oddValue}}!!!"); + equal($.templates("{{for myarray filter=~oddIndex}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "9 8 7 6 -100 100 ", "{{for myarray filter=~oddIndex}}"); + equal($.templates("{{for myarray sort='' filter=~oddValue}}{{:}} {{/for}}").render({myarray: myarray}, {oddValue: oddValue}), "1 9 3 7 5 -1 ", "{{for myarray sort='' filter=~oddValue}}"); + equal($.templates("{{for myarray sort=true filter=~oddValue}}{{:}} {{/for}}").render({myarray: myarray}, {oddValue: oddValue}), "-1 1 3 5 7 9 ", "{{for myarray sort=true filter=~oddValue}}"); + equal($.templates("{{for myarray sort=true filter=~oddIndex}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "-1 2 4 6 8 20 ", "{{for myarray sort=true filter=~oddIndex}}"); + equal($.templates("{{for myarray sort=true filter=~oddIndex start=1 end=3}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "2 4 ", "{{for myarray sort=true filter=~oddIndex start=1 end=3}}"); + equal($.templates("{{for myarray sort=true filter=~oddIndex start=-3 end=-1}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "6 8 ", "{{for myarray sort=true filter=~oddIndex start=-3 end=-1}} Negative start or end count from the end"); + equal($.templates("{{for myarray sort=true filter=~oddIndex start=3 end=3}}{{:}} {{/for}}").render({myarray: myarray}, {oddIndex: oddIndex}), "", "{{for myarray sort=true filter=~oddIndex start=3 end=3}} (outputs nothing)"); +} + + equal($.templates("{{for mypeople sort='name'}}{{:name}}: age {{:details.age}} - {{/for}}").render({mypeople: mypeople}), "Bob: age 2 - Emma: age 12 - Jeff: age 13.5 - Jo: age 22 - Julia: age 0.6 - Xavier: age 0 - ", "{{for mypeople sort='name'}}"); + equal($.templates("{{for mypeople sort='details.age'}}{{:name}}: age {{:details.age}} - {{/for}}").render({mypeople: mypeople}), "Xavier: age 0 - Julia: age 0.6 - Bob: age 2 - Emma: age 12 - Jeff: age 13.5 - Jo: age 22 - ", "{{for mypeople sort='details.age'}}"); + +if (!isIE8) { // IE8 does not support filter. Need to add polyfill on sites that want this support + equal($.templates("{{for mypeople sort='details.age' reverse=true filter=~under20}}{{:name}}: age {{:details.age}} - {{/for}}").render({mypeople: mypeople}, {under20: under20}), "Jeff: age 13.5 - Emma: age 12 - Bob: age 2 - Julia: age 0.6 - Xavier: age 0 - ", "{{for mypeople sort='details.age' reverse=true filter=~under20}}"); + equal($.templates("{{for mypeople sort='details.age' reverse=true filter=~under20 start=1 end=-1}}{{:name}}: age {{:details.age}} - {{/for}}").render({mypeople: mypeople}, {under20: under20}), "Emma: age 12 - Bob: age 2 - Julia: age 0.6 - ", "{{for mypeople sort='details.age' reverse=true filter=~under20 start=1 end=-1}}"); +} + +if (!isIE8) { // IE8 does not support filter. Need to add polyfill on sites that want this support // =============================== Arrange =============================== - var data = {one: true, two: false, three: true}, - boundIfElseTmpl = $.templates( - '{^{if one pane=0}}' - + '{^{if two pane=0}}' - + '{^{if three pane=0}}ONE TWO THREE {{else}}ONE TWO notThree {{/if}}' - + '{{else}}ONE notTwo {^{if three}}THREE {{/if}}{^{if !three}}notThree {{/if}}{{/if}}' - + '{{else three pane=1}}' - + '{^{if two pane=0}}notOne TWO THREE{{else}}notOne notTwo THREE {{/if}}' - + '{{else}}' - + '{^{if two pane=0}}notOne TWO notThree {{else}}notOne TWO notThree {{/if}}' - + '{{/if}}'); + model.things = [{ob: {thing: "box"}}]; + var ctx = {}; + $.templates('|All: {^{for things}}{{:ob.thing}} {{else}}None{{/for}}
\ +|Sort: {^{for this=~ctx.sorted things sort="ob.thing"}}{{:ob.thing}} {{else}}None{{/for}}
\ +|NotTreeReverse: {^{for things filter=~notTree reverse=true}}{{:ob.thing}} {{else}}None{{/for}}
\ +|Start1: {^{for things start=1}}{{:ob.thing}} {{else}}None{{/for}}') + .link("#result", model, { + ctx: ctx, + notTree: function(item) { + return item.ob.thing !== "tree"; + } + }); - // ................................ Act .................................. - boundIfElseTmpl.link("#result", data); + var after = $("#result").text(); // ............................... Assert ................................. + equal(after, "|All: box |Sort: box |NotTreeReverse: box |Start1: None", + '{^{for things}}{{else}}{{/for}} plus sorting and filtering'); + + // ................................ Act .................................. + $.observable(model.things).insert(0, {ob: {thing: "tree"}}); + $.observable(model.things).insert([{ob: {thing: "apple"}}, {ob: {thing: "tree"}}]); after = $("#result").text(); - equal(after, boundIfElseTmpl.render(data), - 'Bound if and else with link render the same as unbound, when using the JsRender render() method'); // ............................... Assert ................................. - equal(after, "ONE notTwo THREE ", - 'Bound if and else render correct blocks based on boolean expressions'); + equal(after, "|All: tree box apple tree |Sort: apple box tree tree |NotTreeReverse: apple box |Start1: box apple tree ", + '{^{for things}}{{else}}{{/for}} plus sorting and filtering binds to array changes on leaf array'); // ................................ Act .................................. - $.observable(data).setProperty({one: false, two: false, three: true}); + $.observable(model.things).remove(0, 3); after = $("#result").text(); - // ............................... Assert ................................. - equal(after, isIE8 ? "notOne notTwo THREE " : "notOne notTwo THREE ", + // ............................... Assert .................................6 + equal(after, "|All: tree |Sort: tree |NotTreeReverse: None|Start1: None", + '{^{for things}}{{else}}{{/for}} plus sorting and filtering renders {{else}} block when array is emptied'); + + // ................................ Act .................................. + $.observable(model.things).insert(0, {ob: {thing: "tree"}}); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All: tree tree |Sort: tree tree |NotTreeReverse: None|Start1: tree ", + '{^{for things}}{{else}}{{/for}} plus sorting and filtering removes {{else}} block when item is added again'); + + // ................................ Act .................................. + $.observable(model).setProperty({things: [{ob: {thing: "triangle"}}, {ob: {thing: "circle"}}]}); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All: triangle circle |Sort: circle triangle |NotTreeReverse: circle triangle |Start1: circle ", + '{^{for things}}{{else}}{{/for}} plus sorting and filtering binds to property change on path'); + + // ................................ Act .................................. + $.observable(model.things).insert([{ob: {thing: "square"}}, {ob: {thing: "tree"}}]); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All: triangle circle square tree |Sort: circle square tree triangle |NotTreeReverse: square circle triangle |Start1: circle square tree ", + '{^{for things}}{{else}}{{/for}} plus sorting and filtering inserts new items with sorting/filtering'); + + // ................................ Act .................................. + $.observable(model).setProperty({things: {ob: {thing: "tree"}}}); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All: tree |Sort: tree |NotTreeReverse: tree |Start1: tree ", + '{^{for things}}{{else}}{{/for}} plus sorting and filtering binds to property change on path - swapping from array to singleton object'); + + // ................................ Act .................................. + $.observable(model).setProperty({things: [{ob: {thing: "square"}}, {ob: {thing: "apple"}}, {ob: {thing: "tree"}}]}); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All: square apple tree |Sort: apple square tree |NotTreeReverse: apple square |Start1: apple tree ", + '{^{for things}}{{else}}{{/for}} plus sorting and filtering binds to property change on path - swapping from singleton object back to array'); + + // ................................ Act .................................. + $.observable(model).removeProperty("things"); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All: None|Sort: None|NotTreeReverse: None|Start1: None", + '{^{for things}}{{else}}{{/for}} plus sorting and filtering binds to removeProperty change on path - and renders {{else}} block'); + + // ................................ Act .................................. + $.observable(model).setProperty("things", [{ob: {thing: "circle"}}, {ob: {thing: "tree"}}, {ob: {thing: "square"}}]); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All: circle tree square |Sort: circle square tree |NotTreeReverse: square circle |Start1: tree square ", + '{^{for things}}{{else}}{{/for}} plus sorting and filtering binds to setProperty change on path - and renders {{for}} block again'); + + // =============================== Arrange =============================== + var tgt = ctx.sorted.tagCtx.map.tgt; + + // ................................ Act .................................. + $.observable(tgt).insert([{ob: {thing: "red"}}, {ob: {thing: "green"}}, {ob: {thing: "blue"}}]); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All: circle tree square red green blue |Sort: circle square tree red green blue |NotTreeReverse: blue green red square circle |Start1: tree square red green blue ", + '{^{for things}} plus sorting and filtering support observable changes to target array tagCtx.map.tgt'); + + // ................................ Reset ................................ + $("#result").empty(); + model.things = []; // reset Prop + + equal(JSON.stringify(_jsv.cbBindings), "{}", + "Bindings all removed when content removed from DOM"); + + // =============================== Arrange =============================== + var movies = [{title: "a0"}, {title: "x0"}, {title: "b0"}, {title: "y0"}, {title: "c0"}, {title: "z0"}]; + ctx = {}; + var cnt = 0; + + $.templates( +'|All:--- {^{for movies}}{{:title}} {{/for}}
\ +|Sort:-- {^{for movies sort="title" reverse=true}}{{:title}} {{/for}}
\ +|Filter: {^{for movies sort="title" reverse=true filter=~odd}}{{:title}} {{/for}}
\ +|Slice:- {^{for movies sort="title" reverse=true filter=~odd start=1 end=-1 this=~ctx.target}}{{:title}} {{/for}}') + .link("#result", {movies: movies}, { + ctx: ctx, + odd: function(item, index, items) { + return index%2; + } + }); + + tgt = ctx.target.tagCtx.map.tgt; // This is the target array for the fourth (and last) {^{for}} tag above - Slice: {^{for ...}} + + // ................................ Act .................................. + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- a0 x0 b0 y0 c0 z0 |Sort:-- z0 y0 x0 c0 b0 a0 |Filter: y0 c0 a0 |Slice:- c0 ", + '{{for}} with sorting, filtering, reverse, start and end settings'); + + // ................................ Act .................................. + $.observable(tgt).insert({title: "t" + cnt++}); // Append item to fourth {^{for}} tag instance above + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- a0 x0 b0 y0 c0 z0 t0 |Sort:-- z0 y0 x0 t0 c0 b0 a0 |Filter: y0 t0 b0 |Slice:- c0 t0 ", + 'Appending of item in target array (sorted, filtered etc) - item is rendered without refreshing sort, filter etc.'); + // But note that in our scenario above this will append an item to the source array movies, which will trigger refreshed + // rendering of the first three {^{for}} instance above + + ctx.target.refresh(); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- a0 x0 b0 y0 c0 z0 t0 |Sort:-- z0 y0 x0 t0 c0 b0 a0 |Filter: y0 t0 b0 |Slice:- t0 ", + 'To refresh sort etc with new item included, call tag.refresh() '); + + // ................................ Act .................................. + $.observable(tgt).insert(0, {title: "t" + cnt++}); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- a0 x0 b0 y0 c0 z0 t0 t1 |Sort:-- z0 y0 x0 t1 t0 c0 b0 a0 |Filter: y0 t1 c0 a0 |Slice:- t1 t0 ", + 'Insertion of item in target array (sorted, filtered etc) - item is rendered without refreshing sort, filter etc.'); + + // ................................ Act .................................. + $.observable(movies).insert(1, {title: "m" + cnt++}); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- a0 m2 x0 b0 y0 c0 z0 t0 t1 |Sort:-- z0 y0 x0 t1 t0 m2 c0 b0 a0 |Filter: y0 t1 m2 b0 |Slice:- t1 m2 ", + 'Insertion of item in source array will also refresh sort, filter etc.'); + + // ................................ Act .................................. + $.observable(tgt).insert(1, [{title: "t" + cnt++}, {title: "t" + cnt++}]); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- a0 m2 x0 b0 y0 c0 z0 t0 t1 t3 t4 |Sort:-- z0 y0 x0 t4 t3 t1 t0 m2 c0 b0 a0 |Filter: y0 t4 t1 m2 b0 |Slice:- t1 t3 t4 m2 ", + 'Insertion of multiple items in target array (sorted, filtered etc) - items are rendered without refreshing sort, filter etc.'); + + // ................................ Act .................................. + $.observable(tgt).refresh([tgt[1], {title: "t" + cnt++}, tgt[0]]); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- a0 x0 b0 y0 c0 z0 t0 t1 t3 t5 |Sort:-- z0 y0 x0 t5 t3 t1 t0 c0 b0 a0 |Filter: y0 t5 t1 c0 a0 |Slice:- t3 t5 t1 ", + 'Calling refresh() on target array will insert and remove items appropriately from source array and target array (and move items in target array) without refreshing sort, filter etc.'); + + // ................................ Act .................................. + $.observable(tgt).remove(); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- a0 x0 b0 y0 c0 z0 t0 t3 t5 |Sort:-- z0 y0 x0 t5 t3 t0 c0 b0 a0 |Filter: y0 t5 t0 b0 |Slice:- t3 t5 ", + 'Removing item in target array (sorted, filtered etc) - items are rendered without refreshing sort, filter etc.'); + + // ................................ Act .................................. + $.observable(movies).remove(0); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- x0 b0 y0 c0 z0 t0 t3 t5 |Sort:-- z0 y0 x0 t5 t3 t0 c0 b0 |Filter: y0 t5 t0 b0 |Slice:- t5 t0 ", + 'Removal of item in source array will also refresh sort, filter etc.'); + + // ................................ Act .................................. + $.observable(tgt).move(0, 1); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- x0 b0 y0 c0 z0 t0 t3 t5 |Sort:-- z0 y0 x0 t5 t3 t0 c0 b0 |Filter: y0 t5 t0 b0 |Slice:- t0 t5 ", + 'Moving items in target array (sorted, filtered etc) - items are moved in target but not in source, and this is without refreshing sort, filter etc.'); + + // ................................ Act .................................. + $.observable(tgt).refresh([{title: "t" + cnt++}]); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- x0 b0 y0 c0 z0 t3 t6 |Sort:-- z0 y0 x0 t6 t3 c0 b0 |Filter: y0 t6 c0 |Slice:- t6 ", + 'Calling refresh() on target array will insert and remove items appropriately from source array and target array (and move items in target array) without refreshing sort, filter etc.'); + + // ................................ Act .................................. + $.observable(movies).insert(1, {title: "m" + cnt++}); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- x0 m7 b0 y0 c0 z0 t3 t6 |Sort:-- z0 y0 x0 t6 t3 m7 c0 b0 |Filter: y0 t6 m7 b0 |Slice:- t6 m7 ", + 'Insertion of item in source array will also refresh sort, filter etc.'); + + // ................................ Act .................................. + $.observable(tgt).insert(1, [{title: "t" + cnt++}, {title: "t" + cnt++}]); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- x0 m7 b0 y0 c0 z0 t3 t6 t8 t9 |Sort:-- z0 y0 x0 t9 t8 t6 t3 m7 c0 b0 |Filter: y0 t9 t6 m7 b0 |Slice:- t6 t8 t9 m7 ", + 'Insertion of multiple items in target array (sorted, filtered etc) - items are rendered without refreshing sort, filter etc.'); + + // ................................ Act .................................. + $.observable(movies).move(1, 3, 2); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- x0 y0 c0 m7 b0 z0 t3 t6 t8 t9 |Sort:-- z0 y0 x0 t9 t8 t6 t3 m7 c0 b0 |Filter: y0 t9 t6 m7 b0 |Slice:- t9 t6 m7 ", + 'Moving of items in source array will also refresh sort, filter etc.'); + + // ................................ Reset ................................ + $("#result").empty(); + + equal(JSON.stringify(_jsv.cbBindings), "{}", + "Bindings all removed when content removed from DOM"); +} + // =============================== Arrange =============================== + movies = [{title: "a0"}, {title: "x0"}, {title: "b0"}, {title: "y0"}, {title: "c0"}, {title: "z0"}]; + ctx = {}; + cnt = 0; + + $.templates( +'|All:--- {^{for movies}}{{:title}} {{/for}}
\ +|Slice:- {^{for movies start=1 end=-1 this=~ctx.target}}{{:title}} {{/for}}') + .link("#result", {movies: movies}, { + ctx: ctx, + odd: function(item, index, items) { + return index%2; + } + }); + + tgt = ctx.target.tagCtx.map.tgt; + + // ................................ Act .................................. + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- a0 x0 b0 y0 c0 z0 |Slice:- x0 b0 y0 c0 ", + '{{for}} with start and end settings ("sliced")'); + + // ................................ Act .................................. + $.observable(tgt).insert({title: "t" + cnt++}); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, isIE8 + ? "|All:--- a0 x0 b0 y0 c0 z0t0 |Slice:- x0 b0 y0 c0t0 " + : "|All:--- a0 x0 b0 y0 c0 z0 t0 |Slice:- x0 b0 y0 c0 t0 ", + 'Appending of item in target array ("sliced") - item is rendered without refreshing sort, filter etc.'); + + ctx.target.refresh(); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, isIE8 + ? "|All:--- a0 x0 b0 y0 c0 z0t0 |Slice:-x0 b0 y0 c0 z0 " + : "|All:--- a0 x0 b0 y0 c0 z0 t0 |Slice:- x0 b0 y0 c0 z0 ", + 'To refresh correct start and end with new item included, call tag.refresh() '); + + // ................................ Act .................................. + $.observable(tgt).insert(0, {title: "t" + cnt++}); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, isIE8 + ? "|All:--- a0 x0 b0 y0 c0 z0t0t1 |Slice:-t1 x0 b0 y0 c0 z0 " + : "|All:--- a0 x0 b0 y0 c0 z0 t0 t1 |Slice:- t1 x0 b0 y0 c0 z0 ", + 'Insertion of item at specific position in target array ("sliced") - item is rendered at insert location, but item is simply appended to source array'); + + // ................................ Act .................................. + $.observable(movies).insert(1, {title: "m" + cnt++}); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, isIE8 + ? "|All:--- a0m2 x0 b0 y0 c0 z0t0t1 |Slice:-m2 x0 b0 y0 c0 z0t0 " + : "|All:--- a0 m2 x0 b0 y0 c0 z0 t0 t1 |Slice:- m2 x0 b0 y0 c0 z0 t0 ", + 'Insertion of item in source array will also refresh "slicing"'); + + // ................................ Act .................................. + $.observable(tgt).insert(1, [{title: "t" + cnt++}, {title: "t" + cnt++}]); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, isIE8 + ? "|All:--- a0m2 x0 b0 y0 c0 z0t0t1t3 t4 |Slice:-m2t3 t4 x0 b0 y0 c0 z0t0 " + : "|All:--- a0 m2 x0 b0 y0 c0 z0 t0 t1 t3 t4 |Slice:- m2 t3 t4 x0 b0 y0 c0 z0 t0 ", + 'Insertion of items at specific position in target array ("sliced") - items are rendered at insert location, but simply appended to source array'); + + // ................................ Act .................................. + $.observable(tgt).refresh([tgt[1], {title: "t" + cnt++}, tgt[0], tgt[2]]); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, isIE8 + ? "|All:--- a0m2 t1t3 t4t5 |Slice:-t3t5 m2 t4 " + : "|All:--- a0 m2 t1 t3 t4 t5 |Slice:- t3 t5 m2 t4 ", + 'Calling refresh() on target array will append and remove items appropriately from source array and target array (and move items in target array)'); + + // ................................ Act .................................. + $.observable(tgt).remove(); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, isIE8 + ? "|All:--- a0m2 t1t3t5 |Slice:-t3t5 m2 " + : "|All:--- a0 m2 t1 t3 t5 |Slice:- t3 t5 m2 ", + 'Removing item in target array ("sliced") - items are rendered without refreshing "slicing".'); + + // ................................ Act .................................. + $.observable(movies).remove(0); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, isIE8 + ? "|All:---m2 t1t3t5 |Slice:-t1 t3 " + : "|All:--- m2 t1 t3 t5 |Slice:- t1 t3 ", + 'Removal of item in source array will also refresh "slicing".'); + + // ................................ Act .................................. + $.observable(tgt).move(0, 1); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, isIE8 + ? "|All:---m2 t1t3t5 |Slice:- t3 t1 " + : "|All:--- m2 t1 t3 t5 |Slice:- t3 t1 ", + 'Moving items in target array ("slice") - items are moved in target but not in source, and this is without refreshing "slicing".'); + + // ................................ Act .................................. + $.observable(movies).move(1, 3, 2); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, isIE8 + ? "|All:---m2 t5 t1t3 |Slice:-t5 t1 " + : "|All:--- m2 t5 t1 t3 |Slice:- t5 t1 ", + 'Moving of items in source array will also refresh "slicing".'); + + // ................................ Reset ................................ + $("#result").empty(); + + equal(JSON.stringify(_jsv.cbBindings), "{}", + "Bindings all removed when content removed from DOM"); + + // =============================== Arrange =============================== +var team = { + members: [ + {name: "one", phones:[]}, + {name: "two", phones:[21, 22]} + ] +}; + + $.templates( +'
    {^{for start=0 members}}{^{for start=0 phones}}
  • |{{:}}
  • {{else}}
  • |NoPhones
  • {{/for}}
  • |{{:name}}
  • {{else}}
  • |NoMembers
  • {{/for}}
') + .link("#result", team); + +var firstLi = $("li")[0]; + + // ............................... Assert ................................. + equal( + $.view("ul").views._1._prv === firstLi + && $.view("ul").views._1.tag._prv === firstLi + && $.view("ul").views._1.views["0"].views._1._prv === firstLi + && $.view("ul").views._1.views["0"].views._1.tag._prv === firstLi + && $("#result").text(), "|NoPhones|one|21|22|two", + "First li is _prv for {{for}} tags"); + + // ................................ Act .................................. + $.observable(team.members).move(1, 0); + + // ............................... Assert ................................. +firstLi = $("li")[0]; + + equal( + $.view("ul").views._1._prv === firstLi + && $.view("ul").views._1.tag._prv === firstLi + && $.view("ul").views._1.views["0"].views._1._prv === firstLi + && $.view("ul").views._1.views["0"].views._1.tag._prv === firstLi + && $("#result").text(), "|21|22|two|NoPhones|one", + "After observable move, first li is _prv for {{for}} tags"); + + // ................................ Act .................................. + $.observable(team.members).remove(0); + + // ............................... Assert ................................. +firstLi = $("li")[0]; + + equal( + $.view("ul").views._1._prv === firstLi + && $.view("ul").views._1.tag._prv === firstLi + && $.view("ul").views._1.views["0"].views._1._prv === firstLi + && $.view("ul").views._1.views["0"].views._1.tag._prv === firstLi + && $("#result").text(), "|NoPhones|one", + "After remove, first li is _prv for {{for}} tags"); + + // ................................ Act .................................. + $.observable(team.members).remove(0); + + // ............................... Assert ................................. +firstLi = $("li")[0]; + + equal( + $.view("ul").views._2._prv === firstLi + && $.view("ul").views._2.tag._prv === firstLi + && $.view("ul").views._3._prv === firstLi + && $.view("ul").views._3.tag._prv === firstLi + && $("#result").text(), "|NoMembers", + "After removing all, first li is _prv for {{for}} tags"); + + //................................ Reset ................................ + $("#result").empty(); + + // ............................... Assert ................................. + equal(JSON.stringify(_jsv.cbBindings), "{}", + "dataMap bindings all removed when tag disposed (content removed from DOM)"); + + $.views.settings.advanced({_jsv: false}); +}); + + +test("{^{if}}...{{else}}...{{/if}}", function() { + $.views.settings.advanced({_jsv: true}); // For using cbBindings store + + // =============================== Arrange =============================== + var data = {one: true, two: false, three: true}, + boundIfElseTmpl = $.templates( + '{^{if one pane=0}}' + + '{^{if two pane=0}}' + + '{^{if three pane=0}}ONE TWO THREE {{else}}ONE TWO notThree {{/if}}' + + '{{else}}ONE notTwo {^{if three}}THREE {{/if}}{^{if !three}}notThree {{/if}}{{/if}}' + + '{{else three pane=1}}' + + '{^{if two pane=0}}notOne TWO THREE{{else}}notOne notTwo THREE {{/if}}' + + '{{else}}' + + '{^{if two pane=0}}notOne TWO notThree {{else}}notOne TWO notThree {{/if}}' + + '{{/if}}'); + + // ................................ Act .................................. + boundIfElseTmpl.link("#result", data); + + // ............................... Assert ................................. + after = $("#result").text(); + equal(after, boundIfElseTmpl.render(data), + 'Bound if and else with link render the same as unbound, when using the JsRender render() method'); + + // ............................... Assert ................................. + equal(after, "ONE notTwo THREE ", + 'Bound if and else render correct blocks based on boolean expressions'); + + // ................................ Act .................................. + $.observable(data).setProperty({one: false, two: false, three: true}); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, isIE8 ? "notOne notTwo THREE " : "notOne notTwo THREE ", 'Bound if and else render correct blocks based on boolean expressions'); // ................................ Act .................................. @@ -9523,7 +10418,7 @@ done(); }, 0); }); -test("{^{props}}..{{else}} ...", function() { +test("{^{props}}...{{else}} ...", function() { $.views.settings.advanced({_jsv: true}); // For using cbBindings store // =============================== Arrange =============================== @@ -9539,112 +10434,250 @@ test("{^{props}}..{{else}} ...", function() { + 'NONE' + '{{/props}}') - .link("#result", root); + .link("#result", root); + + // ................................ Act .................................. + before = $("#result").text(); + $.observable(root.objA).setProperty("propA2", "valA2"); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(before + "|" + after, "propA1:valA1,|propA1:valA1,propA2:valA2,", + '{^{props}} - set new property on objA - shows additional property'); + + // ................................ Act .................................. + before = $("#result").text(); + $.observable(root.objA).removeProperty("propA1").removeProperty("propA2"); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(before + "|" + after, "propA1:valA1,propA2:valA2,|propB1:valb1,propB2:valb2,", + '{^{props}} - remove properties from objA - switches to {{else objB}}'); + + // ................................ Act .................................. + before = $("#result").text(); + $.observable(root.objB).removeProperty("propB1").removeProperty("propB2"); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(before + "|" + after, "propB1:valb1,propB2:valb2,|NONE", + '{^{props}} - remove properties from objB - switches to {{else}}'); + + // ................................ Act .................................. + before = $("#result").text(); + $.observable(root.objB).removeProperty("NotAProperty"); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(before + "|" + after, "NONE|NONE", + '{^{props}} - remove inexistant property from objB - remains on {{else}}'); + + // ................................ Act .................................. + before = $("#result").text(); + $.observable(root.objB).setProperty("newProp", ""); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(before + "|" + after, "NONE|newProp:,", + '{^{props}} - set property on objB to undefined - render {{else objB}}'); + + // ................................ Reset ................................ + $("#result").empty(); + + // ............................... Assert ................................. + equal(JSON.stringify(_jsv.cbBindings), "{}", + "{^{props}} dataMap bindings all removed when tag disposed (content removed from DOM)"); + + // =============================== Arrange =============================== + + root = { + objA: {propA1: "valA1"}, + objB: {propB1: "valb1", propB2: "valb2"} + }; + + $.templates('{^{props objA}}{^{:key}}:{^{:prop}},' + + ',' + + '{{else objB}}{^{:key}}:{^{:prop}},' + + ',' + + '{{else}}' + + 'NONE' + + '{{/props}}') + + .link("#result", root, { + remove: function(ev, eventArgs) { + var view = eventArgs.view, + arr = view.get("array").data, + index = view.index; + $.observable(arr).remove(index); + } + }); + + // ................................ Act .................................. + before = $("#result").text(); + $(".removePropA").click(); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(before + "|" + after, "propA1:valA1,remove,|propB1:valb1,remove,propB2:valb2,remove,", + '{^{props}} - remove properties from objA target array - switches to {{else objB}}'); + + // ................................ Act .................................. + before = $("#result").text(); + $(".removePropB").click(); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(before + "|" + after, "propB1:valb1,remove,propB2:valb2,remove,|NONE", + '{^{props}} - remove properties from objB target array - switches to {{else}}'); + + // ................................ Reset ................................ + $("#result").empty(); + + // ............................... Assert ................................. + equal(JSON.stringify(_jsv.cbBindings), "{}", + "{^{props}} dataMap bindings all removed when tag disposed (content removed from DOM)"); + + $.views.settings.advanced({_jsv: false}); +}); + +if (!isIE8) { // IE8 does not support filter. Need to add polyfill on sites that want this support +test("{^{props start end sort filter reverse}}...{{else}} ...", function() { + $.views.settings.advanced({_jsv: true}); // For using _jsv + + // =============================== Arrange =============================== + var movies = {keyf: {title: "a0"}, keye: {title: "x0"}, keyd: {title: "b0"}, keyc: {title: "y0"}, keyb: {title: "c0"}, keya: {title: "z0"}}, + ctx = {}, + cnt = 0; + +$.templates( +'|All:--- {^{props movies}}{{:key}}:{{:prop.title}} {{/props}}
\ +|Sort:-- {^{props movies sort="prop.title" reverse=true}}{{:prop.title}} {{/props}}
\ +|Filter: {^{props movies sort="prop.title" reverse=true filter=~odd}}{{:prop.title}} {{/props}}
\ +|Slice:- {^{props movies sort="prop.title" reverse=true filter=~odd start=1 end=-1 this=~ctx.target}}{{:prop.title}} {{/props}}') + .link("#result", {movies: movies}, { + ctx: ctx, + odd: function(item, index, items) { + return index%2; + } + }); + + var tgt = ctx.target.tagCtx.contentView.data + function newProp(title) { + return {key: "key"+cnt++, prop: {title: title}} + } + + // ................................ Act .................................. + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- keyf:a0 keye:x0 keyd:b0 keyc:y0 keyb:c0 keya:z0 |Sort:-- z0 y0 x0 c0 b0 a0 |Filter: y0 c0 a0 |Slice:- c0 ", + '{{props}} with Sorting, filtering, reverse, start and end settings'); + + // ................................ Act .................................. + $.observable(tgt).insert(newProp("t" + cnt)); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- keyf:a0 keye:x0 keyd:b0 keyc:y0 keyb:c0 keya:z0 key0:t0 |Sort:-- z0 y0 x0 t0 c0 b0 a0 |Filter: y0 t0 b0 |Slice:- c0 t0 ", + 'Appending of item in target array (sorted, filtered etc) - item is rendered without refreshing sort, filter etc.'); + + ctx.target.refresh(); + after = $("#result").text(); + + // ............................... Assert ................................. + equal(after, "|All:--- keyf:a0 keye:x0 keyd:b0 keyc:y0 keyb:c0 keya:z0 key0:t0 |Sort:-- z0 y0 x0 t0 c0 b0 a0 |Filter: y0 t0 b0 |Slice:- t0 ", + 'To refresh, sort, slice etc with new item included, call tag.refresh() '); // ................................ Act .................................. - before = $("#result").text(); - $.observable(root.objA).setProperty("propA2", "valA2"); + $.observable(tgt).insert(0, newProp("t" + cnt)); after = $("#result").text(); // ............................... Assert ................................. - equal(before + "|" + after, "propA1:valA1,|propA1:valA1,propA2:valA2,", - '{^{props}} - set new property on objA - shows additional property'); + equal(after, "|All:--- keyf:a0 keye:x0 keyd:b0 keyc:y0 keyb:c0 keya:z0 key0:t0 key1:t1 |Sort:-- z0 y0 x0 t1 t0 c0 b0 a0 |Filter: y0 t1 c0 a0 |Slice:- t1 t0 ", + 'Insertion of item in target array (sorted, filtered etc) - item is rendered without refreshing sort, filter etc.'); // ................................ Act .................................. - before = $("#result").text(); - $.observable(root.objA).removeProperty("propA1").removeProperty("propA2"); + $.observable(movies).setProperty("key" + cnt++, {title: "m" + cnt}); after = $("#result").text(); // ............................... Assert ................................. - equal(before + "|" + after, "propA1:valA1,propA2:valA2,|propB1:valb1,propB2:valb2,", - '{^{props}} - remove properties from objA - switches to {{else objB}}'); + equal(after, +"|All:--- keyf:a0 keye:x0 keyd:b0 keyc:y0 keyb:c0 keya:z0 key0:t0 key1:t1 key2:m3 |Sort:-- z0 y0 x0 t1 t0 m3 c0 b0 a0 |Filter: y0 t1 m3 b0 |Slice:- t1 m3 ", + 'Insertion of item in source array will also refresh sort, filter etc.'); // ................................ Act .................................. - before = $("#result").text(); - $.observable(root.objB).removeProperty("propB1").removeProperty("propB2"); + $.observable(tgt).insert(1, [newProp("t" + cnt), newProp("t" + cnt)]); after = $("#result").text(); // ............................... Assert ................................. - equal(before + "|" + after, "propB1:valb1,propB2:valb2,|NONE", - '{^{props}} - remove properties from objB - switches to {{else}}'); + equal(after, "|All:--- keyf:a0 keye:x0 keyd:b0 keyc:y0 keyb:c0 keya:z0 key0:t0 key1:t1 key2:m3 key4:t4 key3:t3 |Sort:-- z0 y0 x0 t4 t3 t1 t0 m3 c0 b0 a0 |Filter: y0 t4 t1 m3 b0 |Slice:- t1 t3 t4 m3 ", + 'Insertion of multiple items in target array (sorted, filtered etc) - items are rendered without refreshing sort, filter etc.'); // ................................ Act .................................. - before = $("#result").text(); - $.observable(root.objB).removeProperty("NotAProperty"); + $.observable(tgt).refresh([tgt[1], newProp("t" + cnt), tgt[0]]); after = $("#result").text(); // ............................... Assert ................................. - equal(before + "|" + after, "NONE|NONE", - '{^{props}} - remove inexistant property from objB - remains on {{else}}'); + equal(after, "|All:--- keyf:a0 keye:x0 keyd:b0 keyc:y0 keyb:c0 keya:z0 key0:t0 key1:t1 key3:t3 key5:t5 |Sort:-- z0 y0 x0 t5 t3 t1 t0 c0 b0 a0 |Filter: y0 t5 t1 c0 a0 |Slice:- t3 t5 t1 ", + 'Calling refresh() on target array will insert and remove items appropriately from source array and target array (and move items in target array) without refreshing sort, filter etc.'); // ................................ Act .................................. - before = $("#result").text(); - $.observable(root.objB).setProperty("newProp", ""); + $.observable(tgt).remove(); after = $("#result").text(); // ............................... Assert ................................. - equal(before + "|" + after, "NONE|newProp:,", - '{^{props}} - set property on objB to undefined - render {{else objB}}'); - + equal(after, "|All:--- keyf:a0 keye:x0 keyd:b0 keyc:y0 keyb:c0 keya:z0 key0:t0 key3:t3 key5:t5 |Sort:-- z0 y0 x0 t5 t3 t0 c0 b0 a0 |Filter: y0 t5 t0 b0 |Slice:- t3 t5 ", + 'Removing item in target array (sorted, filtered etc) - items are rendered without refreshing sort, filter etc.'); - // ................................ Reset ................................ - $("#result").empty(); + // ................................ Act .................................. + $.observable(movies).removeProperty("keyf"); + after = $("#result").text(); // ............................... Assert ................................. - equal(JSON.stringify(_jsv.cbBindings), "{}", - "{^{props}} dataMap bindings all removed when tag disposed (content removed from DOM)"); + equal(after, "|All:--- keye:x0 keyd:b0 keyc:y0 keyb:c0 keya:z0 key0:t0 key3:t3 key5:t5 |Sort:-- z0 y0 x0 t5 t3 t0 c0 b0 |Filter: y0 t5 t0 b0 |Slice:- t5 t0 ", + 'Removal of item in source array will also refresh sort, filter etc.'); - // =============================== Arrange =============================== + // ................................ Act .................................. + $.observable(tgt).move(0, 1); + after = $("#result").text(); - root = { - objA: {propA1: "valA1"}, - objB: {propB1: "valb1", propB2: "valb2"} - }; + // ............................... Assert ................................. + equal(after, "|All:--- keye:x0 keyd:b0 keyc:y0 keyb:c0 keya:z0 key0:t0 key3:t3 key5:t5 |Sort:-- z0 y0 x0 t5 t3 t0 c0 b0 |Filter: y0 t5 t0 b0 |Slice:- t0 t5 ", + 'Moving items in target array (sorted, filtered etc) - items are moved in target but not in source, and this is without refreshing sort, filter etc.'); - $.templates('{^{props objA}}{^{:key}}:{^{:prop}},' - + ',' - + '{{else objB}}{^{:key}}:{^{:prop}},' - + ',' - + '{{else}}' - + 'NONE' - + '{{/props}}') + // ................................ Act .................................. + $.observable(tgt).refresh([newProp("t" + cnt)]); + after = $("#result").text(); - .link("#result", root, { - remove: function(ev, eventArgs) { - var view = eventArgs.view, - arr = view.get("array").data, - index = view.index; - $.observable(arr).remove(index); - } - }); + // ............................... Assert ................................. + equal(after, "|All:--- keye:x0 keyd:b0 keyc:y0 keyb:c0 keya:z0 key3:t3 key6:t6 |Sort:-- z0 y0 x0 t6 t3 c0 b0 |Filter: y0 t6 c0 |Slice:- t6 ", + 'Calling refresh() on target array will insert and remove items appropriately from source array and target array (and move items in target array) without refreshing sort, filter etc.'); // ................................ Act .................................. - before = $("#result").text(); - $(".removePropA").click(); + $.observable(movies).setProperty("key" + cnt++, {title: "m" + cnt}); after = $("#result").text(); // ............................... Assert ................................. - equal(before + "|" + after, "propA1:valA1,remove,|propB1:valb1,remove,propB2:valb2,remove,", - '{^{props}} - remove properties from objA target array - switches to {{else objB}}'); + equal(after, "|All:--- keye:x0 keyd:b0 keyc:y0 keyb:c0 keya:z0 key3:t3 key6:t6 key7:m8 |Sort:-- z0 y0 x0 t6 t3 m8 c0 b0 |Filter: y0 t6 m8 b0 |Slice:- t6 m8 ", + 'Insertion of item in source array will also refresh sort, filter etc.'); // ................................ Act .................................. - before = $("#result").text(); - $(".removePropB").click(); + $.observable(tgt).insert(1, [newProp("t" + cnt), newProp("t" + cnt)]); after = $("#result").text(); // ............................... Assert ................................. - equal(before + "|" + after, "propB1:valb1,remove,propB2:valb2,remove,|NONE", - '{^{props}} - remove properties from objB target array - switches to {{else}}'); + equal(after, "|All:--- keye:x0 keyd:b0 keyc:y0 keyb:c0 keya:z0 key3:t3 key6:t6 key7:m8 key9:t9 key8:t8 |Sort:-- z0 y0 x0 t9 t8 t6 t3 m8 c0 b0 |Filter: y0 t9 t6 m8 b0 |Slice:- t6 t8 t9 m8 ", + 'Insertion of multiple items in target array (sorted, filtered etc) - items are rendered without refreshing sort, filter etc.'); // ................................ Reset ................................ $("#result").empty(); - // ............................... Assert ................................. equal(JSON.stringify(_jsv.cbBindings), "{}", - "{^{props}} dataMap bindings all removed when tag disposed (content removed from DOM)"); + "Bindings all removed when content removed from DOM"); $.views.settings.advanced({_jsv: false}); }); +} test('data-link="{on ...', function() { @@ -9862,7 +10895,11 @@ test('data-link="{on ...', function() { res += "refresh "; eventArgs.linkCtx.tag.refresh(); }, - test: function() { + test: function() + + + + { res += "test "; } }); @@ -11272,13 +12309,14 @@ test('{^{on}}', function() { $("#result").empty(); // =============================== Arrange =============================== + var tmpl = $.templates("{^{on doit id='doIt' class='red' width='100' height='100'/}}"), res = "", data = { name: "Jo", doit: function() { var button = $("button"); - res = button.width() + "|" + button.height() + "|" + button[0].id + "|" + button[0].className; + res = (Math.round(10*button.width())/10) + "|" + (Math.round(10*button.height())/10) + "|" + button[0].id + "|" + button[0].className; } }; @@ -11640,6 +12678,8 @@ test("Fallbacks for missing or undefined paths: using {^{:some.path onError = 'f ok(!viewsAndBindings() && !$._data(initial.value()).events && !$._data(initial.value().value()).events, '$.unlink() removes all views and listeners from the page'); + + $.views.settings.advanced({_jsv: false}); }); test('Bound tag properties and contextual parameters', function() { @@ -11851,8 +12891,8 @@ test('Bound tag properties and contextual parameters', function() { } } }); - $.templates('Updating: {^{updatingTag ^condition=type==="shape"}}{{:type}} {^{:~tag.tagCtx.props.condition}} {{/updatingTag}} ' - + 'Non updating: {^{nonUpdatingTag ^condition=type==="shape"}}{{:type}} {^{:~tag.tagCtx.props.condition}} {{/nonUpdatingTag}}') + $.templates('Updating: {^{updatingTag ^condition=type==="shape"}}{{:type}} {^{:~tagCtx.props.condition}} {{/updatingTag}} ' + + 'Non updating: {^{nonUpdatingTag ^condition=type==="shape"}}{{:type}} {^{:~tagCtx.props.condition}} {{/nonUpdatingTag}}') .link("#result", things); // ................................ Act .................................. @@ -12016,7 +13056,7 @@ $.views.settings.trigger(false); res += $("#result").text() + "|"; } - var tmpl = $.templates( + var tmpl = $.templates( '\ \ \ @@ -12199,7 +13239,7 @@ test("JsViews ArrayChange: insert()", function() { // ............................... Assert ................................. equal($("#result").text(), "TagFirstTagMiddleTagLastTagOrigTag|after", - 'Within element only content, insertion finds correctly the previous view, prevNode, nextNode, etc and establishes correct element order and binding'); + 'Within element only content, insertion maintains correctly prevNode, nextNode, element order and binding on views and tags'); // ................................ Reset ................................ $("#result").empty(); @@ -12238,7 +13278,7 @@ test("JsViews ArrayChange: insert()", function() { // ............................... Assert ................................. equal($("#result").text(), "FirstOrig", - 'Within element only content, insertion finds correctly the previous view, prevNode, nextNode, etc and establishes correct element order and binding'); + 'Within element only content, insertion maintains correctly prevNode, nextNode, element order and binding on views and tags'); // ................................ Reset ................................ $("#result").empty(); @@ -12263,14 +13303,14 @@ test("JsViews ArrayChange: remove()", function() { // ............................... Assert ................................. equal($("#result").text(), "TagOrigTagMiddleTagLastTag|after", - 'Within element only content, remove(1) finds correctly the previous view, prevNode, nextNode, etc and establishes correct element order and binding'); + 'Within element only content, remove(1) maintains correctly prevNode, nextNode, element order and binding on views and tags'); // ................................ Act .................................. $.observable(model.things).remove(); //TagOrigTagFirstTagMiddleTagLastTag|after // ............................... Assert ................................. equal($("#result").text(), "TagOrigTagMiddleTag|after", - 'Within element only content, remov finds correctly the previous view, prevNode, nextNode, etc and establishes correct element order and binding'); + 'Within element only content, remov maintains correctly prevNode, nextNode, element order and binding on views and tags'); // ................................ Reset ................................ $("#result").empty(); @@ -12325,7 +13365,134 @@ test("JsViews ArrayChange: move()", function() { // ............................... Assert ................................. equal($("#result").text(), "TagMiddleTagLastTagOrigTagFirstTag|after", - 'Within element only content, move(2, 0, 2) finds correctly the previous view, prevNode, nextNode, etc and establishes correct element order and binding'); + 'Within element only content, move(2, 0, 2) maintains correctly prevNode, nextNode, element order and binding on views and tags'); + + // ................................ Reset ................................ + $("#result").empty(); + + // =============================== Arrange =============================== + function addResult() { + result += "|" + $("#result").text(); + } + + var result = ""; + model.things = [{thing: "Orig"}, {thing: "First"}, {thing: "Middle"}, {thing: "Last"}]; + model.one = false; + model.two = false; + + $.templates('
    {^{if one}}
  • One
  • {{/if}}{^{if two}}
  • Two
  • {{/if}}{^{for things}}
  • {{:thing}}
  • {{/for}}
') + .link("#result", model); + + // ................................ Act .................................. + $.observable(model.things).move(2, 0, 2); + addResult(); + $.observable(model).setProperty("one", true); + addResult(); + $.observable(model).setProperty("one", false); + addResult(); + $.observable(model).setProperty("one", true); + addResult(); + $.observable(model).setProperty("two", true); + addResult(); + $.observable(model).setProperty("two", false); + addResult(); + $.observable(model).setProperty("two", true); + addResult(); + $.observable(model).setProperty("one", false); + addResult(); + $.observable(model).setProperty("two", false); + addResult(); + + // ............................... Assert ................................. + equal(result, "|MiddleLastOrigFirst|OneMiddleLastOrigFirst|MiddleLastOrigFirst|OneMiddleLastOrigFirst|OneTwoMiddleLastOrigFirst|OneMiddleLastOrigFirst|OneTwoMiddleLastOrigFirst|TwoMiddleLastOrigFirst|MiddleLastOrigFirst", + 'In element only content with preceding collapsible {{if}} blocks, move(2, 0, 2) maintains correctly prevNode, nextNode, element order and binding on views and tags'); + + // ................................ Act .................................. + result = "" + + $.observable(model.things).refresh([{thing: "Orig"}, {thing: "First"}, {thing: "Middle"}, {thing: "Last"}]); + addResult(); + $.observable(model).setProperty("one", true); + addResult(); + $.observable(model).setProperty("one", false); + addResult(); + $.observable(model).setProperty("one", true); + addResult(); + $.observable(model).setProperty("two", true); + addResult(); + $.observable(model).setProperty("two", false); + addResult(); + $.observable(model).setProperty("two", true); + addResult(); + $.observable(model).setProperty("one", false); + addResult(); + $.observable(model).setProperty("two", false); + addResult(); + + // ............................... Assert ................................. + equal(result, "|OrigFirstMiddleLast|OneOrigFirstMiddleLast|OrigFirstMiddleLast|OneOrigFirstMiddleLast|OneTwoOrigFirstMiddleLast|OneOrigFirstMiddleLast|OneTwoOrigFirstMiddleLast|TwoOrigFirstMiddleLast|OrigFirstMiddleLast", + 'In element only content with preceding collapsible {{if}} blocks, refresh(...) maintains correctly prevNode, nextNode, element order and binding on views and tags'); + + // ................................ Reset ................................ + $("#result").empty(); + + // =============================== Arrange =============================== + result = ""; + model.things = [{thing: "Orig"}, {thing: "First"}, {thing: "Middle"}, {thing: "Last"}]; // reset Prop + model.one = []; + model.two = []; + + $.templates('
    {^{for one}}
  • {{:}}
  • {{/for}}{^{for two}}
  • {{:}}
  • {{/for}}{^{for things}}
  • {{:thing}}
  • {{/for}}
') + .link("#result", model); + + // ................................ Act .................................. + $.observable(model.things).move(2, 0, 2); + addResult(); + $.observable(model.one).insert("one"); + addResult(); + $.observable(model.one).remove(); + addResult(); + $.observable(model.one).insert("one"); + addResult(); + $.observable(model.two).insert("two"); + addResult(); + $.observable(model.two).remove(); + addResult(); + $.observable(model.two).insert("two"); + addResult(); + $.observable(model.one).remove(); + addResult(); + $.observable(model.two).remove(); + addResult(); + + // ............................... Assert ................................. + equal(result, "|MiddleLastOrigFirst|oneMiddleLastOrigFirst|MiddleLastOrigFirst|oneMiddleLastOrigFirst|onetwoMiddleLastOrigFirst|oneMiddleLastOrigFirst|onetwoMiddleLastOrigFirst|twoMiddleLastOrigFirst|MiddleLastOrigFirst", + 'In element only content with preceding collapsible {{for}} blocks, move(2, 0, 2) maintains correctly prevNode, nextNode, element order and binding on views and tags'); + + // ................................ Act .................................. + result = "" + $.observable(model.things).refresh([{thing: "Orig"}, {thing: "First"}, {thing: "Middle"}, {thing: "Last"}]); + addResult(); + $.observable(model.one).insert("one"); + addResult(); + $.observable(model.one).remove(); + addResult(); + $.observable(model.one).insert("one"); + addResult(); + $.observable(model.two).insert("two"); + addResult(); + $.observable(model.two).remove(); + addResult(); + $.observable(model.two).insert("two"); + addResult(); + $.observable(model.one).remove(); + addResult(); + $.observable(model.two).remove(); + addResult(); + + // ............................... Assert ................................. + equal(result, "|OrigFirstMiddleLast|oneOrigFirstMiddleLast|OrigFirstMiddleLast|oneOrigFirstMiddleLast|onetwoOrigFirstMiddleLast|oneOrigFirstMiddleLast|onetwoOrigFirstMiddleLast|twoOrigFirstMiddleLast|OrigFirstMiddleLast", + 'In element only content with preceding collapsible {{for}} blocks, refresh(...) maintains correctly prevNode, nextNode, element order and binding on views and tags'); // ................................ Reset ................................ $("#result").empty(); @@ -12422,7 +13589,6 @@ test("JsViews ArrayChange: move()", function() { $(".wrap2").find("li:first").css("color", "red"); $(".wrap3").find("li:nth-of-type(2)").css("color", "red"); - // ................................ Act .................................. move(0, 1); @@ -12868,7 +14034,7 @@ test("JsViews ArrayChange: refresh()", function() { // ............................... Assert ................................. equal($("#result").text(), "TagATagBTagCTag|after", - 'Within element only content, refresh() finds correctly the previous view, prevNode, nextNode, etc and establishes correct element order and binding'); + 'Within element only content, refresh() maintains correctly prevNode, nextNode, element order and binding on views and tags'); // ................................ Reset ................................ $("#result").empty(); @@ -12974,7 +14140,7 @@ test("JsViews jsv-domchange", function() { reset(); }); -module("API - $.observe()"); +module("API - $.observe() (jsv)"); test("observe/unobserve alternative signatures", function() { @@ -13312,12 +14478,17 @@ $.views.settings.trigger(false); $.observable(person.phones()).remove(0); $.observable(person.phones()).refresh([new Phone({number: "replacedPhone1"}), new Phone({number: "replacedPhone2"})]); $.observable(person.phones()).insert(1, [new Phone({number: "insertedPhone3a"}), new Phone({number: "insertedPhone3b"})]); + $.observable(person.phones()).move(1, 3, 2); $.observable(person).setProperty("phones", [new Phone({number: "replacedPhone1"})]); + $.observable(person.phones()).insert(new Phone({number: "insertedPhoneX"})); + $.observable(person.phones()).remove(0); + $.observable(person.phones()).refresh([new Phone({number: "replacedPhoneX1"}), new Phone({number: "replacedPhoneX2"})]); $.observable(person.phones()).insert(1, [new Phone({number: "insertedPhoneX3a"}), new Phone({number: "insertedPhoneX3b"})]); + $.observable(person.phones()).move(1, 3, 2); $.observable(person).setProperty("phones", []); $.observable(person.phones()).insert(new Phone({number: "insertedPhoneY"})); @@ -13336,6 +14507,7 @@ $.views.settings.trigger(false); {\"change\":\"insert\",\"index\":1,\"items\":[{\"_number\":\"insertedPhone3a\"},{\"_number\":\"insertedPhone3b\"}]}\n\ {\"change\":\"move\",\"oldIndex\":1,\"index\":2,\"items\":[{\"_number\":\"insertedPhone3a\"},{\"_number\":\"insertedPhone3b\"}]}\n\ {\"change\":\"set\",\"path\":\"phones\",\"value\":[{\"_number\":\"replacedPhone1\"}],\"oldValue\":[{\"_number\":\"replacedPhone1\"},{\"_number\":\"replacedPhone2\"},{\"_number\":\"insertedPhone3a\"},{\"_number\":\"insertedPhone3b\"}]}\n\ +\ {\"change\":\"insert\",\"index\":1,\"items\":[{\"_number\":\"insertedPhoneX\"}]}\n\ {\"change\":\"remove\",\"index\":0,\"items\":[{\"_number\":\"replacedPhone1\"}]}\n\ {\"change\":\"insert\",\"index\":0,\"items\":[{\"_number\":\"replacedPhoneX1\"},{\"_number\":\"replacedPhoneX2\"}],\"refresh\":true}\n\ @@ -13343,7 +14515,9 @@ $.views.settings.trigger(false); {\"change\":\"refresh\",\"oldItems\":[{\"_number\":\"insertedPhoneX\"}]}\n\ {\"change\":\"insert\",\"index\":1,\"items\":[{\"_number\":\"insertedPhoneX3a\"},{\"_number\":\"insertedPhoneX3b\"}]}\n\ {\"change\":\"move\",\"oldIndex\":1,\"index\":2,\"items\":[{\"_number\":\"insertedPhoneX3a\"},{\"_number\":\"insertedPhoneX3b\"}]}\n\ +\ {\"change\":\"set\",\"path\":\"phones\",\"value\":[],\"oldValue\":[{\"_number\":\"replacedPhoneX1\"},{\"_number\":\"replacedPhoneX2\"},{\"_number\":\"insertedPhoneX3a\"},{\"_number\":\"insertedPhoneX3b\"}]}\n\ +\ {\"change\":\"insert\",\"index\":0,\"items\":[{\"_number\":\"insertedPhoneY\"}]}\n\ {\"change\":\"set\",\"path\":\"number\",\"value\":\"newNumber\",\"oldValue\":\"insertedPhoneY\"}\n', "Paths with computed/getters: address().street() - observeAll correctly tracks all changes on all objects, even as object graph changes"); @@ -14100,33 +15274,37 @@ $.views.settings.trigger(false); }).link("#result", {person:{name: "Jo"}}); // ................................ Act .................................. + var getValues = function() { + result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + "\n"; + } + result = ""; var inputs = $("input"); - result = inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + "\n"; + getValues(); $(inputs[0]).val("Jo2").change(); - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + "\n"; + getValues(); $(inputs[1]).val("Jo3").change(); - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + "\n"; + getValues(); $(inputs[2]).val("Jo4").change(); - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + "\n"; + getValues(); $(inputs[3]).val("Jo5").change(); - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + "\n"; + getValues(); $(inputs[4]).val("Jo6").change(); - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + "\n"; + getValues(); $(inputs[5]).val("Jo7").change(); - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + "\n"; + getValues(); // ............................... Assert ................................. equal(result, "Jo Jo Jo Jo Jo Jo\n" @@ -14174,125 +15352,45 @@ $.views.settings.trigger(false); }).link("#result", {person:{name: "Jo"}}); // ................................ Act .................................. + var getValues = function() { + result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; + } + result = ""; var inputs = $("input"); - result = inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; - - $(inputs[0]).val("Jo0").change(); - - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; - - $(inputs[1]).val("Jo1").change(); - - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; - - $(inputs[2]).val("Jo2").change(); - - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; - - $(inputs[3]).val("Jo3").change(); - - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; - - $(inputs[4]).val("Jo4").change(); - - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; - - $(inputs[5]).val("Jo5").change(); - - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; - - $(inputs[6]).val("Jo6").change(); - - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; - - $(inputs[7]).val("Jo7").change(); - - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; - - // ............................... Assert ................................. - equal(result, "Jo Jo Jo Jo Jo Jo Jo Jo\n" -+ "Jo0 Jo0 Jo0 Jo0 Jo0 Jo0 Jo0 Jo0\n" -+ "Jo1 Jo1 Jo1 Jo1 Jo1 Jo1 Jo1 Jo1\n" -+ "Jo2 Jo2 Jo2 Jo2 Jo2 Jo2 Jo2 Jo2\n" -+ "Jo3 Jo3 Jo3 Jo3 Jo3 Jo3 Jo3 Jo3\n" -+ "Jo4 Jo4 Jo4 Jo4 Jo4 Jo4 Jo4 Jo4\n" -+ "Jo5 Jo5 Jo5 Jo5 Jo5 Jo5 Jo5 Jo5\n" -+ "Jo6 Jo6 Jo6 Jo6 Jo6 Jo6 Jo6 Jo6\n" -+ "Jo7 Jo7 Jo7 Jo7 Jo7 Jo7 Jo7 Jo7\n", - "Custom tag control {{texbox ...}} with linkedCtxParam or linkedElement, data-linked as (1) inline tag, (2) data-linked input or (3) data-linked div"); - - // =============================== Arrange =============================== - $.views.templates({ - markup: - '{^{textbox path=person/}}' - + '

' - - + '{^{textbox2 path=person.name/}}' - + '

' - - + '{^{textbox3 path=person.name/}}' - + '
' - + '
' - + '
', - tags: { - textbox: { - bindTo: "path", - linkedCtxParam: "psn", - template:"", - onUpdate: false - }, - textbox2: { - bindTo: "path", - linkedCtxParam: "nm", - template:"", - onUpdate: false - }, - textbox3: { - bindTo: "path", - linkedElement: "input", - template:"", - onUpdate: false - } - } - }).link("#result", {person:{name: "Jo"}}); - - // ................................ Act .................................. - var inputs = $("input"); - - result = inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; + getValues(); $(inputs[0]).val("Jo0").change(); - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; + getValues(); $(inputs[1]).val("Jo1").change(); - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; + getValues(); $(inputs[2]).val("Jo2").change(); - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; + getValues(); $(inputs[3]).val("Jo3").change(); - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; + getValues(); $(inputs[4]).val("Jo4").change(); - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; + getValues(); $(inputs[5]).val("Jo5").change(); - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; + getValues(); $(inputs[6]).val("Jo6").change(); - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; + getValues(); $(inputs[7]).val("Jo7").change(); - result += inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + "\n"; + getValues(); // ............................... Assert ................................. equal(result, "Jo Jo Jo Jo Jo Jo Jo Jo\n" @@ -14460,6 +15558,25 @@ $.views.settings.trigger(false); equal(result, "Jo Jo|Fred Fred|Fred Fred|Fred Fred|Fred Fred", "Custom editable textbox control {{texbox ...}} with linkedCtxParam. Render method, and programmatic observe state, this.edit"); + // =============================== Arrange =============================== + var data = data = { name: "3.545" }; + + $.views.templates({ + markup: '{^{:(+name).toFixed(2)}} {^{dec:name length=5}}', + converters: { + dec: function(val) { + return (+val).toFixed(this.tagCtx.props.length || 2); + } + } + }).link("#result", data); + + // ................................ Act .................................. + $.observable(data).setProperty("name", "3.745") + + // ............................... Assert ................................. + equal($("#result").text(), isIE8 ? "3.753.74500" : "3.75 3.74500", + "Converter with prop 'length' data-links correctly (no collision with array.length on pathBindings array)."); + $.views.settings.trigger(true); }); @@ -14897,7 +16014,13 @@ test("view.ctxPrm() tag.ctxPrm()", function() { mainElement: "div", template: "
{{include tmpl=#content/}}

", setValue: function(val, index, tagElse) { - this.vals[tagElse][index] = val; + if (val === undefined) { + val = this.getValue(tagElse)[index]; + this.tagCtxs[tagElse].ctxPrm(this.linkedCtxParam[index], val); + } else { + this.vals[tagElse][index] = val; + } +// return val; }, getValue: function(tagElse) { return this.vals[tagElse]; @@ -14912,6 +16035,11 @@ test("view.ctxPrm() tag.ctxPrm()", function() { tmpl.link("#result", {}, {}); + // ............................... Assert ................................. + ok($.view().ctxPrm("toString") === undefined, + "ctxPrm() for built-in non-enumerables such as 'toString' returns undefined"); + + // ................................ Act .................................. var input = $("#1"), view1 = input.view(), content = $("#result"), @@ -15007,20 +16135,79 @@ test("view.ctxPrm() tag.ctxPrm()", function() { res += "|2: " + view1.ctxPrm("foo") + "-" + input.val() + ": {" + content.text() + "} "; // ................................ Act .................................. - input.val("new1"); - input.change(); + input.val("new1"); + input.change(); + + res += "|3: " + view1.ctxPrm("foo") + "-" + input.val() + ": {" + content.text() + "} "; + + // ............................... Assert ................................. + equal(res, isIE8 + ? "1: -: { Outer: , Inner: , Nested inner: }" + + " |2: set1-set1: { Outer:set1 , Inner:set1 , Nested inner:set1 }" + + " |3: new1-new1: { Outer:new1 , Inner:new1 , Nested inner:new1 } " + : "1: -: { Outer: , Inner: , Nested inner: }" + + " |2: set1-set1: { Outer: set1, Inner: set1, Nested inner: set1}" + + " |3: new1-new1: { Outer: new1, Inner: new1, Nested inner: new1} ", + "Observable contextual parameter is scoped to root view (view below top view)"); + + // =============================== Arrange =============================== + tmpl = $.templates( + 'Property: {^{:~prp}} |
' + + 'Function: {^{:is}} |
' + + '{{for items}}' + + 'Inner Property: {^{:~prp}} |
' + + 'Inner Function: {^{:is}} |
' + + '{{/for}}' +); + + var fn = function() { + return this.data.is; + }; + + fn.set = function(val) { + $.observable(this.data).setProperty("is", val); + } + + tmpl.link("#result", [ + {is:"outer1", items: [{is: "inner11"}, {is: "inner12"}]}, + {is:"outer2", items: [{is: "inner21"}, {is: "inner22"}]} + ], + {prp: "PRP", fn: fn} + ); + + var propInput1 = $(".prp").eq(0); + var fnInput1 = $(".fn").eq(0); + var innerPropInput1 = $(".prpb").eq(0); + var innerFnInput1 = $(".fnb").eq(0); + var innerFnInput3 = $(".fnb").eq(3); + content = $("#result"); + res = "1: " + content.text(); + + // ................................ Act .................................. + propInput1.val("prp1"); // first outer propInput + propInput1.change(); + innerPropInput1.val("prp2"); // first inner propInput + innerPropInput1.change(); + fnInput1.val("fn1"); // first outer fnInput + fnInput1.change(); + innerFnInput1.val("fn2"); // first inner fnInput + innerFnInput1.change(); + innerFnInput3.val("fn3"); // first inner fnInput + innerFnInput3.change(); - res += "|3: " + view1.ctxPrm("foo") + "-" + input.val() + ": {" + content.text() + "} "; + res += "2: " + content.text(); // ............................... Assert ................................. - equal(res, isIE8 - ? "1: -: { Outer: , Inner: , Nested inner: }" - + " |2: set1-set1: { Outer:set1 , Inner:set1 , Nested inner:set1 }" - + " |3: new1-new1: { Outer:new1 , Inner:new1 , Nested inner:new1 } " - : "1: -: { Outer: , Inner: , Nested inner: }" - + " |2: set1-set1: { Outer: set1, Inner: set1, Nested inner: set1}" - + " |3: new1-new1: { Outer: new1, Inner: new1, Nested inner: new1} ", - "Observable contextual parameter is scoped to root view (view below top view)"); + equal(res, + "1: Property: PRP | Function: outer1 | " ++ "Inner Property: PRP | Inner Function: inner11 | Inner Property: PRP | Inner Function: inner12 | " ++ "Property: PRP | Function: outer2 | " ++ "Inner Property: PRP | Inner Function: inner21 | Inner Property: PRP | Inner Function: inner22 | " ++ "2: Property: prp2 | Function: fn1 | " ++ "Inner Property: prp2 | Inner Function: fn2 | Inner Property: prp2 | Inner Function: inner12 | " ++ "Property: prp2 | Function: outer2 | " ++ "Inner Property: prp2 | Inner Function: inner21 | Inner Property: prp2 | Inner Function: fn3 | ", + "Observable contextual parameter are scoped: for computed function, to calling view, for properties, not functions, to root view (view below top view)"); // =============================== Arrange =============================== tmpl = $.templates(' {^{:~foo}}'); @@ -15307,6 +16494,183 @@ test("view.ctxPrm() tag.ctxPrm()", function() { "Observable tag contextual parameter within unlinked tag is scoped to tag view, - closest non flow tag ancestor, not shared across else blocks"); // =============================== Arrange =============================== + tmpl = $.templates({ + markup: 'OUTER{^{:~foo}}{^{namebox/}}', + tags: { + namebox: { + template: 'INNER{^{:~foo}}' + } + } + }); + + tmpl.link("#result", [1,2]); + + var inputOuter0 = $("#outer0"), + inputOuter1 = $("#outer1"), + inputInner0 = $("#inner0"), + inputInner1 = $("#inner1"); + + // ................................ Act .................................. + inputInner0.val("inner0!"); + inputInner0.change(); + inputOuter1.val("outer1!"); + inputOuter1.change(); + + var res = $("#result").text() + "%" + inputOuter0.val() + "|" + inputOuter1.val() + "|" + inputInner0.val() + "|" + inputInner1.val(); + + // ............................... Assert ................................. + equal(res, "OUTERouter1!INNERinner0!OUTERouter1!INNER%outer1!|outer1!|inner0!|", + "When contextual parameter not initialized at higher level, it is scoped to nearest tag container, or to root view (view below top view)"); + + // =============================== Arrange =============================== + tmpl = $.templates({ + markup: 'OUTERMOST{^{:~foo}} {^{include ~foo="wrapper!"}}OUTER{^{:~foo}}{^{namebox/}}{{/include}}', + // With {{include ~foo=...}} wrapper + tags: { + namebox: { + template: 'INNER{^{:~foo}}' + } + } + }); + + tmpl.link("#result", [1,2]); + + inputOuter0 = $("#outer0"); + inputOuter1 = $("#outer1"); + inputInner0 = $("#inner0"); + inputInner1 = $("#inner1"); + + res = $("#result").text() + "--" + inputOuter0.val() + "|" + inputOuter1.val() + "|" + inputInner0.val() + "|" + inputInner1.val(); + + // ............................... Assert ................................. + equal(res, "OUTERMOST OUTERwrapper!INNERwrapper!OUTERMOST OUTERwrapper!INNERwrapper!--wrapper!|wrapper!|wrapper!|wrapper!", + "When contextual parameter is initialized at higher level, it is initialized to that level"); + + // ................................ Act .................................. + inputInner0.val("inner0!"); + inputInner0.change(); + inputOuter1.val("outer1!"); + inputOuter1.change(); + + res = $("#result").text() + "%" + inputOuter0.val() + "|" + inputOuter1.val() + "|" + inputInner0.val() + "|" + inputInner1.val(); + + // ............................... Assert ................................. + equal(res, "OUTERMOST OUTERinner0!INNERinner0!OUTERMOST OUTERouter1!INNERouter1!%inner0!|outer1!|inner0!|outer1!", + "When contextual parameter is initialized at higher level, it is scoped to that level"); + + // =============================== Arrange =============================== + tmpl = $.templates({ + markup: 'OUTER{^{:~foo}}{^{namebox/}}', + tags: { + namebox: { + template: 'INNER{^{:~foo}}', + } + }, + helpers: {foo: "helperInit!"} // Global helper + }); + + tmpl.link("#result", [1,2]); + + inputOuter0 = $("#outer0"); + inputOuter1 = $("#outer1"); + inputInner0 = $("#inner0"); + inputInner1 = $("#inner1"); + + // ................................ Act .................................. + inputInner0.val("inner0!"); + inputInner0.change(); + inputOuter1.val("outer1!"); + inputOuter1.change(); + + res = $("#result").text() + "%" + inputOuter0.val() + "|" + inputOuter1.val() + "|" + inputInner0.val() + "|" + inputInner1.val(); + + // ............................... Assert ................................. + equal(res, "OUTERouter1!INNERouter1!OUTERouter1!INNERouter1!%outer1!|outer1!|outer1!|outer1!", + "When contextual parameter is initialized as global helper, it is scoped to root view (view below top view)"); + + // =============================== Arrange =============================== + tmpl = $.templates({ + markup: 'OUTER{^{:~foo}}{^{namebox/}}', + tags: { + namebox: { + template: 'INNER{^{:~foo}}' + } + } + }); + + tmpl.link("#result", [1,2], {foo: "instanceHelperInit!"}); // Instance helper + + inputOuter0 = $("#outer0"); + inputOuter1 = $("#outer1"); + inputInner0 = $("#inner0"); + inputInner1 = $("#inner1"); + + // ................................ Act .................................. + inputInner0.val("inner0!"); + inputInner0.change(); + inputOuter1.val("outer1!"); + inputOuter1.change(); + + res = $("#result").text() + "%" + inputOuter0.val() + "|" + inputOuter1.val() + "|" + inputInner0.val() + "|" + inputInner1.val(); + + // ............................... Assert ................................. + equal(res, "OUTERouter1!INNERouter1!OUTERouter1!INNERouter1!%outer1!|outer1!|outer1!|outer1!", + "When contextual parameter is initialized as instance helper, it is scoped to root view (view below top view)"); + + // =============================== Arrange =============================== + tmpl = $.templates({ + markup: 'OUTER{^{:~foo}}{^{namebox/}}', + tags: { + namebox: { + template: 'INNER{{:~foo}}' // Needs refreshing to show ~foo updates, since {{:~foo}} rather than data-linked {^{:~foo}} + } + }, + helpers: {foo: "helperInit!"} // Global helper + }); + + tmpl.link("#result", [1,2]); + + inputOuter0 = $("#outer0"); + inputOuter1 = $("#outer1"); + + // ................................ Act .................................. + inputOuter1.val("inner1!"); + inputOuter1.change(); + + res = $("#result").text() + "%" + inputOuter0.val() + "|" + inputOuter1.val(); + + // ............................... Assert ................................. + equal(res, "OUTERinner1!INNERhelperInit!OUTERinner1!INNERhelperInit!%inner1!|inner1!", + "When tag needs to be refreshed, if no depends on tag, will not refresh values of ~foo "); + + // =============================== Arrange =============================== + tmpl = $.templates({ + markup: 'OUTER{^{:~foo}}{^{namebox/}}', + tags: { + namebox: { + template: 'INNER{{:~foo}}', // Needs refreshing to show ~foo updates, since {{:~foo}} rather than data-linked {^{:~foo}} + depends: "~foo" // Depends path to ~foo will force refresh when ~foo changes + } + }, + helpers: {foo: "helperInit!"} // Global helper + }); + + tmpl.link("#result", [1,2]); + + inputOuter0 = $("#outer0"); + inputOuter1 = $("#outer1"); + + // ................................ Act .................................. + inputOuter1.val("inner1!"); + inputOuter1.change(); + + res = $("#result").text() + "%" + inputOuter0.val() + "|" + inputOuter1.val(); + + // ............................... Assert ................................. + equal(res, "OUTERinner1!INNERinner1!OUTERinner1!INNERinner1!%inner1!|inner1!", + "When tag needs to be refreshed, if depends='~foo' on tag, will refresh values of ~foo "); + +// =============================== Arrange =============================== tmpl = $.templates(' {^{:~foo}}'); tmpl.link("#result", [1,2], {foo: "val1"}); @@ -15434,6 +16798,234 @@ test("view.ctxPrm() tag.ctxPrm()", function() { + " \n4: newouter/val2/val2-newouter/val2/val2: { newouter val2 val2} ", "link() will initialize contextual parameters, scoped to the newly linked view (within target container), even when the target container is within data-linked content"); + // =============================== Arrange =============================== + tmpl = $.templates('{^{:~nm}} {^{:nm}} {^{:~fnprop()}} {^{:fnprop()}} {^{:~fullName()}} {^{:fullName()}} '); + + function fn1() {return "FN1"} + function fn2() {return "FN2"} + + function fullNameVM() { + return this.nm + $.view("#it").ctxPrm("nm") + "Last"; + } + + fullNameVM.depends = ["nm", "~nm"]; + + fullNameVM.set = function(val) { + $.observable(this).setProperty("nm", val.slice(0, -4)); + }; + + function fullNameCtx() { + return this.data.nm + this.ctxPrm("nm") + "Last"; + } + + fullNameCtx.depends = ["nm", "~nm"]; + + fullNameCtx.set = function(val) { + this.ctxPrm("nm", val.slice(0, -4)); + }; + + var data = { + nm: "Jo", + fullName: fullNameVM, + fnprop: fn1 + }, + ctx = { + nm: "Bob", + fullName: fullNameCtx, + fnprop: fn1 + }; + + tmpl.link("#result", data, ctx); + + // ................................ Act .................................. + var message = ""; + + function changeHandler(ev, eventArgs) { + message += eventArgs.path + "(" + (eventArgs.ctxPrm||"") + "):" + eventArgs.value; + } + + $.observe(data, "nm", changeHandler); + $.observe(data, "fullName", changeHandler); + $.observe($.view("#it"), "~nm", changeHandler); +// $.view("#it").ctxPrm("nm", true, changeHandler); + $.observe($.view("#it"), "~fullName", changeHandler); +// $.view("#it").ctxPrm("fullName", true, changeHandler); + + $.view("#it").ctxPrm("nm", "NewCtxProp"); // Get this to work for triggering computed function helper change + $.observable(data).setProperty("nm", "NewVmProp"); + $.view("#it").ctxPrm("fnprop", fn2); // Get this to work for triggering computed function helper change + $.observable(data).setProperty("fnprop", fn2); + $.view("#it").ctxPrm("fullName", "NewCtxFullname"); // Get this to work for triggering computed function helper change + $.observable(data).setProperty("fullName", "NewVmFullname"); + + // ............................... Assert ................................. + equal($("#result").text(), isIE8 + ? "NewCtxFullNewVmFullFN2FN2NewVmFullNewCtxFullLastNewVmFullNewCtxFullLast " + : "NewCtxFull NewVmFull FN2 FN2 NewVmFullNewCtxFullLast NewVmFullNewCtxFullLast ", + "Observe computed with both data and contextual parameters as depends paths"); + + // ............................... Assert ................................. + equal(message, "_ocp(nm):NewCtxPropnm():NewVmProp_ocp(nm):NewCtxFull_ocp(fullName):NewVmPropNewCtxFullLastnm():NewVmFullfullName():NewVmFullNewCtxFullLast", + "Observe listener registered for props and computed props, and ctxPrm listener registered for contextual parameters and computed contextual parameters. Trigger correctly."); + + // =============================== Arrange =============================== + tmpl = $.templates('{^{:~nm}} {^{:nm}} {^{:~fnprop()}} {^{:fnprop()}} {^{:~fullName()}} {^{:fullName()}} '); + + function fullNameHlp() { + return this.data.nm + this.ctxPrm("nm") + "Last"; + } + + fullNameHlp.depends = ["nm", "~nm"]; + + fullNameHlp.set = function(val) { + this.ctxPrm("nm", val.slice(0, -4)); + }; + + $.views.helpers({ + nm: "Jim", + fnprop: fn1, + fullName: fullNameHlp + }); + + data = { + nm: "Jo", + fullName: fullNameVM, + fnprop: fn1 + }; + + tmpl.link("#result", data); + + // ................................ Act .................................. + var message = ""; + + $.observe(data, "nm", changeHandler); + $.observe(data, "fullName", changeHandler); + $.observe($.view("#it"), "~nm", changeHandler); +// $.view("#it").ctxPrm("nm", true, changeHandler); + $.observe($.view("#it"), "~fullName", changeHandler); +// $.view("#it").ctxPrm("fullName", true, changeHandler); + + $.view("#it").ctxPrm("nm", "NewCtxProp"); // Get this to work for triggering computed function helper change + $.observable(data).setProperty("nm", "NewVmProp"); + $.view("#it").ctxPrm("fnprop", fn2); // Get this to work for triggering computed function helper change + $.observable(data).setProperty("fnprop", fn2); + $.view("#it").ctxPrm("fullName", "NewCtxFullname"); // Get this to work for triggering computed function helper change + $.observable(data).setProperty("fullName", "NewVmFullname"); + + // ............................... Assert ................................. + var fnctions = fullNameHlp === $.views.helpers.fullName && fn1 === $.views.helpers.fnprop; // Make sure helper function have not been replaced by ctxPrm() call + equal(fnctions + $("#result").text(), isIE8 + ? "trueNewCtxFullNewVmFullFN2FN2NewVmFullNewCtxFullLastNewVmFullNewCtxFullLast " + : "trueNewCtxFull NewVmFull FN2 FN2 NewVmFullNewCtxFullLast NewVmFullNewCtxFullLast ", + "Observe registered computed helper with both data and contextual parameters as depends paths"); + + // ............................... Assert ................................. + equal(message, "_ocp(nm):NewCtxPropnm():NewVmProp_ocp(nm):NewCtxFull_ocp(fullName):NewVmPropNewCtxFullLastnm():NewVmFullfullName():NewVmFullNewCtxFullLast", + "Observe listener registered for props and computed props, and ctxPrm listener registered for contextual parameters and computed contextual parameters. Trigger correctly."); + // ................................ Act .................................. + + // =============================== Arrange =============================== + + $("#result").empty(); + + $.views.helpers({ + nm: null, + fnprop: null, + fullName: null + }); + + tmpl = $.templates('{^{:~nm}} {^{:nm}} {^{:~fnprop()}} {^{:fnprop()}} {^{:~fullName()}} {^{:fullName()}} '); + + + function fullNameHlp() { + return this.data.nm + this.ctxPrm("nm") + "Last"; + } + + fullNameHlp.depends = ["nm", "~nm"]; + + fullNameHlp.set = function(val) { + this.ctxPrm("nm", val.slice(0, -4)); + }; + + $.views.helpers({ + nm: "Jim", + fnprop: fn1, + fullName: fullNameHlp + }, tmpl); + + data = { + nm: "Jo", + fullName: fullNameVM, + fnprop: fn1 + }; + + tmpl.link("#result", data); + + // ................................ Act .................................. + var message = ""; + + $.observe(data, "nm", changeHandler); + $.observe(data, "fullName", changeHandler); + $.observe($.view("#it"), "~nm", changeHandler); +// $.view("#it").ctxPrm("nm", true, changeHandler); + $.observe($.view("#it"), "~fullName", changeHandler); +// $.view("#it").ctxPrm("fullName", true, changeHandler); + + $.view("#it").ctxPrm("nm", "NewCtxProp"); // Get this to work for triggering computed function helper change + $.observable(data).setProperty("nm", "NewVmProp"); + $.view("#it").ctxPrm("fnprop", fn2); // Get this to work for triggering computed function helper change + $.observable(data).setProperty("fnprop", fn2); + $.view("#it").ctxPrm("fullName", "NewCtxFullname"); // Get this to work for triggering computed function helper change + $.observable(data).setProperty("fullName", "NewVmFullname"); + + // ............................... Assert ................................. + fnctions = fullNameHlp === tmpl.helpers.fullName && fn1 === tmpl.helpers.fnprop; // Make sure helper function have not been replaced by ctxPrm() call + equal(fnctions + $("#result").text(), isIE8 + ? "trueNewCtxFullNewVmFullFN2FN2NewVmFullNewCtxFullLastNewVmFullNewCtxFullLast " + : "trueNewCtxFull NewVmFull FN2 FN2 NewVmFullNewCtxFullLast NewVmFullNewCtxFullLast ", + "Observe registered computed helper, local to template, with both data and registered helper contextual parameters as depends paths"); + + // ............................... Assert ................................. + equal(message, "_ocp(nm):NewCtxPropnm():NewVmProp_ocp(nm):NewCtxFull_ocp(fullName):NewVmPropNewCtxFullLastnm():NewVmFullfullName():NewVmFullNewCtxFullLast", + "Observe listener registered for props and computed props, and ctxPrm listener registered for contextual parameters and computed contextual parameters. Trigger correctly."); + // ................................ Act .................................. + + message = ""; + res = ""; + + function listeners() { + res += $._data(data).events.propertyChange.length + + $._data($.view("#it")._ocps.nm[0]).events.propertyChange.length + + $._data($.view("#it")._ocps.fullName[0]).events.propertyChange.length + "|"; + } + + listeners(); + $.unobserve(data, "nm", changeHandler); + listeners(); + $.unobserve(data, "fullName", changeHandler); + listeners(); + $.unobserve($.view("#it"), "~nm", changeHandler); + listeners(); + $.unobserve($.view("#it"), "~fullName", changeHandler); + listeners(); + + $.view("#it").ctxPrm("nm", "AddCtxProp"); // Get this to work for triggering computed function helper change + $.observable(data).setProperty("nm", "AddVmProp"); + $.view("#it").ctxPrm("fnprop", fn1); // Get this to work for triggering computed function helper change + $.observable(data).setProperty("fnprop", fn1); + $.view("#it").ctxPrm("fullName", "AddCtxFullname"); // Get this to work for triggering computed function helper change + $.observable(data).setProperty("fullName", "AddVmFullname"); + + // ............................... Assert ................................. + equal(message === "" && res, "14|13|11|10|9|", + "Unobserve programmatic APIs for data and for contextual parameters works correctly. Event handlers removed, and no longer triggered"); + + // ............................... Assert ................................. + equal($("#result").text(), isIE8 + ? "AddCtxFullAddVmFullFN1FN1AddVmFullAddCtxFullLastAddVmFullAddCtxFullLast " + : "AddCtxFull AddVmFull FN1 FN1 AddVmFullAddCtxFullLast AddVmFullAddCtxFullLast ", + "After removing programmatically attached handlers for data and for contextual parameters, declarative UI handlers work correctly"); + // ............................... Reset ................................. $("#result").empty(); }); @@ -15707,7 +17299,7 @@ test("Wrapping", function() { render: function(val) { return "TMPL:" + this.tagCtx.render(val) + "CNT:" + this.tagCtx.content.render(val); }, - template: "1{{include tmpl=#content/}} 2{{include tmpl=~tag.tagCtx.content/}} 3{{:~tag.tagCtx.args[0].name}} " + template: "1{{include tmpl=#content/}} 2{{include tmpl=~tagCtx.content/}} 3{{:~tagCtx.args[0].name}} " } } }).link("#result", {name: "Jo"}); @@ -15727,7 +17319,7 @@ test("Wrapping", function() { render: function(val) { return "TMPL:" + this.tagCtx.render(val) + "CNT:" + this.tagCtx.content.render(val); }, - template: "1{{include tmpl=#content/}} 2{{include tmpl=~tag.tagCtx.content/}} 3{{:~tag.tagCtx.args[0].name}}{{:~tag.tagCtx.index}} " + template: "1{{include tmpl=#content/}} 2{{include tmpl=~tagCtx.content/}} 3{{:~tagCtx.args[0].name}}{{:~tagCtx.index}} " } } }).link("#result", {name: "Jo"}); @@ -16055,12 +17647,12 @@ test("lateRender - for deferred API calls", function() { // ................................ Act .................................. $.templates({ markup: -// These calls are before the targeted instance, so need lateRender=true +// These calls are before the targeted instance, so need lateRender=true (or any other value than false) '
' + '
' + '/
' + -'{^{for #get(true, \'mytag\').tag.value tmpl=\'showVal\' lateRender=true/}}
' + -'{^{for #childTags(\'mytag\')[0].value tmpl=\'showVal\' lateRender=true/}}
' + +'{^{for #get(true, \'mytag\').tag.value tmpl=\'showVal\' lateRender=true/}}' + +'{^{for #childTags(\'mytag\')[0].value tmpl=\'showVal\' lateRender=true/}}' + '/{^{:#childTags(\'mytag\')[0].value lateRender=true}}' + // This is the targeted instance @@ -16071,8 +17663,8 @@ test("lateRender - for deferred API calls", function() { '
' + '/
' + // But these following tags still need lateRender=true, so the rendering is also deferred to after linking has been completed -'{^{for #get(true, \'mytag\').tag.value tmpl=\'showVal\' lateRender=true/}}
' + -'{^{for #childTags(\'mytag\')[0].value tmpl=\'showVal\' lateRender=true/}}
' + +'{^{for #get(true, \'mytag\').tag.value tmpl=\'showVal\' lateRender=true/}}' + +'{^{for #childTags(\'mytag\')[0].value tmpl=\'showVal\' lateRender=true/}}' + '/{^{:#childTags(\'mytag\')[0].value lateRender=true}}' + '/{^{mylaterendertag \'mytag\'/}}' + '/{^{mylaterendertag \'mytag\' lateRender=false/}}', @@ -16101,24 +17693,36 @@ test("lateRender - for deferred API calls", function() { $.templates({ markup: // These calls are before the targeted instance, so need lateRender=true -'
' + -'
' + -'/
' + -'{^{for #get(true, \'mytag\').tag.value tmpl=\'showVal\' lateRender=true/}}
' + -'{^{for #childTags(\'mytag\')[0].value tmpl=\'showVal\' lateRender=true/}}
' + -'/{^{:#childTags(\'mytag\')[0].value lateRender=true}}' + +'
' + +'/
' + +'{^{for #get(true, \'mytag\').tag.value tmpl=\'showVal\' lateRender=undefined/}}' + +'{^{for #childTags(\'mytag\')[0].value tmpl=\'showVal\' lateRender=null/}}' + // This is the targeted instance -'={^{mytag/}}' + +'={^{mytag/}}', + tags: { + mytag: { + template: 'MyTag', + value: 'tagVal' + } + }, + templates: { + showVal: '-{{:}}' + } + }).link("#result", {}); -// These calls are after the targeted instance -'
' + -'
' + -'/
' + -// But these following tags still need lateRender=true, so the rendering is also deferred to after linking has been completed -'{^{for #get(true, \'mytag\').tag.value tmpl=\'showVal\' lateRender=true/}}
' + -'{^{for #childTags(\'mytag\')[0].value tmpl=\'showVal\' lateRender=true/}}
' + -'/{^{:#childTags(\'mytag\')[0].value lateRender=true}}', + // ............................... Assert ................................. + equal($("#result").text(), "-tagVal/tagVal-tagVal-tagVal=MyTag", + "When using APIs such as #childTags() and #get() within binding expressions, to return tag instances, use lateRender=xxx (any value xxx other than false or undefined) to defer the API call until linking is complete" ); + + // ................................ Act .................................. +var myTmpl = $.templates({ + markup: +// These calls are before the targeted instance, so need lateRender=true +'
' + + +// This is the targeted instance +'={^{mytag/}}', tags: { mytag: { template: 'MyTag', @@ -16128,15 +17732,102 @@ test("lateRender - for deferred API calls", function() { templates: { showVal: '-{{:}}' } + }); + +var haserror; +try { + myTmpl.link("#result", {}); +} catch(e) { + haserror = !!e; +} + // ............................... Assert ................................. + ok(haserror, + "When using APIs such as #childTags() within binding expressions, using lateRender=false does not defer the API call" ); + + // ................................ Reset ................................ + $("#result").empty(); + +}); + +test("this= and @some.path", function() { + $.views.settings.trigger(false); + + // =============================== Arrange =============================== + + // ................................ Act .................................. + $.templates({ + markup: +'' + +'BEFORE:{^{:@~o1.tagCtx.props.p}}' + +'' + + +'TAGS:' + +'{^{if this=~o2 ^p=@~o3.tagCtx.props.n n="two "}}B{{/if}}' + +'{^{if this=~o3 ^p=@~o1.tagCtx.props.n n="three "}}C{{/if}}' + + +'AFTER:{^{:@~o1.tagCtx.props.p}}' + +'' + +'', + tags: { + out: { + template: "OUT:{^{:~tagCtx.props.p}}", + onUpdate: false, + } + } + }).link("#result", {}); + + // ............................... Assert ................................. + equal($("#result").text(), +"BEFORE:two two TAGS:DBCAFTER:two two ", + "Declarative this=ref binding on built-in flow tag and late path @ref... works correctly"); + + // ................................ Act .................................. + $.templates({ + markup: +'' + +'BEFORE:{^{:@~o1.tagCtx.props.p}}' + +'' + + +'TAGS:' + +'{^{out this=~o2 ^p=@~o3.tagCtx.props.n n="two "/}}' + +'{^{out this=~o3 ^p=@~o1.tagCtx.props.n n="three "/}}' + + +'AFTER:{^{:@~o1.tagCtx.props.p}}' + +'' + +'', + tags: { + out: { + template: "OUT:{^{:~tagCtx.props.p}}", + onUpdate: false, + } + } }).link("#result", {}); - // ............................... Assert ................................. - equal($("#result").text(), "-tagVal-tagVal/tagVal-tagVal-tagVal/tagVal=MyTag-tagVal-tagVal/tagVal-tagVal-tagVal/tagVal", - "When using APIs such as #childTags() and #get() within binding expressions, to return tag instances, use lateRender=true to defer the API call until linking is complete" ); + // ............................... Assert ................................. + equal($("#result").text(), "BEFORE:two two TAGS:OUT:two OUT:three OUT:one AFTER:two two ", + "Declarative this=ref binding on custom tag and late path @ref... works correctly"); + + // ................................ Act .................................. + var input1 = $("#inp1"), + input2 = $("#inp1"), + result = ""; + + input1.val("newp "); + input1.change(); + + result += $("#result").text(); + + input2.val("newp2 "); + input2.change(); + result += "|" + $("#result").text(); + + equal(result, "BEFORE:newp newp TAGS:OUT:newp OUT:three OUT:one AFTER:newp newp |BEFORE:newp2 newp2 TAGS:OUT:newp2 OUT:three OUT:one AFTER:newp2 newp2 ", + "Declarative this=ref binding on custom tag and late path @ref... works correctly even for two-way binding"); // ................................ Reset ................................ $("#result").empty(); + $.views.settings.trigger(true); }); //TODO add tests for tag.refresh() @@ -16945,7 +18636,7 @@ $.views.settings.trigger(false); tags: { textbox: { state: "state1", - template: "{{:}} {{:#parent.data.bar}} {{:~tag.state}} {{:~tag.tagCtx.props.type}}", + template: "{{:}} {{:#parent.data.bar}} {{:~tag.state}} {{:~tagCtx.props.type}}", convert: conv3, depends: function(data) { return [data, "bar", this, "state" ]; @@ -17244,7 +18935,7 @@ test("Tag options versus setting in init()", function() { $.views.settings.trigger(false); // =============================== Arrange =============================== - function getValues() { + var getValues = function() { result += "{{mytag}}: " + inputs[0].value + " " + inputs[1].value + " " + inputs[2].value + " " + inputs[3].value + " {{else}}: " + inputs[4].value + " " + inputs[5].value + " " + inputs[6].value + " " + inputs[7].value + " |data: " + inputs[8].value + " " + inputs[9].value + " " + inputs[10].value + " |text: " + $("#result").text() + "\n"; @@ -17260,7 +18951,7 @@ test("Tag options versus setting in init()", function() { this.bindTo = ["prop", 1]; this.linkedElement = [".a", ".b"]; this.linkedCtxParam = ["a", "b"]; - this.template = '{^{:~tag.tagCtx.props.title}}'; + this.template = '{^{:~tagCtx.props.title}}'; this.boundProps = ["title"]; //this.depends = "title"; }, @@ -17328,7 +19019,7 @@ test("Tag options versus setting in init()", function() { this.bindTo = ["prop", 1]; this.linkedElement = [".a", ".b"]; this.linkedCtxParam = ["a", "b"]; - this.template = '{{:~tag.tagCtx.props.title}}'; + this.template = '{{:~tagCtx.props.title}}'; //this.boundProps = ["title"]; this.depends = "title"; } @@ -17368,11 +19059,10 @@ test("Tag options versus setting in init()", function() { $(inputs[5]).val("Jo5").change(); inputs = $("input:text", container); getValues(); -window.good=true + $(inputs[8]).val("Jo8").change(); inputs = $("input:text", container); getValues(); -window.good=false $(inputs[9]).val("Blow9").change(); inputs = $("input:text", container); @@ -17540,7 +19230,7 @@ window.good=false this.contentCtx = tagCtx.props.useOuterCtx; }, onUpdate: false, - template: '{{:!!~tag.tagCtx.args[0] && ~tag.tagCtx.args[0].first}} {{:first}} ' + template: '{{:!!~tagCtx.args[0] && ~tagCtx.args[0].first}} {{:first}} ' } } }).link("#result", {first: "Jo"}, {person2: {first: "Fred"}}); @@ -17555,6 +19245,42 @@ window.good=false + "4 Fred Jo Fred Jo Fred Jo Fred Jo ", "Setting argDefault or contentCtx in init() work correctly."); +// =============================== Arrange =============================== + person = {first: "Jo"}; + + $.views.templates({ + markup: "1: {{mytag person=~person2/}} " + + "2: {{mytag person=~person2}}inner block: {{:first}}{{/mytag}} " + + "3: {{myrendertag person=~person2}}inner block: {{:first}}{{/myrendertag}}", + tags: { + mytag: { + contentCtx: function() { + return this.tagCtx.props.person; + }, + onUpdate: false, + template: 'In template: {{:first}} {{include tmpl=#content/}}' + }, + myrendertag: { + contentCtx: function() { + return this.tagCtx.props.person; + }, + onUpdate: false, + render: function() { + return this.tagCtx.render(); + } + } + } + }).link("#result", {first: "Jo"}, {person2: {first: "Fred"}}); + + // ............................... Assert ................................. + result = ""; + + equal($("#result").text(), + "1: In template: Fred " + (isIE8 ? "" : " ") + + "2: In template: Fred inner block: Fred " + + "3: inner block: Fred", + "contentCtx as a function returns the data context both for the template and for block content."); + $.views.settings.trigger(true); }); @@ -17714,7 +19440,6 @@ test("Global trigger=true - ", function(assert) { person = {member: true}; $.templates('').link("#result", person); - var linkedElem = $("#result input")[0]; var events = $._data(linkedElem).events; @@ -18026,25 +19751,25 @@ $.views.settings.trigger(true); linkedElem = tag.linkedElem[0], events = $._data(linkedElem).events, - handlers = "|" + events[inputOrKeydown].length; + handlers = "|" + events[inputOrKeydownContentEditable].length; // ................................ Act .................................. before = linkedElem.innerHTML; linkedElem.innerHTML = "New Name"; - keydown(tag.linkedElem); + tag.linkedElem.trigger(inputOrKeydownContentEditable); setTimeout(function() { before += "|" + person.name; linkedElem.innerHTML = "New2

Name2

"; - keydown(tag.linkedElem); + tag.linkedElem.trigger(inputOrKeydownContentEditable); setTimeout(function() { before += "|" + person.name; linkedElem.innerHTML = "New3
Name3
"; - keydown(tag.linkedElem); + tag.linkedElem.trigger(inputOrKeydownContentEditable); setTimeout(function() { // ............................... Assert ................................. @@ -18053,7 +19778,7 @@ setTimeout(function() { : "JO SMITH|new name|new2

name2

|new3
name3
", 'Data link using: {^{contentEditable name convertBack=~lower/}} - triggers after keydown, converts the data, and sets on data'); - handlers += "|" + events[inputOrKeydown].length; + handlers += "|" + events[inputOrKeydownContentEditable].length; // ............................... Assert ................................. equal(handlers, @@ -18461,7 +20186,8 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { this.contents(".nm").text(this.bndArgs()[0]); // Programmatically update span content }, doupdate: function() { - this.updateValue(this.bndArgs()[0] + this.cnt++).setValue(); // Programmatically call update() from within tag + var val = this.bndArgs()[0] + this.cnt++ + this.updateValue(val).setValue(val); // Programmatically call update() from within tag }, onUpdate: false, cnt: 0 // Counter for programmatically updated content @@ -18492,7 +20218,7 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { // ................................ Act .................................. result = "" + mytag.bndArgs(); - mytag.updateValue("updatedFirst").setValue(); + mytag.updateValue("updatedFirst").setValue("updatedFirst"); result += "--" + mytag.bndArgs() + "|" + linkedEl.value + "|" + person.first + "|" + $("#result").text(); @@ -18671,7 +20397,7 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { result += "--" + person.first; - mytag.updateValue("updatedFirst").setValue(); + mytag.updateValue("updatedFirst").setValue("updatedFirst"); result += "--" + person.first + "|" + linkedEl.value; @@ -18709,7 +20435,7 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { result += "--" + person.first + "|" + $("#result").text(); - mytag.updateValue("updatedFirst").setValue(); + mytag.updateValue("updatedFirst").setValue("updatedFirst"); result += "--" + person.first + "|" + linkedEl.value + "|" + $("#result").text(); @@ -18797,12 +20523,12 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { // ................................ Act .................................. result = "" + mytag.bndArgs(); - mytag.updateValues("updatedFirst", "updatedLast").setValue(); + mytag.updateValues("updatedFirst", "updatedLast").setValues("updatedFirst", "updatedLast"); result += "--" + mytag.bndArgs() + "|" + linkedEl1.value + "|" + linkedEl2.value + "|" + person.first + "|" + person.last + "|" + $("#result").text(); equal(result, "newLast,newFirst--updatedFirst,updatedLast|updatedLast|updatedFirst|updatedLast|updatedFirst|updatedLast updatedFirst", - "mytag.bndArgs() and mytag.updateValues().setValue() work correctly for accessing/updating two-way bound tag contextual parameters"); + "mytag.bndArgs() and mytag.updateValues().setValues() work correctly for accessing/updating two-way bound tag contextual parameters"); // =============================== Arrange =============================== person = {first: "Jo", last: "Blow"}; @@ -18828,13 +20554,13 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { result = linkedEl1.value + "|" + linkedEl2.innerText + "|" + $("#result").text(); // ................................ Act .................................. - mytag.updateValues("updatedFirst", "updatedLast").setValue(); + mytag.updateValues("updatedFirst", "updatedLast").setValues("updatedFirst", "updatedLast"); result += "--" + mytag.bndArgs() + "|" + linkedEl1.value + "|" + person.first + "|" + person.last + "|" + $("#result").text(); // ............................... Assert ................................. equal(result, "Jo|Blow| Blow--updatedFirst,updatedLast|updatedFirst|updatedFirst|updatedLast| updatedLast", - "mytag.bndArgs() and mytag.updateValues().setValue() work correctly for accessing/updating two-way bound linkedElems"); + "mytag.bndArgs() and mytag.updateValues().setValues() work correctly for accessing/updating two-way bound linkedElems"); // =============================== Arrange =============================== person = {first: "Jo", last: "Blow"}; @@ -18849,9 +20575,9 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { onBind: function() { var inputs = this.contents("input"); this.linkedElems[0] = $(inputs[0]); // Programmatically set linkedElems - }, - onAfterLink: function() { - this.linkedElems[1].text(this.bndArgs()[1]); + //}, + //onAfterLink: function() { + // this.linkedElems[1].text(this.bndArgs()[1]); } } } @@ -18868,7 +20594,7 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { + linkedEl1.value + "|" + linkedEl2.innerText + "|" + $("#result").text(); // ................................ Act .................................. - mytag.updateValues("updatedFirst", "updatedLast").setValue(); + mytag.updateValues("updatedFirst", "updatedLast").setValues("updatedFirst", "updatedLast"); result += "--" + mytag.bndArgs() + "|" + linkedEl1.value + "|" + person.first + "|" + person.last + "|" + $("#result").text(); @@ -18889,16 +20615,14 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { onBind: function() { var inputs = this.contents("input"); this.linkedElems[0] = $(inputs[0]); // Programmatically set linkedElems - }, - onAfterLink: function() { - this.linkedElems[1].text(this.bndArgs()[0]); + //}, + //onAfterLink: function() { + // this.linkedElems[1].text(this.bndArgs()[0]); } } } }).link("#result", person); - mytag = $.view().childTags("mytag")[0]; - mytag = $.view().childTags("mytag")[0]; linkedEl1 = $("#linkedElm1")[0]; linkedEl2 = $("#linkedElm2")[0]; @@ -18906,12 +20630,12 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { result = linkedEl1.value + "|" + linkedEl2.innerText + "|" + $("#result").text(); // ................................ Act .................................. - mytag.updateValues("updatedFirst", "updatedLast").setValue(); + mytag.updateValues("updatedFirst", "updatedLast").setValues("updatedFirst", "updatedLast"); result += "--" + mytag.bndArgs() + "|" + linkedEl1.value + "|" + person.first + "|" + person.last + "|" + $("#result").text(); // ............................... Assert ................................. - equal(result, "Jo|Jo| Jo--updatedFirst,updatedLast|updatedFirst|updatedFirst|updatedLast| updatedFirst", + equal(result, "Jo|Blow| Blow--updatedFirst,updatedLast|updatedFirst|updatedFirst|updatedLast| updatedLast", "Mixed declarative linkedElement and programmatic onBind approaches for defining linkedElems"); // =============================== Arrange =============================== @@ -18924,7 +20648,7 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { bindTo: ["name1", "1"], linkedElement: [undefined, "input"], linkedCtxParam: ["foo", undefined], - template: ' ', + template: ' ' } } }).link("#result", person); @@ -18936,7 +20660,7 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { result = linkedEl1.value + "|" + linkedEl2.innerText + "|" + $("#result").text(); // ................................ Act .................................. - mytag.updateValues("updatedFirst", "updatedLast").setValue(); + mytag.updateValues("updatedFirst", "updatedLast").setValues("updatedFirst", "updatedLast"); result += "--" + mytag.bndArgs() + "|" + linkedEl1.value + "|" + person.first + "|" + person.last + "|" + $("#result").text(); @@ -18969,7 +20693,7 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { result = linkedEl1.value + "|" + linkedEl2.innerText + "|" + $("#result").text(); // ................................ Act .................................. - mytag.updateValues("updatedFirst", "updatedLast").setValue(); + mytag.updateValues("updatedFirst", "updatedLast").setValues("updatedFirst", "updatedLast"); result += "--" + mytag.bndArgs() + "|" + linkedEl1.value + "|" + person.first + "|" + person.last + "|" + $("#result").text(); @@ -19009,7 +20733,7 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { result = person.first + "|" + person.last; // ................................ Act .................................. - mytag.updateValues("updatedFirst", "updatedLast").setValue(); + mytag.updateValue("updatedFirst").setValue(mytag.bndArgs()[0]); result += "--" + mytag.bndArgs() + "|" + linkedEl.value + "|" + person.first + "|" + person.last; @@ -19028,7 +20752,7 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { }; $.templates({ - markup: '{^{mytag first convert=cvt convertBack=cvtbk/}}', + markup: '{^{mytag first last convert=cvt convertBack=cvtbk/}}', tags: { mytag: { linkedElement: ["input"], @@ -19046,7 +20770,7 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { result = person.first + "|" + person.last; // ................................ Act .................................. - mytag.updateValues("updatedFirst", "updatedLast").setValue(); + mytag.updateValues("updatedFirst", "updatedLast").setValues(mytag.bndArgs()[0], mytag.bndArgs()[1]); result += "--" + mytag.bndArgs() + "|" + linkedEl.value + "|" + person.first + "|" + person.last; @@ -19071,34 +20795,32 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { bindTo: ["name1", "1"], linkedElement: [undefined, "input"], linkedCtxParam: ["foo", undefined], - template: ' ', + template: ' ' } } }).link("#result", person); mytag = $.view().childTags("mytag")[0]; - linkedEl1 = mytag.contents("#linkedElm1")[0]; - linkedEl2 = mytag.linkedElems[1][0]; - - result = linkedEl1.innerText + "," + linkedEl2.value; + linkedEl1 = mytag.contents("#linkedElm1")[0]; // first - param + linkedEl2 = mytag.linkedElems[1][0]; // last - el + result = linkedEl1.innerText + "," + linkedEl2.value; // Jo*, BLOW - linkedEl2.value += "+"; + linkedEl2.value += "+"; // BLOW+ mytag.linkedElems[1].change(); result += "|" + person.first + "," + person.last; // ................................ Act .................................. - mytag.updateValues("updatedFirst", "updatedLast").setValue(); + mytag.updateValues("updatedFirst", "updatedLast"); + mytag.setValues(mytag.bndArgs()[0], mytag.bndArgs()[1]); result += "|" + mytag.bndArgs() + "|" + linkedEl1.innerText + "," + linkedEl2.value + "|" + person.first + "," + person.last; // ............................... Assert ................................. equal(result, "Jo*,BLOW|Jo,blow+|updatedFirst*,UPDATEDLAST|updatedFirst*,UPDATEDLAST|updatedFirst,updatedlast", "bindTo with converters, using linkedElement and linkedCtxParam"); - - - + // =============================== Arrange =============================== $.views.tags("mytag", { bindTo: ["height", "width"], @@ -19124,8 +20846,14 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { $(document.body).off("mousemove"); }); }, - setValue: function(val, index) { - this.mainElem[index ? "width" : "height"](val || 0); + setValue: function(val, index, tagElse) { + if (val === undefined) { + val = this.getValue(tagElse)[index]; + } else { + this.mainElem[index ? "width" : "height"](val || 0); + } + this.tagCtxs[tagElse].ctxPrm(this.linkedCtxParam[index], val); + return val; }, getValue: function() { var mainElem = this.mainElem; @@ -19500,7 +21228,7 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { linkedElCx = $(".cx")[0]; linkedElCy = $(".cy")[0]; - result = linkedElHt.value === linkedCtxPrmHts[0].value && linkedElHt.value === linkedCtxPrmHts[1].value && linkedElHt.value === "" + mytag.getValue()[0] + result = linkedElHt.value === linkedCtxPrmHts[0].value && linkedElHt.value === linkedCtxPrmHts[1].value && Math.round(10*linkedElHt.value) === Math.round(10*mytag.getValue()[0]) && linkedElCx.value === "40" && linkedElWd.value === "50" && linkedCtxPrmWds[0].value === "50" && linkedCtxPrmWds[1].value === "50"; result += "|" + mytag.getValue()[1]; @@ -19576,7 +21304,7 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { tagCtx.linkedElems = [tagCtx.contents("input")]; } }, - template: " {{:~tag.tagCtx.props.label}}{^{include tmpl=#content/}}", + template: " {{:~tagCtx.props.label}}{^{include tmpl=#content/}}", onUpdate: false, // No need to re-render whole tag, when content updates. }, child: function(val) { @@ -19950,6 +21678,381 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { "0,updatedLast2|0,updatedLast2|0,updatedFirst2--updatedFirst2,updatedLast2|updatedFirst2,updatedLast2|updatedLast2,updatedFirst2", "Two-way tag with multiple bindings and multiple else blocks - calls to tag.cvtArgs(), tagCtx.cvtArgs() tag.bndArgs() tagCtx.bndArgs() work correctly"); +// ............................... Reset ................................. + + $("#result").empty(); + + // =============================== Arrange =============================== + var ret, + data = {current: "cur", modified: "mod"}; + + $.templates({ + markup: '{^{mytag current modified/}}', + tags: { + mytag: { + onUpdate: false, + bindTo: 1, + bindFrom: 0, + linkedElement: "input", + linkedCtxParam: "fm", + template: "", + update: function(val) { + this.updateValue(val); // Update external data, through two-way binding + } + } + } + }).link("#result", data); + + mytag = $.view().childTags()[0]; + var linkedElem = mytag.tagCtx.contents("input")[0]; + + ret = data.current + "-" + data.modified + ":" + linkedElem.value; + + // ............................... Assert ................................. + equal(ret, "cur-mod:cur", + "Two-way tag with bindTo and bindFrom to different paths (1, 0): initial render"); + + // ................................ Act .................................. + $.observable(data).setProperty({current: "cur2"}); + ret = data.current + "-" + data.modified + ":" + linkedElem.value; + + // ............................... Assert ................................. + equal(ret, "cur2-mod:cur2", + "Two-way tag with bindTo and bindFrom to different paths (1, 0): bindFrom binding updates from data"); + + // ................................ Act .................................. + $.observable(data).setProperty({modified: "mod2"}); + ret = data.current + "-" + data.modified + ":" + linkedElem.value; + + // ............................... Assert ................................. + equal(ret, "cur2-mod2:cur2", + "Two-way tag with bindTo and bindFrom to different paths (1, 0): bindTo binding does not update from data"); + + // ................................ Act .................................. + linkedElem.value = "set1"; + $(linkedElem).change(); + ret = data.current + "-" + data.modified + ":" + linkedElem.value; + + // ............................... Assert ................................. + equal(ret, "cur2-set1:set1", + "Two-way tag with bindTo and bindFrom to different paths (1, 0): bindTo binding updates to data - bindFrom binding does not"); + + // ................................ Act .................................. + mytag.setValue("setval", 0, 0); + ret = data.current + "-" + data.modified + ":" + linkedElem.value; + + // ............................... Assert ................................. + equal(ret, "cur2-set1:setval", + "Two-way tag with bindTo and bindFrom to different paths (1, 0): setValue works"); + + // ................................ Act .................................. + mytag.setValues("setval2"); + ret = data.current + "-" + data.modified + ":" + linkedElem.value; + + // ............................... Assert ................................. + equal(ret, "cur2-set1:setval2", + "Two-way tag with bindTo and bindFrom to different paths (1, 0): setValues works"); + + // ................................ Act .................................. + mytag.update("updated1"); + ret = data.current + "-" + data.modified + ":" + linkedElem.value; + + // ............................... Assert ................................. + equal(ret, "cur2-updated1:setval2", + "Two-way tag with bindTo and bindFrom to different paths (1, 0): update() updates bindTo target"); + + // ................................ Act .................................. + mytag.updateValue("updated2"); + ret = data.current + "-" + data.modified + ":" + linkedElem.value; + + // ............................... Assert ................................. + equal(ret, "cur2-updated2:setval2", + "Two-way tag with bindTo and bindFrom to different paths (1, 0): update() updates bindTo target (variant)"); + +// ............................... Reset ................................. + + $("#result").empty(); + + // =============================== Arrange =============================== + var ret, + data = {current: "cur", modified: "mod"}; + + $.templates({ + markup: '{^{mytag modified current/}}', + tags: { + mytag: { + onUpdate: false, + bindTo: 0, + bindFrom: 1, + linkedElement: "input", + linkedCtxParam: "fm", + template: "", + update: function(val) { + this.updateValue(val); // Update external data, through two-way binding + } + } + } + }).link("#result", data); + + mytag = $.view().childTags()[0]; + var linkedElem = mytag.tagCtx.contents("input")[0]; + + ret = data.current + "-" + data.modified + ":" + linkedElem.value; + + // ............................... Assert ................................. + equal(ret, "cur-mod:cur", + "Two-way tag with bindTo and bindFrom to different paths (0, 1): initial render"); + + // ................................ Act .................................. + $.observable(data).setProperty({current: "cur2"}); + ret = data.current + "-" + data.modified + ":" + linkedElem.value; + + // ............................... Assert ................................. + equal(ret, "cur2-mod:cur2", + "Two-way tag with bindTo and bindFrom to different paths (0, 1): bindFrom binding updates from data"); + + // ................................ Act .................................. + $.observable(data).setProperty({modified: "mod2"}); + ret = data.current + "-" + data.modified + ":" + linkedElem.value; + + // ............................... Assert ................................. + equal(ret, "cur2-mod2:cur2", + "Two-way tag with bindTo and bindFrom to different paths (0, 1): bindTo binding does not update from data"); + + // ................................ Act .................................. + linkedElem.value = "set1"; + $(linkedElem).change(); + ret = data.current + "-" + data.modified + ":" + linkedElem.value; + + // ............................... Assert ................................. + equal(ret, "cur2-set1:set1", + "Two-way tag with bindTo and bindFrom to different paths (0, 1): bindTo binding updates to data - bindFrom binding does not"); + + // ................................ Act .................................. + mytag.setValue("setval", 0, 0); + ret = data.current + "-" + data.modified + ":" + linkedElem.value; + + // ............................... Assert ................................. + equal(ret, "cur2-set1:setval", + "Two-way tag with bindTo and bindFrom to different paths (0, 1): setValue works"); + + // ................................ Act .................................. + mytag.setValues("setval2"); + ret = data.current + "-" + data.modified + ":" + linkedElem.value; + + // ............................... Assert ................................. + equal(ret, "cur2-set1:setval2", + "Two-way tag with bindTo and bindFrom to different paths (0, 1): setValues works"); + + // ................................ Act .................................. + mytag.update("updated1"); + ret = data.current + "-" + data.modified + ":" + linkedElem.value; + + // ............................... Assert ................................. + equal(ret, "cur2-updated1:setval2", + "Two-way tag with bindTo and bindFrom to different paths (0, 1): update() updates bindTo target"); + + // ................................ Act .................................. + mytag.updateValue("updated2"); + ret = data.current + "-" + data.modified + ":" + linkedElem.value; + + // ............................... Assert ................................. + equal(ret, "cur2-updated2:setval2", + "Two-way tag with bindTo and bindFrom to different paths (0, 1): update() updates bindTo target (variant)"); + +// ............................... Reset ................................. + + $("#result").empty(); + + // =============================== Arrange =============================== + var ret, + data = {current: "cur", modified: "mod"}; + + $.templates({ + markup: '{^{mytag modified fm=current/}}', + tags: { + mytag: { + onUpdate: false, + bindTo: 0, + bindFrom: "fm", + linkedElement: "input", + linkedCtxParam: "fm", + template: "", + update: function(val) { + this.updateValue(val); // Update external data, through two-way binding + } + } + } + }).link("#result", data); + + mytag = $.view().childTags()[0]; + var linkedElem = mytag.tagCtx.contents("input")[0]; + + ret = data.current + "-" + data.modified + ":" + linkedElem.value + "-" + $("#result").text(); + + // ............................... Assert ................................. + equal(ret, "cur-mod:-cur", + "Two-way tag with bindTo and bindFrom to different paths ('fm', 0): initial render"); + + // ................................ Act .................................. + $.observable(data).setProperty({current: "cur2"}); + ret = data.current + "-" + data.modified + ":" + linkedElem.value + "-" + $("#result").text(); + + // ............................... Assert ................................. + equal(ret, "cur2-mod:-cur2", + "Two-way tag with bindTo and bindFrom to different paths ('fm', 0): bindFrom binding updates from data"); + + // ................................ Act .................................. + $.observable(data).setProperty({modified: "mod2"}); + ret = data.current + "-" + data.modified + ":" + linkedElem.value + "-" + $("#result").text(); + + // ............................... Assert ................................. + equal(ret, "cur2-mod2:-cur2", + "Two-way tag with bindTo and bindFrom to different paths ('fm', 0): bindTo binding does not update from data"); + + // ................................ Act .................................. + linkedElem.value = "set1"; + $(linkedElem).change(); + ret = data.current + "-" + data.modified + ":" + linkedElem.value + "-" + $("#result").text(); + + // ............................... Assert ................................. + equal(ret, "cur2-set1:set1-cur2", + "Two-way tag with bindTo and bindFrom to different paths ('fm', 0): bindTo binding updates to data - bindFrom binding does not"); + + // ................................ Act .................................. + mytag.setValue("setval", 0, 0); + ret = data.current + "-" + data.modified + ":" + linkedElem.value + "-" + $("#result").text(); + + // ............................... Assert ................................. + equal(ret, "cur2-set1:set1-setval", + "Two-way tag with bindTo and bindFrom to different paths ('fm', 0): setValue sets the bindFrom linkedPrm but not the bindTo linkedElem"); + + // ................................ Act .................................. + mytag.setValues("setval2"); + ret = data.current + "-" + data.modified + ":" + linkedElem.value + "-" + $("#result").text(); + + // ............................... Assert ................................. + equal(ret, "cur2-set1:set1-setval2", + "Two-way tag with bindTo and bindFrom to different paths ('fm', 0): setValues sets the bindFrom linkedPrm but not the bindTo linkedElem"); + + // ................................ Act .................................. + mytag.update("updated1"); + ret = data.current + "-" + data.modified + ":" + linkedElem.value + "-" + $("#result").text(); + + // ............................... Assert ................................. + equal(ret, "cur2-updated1:set1-setval2", + "Two-way tag with bindTo and bindFrom to different paths ('fm', 0): update() updates bindTo target"); + + // ................................ Act .................................. + mytag.updateValue("updated2"); + ret = data.current + "-" + data.modified + ":" + linkedElem.value + "-" + $("#result").text(); + + // ............................... Assert ................................. + equal(ret, "cur2-updated2:set1-setval2", + "Two-way tag with bindTo and bindFrom to different paths ('fm', 0): update() updates bindTo target (variant)"); + +// ............................... Reset ................................. + + $("#result").empty(); + + // =============================== Arrange =============================== + var ret, + data = {current: "cur", modified: "mod", two: 2, title: "Title"}; + + $.templates({ + markup: '{^{mytag modified 1 two fm=current title=title/}}', + tags: { + mytag: { + onUpdate: false, + bindTo: [0, "title"], + bindFrom: ["fm", 1, 2], + linkedElement: ["input", ".title"], + linkedCtxParam: ["fm", undefined, "arg2"], + template: "{^{:~arg2}}", + convert: function(from, one, two) { + return [from + "F", one + "O", two + "T"]; + }, + setValue: function(val, ind, tagElse) { + return val + "V" + ind; + }, + convertBack: function(val, one) { + return [ + val ? val + "V" : undefined, + one ? one + "O" : undefined + ]; + } + } + } + }).link("#result", data); + + mytag = $.view().childTags()[0]; + var linkedElem = mytag.tagCtx.contents("input")[0]; + + ret = data.current + "-" + data.modified + ":" + linkedElem.value + "-" + $("#result").text(); + + // ............................... Assert ................................. + equal(ret, "cur-mod:curFV0-2TV2", + "Two-way tag with bindTo and bindFrom to different paths ('fm', 0) and convert/convertBack: initial render"); + + // ................................ Act .................................. + $.observable(data).setProperty({current: "cur2", two: "two2"}); + ret = data.current + "-" + data.modified + ":" + linkedElem.value + "-" + $("#result").text(); + + // ............................... Assert ................................. + equal(ret, "cur2-mod:cur2FV0-two2TV2", + "Two-way tag with bindTo and bindFrom to different paths ('fm', 0) and convert/convertBack: bindFrom binding updates from data"); + + // ................................ Act .................................. + $.observable(data).setProperty({modified: "mod2"}); + ret = data.current + "-" + data.modified + ":" + linkedElem.value + "-" + $("#result").text(); + + // ............................... Assert ................................. + equal(ret, "cur2-mod2:cur2FV0-two2TV2", + "Two-way tag with bindTo and bindFrom to different paths ('fm', 0) and convert/convertBack: bindTo binding does not update from data"); + + // ................................ Act .................................. + linkedElem.value = "set1"; + $(linkedElem).change(); + ret = data.current + "-" + data.modified + ":" + linkedElem.value + "-" + $("#result").text(); + + // ............................... Assert ................................. + equal(ret, "cur2-set1V:set1-two2TV2", + "Two-way tag with bindTo and bindFrom to different paths ('fm', 0) and convert/convertBack: bindTo binding updates to data - bindFrom binding does not"); + + // ................................ Act .................................. + mytag.setValue("setval", 0, 0); + mytag.setValue("setval2", 2, 0); + ret = data.current + "-" + data.modified + ":" + linkedElem.value + "-" + $("#result").text(); + + // ............................... Assert ................................. + equal(ret, "cur2-set1V:setvalV0-setval2V2", + "Two-way tag with bindTo and bindFrom to different paths ('fm', 0) and convert/convertBack: setValue sets the bindFrom linkedPrm but not the bindTo linkedElem"); + + // ................................ Act .................................. + mytag.setValues("setval3", "setval4", "setval5"); + ret = data.current + "-" + data.modified + ":" + linkedElem.value + "-" + $("#result").text(); + + // ............................... Assert ................................. + equal(ret, "cur2-set1V:setval3V0-setval5V2", + "Two-way tag with bindTo and bindFrom to different paths ('fm', 0) and convert/convertBack: setValues sets the bindFrom linkedPrm but not the bindTo linkedElem"); + + // ................................ Act .................................. + mytag.updateValue("updatedMod2", 0); + mytag.updateValue("updatedTitle2", 1); + ret = data.current + "-" + data.modified + "-" + data.title + ":" + linkedElem.value + "-" + $("#result").text(); + + // ............................... Assert ................................. + equal(ret, "cur2-updatedMod2V-updatedTitle2O:setval3V0-setval5V2", + "Two-way tag with bindTo and bindFrom to different paths ('fm', 0) and convert/convertBack: update() updates bindTo target (variant)"); + + // ................................ Act .................................. + mytag.updateValues("updateMod3", "updateTitle3"); + ret = data.current + "-" + data.modified + "-" + data.title + ":" + linkedElem.value + "-" + $("#result").text(); + + // ............................... Assert ................................. + equal(ret, "cur2-updateMod3V-updateTitle3O:setval3V0-setval5V2", + "Two-way tag with bindTo and bindFrom to different paths ('fm', 0) and convert/convertBack: update() updates bindTo target (variant)"); + // ............................... Reset ................................. $("#result").empty(); @@ -20090,4 +22193,4 @@ test('Custom Tag Controls - two-way binding (multiple targets)', function() { }); -})(this, this.jQuery); +})(this, this.jQuery); \ No newline at end of file