addon-sdk/source/lib/sdk/util/collection.js

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:79d20b06154b
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 "use strict";
6
7 module.metadata = {
8 "stability": "experimental"
9 };
10
11 exports.Collection = Collection;
12
13 /**
14 * Adds a collection property to the given object. Setting the property to a
15 * scalar value empties the collection and adds the value. Setting it to an
16 * array empties the collection and adds all the items in the array.
17 *
18 * @param obj
19 * The property will be defined on this object.
20 * @param propName
21 * The name of the property.
22 * @param array
23 * If given, this will be used as the collection's backing array.
24 */
25 exports.addCollectionProperty = function addCollProperty(obj, propName, array) {
26 array = array || [];
27 let publicIface = new Collection(array);
28
29 Object.defineProperty(obj, propName, {
30 configurable: true,
31 enumerable: true,
32
33 set: function set(itemOrItems) {
34 array.splice(0, array.length);
35 publicIface.add(itemOrItems);
36 },
37
38 get: function get() {
39 return publicIface;
40 }
41 });
42 };
43
44 /**
45 * A collection is ordered, like an array, but its items are unique, like a set.
46 *
47 * @param array
48 * The collection is backed by an array. If this is given, it will be
49 * used as the backing array. This way the caller can fully control the
50 * collection. Otherwise a new empty array will be used, and no one but
51 * the collection will have access to it.
52 */
53 function Collection(array) {
54 array = array || [];
55
56 /**
57 * Provides iteration over the collection. Items are yielded in the order
58 * they were added.
59 */
60 this.__iterator__ = function Collection___iterator__() {
61 let items = array.slice();
62 for (let i = 0; i < items.length; i++)
63 yield items[i];
64 };
65
66 /**
67 * The number of items in the collection.
68 */
69 this.__defineGetter__("length", function Collection_get_length() {
70 return array.length;
71 });
72
73 /**
74 * Adds a single item or an array of items to the collection. Any items
75 * already contained in the collection are ignored.
76 *
77 * @param itemOrItems
78 * An item or array of items.
79 * @return The collection.
80 */
81 this.add = function Collection_add(itemOrItems) {
82 let items = toArray(itemOrItems);
83 for (let i = 0; i < items.length; i++) {
84 let item = items[i];
85 if (array.indexOf(item) < 0)
86 array.push(item);
87 }
88 return this;
89 };
90
91 /**
92 * Removes a single item or an array of items from the collection. Any items
93 * not contained in the collection are ignored.
94 *
95 * @param itemOrItems
96 * An item or array of items.
97 * @return The collection.
98 */
99 this.remove = function Collection_remove(itemOrItems) {
100 let items = toArray(itemOrItems);
101 for (let i = 0; i < items.length; i++) {
102 let idx = array.indexOf(items[i]);
103 if (idx >= 0)
104 array.splice(idx, 1);
105 }
106 return this;
107 };
108 };
109
110 function toArray(itemOrItems) {
111 let isArr = itemOrItems &&
112 itemOrItems.constructor &&
113 itemOrItems.constructor.name === "Array";
114 return isArr ? itemOrItems : [itemOrItems];
115 }

mercurial