Skip to content

Commit 813541c

Browse files
committed
Commit v1.0.6
Some minor bug fixes, including: - BorisMoore/jsviews#444 linking of selected value on select element does not work correctly with all jquery versions - BorisMoore/jsviews#442 for tag with range and data-linked tr give error when removing object from array - BorisMoore/jsviews#440 linked tag property changed handler called when it shouldn't - BorisMoore/jsviews#439 observable ev.data.observeAll helper broken when path is "*" Small corrections or improvements to documentation and some additional unit tests...
1 parent 61e01ed commit 813541c

File tree

74 files changed

+1247
-870
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+1247
-870
lines changed

_src/jquery.observable.js

+31-30
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ if (!$.observe) {
367367
object = arr;
368368
if (relPath) {
369369
object = arr[relPath];
370-
allPath += "." + relPath;
370+
allPath = allPath ? allPath + "." + relPath : allPath;
371371
}
372372
if (filter && object) {
373373
object = $observable._fltr(allPath, object, relPath ? [arr].concat(parentObs) : parentObs, filter);
@@ -875,40 +875,41 @@ if (!$.observe) {
875875
var setter, getter, removeProp, eventArgs, view,
876876
property = path ? leaf[path] : leaf;
877877

878-
if ($isFunction(property) && property.set) {
879-
// Case of property setter/getter - with convention that property is getter and property.set is setter
880-
view = leaf._vw // Case of JsViews 2-way data-linking to an observable context parameter, with a setter.
881-
// The view will be the this pointer for getter and setter. Note: this is the one scenario where path is "".
882-
|| leaf;
883-
getter = property;
884-
setter = getter.set === true ? getter : getter.set;
885-
property = getter.call(view); // get - only treated as getter if also a setter. Otherwise it is simply a property of type function.
886-
// See unit tests 'Can observe properties of type function'.
887-
}
878+
if (property !== value || nonStrict && property != value) {
879+
if ($isFunction(property) && property.set) {
880+
// Case of property setter/getter - with convention that property is getter and property.set is setter
881+
view = leaf._vw // Case of JsViews 2-way data-linking to an observable context parameter, with a setter.
882+
// The view will be the this pointer for getter and setter. Note: this is the one scenario where path is "".
883+
|| leaf;
884+
getter = property;
885+
setter = getter.set === true ? getter : getter.set;
886+
property = getter.call(view); // get - only treated as getter if also a setter. Otherwise it is simply a property of type function.
887+
// See unit tests 'Can observe properties of type function'.
888+
}
888889

889-
if ((property !== value || nonStrict && property != value)
890890
// Optional non-strict equality, since serializeArray, and form-based editors can map numbers to strings, etc.
891891
// Date objects don't support != comparison. Treat as special case.
892-
&& (!(property instanceof Date && value instanceof Date) || property > value || property < value)) {
893-
if (setter) {
894-
setter.call(view, value); // set
895-
value = getter.call(view); // get updated value
896-
} else if (removeProp = value === remove) {
897-
if (property !== undefined) {
898-
delete leaf[path];
899-
value = undefined;
900-
} else {
901-
path = undefined; // If value was already undefined, don't trigger handler for removeProp
892+
if (!(property instanceof Date && value instanceof Date) || property > value || property < value) {
893+
if (setter) {
894+
setter.call(view, value); // set
895+
value = getter.call(view); // get updated value
896+
} else if (removeProp = value === remove) {
897+
if (property !== undefined) {
898+
delete leaf[path];
899+
value = undefined;
900+
} else {
901+
path = undefined; // If value was already undefined, don't trigger handler for removeProp
902+
}
903+
} else if (path) {
904+
leaf[path] = value;
902905
}
903-
} else if (path) {
904-
leaf[path] = value;
905-
}
906-
if (path) {
907-
eventArgs = {change: "set", path: path, value: value, oldValue: property, remove: removeProp};
908-
if (leaf._ocp) {
909-
eventArgs.ctxPrm = leaf._key;
906+
if (path) {
907+
eventArgs = {change: "set", path: path, value: value, oldValue: property, remove: removeProp};
908+
if (leaf._ocp) {
909+
eventArgs.ctxPrm = leaf._key;
910+
}
911+
this._trigger(leaf, eventArgs);
910912
}
911-
this._trigger(leaf, eventArgs);
912913
}
913914
}
914915
},

_src/jquery.views.js

+36-17
Original file line numberDiff line numberDiff line change
@@ -1697,7 +1697,8 @@ function bindDataLinkTarget(linkCtx, late) {
16971697
linkCtx._ctxCb = $sub._gccb(view = linkCtx.view); // getContextCallback: _ctxCb, for filtering/appending to dependency paths: function(path, object) { return [(object|path)*]}
16981698
linkCtx._hdl = handler;
16991699
// handler._ctx = linkCtx; Could pass linkCtx for use in a depends = function() {} call, so depends is different for different linkCtx's
1700-
if (linkCtx.elem.nodeName === "SELECT" && linkCtxType === "link" && !linkCtx.attr) {
1700+
if (linkCtx.elem.nodeName === "SELECT" && linkCtxType === "link" && !linkCtx.attr
1701+
&& 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)
17011702
var $elem = $(linkCtx.elem);
17021703
$elem.on("jsv-domchange", function() {
17031704
// If the options have changed dynamically under the select, we need to refresh the data-linked selection, using the new options
@@ -1950,8 +1951,10 @@ function callAfterLink(tag, ev, eventArgs) {
19501951
props = tag.cvtArgs(m, 1); // array of bindFrom args/props
19511952
l = props.length;
19521953
while (l--) {
1953-
val = props[l];
1954-
tag.setValue(val, l, m);
1954+
// If the bound property or arg has not yet been set (e.g. during initial rendering),
1955+
// or has been unset, because onUpdate is set to true, or if onUpdate is false,
1956+
// but this particular bound arg/prop is being changed observably: call setValue()
1957+
tag.setValue(props[l], l, m, ev, eventArgs);
19551958
}
19561959
if (tag._.unlinked) {
19571960
tagCtx = tagCtxs[m];
@@ -2510,10 +2513,12 @@ function updateValue(val, index, tagElse, async, bindId, ev) {
25102513
}
25112514

25122515
function setValues() {
2513-
// tagCtx.setValues() calls tag.setValue() on that tagCtx for each bindTo target
2514-
var m = arguments.length;
2516+
// tagCtx.setValues() calls tag.setValue() on that tagCtx for each bindTo target
2517+
var m = this.tag.bindTo.length,
2518+
ev = arguments[m],
2519+
eventArgs = arguments[m+1];
25152520
while (m--) {
2516-
this.tag.setValue(arguments[m], m, this.index);
2521+
this.tag.setValue(arguments[m], m, this.index, ev, eventArgs);
25172522
}
25182523
}
25192524

@@ -2641,20 +2646,30 @@ function addLinkMethods(tagOrView) { // tagOrView is View prototype or tag insta
26412646
theTag.constructor.prototype.setValue || function(val) { // base method
26422647
return val;
26432648
},
2644-
function(val, indexFrom, tagElse) {
2649+
function(val, indexFrom, tagElse, ev, eventArgs) {
26452650
indexFrom = indexFrom || 0;
26462651
tagElse = tagElse || 0;
26472652

2648-
var linkedElem, linkedEl, linkedCtxParam, linkedCtxPrmKey, indexTo, linkedElems,
2649-
tagCtx = theTag.tagCtxs[tagElse],
2650-
newVal = theTag.base.call(theTag, val, indexFrom, tagElse);
2653+
var linkedElem, linkedEl, linkedCtxParam, linkedCtxPrmKey, indexTo, linkedElems, newVal,
2654+
tagCtx = theTag.tagCtxs[tagElse];
26512655

2652-
if (newVal !== undefined) { // Call tag method tag.setValue(), if implemented
2653-
val = newVal;
2656+
if ((eventArgs || val !== undefined) && tagCtx._bdArgs && tagCtx._bdArgs[indexFrom]===val) {
2657+
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()
2658+
val = tagCtx._bdVals[indexFrom];
2659+
}
2660+
} else {
2661+
// Call tag method tag.setValue(), if implemented
2662+
tagCtx._bdArgs = tagCtx._bdArgs || [];
2663+
tagCtx._bdArgs[indexFrom] = val;
2664+
newVal = theTag.base.call(theTag, val, indexFrom, tagElse, ev, eventArgs);
2665+
if (newVal !== undefined) {
2666+
tagCtx._bdVals = tagCtx._bdVals || [];
2667+
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()
2668+
val = newVal;
2669+
}
26542670
}
2655-
if (val !== undefined && (theTag.convert || theTag._.toIndex[indexFrom] === undefined)
2656-
&& (linkedCtxParam = theTag.linkedCtxParam)
2657-
&& linkedCtxParam[indexFrom]
2671+
2672+
if (val !== undefined && (linkedCtxParam = theTag.linkedCtxParam) && linkedCtxParam[indexFrom]
26582673
// If this setValue call corresponds to a tag contextual parameter and the tag has a converter, then we need to set the
26592674
// value of this contextual parameter (since it is not directly bound to the tag argument/property when there is a converter).
26602675
&& (linkedCtxPrmKey = linkedCtxParam[indexFrom])
@@ -2885,10 +2900,14 @@ function addLinkMethods(tagOrView) { // tagOrView is View prototype or tag insta
28852900
return RegExp("^(.*)(" + (str ? "\\/" : "#") + itemView._.id + "_.*)$").exec(str || itemView._prv.getAttribute(jsvAttrStr));
28862901
}
28872902
function setPrv(itemView, tokens) {
2888-
var prv = itemView._prv;
2903+
var tag,
2904+
prv = itemView._prv;
28892905
prv.setAttribute(jsvAttrStr, tokens);
28902906
tokens.replace(rTagMarkers, function(all, open, close, id) {
2891-
bindingStore[id].linkCtx.tag[open ? "_prv" : "_nxt"] = prv;
2907+
tag = bindingStore[id].linkCtx.tag;
2908+
if (tag.inline) {
2909+
tag[open ? "_prv" : "_nxt"] = prv;
2910+
}
28922911
});
28932912
tokens.replace(rViewMarkers, function(all, open, close, id) {
28942913
viewStore[id][open ? "_prv" : "_nxt"] = prv;

_src/jsrender-node-starter/package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jsrender-node-starter",
3-
"version": "1.0.5",
3+
"version": "1.0.6",
44
"description": "Starter app for JsRender server-rendered templates on Node.js using Express 4 or Hapi, and optionally Browserify and JsRenderify",
55
"main": "index-express.js",
66
"scripts": {
@@ -21,8 +21,8 @@
2121
"@hapi/inert": "^5.2.1",
2222
"@hapi/vision": "^5.5.2",
2323
"jquery": "^3.4.1",
24-
"jsrender": "^1.0.5",
25-
"jsviews": "^1.0.5",
24+
"jsrender": "^1.0.6",
25+
"jsviews": "^1.0.6",
2626
"serve-favicon": "^2.5.0",
2727
"through2": "^3.0.1"
2828
},

_src/jsrender.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -426,9 +426,7 @@ function contextParameter(key, value, get) {
426426
: res[1](res[0].data, res[0], $sub) // = fn(data, view, $sub) for compiled binding expression
427427
: res[0]._ocp; // Observable contextual parameter (uninitialized, or initialized as static expression, so no path dependencies)
428428
if (isUpdate) {
429-
if (res && newRes !== value) {
430-
$sub._ucp(key, value, storeView, obsCtxPrm); // Update observable contextual parameter
431-
}
429+
$sub._ucp(key, value, storeView, obsCtxPrm); // Update observable contextual parameter
432430
return storeView;
433431
}
434432
res = newRes;

_src/jsrender/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jsrender",
3-
"version": "v1.0.5",
3+
"version": "v1.0.6",
44
"description": "Best-of-breed templating in browser or on Node.js (with Express 4, Hapi and Browserify integration)",
55
"main": "./jsrender-node.js",
66
"browser": "./jsrender.js",

_src/jsviews/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jsviews",
3-
"version": "v1.0.5",
3+
"version": "v1.0.6",
44
"description": "Next-generation MVVM and MVP framework - built on top of JsRender templates. Bringing templates to life...",
55
"main": "./jsviews.js",
66
"author": {
@@ -35,7 +35,7 @@
3535
"browserify": "^11.0.1",
3636
"glob-stream": "^5.0.0",
3737
"gulp": "^3.9.0",
38-
"jsrender": "^1.0.5",
38+
"jsrender": "^1.0.6",
3939
"qunit": "^0.7.6"
4040
},
4141
"dependencies": {

documentation/contents-download.js

+5-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

documentation/contents-download.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

documentation/contents-download.min.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)