|
1 |
| -/*! jquery.views.js v1.0.5: http://jsviews.com/ */ |
| 1 | +/*! jquery.views.js v1.0.6: http://jsviews.com/ */ |
2 | 2 | /*
|
3 | 3 | * Interactive data-driven views using JsRender templates.
|
4 | 4 | * Subcomponent of JsViews
|
|
7 | 7 | * Also requires jquery.observable.js
|
8 | 8 | * See JsObservable at http://jsviews.com/#download and http://github.com/BorisMoore/jsviews
|
9 | 9 | *
|
10 |
| - * Copyright 2019, Boris Moore |
| 10 | + * Copyright 2020, Boris Moore |
11 | 11 | * Released under the MIT License.
|
12 | 12 | */
|
13 | 13 |
|
@@ -44,7 +44,7 @@ var setGlobals = $ === false; // Only set globals if script block in browser (no
|
44 | 44 | jsr = jsr || setGlobals && global.jsrender;
|
45 | 45 | $ = $ || global.jQuery;
|
46 | 46 |
|
47 |
| -var versionNumber = "v1.0.5", |
| 47 | +var versionNumber = "v1.0.6", |
48 | 48 | requiresStr = "JsViews requires ";
|
49 | 49 |
|
50 | 50 | if (!$ || !$.fn) {
|
@@ -1787,7 +1787,8 @@ function bindDataLinkTarget(linkCtx, late) {
|
1787 | 1787 | linkCtx._ctxCb = $sub._gccb(view = linkCtx.view); // getContextCallback: _ctxCb, for filtering/appending to dependency paths: function(path, object) { return [(object|path)*]}
|
1788 | 1788 | linkCtx._hdl = handler;
|
1789 | 1789 | // handler._ctx = linkCtx; Could pass linkCtx for use in a depends = function() {} call, so depends is different for different linkCtx's
|
1790 |
| - if (linkCtx.elem.nodeName === "SELECT" && linkCtxType === "link" && !linkCtx.attr) { |
| 1790 | + if (linkCtx.elem.nodeName === "SELECT" && linkCtxType === "link" && !linkCtx.attr |
| 1791 | + && linkCtx.convert !== undefined) { // data-link expression on <select> tag is the assign tag {:...}, not some other expression such as {on ...} (See https://github.com/BorisMoore/jsviews/issues/444) |
1791 | 1792 | var $elem = $(linkCtx.elem);
|
1792 | 1793 | $elem.on("jsv-domchange", function() {
|
1793 | 1794 | // If the options have changed dynamically under the select, we need to refresh the data-linked selection, using the new options
|
@@ -2040,8 +2041,10 @@ function callAfterLink(tag, ev, eventArgs) {
|
2040 | 2041 | props = tag.cvtArgs(m, 1); // array of bindFrom args/props
|
2041 | 2042 | l = props.length;
|
2042 | 2043 | while (l--) {
|
2043 |
| - val = props[l]; |
2044 |
| - tag.setValue(val, l, m); |
| 2044 | + // If the bound property or arg has not yet been set (e.g. during initial rendering), |
| 2045 | + // or has been unset, because onUpdate is set to true, or if onUpdate is false, |
| 2046 | + // but this particular bound arg/prop is being changed observably: call setValue() |
| 2047 | + tag.setValue(props[l], l, m, ev, eventArgs); |
2045 | 2048 | }
|
2046 | 2049 | if (tag._.unlinked) {
|
2047 | 2050 | tagCtx = tagCtxs[m];
|
@@ -2595,10 +2598,12 @@ function updateValue(val, index, tagElse, async, bindId, ev) {
|
2595 | 2598 | }
|
2596 | 2599 |
|
2597 | 2600 | function setValues() {
|
2598 |
| -// tagCtx.setValues() calls tag.setValue() on that tagCtx for each bindTo target |
2599 |
| - var m = arguments.length; |
| 2601 | + // tagCtx.setValues() calls tag.setValue() on that tagCtx for each bindTo target |
| 2602 | + var m = this.tag.bindTo.length, |
| 2603 | + ev = arguments[m], |
| 2604 | + eventArgs = arguments[m+1]; |
2600 | 2605 | while (m--) {
|
2601 |
| - this.tag.setValue(arguments[m], m, this.index); |
| 2606 | + this.tag.setValue(arguments[m], m, this.index, ev, eventArgs); |
2602 | 2607 | }
|
2603 | 2608 | }
|
2604 | 2609 |
|
@@ -2726,20 +2731,30 @@ function addLinkMethods(tagOrView) { // tagOrView is View prototype or tag insta
|
2726 | 2731 | theTag.constructor.prototype.setValue || function(val) { // base method
|
2727 | 2732 | return val;
|
2728 | 2733 | },
|
2729 |
| - function(val, indexFrom, tagElse) { |
| 2734 | + function(val, indexFrom, tagElse, ev, eventArgs) { |
2730 | 2735 | indexFrom = indexFrom || 0;
|
2731 | 2736 | tagElse = tagElse || 0;
|
2732 | 2737 |
|
2733 |
| - var linkedElem, linkedEl, linkedCtxParam, linkedCtxPrmKey, indexTo, linkedElems, |
2734 |
| - tagCtx = theTag.tagCtxs[tagElse], |
2735 |
| - newVal = theTag.base.call(theTag, val, indexFrom, tagElse); |
| 2738 | + var linkedElem, linkedEl, linkedCtxParam, linkedCtxPrmKey, indexTo, linkedElems, newVal, |
| 2739 | + tagCtx = theTag.tagCtxs[tagElse]; |
2736 | 2740 |
|
2737 |
| - if (newVal !== undefined) { // Call tag method tag.setValue(), if implemented |
2738 |
| - val = newVal; |
| 2741 | + if ((eventArgs || val !== undefined) && tagCtx._bdArgs && tagCtx._bdArgs[indexFrom]===val) { |
| 2742 | + if (tagCtx._bdVals) { // If val is not undefined (or is coming from an observable change event), and is a value that was already returned, use stored value and don't call tag.setValue() |
| 2743 | + val = tagCtx._bdVals[indexFrom]; |
| 2744 | + } |
| 2745 | + } else { |
| 2746 | + // Call tag method tag.setValue(), if implemented |
| 2747 | + tagCtx._bdArgs = tagCtx._bdArgs || []; |
| 2748 | + tagCtx._bdArgs[indexFrom] = val; |
| 2749 | + newVal = theTag.base.call(theTag, val, indexFrom, tagElse, ev, eventArgs); |
| 2750 | + if (newVal !== undefined) { |
| 2751 | + tagCtx._bdVals = tagCtx._bdVals || []; |
| 2752 | + tagCtx._bdVals[indexFrom] = newVal; // store value, so that if same value is called later we'll use the stored value, and won't call tag.setValue() |
| 2753 | + val = newVal; |
| 2754 | + } |
2739 | 2755 | }
|
2740 |
| - if (val !== undefined && (theTag.convert || theTag._.toIndex[indexFrom] === undefined) |
2741 |
| - && (linkedCtxParam = theTag.linkedCtxParam) |
2742 |
| - && linkedCtxParam[indexFrom] |
| 2756 | + |
| 2757 | + if (val !== undefined && (linkedCtxParam = theTag.linkedCtxParam) && linkedCtxParam[indexFrom] |
2743 | 2758 | // If this setValue call corresponds to a tag contextual parameter and the tag has a converter, then we need to set the
|
2744 | 2759 | // value of this contextual parameter (since it is not directly bound to the tag argument/property when there is a converter).
|
2745 | 2760 | && (linkedCtxPrmKey = linkedCtxParam[indexFrom])
|
@@ -2970,10 +2985,14 @@ function addLinkMethods(tagOrView) { // tagOrView is View prototype or tag insta
|
2970 | 2985 | return RegExp("^(.*)(" + (str ? "\\/" : "#") + itemView._.id + "_.*)$").exec(str || itemView._prv.getAttribute(jsvAttrStr));
|
2971 | 2986 | }
|
2972 | 2987 | function setPrv(itemView, tokens) {
|
2973 |
| - var prv = itemView._prv; |
| 2988 | + var tag, |
| 2989 | + prv = itemView._prv; |
2974 | 2990 | prv.setAttribute(jsvAttrStr, tokens);
|
2975 | 2991 | tokens.replace(rTagMarkers, function(all, open, close, id) {
|
2976 |
| - bindingStore[id].linkCtx.tag[open ? "_prv" : "_nxt"] = prv; |
| 2992 | + tag = bindingStore[id].linkCtx.tag; |
| 2993 | + if (tag.inline) { |
| 2994 | + tag[open ? "_prv" : "_nxt"] = prv; |
| 2995 | + } |
2977 | 2996 | });
|
2978 | 2997 | tokens.replace(rViewMarkers, function(all, open, close, id) {
|
2979 | 2998 | viewStore[id][open ? "_prv" : "_nxt"] = prv;
|
|
0 commit comments