diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b0a69b3ec1..bedb9eded99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - fix(fabric.Object): support `excludeFromExport` set on `clipPath` [#7148](https://github.com/fabricjs/fabric.js/pull/7148). - fix(fabric.Group): support `excludeFromExport` set on objects [#7148](https://github.com/fabricjs/fabric.js/pull/7148). - fix(fabric.StaticCanvas): support `excludeFromExport` set on `backgroundColor`, `overlayColor`, `clipPath` [#7148](https://github.com/fabricjs/fabric.js/pull/7148). +- feat(fabric.Collection): the `contains` method now accepts a second boolean parameter `deep`, checking all descendants, `collection.contains(obj, true)` [#7139](https://github.com/fabricjs/fabric.js/pull/7139). ## [4.5.1] diff --git a/src/mixins/collection.mixin.js b/src/mixins/collection.mixin.js index 86dd68c6ea5..49af03f1960 100644 --- a/src/mixins/collection.mixin.js +++ b/src/mixins/collection.mixin.js @@ -142,10 +142,19 @@ fabric.Collection = { /** * Returns true if collection contains an object * @param {Object} object Object to check against + * @param {Boolean} [deep=false] `true` to check all descendants, `false` to check only `_objects` * @return {Boolean} `true` if collection contains an object */ - contains: function(object) { - return this._objects.indexOf(object) > -1; + contains: function (object, deep) { + if (this._objects.indexOf(object) > -1) { + return true; + } + else if (deep) { + return this._objects.some(function (obj) { + return typeof obj.contains === 'function' && obj.contains(object, true); + }); + } + return false; }, /** diff --git a/test/unit/collection.js b/test/unit/collection.js index f0bd74f7066..6a92b83b6be 100644 --- a/test/unit/collection.js +++ b/test/unit/collection.js @@ -1,6 +1,7 @@ (function() { var collection = fabric.Collection; + var collection2 = fabric.util.object.clone(collection); QUnit.module('fabric.Collection', { beforeEach: function() { @@ -9,6 +10,7 @@ delete collection.renderOnAddRemove; delete collection._onObjectAdded; delete collection._onObjectRemoved; + collection2._objects = []; } }); @@ -173,7 +175,16 @@ assert.equal(returned, false, 'collection is empty so does not contains obj'); collection.add(obj); returned = collection.contains(obj); - assert.equal(returned, true, 'collection contais obj'); + assert.equal(returned, true, 'collection contains obj'); + var obj2 = { type: 'b' }; + collection2.add(obj2); + collection.add(collection2); + returned = collection.contains(obj2); + assert.equal(returned, false, 'collection deeply contains obj, this check is shallow'); + returned = collection.contains(obj2, false); + assert.equal(returned, false, 'collection deeply contains obj, this check is shallow'); + returned = collection.contains(obj2, true); + assert.equal(returned, true, 'collection deeply contains obj'); }); QUnit.test('complexity', function(assert) {