Introduce Base.filter(), to copy and filter object properties.

This commit is contained in:
Jürg Lehni 2016-02-12 19:58:32 +01:00
parent 5ec5c265ac
commit 6d5d1ce077
3 changed files with 48 additions and 23 deletions

View file

@ -76,24 +76,9 @@ Base.inject(/** @lends Base# */{
* Base.isPlainObject() check on props or not
* @return {Boolean} {@true if the object is a plain object}
*/
_set: function(props, exclude, dontCheck) {
if (props && (dontCheck || Base.isPlainObject(props))) {
// If props is a filtering object, we need to execute hasOwnProperty
// on the original object (it's parent / prototype). See _filtered
// inheritance trick in the argument reading code.
var keys = Object.keys(props._filtering || props);
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i];
if (!(exclude && exclude[key])) {
// Due to the _filtered inheritance trick, undefined is used
// to mask already consumed named arguments.
var value = props[key];
if (value !== undefined)
this[key] = value;
}
}
return props;
}
_set: function(props) {
if (props && Base.isPlainObject(props))
return Base.filter(this, props);
},
statics: /** @lends Base */{
@ -308,6 +293,29 @@ Base.inject(/** @lends Base# */{
return !!this.getNamed(list, name);
},
/**
* Copies all properties from `source` over to `dest`, supporting
* _filtered handling as required by Base.readNamed() mechanism, as well
* as an optional exclude` object that lists properties to exclude.
*/
filter: function(dest, source, exclude) {
// If source is a filtering object, we need to get the keys from the
// the original object (it's parent / prototype). See _filtered
// inheritance trick in the argument reading code.
var keys = Object.keys(source._filtering || source);
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i];
if (!(exclude && exclude[key])) {
// Due to the _filtered inheritance trick, undefined is used
// to mask already consumed named arguments.
var value = source[key];
if (value !== undefined)
dest[key] = value;
}
}
return dest;
},
/**
* Returns true if obj is either a plain object or an array, as used by
* many argument reading methods.

View file

@ -150,10 +150,9 @@ new function() { // // Scope to inject various item event handlers
if (hasProps && props !== Item.NO_INSERT) {
// Filter out internal, insert, parent and project properties as
// these were handled above.
this._set(props,
{ internal: true, insert: true, project: true, parent: true },
// Don't check for plain object, as that's handled by hasProps.
true);
Base.filter(this, props, {
internal: true, insert: true, project: true, parent: true
});
}
return hasProps;
},
@ -2031,7 +2030,7 @@ new function() { // // Scope to inject various item event handlers
if (obj) {
// Create a copy of the match object that doesn't contain
// these special properties:
match = new Base()._set(match, {
match = Base.filter({}, match, {
recursive: true, inside: true, overlapping: true
});
}

View file

@ -207,3 +207,21 @@ test('Project#getItems() empty: true', function() {
}).length;
}, 2);
});
test('Project#getItems() overlapping', function() {
var path = new Path.Circle({
radius: 100,
center: [200, 200],
fillColor: 'red'
});
var rect = new Rectangle(0, 0, 400, 400);
equals(function() {
var matches = project.getItems({
class: Path,
overlapping: rect
});
return matches.length == 1 && matches[0] == path;
}, true);
});