From 6d5d1ce07787f76f3eb537e564e94de3bc5cc460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Fri, 12 Feb 2016 19:58:32 +0100 Subject: [PATCH] Introduce Base.filter(), to copy and filter object properties. --- src/core/Base.js | 44 ++++++++++++++++++++++---------------- src/item/Item.js | 9 ++++---- test/tests/Item_Getting.js | 18 ++++++++++++++++ 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/src/core/Base.js b/src/core/Base.js index 7952ba51..375d142d 100644 --- a/src/core/Base.js +++ b/src/core/Base.js @@ -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. diff --git a/src/item/Item.js b/src/item/Item.js index e6909ff3..d31f9e4e 100644 --- a/src/item/Item.js +++ b/src/item/Item.js @@ -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 }); } diff --git a/test/tests/Item_Getting.js b/test/tests/Item_Getting.js index ec8c8912..aab2656a 100644 --- a/test/tests/Item_Getting.js +++ b/test/tests/Item_Getting.js @@ -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); +});