]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/debian/missing-sources/framework/Web/Javascripts/source/tinymce-405/classes/ui/Selector.js
baculum: Add missing-sources directory in debian metadata structure
[bacula/bacula] / gui / baculum / debian / missing-sources / framework / Web / Javascripts / source / tinymce-405 / classes / ui / Selector.js
1 /**
2  * Selector.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  * Selector engine, enables you to select controls by using CSS like expressions.
13  * We currently only support basic CSS expressions to reduce the size of the core
14  * and the ones we support should be enough for most cases.
15  *
16  * @example
17  * Supported expressions:
18  *  element
19  *  element#name
20  *  element.class
21  *  element[attr]
22  *  element[attr*=value]
23  *  element[attr~=value]
24  *  element[attr!=value]
25  *  element[attr^=value]
26  *  element[attr$=value]
27  *  element:<state>
28  *  element:not(<expression>)
29  *  element:first
30  *  element:last
31  *  element:odd
32  *  element:even
33  *  element element
34  *  element > element
35  *
36  * @class tinymce.ui.Selector
37  */
38 define("tinymce/ui/Selector", [
39         "tinymce/util/Class",
40         "tinymce/util/Tools"
41 ], function(Class, Tools) {
42         "use strict";
43
44         /**
45          * Produces an array with a unique set of objects. It will not compare the values
46          * but the references of the objects.
47          *
48          * @private
49          * @method unqiue
50          * @param {Array} array Array to make into an array with unique items.
51          * @return {Array} Array with unique items.
52          */
53         function unique(array) {
54                 var uniqueItems = [], i = array.length, item;
55
56                 while (i--) {
57                         item = array[i];
58
59                         if (!item.__checked) {
60                                 uniqueItems.push(item);
61                                 item.__checked = 1;
62                         }
63                 }
64
65                 i = uniqueItems.length;
66                 while (i--) {
67                         delete uniqueItems[i].__checked;
68                 }
69
70                 return uniqueItems;
71         }
72
73         var expression = /^([\w\\*]+)?(?:#([\w\\]+))?(?:\.([\w\\\.]+))?(?:\[\@?([\w\\]+)([\^\$\*!~]?=)([\w\\]+)\])?(?:\:(.+))?/i;
74
75         /*jshint maxlen:255 */
76         var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
77                 whiteSpace = /^\s*|\s*$/g,
78                 Collection;
79
80         var Selector = Class.extend({
81                 /**
82                  * Constructs a new Selector instance.
83                  *
84                  * @constructor
85                  * @method init
86                  * @param {String} selector CSS like selector expression.
87                  */
88                 init: function(selector) {
89                         var match = this.match;
90
91                         function compileNameFilter(name) {
92                                 if (name) {
93                                         name = name.toLowerCase();
94
95                                         return function(item) {
96                                                 return name === '*' || item.type === name;
97                                         };
98                                 }
99                         }
100
101                         function compileIdFilter(id) {
102                                 if (id) {
103                                         return function(item) {
104                                                 return item._name === id;
105                                         };
106                                 }
107                         }
108
109                         function compileClassesFilter(classes) {
110                                 if (classes) {
111                                         classes = classes.split('.');
112
113                                         return function(item) {
114                                                 var i = classes.length;
115
116                                                 while (i--) {
117                                                         if (!item.hasClass(classes[i])) {
118                                                                 return false;
119                                                         }
120                                                 }
121
122                                                 return true;
123                                         };
124                                 }
125                         }
126
127                         function compileAttrFilter(name, cmp, check) {
128                                 if (name) {
129                                         return function(item) {
130                                                 var value = item[name] ? item[name]() : '';
131
132                                                 return !cmp ? !!check :
133                                                         cmp === "=" ? value === check :
134                                                         cmp === "*=" ? value.indexOf(check) >= 0 :
135                                                         cmp === "~=" ? (" " + value + " ").indexOf(" " + check + " ") >= 0 :
136                                                         cmp === "!=" ? value != check :
137                                                         cmp === "^=" ? value.indexOf(check) === 0 :
138                                                         cmp === "$=" ? value.substr(value.length - check.length) === check :
139                                                         false;
140                                         };
141                                 }
142                         }
143
144                         function compilePsuedoFilter(name) {
145                                 var notSelectors;
146
147                                 if (name) {
148                                         name = /(?:not\((.+)\))|(.+)/i.exec(name);
149
150                                         if (!name[1]) {
151                                                 name = name[2];
152
153                                                 return function(item, index, length) {
154                                                         return name === 'first' ? index === 0 :
155                                                                 name === 'last' ? index === length - 1 :
156                                                                 name === 'even' ? index % 2 === 0 :
157                                                                 name === 'odd' ? index % 2 === 1 :
158                                                                 item[name] ? item[name]() :
159                                                                 false;
160                                                 };
161                                         } else {
162                                                 // Compile not expression
163                                                 notSelectors = parseChunks(name[1], []);
164
165                                                 return function(item) {
166                                                         return !match(item, notSelectors);
167                                                 };
168                                         }
169                                 }
170                         }
171
172                         function compile(selector, filters, direct) {
173                                 var parts;
174
175                                 function add(filter) {
176                                         if (filter) {
177                                                 filters.push(filter);
178                                         }
179                                 }
180
181                                 // Parse expression into parts
182                                 parts = expression.exec(selector.replace(whiteSpace, ''));
183
184                                 add(compileNameFilter(parts[1]));
185                                 add(compileIdFilter(parts[2]));
186                                 add(compileClassesFilter(parts[3]));
187                                 add(compileAttrFilter(parts[4], parts[5], parts[6]));
188                                 add(compilePsuedoFilter(parts[7]));
189
190                                 // Mark the filter with psuedo for performance
191                                 filters.psuedo = !!parts[7];
192                                 filters.direct = direct;
193
194                                 return filters;
195                         }
196
197                         // Parser logic based on Sizzle by John Resig
198                         function parseChunks(selector, selectors) {
199                                 var parts = [], extra, matches, i;
200
201                                 do {
202                                         chunker.exec("");
203                                         matches = chunker.exec(selector);
204
205                                         if (matches) {
206                                                 selector = matches[3];
207                                                 parts.push(matches[1]);
208
209                                                 if (matches[2]) {
210                                                         extra = matches[3];
211                                                         break;
212                                                 }
213                                         }
214                                 } while (matches);
215
216                                 if (extra) {
217                                         parseChunks(extra, selectors);
218                                 }
219
220                                 selector = [];
221                                 for (i = 0; i < parts.length; i++) {
222                                         if (parts[i] != '>') {
223                                                 selector.push(compile(parts[i], [], parts[i - 1] === '>'));
224                                         }
225                                 }
226
227                                 selectors.push(selector);
228
229                                 return selectors;
230                         }
231
232                         this._selectors = parseChunks(selector, []);
233                 },
234
235                 /**
236                  * Returns true/false if the selector matches the specified control.
237                  *
238                  * @method match
239                  * @param {tinymce.ui.Control} control Control to match agains the selector.
240                  * @param {Array} selectors Optional array of selectors, mostly used internally.
241                  * @return {Boolean} true/false state if the control matches or not.
242                  */
243                 match: function(control, selectors) {
244                         var i, l, si, sl, selector, fi, fl, filters, index, length, siblings, count, item;
245
246                         selectors = selectors || this._selectors;
247                         for (i = 0, l = selectors.length; i < l; i++) {
248                                 selector = selectors[i];
249                                 sl = selector.length;
250                                 item = control;
251                                 count = 0;
252
253                                 for (si = sl - 1; si >= 0; si--) {
254                                         filters = selector[si];
255
256                                         while (item) {
257                                                 // Find the index and length since a psuedo filter like :first needs it
258                                                 if (filters.psuedo) {
259                                                         siblings = item.parent().items();
260                                                         index = Tools.inArray(item, siblings);
261                                                         length = siblings.length;
262                                                 }
263
264                                                 for (fi = 0, fl = filters.length; fi < fl; fi++) {
265                                                         if (!filters[fi](item, index, length)) {
266                                                                 fi = fl + 1;
267                                                                 break;
268                                                         }
269                                                 }
270
271                                                 if (fi === fl) {
272                                                         count++;
273                                                         break;
274                                                 } else {
275                                                         // If it didn't match the right most expression then
276                                                         // break since it's no point looking at the parents
277                                                         if (si === sl - 1) {
278                                                                 break;
279                                                         }
280                                                 }
281
282                                                 item = item.parent();
283                                         }
284                                 }
285
286                                 // If we found all selectors then return true otherwise continue looking
287                                 if (count === sl) {
288                                         return true;
289                                 }
290                         }
291
292                         return false;
293                 },
294
295                 /**
296                  * Returns a tinymce.ui.Collection with matches of the specified selector inside the specified container.
297                  *
298                  * @method find
299                  * @param {tinymce.ui.Control} container Container to look for items in.
300                  * @return {tinymce.ui.Collection} Collection with matched elements.
301                  */
302                 find: function(container) {
303                         var matches = [], i, l, selectors = this._selectors;
304
305                         function collect(items, selector, index) {
306                                 var i, l, fi, fl, item, filters = selector[index];
307
308                                 for (i = 0, l = items.length; i < l; i++) {
309                                         item = items[i];
310
311                                         // Run each filter agains the item
312                                         for (fi = 0, fl = filters.length; fi < fl; fi++) {
313                                                 if (!filters[fi](item, i, l)) {
314                                                         fi = fl + 1;
315                                                         break;
316                                                 }
317                                         }
318
319                                         // All filters matched the item
320                                         if (fi === fl) {
321                                                 // Matched item is on the last expression like: panel toolbar [button]
322                                                 if (index == selector.length - 1) {
323                                                         matches.push(item);
324                                                 } else {
325                                                         // Collect next expression type
326                                                         if (item.items) {
327                                                                 collect(item.items(), selector, index + 1);
328                                                         }
329                                                 }
330                                         } else if (filters.direct) {
331                                                 return;
332                                         }
333
334                                         // Collect child items
335                                         if (item.items) {
336                                                 collect(item.items(), selector, index);
337                                         }
338                                 }
339                         }
340
341                         if (container.items) {
342                                 for (i = 0, l = selectors.length; i < l; i++) {
343                                         collect(container.items(), selectors[i], 0);
344                                 }
345
346                                 // Unique the matches if needed
347                                 if (l > 1) {
348                                         matches = unique(matches);
349                                 }
350                         }
351
352                         // Fix for circular reference
353                         if (!Collection) {
354                                 // TODO: Fix me!
355                                 Collection = Selector.Collection;
356                         }
357
358                         return new Collection(matches);
359                 }
360         });
361
362         return Selector;
363 });