Define Base.equals(), supporting Arrays and Objects.

And use it for style comparisons.
This commit is contained in:
Jürg Lehni 2012-11-04 09:00:40 -08:00
parent 9ec5ad29ef
commit b979c3b362
2 changed files with 36 additions and 13 deletions

41
lib/bootstrap.js vendored
View file

@ -229,6 +229,38 @@ var Base = new function() { // Bootstrap scope
}, new obj.constructor());
}
/**
* Checks if two values or objects are equals to each other, by using their
* equals() methods if available, and also comparing elements of arrays.
*/
function equals(obj1, obj2) {
if (obj1 == obj2 || obj1 != null && obj1.equals && obj1.equals(obj2))
return true;
if (isArray(obj1) && isArray(obj2)) {
if (obj1.length !== obj2.length)
return false;
for (var i = 0, l = obj1.length; i < l; i++) {
if (!Base.equals(obj1, obj2))
return false;
}
return true;
} else if (typeof obj1 === 'object' && typeof obj2 === 'object') {
function checkKeys(o1, o2) {
for (var i in o1)
if (typeof o2[i] === 'undefined')
return false;
return true;
}
if (!checkKeys(obj1, obj2) || !checkKeys(obj2, obj1))
return false;
for (var i in obj1)
if (obj1.hasOwnProperty(i) && !Base.equals(obj1[i], obj2[i]))
return false;
return true;
}
return false;
}
// Inject into new ctor object that's passed to inject(), and then returned
return inject(function() {}, {
inject: function(src/*, ... */) {
@ -284,14 +316,6 @@ var Base = new function() { // Bootstrap scope
// Pass true for enumerable, so inject() and extend() can be passed on
// to subclasses of Base through Base.inject() / extend().
}, true).inject({
/**
* Returns true if the object contains a property with the given name,
* false otherwise.
* Just like in .each, objects only contained in the prototype(s) are
* filtered.
*/
has: has,
/**
* Injects the fields from the given object, adding this.base()
* functionality
@ -330,6 +354,7 @@ var Base = new function() { // Bootstrap scope
// Expose some local privates as Base generics.
each: each,
clone: clone,
equals: equals,
// Base.create does something different from Object.create, it only
// works on constructors and uses their prototype.
create: function(ctor) {

View file

@ -70,7 +70,7 @@ var Style = Item.extend({
};
Base.each(src._defaults, function(value, key) {
var isColor = !!key.match(/Color$/),
var isColor = /Color$/.test(key),
part = Base.capitalize(key),
set = 'set' + part,
get = 'get' + part;
@ -85,8 +85,7 @@ var Style = Item.extend({
children[i][styleKey][set](value);
} else {
var old = this['_' + key];
if (old != value && !(old && old.equals
&& old.equals(value))) {
if (!Base.equals(old, value)) {
if (isColor) {
if (old)
delete old._owner;
@ -115,8 +114,7 @@ var Style = Item.extend({
var childStyle = children[i][styleKey][get]();
if (!style) {
style = childStyle;
} else if (style != childStyle && !(style
&& style.equals && style.equals(childStyle))) {
} else if (!Base.equals(style, childStyle)) {
// If there is another item with a different
// style, the style is not defined:
// PORT: Change this in Scriptographer