ObservableArray.js
4.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/**
* ObservableArray.js
*
* Released under LGPL License.
* Copyright (c) 1999-2015 Ephox Corp. All rights reserved
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/**
* This class is an array that emmits events when mutation occurs.
*
* @private
* @class tinymce.data.ObservableArray
*/
define("tinymce/data/ObservableArray", [
"tinymce/util/Observable",
"tinymce/util/Class"
], function(Observable, Class) {
var push = Array.prototype.push, slice = Array.prototype.slice, splice = Array.prototype.splice;
var ObservableArray = Class.extend({
Mixins: [Observable],
/**
* Number of items in array.
*
* @field length
* @type Number
*/
length: 0,
/**
* Constructs a new observable object instance.
*
* @constructor
* @param {Object} data Optional initial data for the object.
*/
init: function(data) {
if (data) {
this.push.apply(this, data);
}
},
/**
* Adds items to the end of array.
*
* @method push
* @param {Object} item... Item or items to add to the end of array.
* @return {Number} Number of items that got added.
*/
push: function() {
var args, index = this.length;
args = Array.prototype.slice.call(arguments);
push.apply(this, args);
this.fire('add', {
items: args,
index: index
});
return args.length;
},
/**
* Pops the last item off the array.
*
* @method pop
* @return {Object} Item that got popped out.
*/
pop: function() {
return this.splice(this.length - 1, 1)[0];
},
/**
* Slices out a portion of the array as a new array.
*
* @method slice
* @param {Number} begin Beginning of slice.
* @param {Number} end End of slice.
* @return {Array} Native array instance with items.
*/
slice: function(begin, end) {
return slice.call(this, begin, end);
},
/**
* Removes/replaces/inserts items in the array.
*
* @method splice
* @param {Number} index Index to splice at.
* @param {Number} howMany Optional number of items to splice away.
* @param {Object} item ... Item or items to insert at the specified index.
*/
splice: function(index) {
var added, removed, args = slice.call(arguments);
if (args.length === 1) {
args[1] = this.length;
}
removed = splice.apply(this, args);
added = args.slice(2);
if (removed.length > 0) {
this.fire('remove', {items: removed, index: index});
}
if (added.length > 0) {
this.fire('add', {items: added, index: index});
}
return removed;
},
/**
* Removes and returns the first item of the array.
*
* @method shift
* @return {Object} First item of the array.
*/
shift: function() {
return this.splice(0, 1)[0];
},
/**
* Appends an item to the top of array.
*
* @method unshift
* @param {Object} item... Item or items to prepend to array.
* @return {Number} Number of items that got added.
*/
unshift: function() {
var args = slice.call(arguments);
this.splice.apply(this, [0, 0].concat(args));
return args.length;
},
/**
* Executes the callback for each item in the array.
*
* @method forEach
* @param {function} callback Callback to execute for each item in array.
* @param {Object} scope Optional scope for this when executing the callback.
*/
forEach: function(callback, scope) {
var i;
scope = scope || this;
for (i = 0; i < this.length; i++) {
callback.call(scope, this[i], i, this);
}
},
/**
* Returns the index of the specified item or -1 if it wasn't found.
*
* @method indexOf
* @return {Number} Index of item or null if it wasn't found.
*/
indexOf: function(item) {
for (var i = 0; i < this.length; i++) {
if (this[i] === item) {
return i;
}
}
return -1;
},
/**
* Filters the observable array into a new observable array
* based on the true/false return value of the specified callback.
*
* @method filter
* @param {function} callback Callback function to execute for each item and filter by.
* @param {Object} thisArg Optional scope for this when executing the callback.
* @return {tinymce.data.ObservableArray} Filtered observable array instance.
*/
filter: function(callback, thisArg) {
var self = this, out = new ObservableArray();
this.forEach(function(item, index) {
if (callback.call(thisArg || self, item, index, self)) {
out.push(item);
}
});
return out;
}
});
return ObservableArray;
});