Skip to content

Commit 9b06116

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

29 files changed

+1068
-708
lines changed

MIT-LICENSE.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright (c) 2019 Boris Moore https://github.com/BorisMoore/jsviews
1+
Copyright (c) 2020 Boris Moore https://github.com/BorisMoore/jsviews
22

33
Permission is hereby granted, free of charge, to any person obtaining
44
a copy of this software and associated documentation files (the

jquery.observable.js

+34-33
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
/*! JsObservable v1.0.5: http://jsviews.com/#jsobservable */
1+
/*! JsObservable v1.0.6: http://jsviews.com/#jsobservable */
22
/*
33
* Subcomponent of JsViews
44
* Data change events for data-linking
55
*
6-
* Copyright 2019, Boris Moore
6+
* Copyright 2020, Boris Moore
77
* Released under the MIT License.
88
*/
99

@@ -44,7 +44,7 @@ if (!$ || !$.fn) {
4444
throw "JsObservable requires jQuery"; // We require jQuery
4545
}
4646

47-
var versionNumber = "v1.0.5",
47+
var versionNumber = "v1.0.6",
4848
_ocp = "_ocp", // Observable contextual parameter
4949
$observe, $observable,
5050

@@ -452,7 +452,7 @@ if (!$.observe) {
452452
object = arr;
453453
if (relPath) {
454454
object = arr[relPath];
455-
allPath += "." + relPath;
455+
allPath = allPath ? allPath + "." + relPath : allPath;
456456
}
457457
if (filter && object) {
458458
object = $observable._fltr(allPath, object, relPath ? [arr].concat(parentObs) : parentObs, filter);
@@ -960,40 +960,41 @@ if (!$.observe) {
960960
var setter, getter, removeProp, eventArgs, view,
961961
property = path ? leaf[path] : leaf;
962962

963-
if ($isFunction(property) && property.set) {
964-
// Case of property setter/getter - with convention that property is getter and property.set is setter
965-
view = leaf._vw // Case of JsViews 2-way data-linking to an observable context parameter, with a setter.
966-
// The view will be the this pointer for getter and setter. Note: this is the one scenario where path is "".
967-
|| leaf;
968-
getter = property;
969-
setter = getter.set === true ? getter : getter.set;
970-
property = getter.call(view); // get - only treated as getter if also a setter. Otherwise it is simply a property of type function.
971-
// See unit tests 'Can observe properties of type function'.
972-
}
963+
if (property !== value || nonStrict && property != value) {
964+
if ($isFunction(property) && property.set) {
965+
// Case of property setter/getter - with convention that property is getter and property.set is setter
966+
view = leaf._vw // Case of JsViews 2-way data-linking to an observable context parameter, with a setter.
967+
// The view will be the this pointer for getter and setter. Note: this is the one scenario where path is "".
968+
|| leaf;
969+
getter = property;
970+
setter = getter.set === true ? getter : getter.set;
971+
property = getter.call(view); // get - only treated as getter if also a setter. Otherwise it is simply a property of type function.
972+
// See unit tests 'Can observe properties of type function'.
973+
}
973974

974-
if ((property !== value || nonStrict && property != value)
975975
// Optional non-strict equality, since serializeArray, and form-based editors can map numbers to strings, etc.
976976
// Date objects don't support != comparison. Treat as special case.
977-
&& (!(property instanceof Date && value instanceof Date) || property > value || property < value)) {
978-
if (setter) {
979-
setter.call(view, value); // set
980-
value = getter.call(view); // get updated value
981-
} else if (removeProp = value === remove) {
982-
if (property !== undefined) {
983-
delete leaf[path];
984-
value = undefined;
985-
} else {
986-
path = undefined; // If value was already undefined, don't trigger handler for removeProp
977+
if (!(property instanceof Date && value instanceof Date) || property > value || property < value) {
978+
if (setter) {
979+
setter.call(view, value); // set
980+
value = getter.call(view); // get updated value
981+
} else if (removeProp = value === remove) {
982+
if (property !== undefined) {
983+
delete leaf[path];
984+
value = undefined;
985+
} else {
986+
path = undefined; // If value was already undefined, don't trigger handler for removeProp
987+
}
988+
} else if (path) {
989+
leaf[path] = value;
987990
}
988-
} else if (path) {
989-
leaf[path] = value;
990-
}
991-
if (path) {
992-
eventArgs = {change: "set", path: path, value: value, oldValue: property, remove: removeProp};
993-
if (leaf._ocp) {
994-
eventArgs.ctxPrm = leaf._key;
991+
if (path) {
992+
eventArgs = {change: "set", path: path, value: value, oldValue: property, remove: removeProp};
993+
if (leaf._ocp) {
994+
eventArgs.ctxPrm = leaf._key;
995+
}
996+
this._trigger(leaf, eventArgs);
995997
}
996-
this._trigger(leaf, eventArgs);
997998
}
998999
}
9991000
},

jquery.observable.min.js

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

jquery.observable.min.js.map

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

jquery.views.js

+39-20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*! jquery.views.js v1.0.5: http://jsviews.com/ */
1+
/*! jquery.views.js v1.0.6: http://jsviews.com/ */
22
/*
33
* Interactive data-driven views using JsRender templates.
44
* Subcomponent of JsViews
@@ -7,7 +7,7 @@
77
* Also requires jquery.observable.js
88
* See JsObservable at http://jsviews.com/#download and http://github.com/BorisMoore/jsviews
99
*
10-
* Copyright 2019, Boris Moore
10+
* Copyright 2020, Boris Moore
1111
* Released under the MIT License.
1212
*/
1313

@@ -44,7 +44,7 @@ var setGlobals = $ === false; // Only set globals if script block in browser (no
4444
jsr = jsr || setGlobals && global.jsrender;
4545
$ = $ || global.jQuery;
4646

47-
var versionNumber = "v1.0.5",
47+
var versionNumber = "v1.0.6",
4848
requiresStr = "JsViews requires ";
4949

5050
if (!$ || !$.fn) {
@@ -1787,7 +1787,8 @@ function bindDataLinkTarget(linkCtx, late) {
17871787
linkCtx._ctxCb = $sub._gccb(view = linkCtx.view); // getContextCallback: _ctxCb, for filtering/appending to dependency paths: function(path, object) { return [(object|path)*]}
17881788
linkCtx._hdl = handler;
17891789
// 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)
17911792
var $elem = $(linkCtx.elem);
17921793
$elem.on("jsv-domchange", function() {
17931794
// 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) {
20402041
props = tag.cvtArgs(m, 1); // array of bindFrom args/props
20412042
l = props.length;
20422043
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);
20452048
}
20462049
if (tag._.unlinked) {
20472050
tagCtx = tagCtxs[m];
@@ -2595,10 +2598,12 @@ function updateValue(val, index, tagElse, async, bindId, ev) {
25952598
}
25962599

25972600
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];
26002605
while (m--) {
2601-
this.tag.setValue(arguments[m], m, this.index);
2606+
this.tag.setValue(arguments[m], m, this.index, ev, eventArgs);
26022607
}
26032608
}
26042609

@@ -2726,20 +2731,30 @@ function addLinkMethods(tagOrView) { // tagOrView is View prototype or tag insta
27262731
theTag.constructor.prototype.setValue || function(val) { // base method
27272732
return val;
27282733
},
2729-
function(val, indexFrom, tagElse) {
2734+
function(val, indexFrom, tagElse, ev, eventArgs) {
27302735
indexFrom = indexFrom || 0;
27312736
tagElse = tagElse || 0;
27322737

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];
27362740

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+
}
27392755
}
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]
27432758
// If this setValue call corresponds to a tag contextual parameter and the tag has a converter, then we need to set the
27442759
// value of this contextual parameter (since it is not directly bound to the tag argument/property when there is a converter).
27452760
&& (linkedCtxPrmKey = linkedCtxParam[indexFrom])
@@ -2970,10 +2985,14 @@ function addLinkMethods(tagOrView) { // tagOrView is View prototype or tag insta
29702985
return RegExp("^(.*)(" + (str ? "\\/" : "#") + itemView._.id + "_.*)$").exec(str || itemView._prv.getAttribute(jsvAttrStr));
29712986
}
29722987
function setPrv(itemView, tokens) {
2973-
var prv = itemView._prv;
2988+
var tag,
2989+
prv = itemView._prv;
29742990
prv.setAttribute(jsvAttrStr, tokens);
29752991
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+
}
29772996
});
29782997
tokens.replace(rViewMarkers, function(all, open, close, id) {
29792998
viewStore[id][open ? "_prv" : "_nxt"] = prv;

jquery.views.min.js

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

jquery.views.min.js.map

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

jsrender.js

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
/*! JsRender v1.0.5: http://jsviews.com/#jsrender */
1+
/*! JsRender v1.0.6: http://jsviews.com/#jsrender */
22
/*! **VERSION FOR WEB** (For NODE.JS see http://jsviews.com/download/jsrender-node.js) */
33
/*
44
* Best-of-breed templating in browser or on Node.js.
55
* Does not require jQuery, or HTML DOM
66
* Integrates with JsViews (http://jsviews.com/#jsviews)
77
*
8-
* Copyright 2019, Boris Moore
8+
* Copyright 2020, Boris Moore
99
* Released under the MIT License.
1010
*/
1111

@@ -44,7 +44,7 @@ var setGlobals = $ === false; // Only set globals if script block in browser (no
4444

4545
$ = $ && $.fn ? $ : global.jQuery; // $ is jQuery passed in by CommonJS loader (Browserify), or global jQuery.
4646

47-
var versionNumber = "v1.0.5",
47+
var versionNumber = "v1.0.6",
4848
jsvStoreName, rTag, rTmplString, topView, $views, $expando,
4949
_ocp = "_ocp", // Observable contextual parameter
5050

@@ -476,9 +476,7 @@ function contextParameter(key, value, get) {
476476
: res[1](res[0].data, res[0], $sub) // = fn(data, view, $sub) for compiled binding expression
477477
: res[0]._ocp; // Observable contextual parameter (uninitialized, or initialized as static expression, so no path dependencies)
478478
if (isUpdate) {
479-
if (res && newRes !== value) {
480-
$sub._ucp(key, value, storeView, obsCtxPrm); // Update observable contextual parameter
481-
}
479+
$sub._ucp(key, value, storeView, obsCtxPrm); // Update observable contextual parameter
482480
return storeView;
483481
}
484482
res = newRes;

jsrender.min.js

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

jsrender.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)