|
1 /** |
|
2 * Collection.js |
|
3 * |
|
4 * Copyright, Moxiecode Systems AB |
|
5 * Released under LGPL License. |
|
6 * |
|
7 * License: http://www.tinymce.com/license |
|
8 * Contributing: http://www.tinymce.com/contributing |
|
9 */ |
|
10 |
|
11 /** |
|
12 * Control collection, this class contains control instances and it enables you to |
|
13 * perform actions on all the contained items. This is very similar to how jQuery works. |
|
14 * |
|
15 * @example |
|
16 * someCollection.show().disabled(true); |
|
17 * |
|
18 * @class tinymce.ui.Collection |
|
19 */ |
|
20 define("tinymce/ui/Collection", [ |
|
21 "tinymce/util/Tools", |
|
22 "tinymce/ui/Selector", |
|
23 "tinymce/util/Class" |
|
24 ], function(Tools, Selector, Class) { |
|
25 "use strict"; |
|
26 |
|
27 var Collection, proto, push = Array.prototype.push, slice = Array.prototype.slice; |
|
28 |
|
29 proto = { |
|
30 /** |
|
31 * Current number of contained control instances. |
|
32 * |
|
33 * @field length |
|
34 * @type Number |
|
35 */ |
|
36 length: 0, |
|
37 |
|
38 /** |
|
39 * Constructor for the collection. |
|
40 * |
|
41 * @constructor |
|
42 * @method init |
|
43 * @param {Array} items Optional array with items to add. |
|
44 */ |
|
45 init: function(items) { |
|
46 if (items) { |
|
47 this.add(items); |
|
48 } |
|
49 }, |
|
50 |
|
51 /** |
|
52 * Adds new items to the control collection. |
|
53 * |
|
54 * @method add |
|
55 * @param {Array} items Array if items to add to collection. |
|
56 * @return {tinymce.ui.Collection} Current collection instance. |
|
57 */ |
|
58 add: function(items) { |
|
59 var self = this; |
|
60 |
|
61 // Force single item into array |
|
62 if (!Tools.isArray(items)) { |
|
63 if (items instanceof Collection) { |
|
64 self.add(items.toArray()); |
|
65 } else { |
|
66 push.call(self, items); |
|
67 } |
|
68 } else { |
|
69 push.apply(self, items); |
|
70 } |
|
71 |
|
72 return self; |
|
73 }, |
|
74 |
|
75 /** |
|
76 * Sets the contents of the collection. This will remove any existing items |
|
77 * and replace them with the ones specified in the input array. |
|
78 * |
|
79 * @method set |
|
80 * @param {Array} items Array with items to set into the Collection. |
|
81 * @return {tinymce.ui.Collection} Collection instance. |
|
82 */ |
|
83 set: function(items) { |
|
84 var self = this, len = self.length, i; |
|
85 |
|
86 self.length = 0; |
|
87 self.add(items); |
|
88 |
|
89 // Remove old entries |
|
90 for (i = self.length; i < len; i++) { |
|
91 delete self[i]; |
|
92 } |
|
93 |
|
94 return self; |
|
95 }, |
|
96 |
|
97 /** |
|
98 * Filters the collection item based on the specified selector expression or selector function. |
|
99 * |
|
100 * @method filter |
|
101 * @param {String} selector Selector expression to filter items by. |
|
102 * @return {tinymce.ui.Collection} Collection containing the filtered items. |
|
103 */ |
|
104 filter: function(selector) { |
|
105 var self = this, i, l, matches = [], item, match; |
|
106 |
|
107 // Compile string into selector expression |
|
108 if (typeof selector === "string") { |
|
109 selector = new Selector(selector); |
|
110 |
|
111 match = function(item) { |
|
112 return selector.match(item); |
|
113 }; |
|
114 } else { |
|
115 // Use selector as matching function |
|
116 match = selector; |
|
117 } |
|
118 |
|
119 for (i = 0, l = self.length; i < l; i++) { |
|
120 item = self[i]; |
|
121 |
|
122 if (match(item)) { |
|
123 matches.push(item); |
|
124 } |
|
125 } |
|
126 |
|
127 return new Collection(matches); |
|
128 }, |
|
129 |
|
130 /** |
|
131 * Slices the items within the collection. |
|
132 * |
|
133 * @method slice |
|
134 * @param {Number} index Index to slice at. |
|
135 * @param {Number} len Optional length to slice. |
|
136 * @return {tinymce.ui.Collection} Current collection. |
|
137 */ |
|
138 slice: function() { |
|
139 return new Collection(slice.apply(this, arguments)); |
|
140 }, |
|
141 |
|
142 /** |
|
143 * Makes the current collection equal to the specified index. |
|
144 * |
|
145 * @method eq |
|
146 * @param {Number} index Index of the item to set the collection to. |
|
147 * @return {tinymce.ui.Collection} Current collection. |
|
148 */ |
|
149 eq: function(index) { |
|
150 return index === -1 ? this.slice(index) : this.slice(index, +index + 1); |
|
151 }, |
|
152 |
|
153 /** |
|
154 * Executes the specified callback on each item in collection. |
|
155 * |
|
156 * @method each |
|
157 * @param {function} callback Callback to execute for each item in collection. |
|
158 * @return {tinymce.ui.Collection} Current collection instance. |
|
159 */ |
|
160 each: function(callback) { |
|
161 Tools.each(this, callback); |
|
162 |
|
163 return this; |
|
164 }, |
|
165 |
|
166 /** |
|
167 * Returns an JavaScript array object of the contents inside the collection. |
|
168 * |
|
169 * @method toArray |
|
170 * @return {Array} Array with all items from collection. |
|
171 */ |
|
172 toArray: function() { |
|
173 return Tools.toArray(this); |
|
174 }, |
|
175 |
|
176 /** |
|
177 * Finds the index of the specified control or return -1 if it isn't in the collection. |
|
178 * |
|
179 * @method indexOf |
|
180 * @param {Control} ctrl Control instance to look for. |
|
181 * @return {Number} Index of the specified control or -1. |
|
182 */ |
|
183 indexOf: function(ctrl) { |
|
184 var self = this, i = self.length; |
|
185 |
|
186 while (i--) { |
|
187 if (self[i] === ctrl) { |
|
188 break; |
|
189 } |
|
190 } |
|
191 |
|
192 return i; |
|
193 }, |
|
194 |
|
195 /** |
|
196 * Returns a new collection of the contents in reverse order. |
|
197 * |
|
198 * @method reverse |
|
199 * @return {tinymce.ui.Collection} Collection instance with reversed items. |
|
200 */ |
|
201 reverse: function() { |
|
202 return new Collection(Tools.toArray(this).reverse()); |
|
203 }, |
|
204 |
|
205 /** |
|
206 * Returns true/false if the class exists or not. |
|
207 * |
|
208 * @method hasClass |
|
209 * @param {String} cls Class to check for. |
|
210 * @return {Boolean} true/false state if the class exists or not. |
|
211 */ |
|
212 hasClass: function(cls) { |
|
213 return this[0] ? this[0].hasClass(cls) : false; |
|
214 }, |
|
215 |
|
216 /** |
|
217 * Sets/gets the specific property on the items in the collection. The same as executing control.<property>(<value>); |
|
218 * |
|
219 * @method prop |
|
220 * @param {String} name Property name to get/set. |
|
221 * @param {Object} value Optional object value to set. |
|
222 * @return {tinymce.ui.Collection} Current collection instance or value of the first item on a get operation. |
|
223 */ |
|
224 prop: function(name, value) { |
|
225 var self = this, undef, item; |
|
226 |
|
227 if (value !== undef) { |
|
228 self.each(function(item) { |
|
229 if (item[name]) { |
|
230 item[name](value); |
|
231 } |
|
232 }); |
|
233 |
|
234 return self; |
|
235 } |
|
236 |
|
237 item = self[0]; |
|
238 |
|
239 if (item && item[name]) { |
|
240 return item[name](); |
|
241 } |
|
242 }, |
|
243 |
|
244 /** |
|
245 * Executes the specific function name with optional arguments an all items in collection if it exists. |
|
246 * |
|
247 * @example collection.exec("myMethod", arg1, arg2, arg3); |
|
248 * @method exec |
|
249 * @param {String} name Name of the function to execute. |
|
250 * @param {Object} ... Multiple arguments to pass to each function. |
|
251 * @return {tinymce.ui.Collection} Current collection. |
|
252 */ |
|
253 exec: function(name) { |
|
254 var self = this, args = Tools.toArray(arguments).slice(1); |
|
255 |
|
256 self.each(function(item) { |
|
257 if (item[name]) { |
|
258 item[name].apply(item, args); |
|
259 } |
|
260 }); |
|
261 |
|
262 return self; |
|
263 }, |
|
264 |
|
265 /** |
|
266 * Remove all items from collection and DOM. |
|
267 * |
|
268 * @method remove |
|
269 * @return {tinymce.ui.Collection} Current collection. |
|
270 */ |
|
271 remove: function() { |
|
272 var i = this.length; |
|
273 |
|
274 while (i--) { |
|
275 this[i].remove(); |
|
276 } |
|
277 |
|
278 return this; |
|
279 } |
|
280 |
|
281 /** |
|
282 * Fires the specified event by name and arguments on the control. This will execute all |
|
283 * bound event handlers. |
|
284 * |
|
285 * @method fire |
|
286 * @param {String} name Name of the event to fire. |
|
287 * @param {Object} args Optional arguments to pass to the event. |
|
288 * @return {tinymce.ui.Collection} Current collection instance. |
|
289 */ |
|
290 // fire: function(event, args) {}, -- Generated by code below |
|
291 |
|
292 /** |
|
293 * Binds a callback to the specified event. This event can both be |
|
294 * native browser events like "click" or custom ones like PostRender. |
|
295 * |
|
296 * The callback function will have two parameters the first one being the control that received the event |
|
297 * the second one will be the event object either the browsers native event object or a custom JS object. |
|
298 * |
|
299 * @method on |
|
300 * @param {String} name Name of the event to bind. For example "click". |
|
301 * @param {String/function} callback Callback function to execute ones the event occurs. |
|
302 * @return {tinymce.ui.Collection} Current collection instance. |
|
303 */ |
|
304 // on: function(name, callback) {}, -- Generated by code below |
|
305 |
|
306 /** |
|
307 * Unbinds the specified event and optionally a specific callback. If you omit the name |
|
308 * parameter all event handlers will be removed. If you omit the callback all event handles |
|
309 * by the specified name will be removed. |
|
310 * |
|
311 * @method off |
|
312 * @param {String} name Optional name for the event to unbind. |
|
313 * @param {function} callback Optional callback function to unbind. |
|
314 * @return {tinymce.ui.Collection} Current collection instance. |
|
315 */ |
|
316 // off: function(name, callback) {}, -- Generated by code below |
|
317 |
|
318 /** |
|
319 * Shows the items in the current collection. |
|
320 * |
|
321 * @method show |
|
322 * @return {tinymce.ui.Collection} Current collection instance. |
|
323 */ |
|
324 // show: function() {}, -- Generated by code below |
|
325 |
|
326 /** |
|
327 * Hides the items in the current collection. |
|
328 * |
|
329 * @method hide |
|
330 * @return {tinymce.ui.Collection} Current collection instance. |
|
331 */ |
|
332 // hide: function() {}, -- Generated by code below |
|
333 |
|
334 /** |
|
335 * Sets/gets the text contents of the items in the current collection. |
|
336 * |
|
337 * @method text |
|
338 * @return {tinymce.ui.Collection} Current collection instance or text value of the first item on a get operation. |
|
339 */ |
|
340 // text: function(value) {}, -- Generated by code below |
|
341 |
|
342 /** |
|
343 * Sets/gets the name contents of the items in the current collection. |
|
344 * |
|
345 * @method name |
|
346 * @return {tinymce.ui.Collection} Current collection instance or name value of the first item on a get operation. |
|
347 */ |
|
348 // name: function(value) {}, -- Generated by code below |
|
349 |
|
350 /** |
|
351 * Sets/gets the disabled state on the items in the current collection. |
|
352 * |
|
353 * @method disabled |
|
354 * @return {tinymce.ui.Collection} Current collection instance or disabled state of the first item on a get operation. |
|
355 */ |
|
356 // disabled: function(state) {}, -- Generated by code below |
|
357 |
|
358 /** |
|
359 * Sets/gets the active state on the items in the current collection. |
|
360 * |
|
361 * @method active |
|
362 * @return {tinymce.ui.Collection} Current collection instance or active state of the first item on a get operation. |
|
363 */ |
|
364 // active: function(state) {}, -- Generated by code below |
|
365 |
|
366 /** |
|
367 * Sets/gets the selected state on the items in the current collection. |
|
368 * |
|
369 * @method selected |
|
370 * @return {tinymce.ui.Collection} Current collection instance or selected state of the first item on a get operation. |
|
371 */ |
|
372 // selected: function(state) {}, -- Generated by code below |
|
373 |
|
374 /** |
|
375 * Sets/gets the selected state on the items in the current collection. |
|
376 * |
|
377 * @method visible |
|
378 * @return {tinymce.ui.Collection} Current collection instance or visible state of the first item on a get operation. |
|
379 */ |
|
380 // visible: function(state) {}, -- Generated by code below |
|
381 |
|
382 /** |
|
383 * Adds a class to all items in the collection. |
|
384 * |
|
385 * @method addClass |
|
386 * @param {String} cls Class to add to each item. |
|
387 * @return {tinymce.ui.Collection} Current collection instance. |
|
388 */ |
|
389 // addClass: function(cls) {}, -- Generated by code below |
|
390 |
|
391 /** |
|
392 * Removes the specified class from all items in collection. |
|
393 * |
|
394 * @method removeClass |
|
395 * @param {String} cls Class to remove from each item. |
|
396 * @return {tinymce.ui.Collection} Current collection instance. |
|
397 */ |
|
398 // removeClass: function(cls) {}, -- Generated by code below |
|
399 }; |
|
400 |
|
401 // Extend tinymce.ui.Collection prototype with some generated control specific methods |
|
402 Tools.each('fire on off show hide addClass removeClass append prepend before after reflow'.split(' '), function(name) { |
|
403 proto[name] = function() { |
|
404 var args = Tools.toArray(arguments); |
|
405 |
|
406 this.each(function(ctrl) { |
|
407 if (name in ctrl) { |
|
408 ctrl[name].apply(ctrl, args); |
|
409 } |
|
410 }); |
|
411 |
|
412 return this; |
|
413 }; |
|
414 }); |
|
415 |
|
416 // Extend tinymce.ui.Collection prototype with some property methods |
|
417 Tools.each('text name disabled active selected checked visible parent value data'.split(' '), function(name) { |
|
418 proto[name] = function(value) { |
|
419 return this.prop(name, value); |
|
420 }; |
|
421 }); |
|
422 |
|
423 // Create class based on the new prototype |
|
424 Collection = Class.extend(proto); |
|
425 |
|
426 // Stick Collection into Selector to prevent circual references |
|
427 Selector.Collection = Collection; |
|
428 |
|
429 return Collection; |
|
430 }); |