Skip to content

Commit d02fbf0

Browse files
ShaMan123asturur
andauthored
chore(TS): Migrate fabric.Collection (#8433)
Co-authored-by: Andrea Bogazzi <[email protected]>
1 parent 63672d6 commit d02fbf0

File tree

11 files changed

+362
-467
lines changed

11 files changed

+362
-467
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## [next]
44

5+
- chore(TS): migrate Collection [#8433](https://github.com/fabricjs/fabric.js/pull/8433)
56
- ci(): Simplify filestats even more [#8449](https://github.com/fabricjs/fabric.js/pull/8449)
67
- chore(TS): migrate filter backends [#8403](https://github.com/fabricjs/fabric.js/pull/8403)
78
- chore(TS): migrate Text classes/mixins [#8408](https://github.com/fabricjs/fabric.js/pull/8408)

src/mixins/canvas_serialization.mixin.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,10 @@
7474
* @param {Array} enlivenedObjects canvas objects
7575
*/
7676
__setupCanvas: function (serialized, enlivenedObjects) {
77-
var _this = this;
78-
enlivenedObjects.forEach(function (obj, index) {
77+
enlivenedObjects.forEach((obj, index) => {
7978
// we splice the array just in case some custom classes restored from JSON
8079
// will add more object to canvas at canvas init.
81-
_this.insertAt(obj, index);
80+
this.insertAt(index, obj);
8281
});
8382
// remove parts i cannot set as options
8483
delete serialized.objects;

src/mixins/collection.mixin.ts

Lines changed: 79 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,167 +1,155 @@
1-
//@ts-nocheck
2-
(function (global) {
3-
var fabric = global.fabric;
4-
/**
5-
* @namespace fabric.Collection
6-
*/
7-
fabric.Collection = {
1+
import { fabric } from '../../HEADER';
2+
import type { FabricObject } from '../shapes/fabricObject.class';
3+
4+
export function createCollectionMixin(Klass: { new (...args: any[]): any }) {
5+
return class Collection extends Klass {
86
/**
9-
* @type {fabric.Object[]}
7+
* @type {FabricObject[]}
108
*/
11-
_objects: [],
9+
_objects: FabricObject[] = [];
10+
11+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
12+
_onObjectAdded(object: FabricObject) {
13+
// subclasses should override this method
14+
}
15+
16+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
17+
_onObjectRemoved(object: FabricObject) {
18+
// subclasses should override this method
19+
}
1220

1321
/**
14-
* Adds objects to collection, Canvas or Group, then renders canvas
15-
* (if `renderOnAddRemove` is not `false`).
16-
* Objects should be instances of (or inherit from) fabric.Object
17-
* @private
18-
* @param {fabric.Object[]} objects to add
19-
* @param {(object:fabric.Object) => any} [callback]
22+
* Adds objects to collection
23+
* Objects should be instances of (or inherit from) FabricObject
24+
* @param {...FabricObject[]} objects to add
2025
* @returns {number} new array length
2126
*/
22-
add: function (objects, callback) {
23-
var size = this._objects.push.apply(this._objects, objects);
24-
if (callback) {
25-
for (var i = 0; i < objects.length; i++) {
26-
callback.call(this, objects[i]);
27-
}
28-
}
27+
add(...objects: FabricObject[]) {
28+
const size = this._objects.push(...objects);
29+
objects.forEach((object) => this._onObjectAdded(object));
2930
return size;
30-
},
31+
}
3132

3233
/**
33-
* Inserts an object into collection at specified index, then renders canvas (if `renderOnAddRemove` is not `false`)
34-
* An object should be an instance of (or inherit from) fabric.Object
35-
* @private
36-
* @param {fabric.Object|fabric.Object[]} objects Object(s) to insert
37-
* @param {Number} index Index to insert object at
38-
* @param {(object:fabric.Object) => any} [callback]
34+
* Inserts an object into collection at specified index
35+
* @param {number} index Index to insert object at
36+
* @param {...FabricObject[]} objects Object(s) to insert
3937
* @returns {number} new array length
4038
*/
41-
insertAt: function (objects, index, callback) {
42-
var args = [index, 0].concat(objects);
43-
this._objects.splice.apply(this._objects, args);
44-
if (callback) {
45-
for (var i = 2; i < args.length; i++) {
46-
callback.call(this, args[i]);
47-
}
48-
}
39+
insertAt(index: number, ...objects: FabricObject[]) {
40+
this._objects.splice(index, 0, ...objects);
41+
objects.forEach((object) => this._onObjectAdded(object));
4942
return this._objects.length;
50-
},
43+
}
5144

5245
/**
5346
* Removes objects from a collection, then renders canvas (if `renderOnAddRemove` is not `false`)
5447
* @private
55-
* @param {fabric.Object[]} objectsToRemove objects to remove
56-
* @param {(object:fabric.Object) => any} [callback] function to call for each object removed
57-
* @returns {fabric.Object[]} removed objects
48+
* @param {...FabricObject[]} objects objects to remove
49+
* @returns {FabricObject[]} removed objects
5850
*/
59-
remove: function (objectsToRemove, callback) {
60-
var objects = this._objects,
61-
removed = [];
62-
for (var i = 0, object, index; i < objectsToRemove.length; i++) {
63-
object = objectsToRemove[i];
64-
index = objects.indexOf(object);
51+
remove(...objects: FabricObject[]) {
52+
const array = this._objects,
53+
removed: FabricObject[] = [];
54+
objects.forEach((object) => {
55+
const index = array.indexOf(object);
6556
// only call onObjectRemoved if an object was actually removed
6657
if (index !== -1) {
67-
objects.splice(index, 1);
58+
array.splice(index, 1);
6859
removed.push(object);
69-
callback && callback.call(this, object);
60+
this._onObjectRemoved(object);
7061
}
71-
}
62+
});
7263
return removed;
73-
},
64+
}
7465

7566
/**
7667
* Executes given function for each object in this group
68+
* A simple shortcut for getObjects().forEach, before es6 was more complicated,
69+
* now is just a shortcut.
7770
* @param {Function} callback
7871
* Callback invoked with current object as first argument,
7972
* index - as second and an array of all objects - as third.
80-
* Callback is invoked in a context of Global Object (e.g. `window`)
81-
* when no `context` argument is given
82-
*
83-
* @param {Object} context Context (aka thisObject)
84-
* @return {Self} thisArg
85-
* @chainable
8673
*/
87-
forEachObject: function (callback, context) {
88-
var objects = this.getObjects();
89-
for (var i = 0; i < objects.length; i++) {
90-
callback.call(context, objects[i], i, objects);
91-
}
92-
return this;
93-
},
74+
forEachObject(
75+
callback: (
76+
object: FabricObject,
77+
index: number,
78+
array: FabricObject[]
79+
) => any
80+
) {
81+
this.getObjects().forEach((object, index, objects) =>
82+
callback(object, index, objects)
83+
);
84+
}
9485

9586
/**
9687
* Returns an array of children objects of this instance
9788
* @param {...String} [types] When specified, only objects of these types are returned
9889
* @return {Array}
9990
*/
100-
getObjects: function () {
101-
if (arguments.length === 0) {
102-
return this._objects.concat();
91+
getObjects(...types: string[]) {
92+
if (types.length === 0) {
93+
return [...this._objects];
10394
}
104-
var types = Array.from(arguments);
105-
return this._objects.filter(function (o) {
106-
return types.indexOf(o.type) > -1;
107-
});
108-
},
95+
return this._objects.filter((o) => types.includes(o.type));
96+
}
10997

11098
/**
11199
* Returns object at specified index
112100
* @param {Number} index
113101
* @return {Object} object at index
114102
*/
115-
item: function (index) {
103+
item(index: number) {
116104
return this._objects[index];
117-
},
105+
}
118106

119107
/**
120108
* Returns true if collection contains no objects
121109
* @return {Boolean} true if collection is empty
122110
*/
123-
isEmpty: function () {
111+
isEmpty() {
124112
return this._objects.length === 0;
125-
},
113+
}
126114

127115
/**
128116
* Returns a size of a collection (i.e: length of an array containing its objects)
129117
* @return {Number} Collection size
130118
*/
131-
size: function () {
119+
size() {
132120
return this._objects.length;
133-
},
121+
}
134122

135123
/**
136124
* Returns true if collection contains an object.\
137-
* **Prefer using {@link `fabric.Object#isDescendantOf`} for performance reasons**
125+
* **Prefer using {@link `FabricObject#isDescendantOf`} for performance reasons**
138126
* instead of a.contains(b) use b.isDescendantOf(a)
139127
* @param {Object} object Object to check against
140128
* @param {Boolean} [deep=false] `true` to check all descendants, `false` to check only `_objects`
141129
* @return {Boolean} `true` if collection contains an object
142130
*/
143-
contains: function (object, deep) {
144-
if (this._objects.indexOf(object) > -1) {
131+
contains(object: FabricObject, deep?: boolean): boolean {
132+
if (this._objects.includes(object)) {
145133
return true;
146134
} else if (deep) {
147-
return this._objects.some(function (obj) {
148-
return (
149-
typeof obj.contains === 'function' && obj.contains(object, true)
150-
);
151-
});
135+
return this._objects.some(
136+
(obj) => obj instanceof Collection && obj.contains(object, true)
137+
);
152138
}
153139
return false;
154-
},
140+
}
155141

156142
/**
157143
* Returns number representation of a collection complexity
158144
* @return {Number} complexity
159145
*/
160-
complexity: function () {
161-
return this._objects.reduce(function (memo, current) {
146+
complexity() {
147+
return this._objects.reduce((memo, current) => {
162148
memo += current.complexity ? current.complexity() : 0;
163149
return memo;
164150
}, 0);
165-
},
151+
}
166152
};
167-
})(typeof exports !== 'undefined' ? exports : window);
153+
}
154+
155+
fabric.createCollectionMixin = createCollectionMixin;

src/mixins/object_ancestry.mixin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { FabricObject } from '../shapes/fabricObject.class';
88
/** @lends FabricObject.prototype */ {
99
/**
1010
* Checks if object is decendant of target
11-
* Should be used instead of @link {fabric.Collection.contains} for performance reasons
11+
* Should be used instead of @link {Group.contains} or @link {StaticCanvas.contains} for performance reasons
1212
* @param {fabric.Object|fabric.StaticCanvas} target
1313
* @returns {boolean}
1414
*/

0 commit comments

Comments
 (0)