Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

* Allow trigger values both given to #set and transformed via onChange.

* Respected _shared flag and only reference those objects. Allow outside mutation
* Make journal skip trigger values when resetting to previous value
* Fix a bug in _watcher helper and make it use _callback too
  • Loading branch information...
commit 65a93654b892cdb72a3257c6a5e5ed52566b6f29 1 parent 1f71f89
Yaroslaff Fedin authored
View
15 Source/Object/Journal.js
@@ -146,10 +146,17 @@ LSD.Journal.prototype.unset = function(key, value, memo, prepend, hash) {
if (j == -1) return
}
}
- if (length > 1 && (value == null || !value[this._trigger])) {
- var method = '_set';
- value = group[length - 2];
- } else var method = '_unset';
+ if (length > 1) {
+ if (value != null && value[this._trigger]) {
+ this._unscript(key, value, memo, index, hash);
+ if (--length === 1) return true;
+ }
+ var val = group[length - 2];
+ if (val == null || !val[this._trigger]) {
+ var method = '_set';
+ value = val;
+ }
+ }
}
if (method !== '_set' || value != this[key])
return this[method || '_unset'](key, value, memo, index, hash);
View
35 Source/Object/Object.js
@@ -59,6 +59,15 @@ LSD.Object.prototype.set = function(key, value, memo, index, hash) {
if (hash == null && typeof index != 'number') index = key.indexOf('.');
if (index > -1) return this.mix(key, value, memo, undefined, null, null, null, index);
/*
+ Objects accept special kind of values, compiled LSD.Script expressions.
+ They may use other keys in the object as observable variables, call
+ functions and iterate data. Script updates value for the key when it
+ computes its value asynchronously. The value stays undefined, while the
+ script doesn't have enough data to compute.
+*/
+ var nonscript = nonenum === true || value == null || (this._literal && this._literal[key]);
+ if (!nonscript && value[this._trigger] != null) return this._script(key, value, memo);
+/*
`hash` argument may disable all mutation caused by the setter, the value by
the key will not be mofified. May be used by subclasses to implement its
own mechanism of object mutations.
@@ -75,8 +84,7 @@ LSD.Object.prototype.set = function(key, value, memo, index, hash) {
writing a link (e.g. Arrays dont write a link to its object values, and DOM
elements dont let any objects write a link either).
*/
- if (nonenum !== true && value != null && !value._owner
- && value._set && this._owning !== false)
+ if (nonenum !== true && value != null && !value._owner && value._set && this._owning !== false)
if (memo !== 'reference') {
if (value._ownable !== false) value._set('_owner', this);
} else value._references = (value._references || 0) + 1;
@@ -98,16 +106,13 @@ LSD.Object.prototype.set = function(key, value, memo, index, hash) {
if (hash == null) this[key] = old;
return;
} else value = changed;
+ }
/*
- Objects accept special kind of values, compiled LSD.Script expressions.
- They may use other keys in the object as observable variables, call
- functions and iterate data. Script updates value for the key when it
- computes its value asynchronously. The value stays undefined, while the
- script doesn't have enough data to compute.
+ Global object listeners (and so custom property handlers in structs)
+ may compile given value into expression (e.g. a textnode may find
+ interpolations in a given `textContent`).
*/
- }
- if (nonenum !== true && nonenum !== true && value != null
- && value[this._trigger] != null && (!this._literal || !this._literal[key])) {
+ if (!nonscript && value != null && value[this._trigger] != null) {
if (hash == null) this[key] = old;
return this._script(key, value, memo);
}
@@ -408,7 +413,8 @@ LSD.Object.prototype.mix = function(key, value, memo, old, merge, prepend, lazy,
creating a new object that is subscribed to all values and changes of a
referenced object.
*/
- if (vdef && old !== obj && (parent ? parent !== this : obj._references > 0) && this._owning !== false) {
+ if (vdef && old !== obj && this._owning !== false && obj._shared !== true
+ && (parent ? parent !== this : obj._references > 0)) {
obj = this._construct(name, null, 'copy')
} else if (typeof obj.mix == 'function' && obj._ownable !== false) {
obj.mix(subkey, value, memo, old, merge, prepend, lazy);
@@ -503,7 +509,7 @@ LSD.Object.prototype.mix = function(key, value, memo, old, merge, prepend, lazy,
if (vdef) this.set(key, value, memo, prepend);
if (odef && (!vdef || this._journal)) this.unset(key, old, memo, prepend);
} else if (vdef && obj !== old && (obj._owner ? obj._owner !== this : obj._references > 0)
- && this._owning !== false && (!memo || !memo._delegate)) {
+ && this._owning !== false && (!memo || !memo._delegate) && obj._shared !== true) {
obj = this._construct(key, null, 'copy')
} else {
/*
@@ -810,10 +816,13 @@ LSD.Object.prototype._watcher = function(call, key, value, old, memo) {
dot = call.key.indexOf('.', start)
if (object && object._watch) {
object[i ? '_watch' : '_unwatch'](call.key.substring(start), call.callback, call.lazy);
+ break;
} else {
var subkey = call.key.substring(start, dot == -1 ? call.key.length : dot);
if (typeof (object = object[subkey]) == 'undefined') break;
- if (dot == -1) call.callback(object);
+ if (dot == -1)
+ if (typeof call.callback == 'function') call.callback(object);
+ else this._callback(call.callback, key, object, undefined, memo);
}
}
}
View
7 Source/Properties/Attributes.js
@@ -32,14 +32,14 @@ LSD.Properties.Attributes.prototype.onChange = function(key, value, memo, old) {
if (attribute) {
if (typeof attribute == 'string') {
this._owner.mix(attribute, value, memo, old);
- } else if (value && !value.Script){
+ } else if (value){
var result = attribute.call(this._owner, value, old);
if (typeof result != 'undefined') value = result;
}
}
if (this._owner.element && (key != 'type' || LSD.toLowerCase(this._owner.element.tagName) != 'input')) {
this._owner.element[key] = vdef;
- if (vdef && !value.script) this._owner.element.setAttribute(key, value === true ? key : value);
+ if (vdef) this._owner.element.setAttribute(key, value === true ? key : value);
else this._owner.element.removeAttribute(key);
}
if (((!memo || memo !== 'states') && ns.states[key]) || this._owner.__properties[key])
@@ -56,7 +56,7 @@ LSD.Properties.Microdata.prototype.onChange = function(key, value, memo, old) {
if (!this._elements) return;
var element = this._elements[key];
var storage = this._values;
- if (!storage) storage = this.values = {};
+ if (!storage) storage = this._values = {};
if (odef && old !== storage[key]) odef = old = undefined;
if (typeof storage[key] == 'undefined' ? !vdef || value === element.nodeValue : !odef) return;
if (vdef) storage[key] = value;
@@ -64,6 +64,7 @@ LSD.Properties.Microdata.prototype.onChange = function(key, value, memo, old) {
}
}
LSD.Properties.Microdata.prototype._trigger = 'lsd';
+LSD.Properties.Microdata.prototype._shared = true;
LSD.Properties.Microdata.prototype._script = function(key, value, memo) {
var storage = this._elements;
if (!storage) storage = this._elements = {};
View
9 Source/Properties/Styles.js
@@ -653,6 +653,10 @@ LSD.Styles.Parser = new LSD.RegExp({
}
return unit ? {number: num, unit: unit} : num;
},
+ /*
+ Url is an specific case of a function that does not require its argument
+ be escaped with quotes.
+ */
url: function(type, path) {
var obj = {};
var first = path.charAt(0), length = path.length;
@@ -661,6 +665,11 @@ LSD.Styles.Parser = new LSD.RegExp({
obj[type] = path
return obj;
},
+ /*
+ Values may constitute a list when separated with whitespaces or commas.
+ Either way makes an array of values. A whitespace separated value inside
+ of a comma separated value makes a nested array.
+ */
separator: function(character) {
switch (character) {
case ',':
Please sign in to comment.
Something went wrong with that request. Please try again.