1 | /* |
---|
2 | --- |
---|
3 | MooTools: the javascript framework |
---|
4 | |
---|
5 | web build: |
---|
6 | - http://mootools.net/core/0bb72753f8ff27906af5b045a6c39e25 |
---|
7 | |
---|
8 | packager build: |
---|
9 | - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Delegation Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/JSON Core/DOMReady Core/Swiff |
---|
10 | |
---|
11 | ... |
---|
12 | */ |
---|
13 | |
---|
14 | /* |
---|
15 | --- |
---|
16 | |
---|
17 | name: Core |
---|
18 | |
---|
19 | description: The heart of MooTools. |
---|
20 | |
---|
21 | license: MIT-style license. |
---|
22 | |
---|
23 | copyright: Copyright (c) 2006-2012 [Valerio Proietti](http://mad4milk.net/). |
---|
24 | |
---|
25 | authors: The MooTools production team (http://mootools.net/developers/) |
---|
26 | |
---|
27 | inspiration: |
---|
28 | - Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php) |
---|
29 | - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php) |
---|
30 | |
---|
31 | provides: [Core, MooTools, Type, typeOf, instanceOf, Native] |
---|
32 | |
---|
33 | ... |
---|
34 | */ |
---|
35 | |
---|
36 | (function(){ |
---|
37 | |
---|
38 | this.MooTools = { |
---|
39 | version: '1.4.5', |
---|
40 | build: 'ab8ea8824dc3b24b6666867a2c4ed58ebb762cf0' |
---|
41 | }; |
---|
42 | |
---|
43 | // typeOf, instanceOf |
---|
44 | |
---|
45 | var typeOf = this.typeOf = function(item){ |
---|
46 | if (item == null) return 'null'; |
---|
47 | if (item.$family != null) return item.$family(); |
---|
48 | |
---|
49 | if (item.nodeName){ |
---|
50 | if (item.nodeType == 1) return 'element'; |
---|
51 | if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace'; |
---|
52 | } else if (typeof item.length == 'number'){ |
---|
53 | if (item.callee) return 'arguments'; |
---|
54 | if ('item' in item) return 'collection'; |
---|
55 | } |
---|
56 | |
---|
57 | return typeof item; |
---|
58 | }; |
---|
59 | |
---|
60 | var instanceOf = this.instanceOf = function(item, object){ |
---|
61 | if (item == null) return false; |
---|
62 | var constructor = item.$constructor || item.constructor; |
---|
63 | while (constructor){ |
---|
64 | if (constructor === object) return true; |
---|
65 | constructor = constructor.parent; |
---|
66 | } |
---|
67 | /*<ltIE8>*/ |
---|
68 | if (!item.hasOwnProperty) return false; |
---|
69 | /*</ltIE8>*/ |
---|
70 | return item instanceof object; |
---|
71 | }; |
---|
72 | |
---|
73 | // Function overloading |
---|
74 | |
---|
75 | var Function = this.Function; |
---|
76 | |
---|
77 | var enumerables = true; |
---|
78 | for (var i in {toString: 1}) enumerables = null; |
---|
79 | if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor']; |
---|
80 | |
---|
81 | Function.prototype.overloadSetter = function(usePlural){ |
---|
82 | var self = this; |
---|
83 | return function(a, b){ |
---|
84 | if (a == null) return this; |
---|
85 | if (usePlural || typeof a != 'string'){ |
---|
86 | for (var k in a) self.call(this, k, a[k]); |
---|
87 | if (enumerables) for (var i = enumerables.length; i--;){ |
---|
88 | k = enumerables[i]; |
---|
89 | if (a.hasOwnProperty(k)) self.call(this, k, a[k]); |
---|
90 | } |
---|
91 | } else { |
---|
92 | self.call(this, a, b); |
---|
93 | } |
---|
94 | return this; |
---|
95 | }; |
---|
96 | }; |
---|
97 | |
---|
98 | Function.prototype.overloadGetter = function(usePlural){ |
---|
99 | var self = this; |
---|
100 | return function(a){ |
---|
101 | var args, result; |
---|
102 | if (typeof a != 'string') args = a; |
---|
103 | else if (arguments.length > 1) args = arguments; |
---|
104 | else if (usePlural) args = [a]; |
---|
105 | if (args){ |
---|
106 | result = {}; |
---|
107 | for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]); |
---|
108 | } else { |
---|
109 | result = self.call(this, a); |
---|
110 | } |
---|
111 | return result; |
---|
112 | }; |
---|
113 | }; |
---|
114 | |
---|
115 | Function.prototype.extend = function(key, value){ |
---|
116 | this[key] = value; |
---|
117 | }.overloadSetter(); |
---|
118 | |
---|
119 | Function.prototype.implement = function(key, value){ |
---|
120 | this.prototype[key] = value; |
---|
121 | }.overloadSetter(); |
---|
122 | |
---|
123 | // From |
---|
124 | |
---|
125 | var slice = Array.prototype.slice; |
---|
126 | |
---|
127 | Function.from = function(item){ |
---|
128 | return (typeOf(item) == 'function') ? item : function(){ |
---|
129 | return item; |
---|
130 | }; |
---|
131 | }; |
---|
132 | |
---|
133 | Array.from = function(item){ |
---|
134 | if (item == null) return []; |
---|
135 | return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item]; |
---|
136 | }; |
---|
137 | |
---|
138 | Number.from = function(item){ |
---|
139 | var number = parseFloat(item); |
---|
140 | return isFinite(number) ? number : null; |
---|
141 | }; |
---|
142 | |
---|
143 | String.from = function(item){ |
---|
144 | return item + ''; |
---|
145 | }; |
---|
146 | |
---|
147 | // hide, protect |
---|
148 | |
---|
149 | Function.implement({ |
---|
150 | |
---|
151 | hide: function(){ |
---|
152 | this.$hidden = true; |
---|
153 | return this; |
---|
154 | }, |
---|
155 | |
---|
156 | protect: function(){ |
---|
157 | this.$protected = true; |
---|
158 | return this; |
---|
159 | } |
---|
160 | |
---|
161 | }); |
---|
162 | |
---|
163 | // Type |
---|
164 | |
---|
165 | var Type = this.Type = function(name, object){ |
---|
166 | if (name){ |
---|
167 | var lower = name.toLowerCase(); |
---|
168 | var typeCheck = function(item){ |
---|
169 | return (typeOf(item) == lower); |
---|
170 | }; |
---|
171 | |
---|
172 | Type['is' + name] = typeCheck; |
---|
173 | if (object != null){ |
---|
174 | object.prototype.$family = (function(){ |
---|
175 | return lower; |
---|
176 | }).hide(); |
---|
177 | |
---|
178 | } |
---|
179 | } |
---|
180 | |
---|
181 | if (object == null) return null; |
---|
182 | |
---|
183 | object.extend(this); |
---|
184 | object.$constructor = Type; |
---|
185 | object.prototype.$constructor = object; |
---|
186 | |
---|
187 | return object; |
---|
188 | }; |
---|
189 | |
---|
190 | var toString = Object.prototype.toString; |
---|
191 | |
---|
192 | Type.isEnumerable = function(item){ |
---|
193 | return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' ); |
---|
194 | }; |
---|
195 | |
---|
196 | var hooks = {}; |
---|
197 | |
---|
198 | var hooksOf = function(object){ |
---|
199 | var type = typeOf(object.prototype); |
---|
200 | return hooks[type] || (hooks[type] = []); |
---|
201 | }; |
---|
202 | |
---|
203 | var implement = function(name, method){ |
---|
204 | if (method && method.$hidden) return; |
---|
205 | |
---|
206 | var hooks = hooksOf(this); |
---|
207 | |
---|
208 | for (var i = 0; i < hooks.length; i++){ |
---|
209 | var hook = hooks[i]; |
---|
210 | if (typeOf(hook) == 'type') implement.call(hook, name, method); |
---|
211 | else hook.call(this, name, method); |
---|
212 | } |
---|
213 | |
---|
214 | var previous = this.prototype[name]; |
---|
215 | if (previous == null || !previous.$protected) this.prototype[name] = method; |
---|
216 | |
---|
217 | if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){ |
---|
218 | return method.apply(item, slice.call(arguments, 1)); |
---|
219 | }); |
---|
220 | }; |
---|
221 | |
---|
222 | var extend = function(name, method){ |
---|
223 | if (method && method.$hidden) return; |
---|
224 | var previous = this[name]; |
---|
225 | if (previous == null || !previous.$protected) this[name] = method; |
---|
226 | }; |
---|
227 | |
---|
228 | Type.implement({ |
---|
229 | |
---|
230 | implement: implement.overloadSetter(), |
---|
231 | |
---|
232 | extend: extend.overloadSetter(), |
---|
233 | |
---|
234 | alias: function(name, existing){ |
---|
235 | implement.call(this, name, this.prototype[existing]); |
---|
236 | }.overloadSetter(), |
---|
237 | |
---|
238 | mirror: function(hook){ |
---|
239 | hooksOf(this).push(hook); |
---|
240 | return this; |
---|
241 | } |
---|
242 | |
---|
243 | }); |
---|
244 | |
---|
245 | new Type('Type', Type); |
---|
246 | |
---|
247 | // Default Types |
---|
248 | |
---|
249 | var force = function(name, object, methods){ |
---|
250 | var isType = (object != Object), |
---|
251 | prototype = object.prototype; |
---|
252 | |
---|
253 | if (isType) object = new Type(name, object); |
---|
254 | |
---|
255 | for (var i = 0, l = methods.length; i < l; i++){ |
---|
256 | var key = methods[i], |
---|
257 | generic = object[key], |
---|
258 | proto = prototype[key]; |
---|
259 | |
---|
260 | if (generic) generic.protect(); |
---|
261 | if (isType && proto) object.implement(key, proto.protect()); |
---|
262 | } |
---|
263 | |
---|
264 | if (isType){ |
---|
265 | var methodsEnumerable = prototype.propertyIsEnumerable(methods[0]); |
---|
266 | object.forEachMethod = function(fn){ |
---|
267 | if (!methodsEnumerable) for (var i = 0, l = methods.length; i < l; i++){ |
---|
268 | fn.call(prototype, prototype[methods[i]], methods[i]); |
---|
269 | } |
---|
270 | for (var key in prototype) fn.call(prototype, prototype[key], key) |
---|
271 | }; |
---|
272 | } |
---|
273 | |
---|
274 | return force; |
---|
275 | }; |
---|
276 | |
---|
277 | force('String', String, [ |
---|
278 | 'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search', |
---|
279 | 'slice', 'split', 'substr', 'substring', 'trim', 'toLowerCase', 'toUpperCase' |
---|
280 | ])('Array', Array, [ |
---|
281 | 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', |
---|
282 | 'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight' |
---|
283 | ])('Number', Number, [ |
---|
284 | 'toExponential', 'toFixed', 'toLocaleString', 'toPrecision' |
---|
285 | ])('Function', Function, [ |
---|
286 | 'apply', 'call', 'bind' |
---|
287 | ])('RegExp', RegExp, [ |
---|
288 | 'exec', 'test' |
---|
289 | ])('Object', Object, [ |
---|
290 | 'create', 'defineProperty', 'defineProperties', 'keys', |
---|
291 | 'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', |
---|
292 | 'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen' |
---|
293 | ])('Date', Date, ['now']); |
---|
294 | |
---|
295 | Object.extend = extend.overloadSetter(); |
---|
296 | |
---|
297 | Date.extend('now', function(){ |
---|
298 | return +(new Date); |
---|
299 | }); |
---|
300 | |
---|
301 | new Type('Boolean', Boolean); |
---|
302 | |
---|
303 | // fixes NaN returning as Number |
---|
304 | |
---|
305 | Number.prototype.$family = function(){ |
---|
306 | return isFinite(this) ? 'number' : 'null'; |
---|
307 | }.hide(); |
---|
308 | |
---|
309 | // Number.random |
---|
310 | |
---|
311 | Number.extend('random', function(min, max){ |
---|
312 | return Math.floor(Math.random() * (max - min + 1) + min); |
---|
313 | }); |
---|
314 | |
---|
315 | // forEach, each |
---|
316 | |
---|
317 | var hasOwnProperty = Object.prototype.hasOwnProperty; |
---|
318 | Object.extend('forEach', function(object, fn, bind){ |
---|
319 | for (var key in object){ |
---|
320 | if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object); |
---|
321 | } |
---|
322 | }); |
---|
323 | |
---|
324 | Object.each = Object.forEach; |
---|
325 | |
---|
326 | Array.implement({ |
---|
327 | |
---|
328 | forEach: function(fn, bind){ |
---|
329 | for (var i = 0, l = this.length; i < l; i++){ |
---|
330 | if (i in this) fn.call(bind, this[i], i, this); |
---|
331 | } |
---|
332 | }, |
---|
333 | |
---|
334 | each: function(fn, bind){ |
---|
335 | Array.forEach(this, fn, bind); |
---|
336 | return this; |
---|
337 | } |
---|
338 | |
---|
339 | }); |
---|
340 | |
---|
341 | // Array & Object cloning, Object merging and appending |
---|
342 | |
---|
343 | var cloneOf = function(item){ |
---|
344 | switch (typeOf(item)){ |
---|
345 | case 'array': return item.clone(); |
---|
346 | case 'object': return Object.clone(item); |
---|
347 | default: return item; |
---|
348 | } |
---|
349 | }; |
---|
350 | |
---|
351 | Array.implement('clone', function(){ |
---|
352 | var i = this.length, clone = new Array(i); |
---|
353 | while (i--) clone[i] = cloneOf(this[i]); |
---|
354 | return clone; |
---|
355 | }); |
---|
356 | |
---|
357 | var mergeOne = function(source, key, current){ |
---|
358 | switch (typeOf(current)){ |
---|
359 | case 'object': |
---|
360 | if (typeOf(source[key]) == 'object') Object.merge(source[key], current); |
---|
361 | else source[key] = Object.clone(current); |
---|
362 | break; |
---|
363 | case 'array': source[key] = current.clone(); break; |
---|
364 | default: source[key] = current; |
---|
365 | } |
---|
366 | return source; |
---|
367 | }; |
---|
368 | |
---|
369 | Object.extend({ |
---|
370 | |
---|
371 | merge: function(source, k, v){ |
---|
372 | if (typeOf(k) == 'string') return mergeOne(source, k, v); |
---|
373 | for (var i = 1, l = arguments.length; i < l; i++){ |
---|
374 | var object = arguments[i]; |
---|
375 | for (var key in object) mergeOne(source, key, object[key]); |
---|
376 | } |
---|
377 | return source; |
---|
378 | }, |
---|
379 | |
---|
380 | clone: function(object){ |
---|
381 | var clone = {}; |
---|
382 | for (var key in object) clone[key] = cloneOf(object[key]); |
---|
383 | return clone; |
---|
384 | }, |
---|
385 | |
---|
386 | append: function(original){ |
---|
387 | for (var i = 1, l = arguments.length; i < l; i++){ |
---|
388 | var extended = arguments[i] || {}; |
---|
389 | for (var key in extended) original[key] = extended[key]; |
---|
390 | } |
---|
391 | return original; |
---|
392 | } |
---|
393 | |
---|
394 | }); |
---|
395 | |
---|
396 | // Object-less types |
---|
397 | |
---|
398 | ['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){ |
---|
399 | new Type(name); |
---|
400 | }); |
---|
401 | |
---|
402 | // Unique ID |
---|
403 | |
---|
404 | var UID = Date.now(); |
---|
405 | |
---|
406 | String.extend('uniqueID', function(){ |
---|
407 | return (UID++).toString(36); |
---|
408 | }); |
---|
409 | |
---|
410 | |
---|
411 | |
---|
412 | })(); |
---|
413 | |
---|
414 | |
---|
415 | /* |
---|
416 | --- |
---|
417 | |
---|
418 | name: Array |
---|
419 | |
---|
420 | description: Contains Array Prototypes like each, contains, and erase. |
---|
421 | |
---|
422 | license: MIT-style license. |
---|
423 | |
---|
424 | requires: Type |
---|
425 | |
---|
426 | provides: Array |
---|
427 | |
---|
428 | ... |
---|
429 | */ |
---|
430 | |
---|
431 | Array.implement({ |
---|
432 | |
---|
433 | /*<!ES5>*/ |
---|
434 | every: function(fn, bind){ |
---|
435 | for (var i = 0, l = this.length >>> 0; i < l; i++){ |
---|
436 | if ((i in this) && !fn.call(bind, this[i], i, this)) return false; |
---|
437 | } |
---|
438 | return true; |
---|
439 | }, |
---|
440 | |
---|
441 | filter: function(fn, bind){ |
---|
442 | var results = []; |
---|
443 | for (var value, i = 0, l = this.length >>> 0; i < l; i++) if (i in this){ |
---|
444 | value = this[i]; |
---|
445 | if (fn.call(bind, value, i, this)) results.push(value); |
---|
446 | } |
---|
447 | return results; |
---|
448 | }, |
---|
449 | |
---|
450 | indexOf: function(item, from){ |
---|
451 | var length = this.length >>> 0; |
---|
452 | for (var i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++){ |
---|
453 | if (this[i] === item) return i; |
---|
454 | } |
---|
455 | return -1; |
---|
456 | }, |
---|
457 | |
---|
458 | map: function(fn, bind){ |
---|
459 | var length = this.length >>> 0, results = Array(length); |
---|
460 | for (var i = 0; i < length; i++){ |
---|
461 | if (i in this) results[i] = fn.call(bind, this[i], i, this); |
---|
462 | } |
---|
463 | return results; |
---|
464 | }, |
---|
465 | |
---|
466 | some: function(fn, bind){ |
---|
467 | for (var i = 0, l = this.length >>> 0; i < l; i++){ |
---|
468 | if ((i in this) && fn.call(bind, this[i], i, this)) return true; |
---|
469 | } |
---|
470 | return false; |
---|
471 | }, |
---|
472 | /*</!ES5>*/ |
---|
473 | |
---|
474 | clean: function(){ |
---|
475 | return this.filter(function(item){ |
---|
476 | return item != null; |
---|
477 | }); |
---|
478 | }, |
---|
479 | |
---|
480 | invoke: function(methodName){ |
---|
481 | var args = Array.slice(arguments, 1); |
---|
482 | return this.map(function(item){ |
---|
483 | return item[methodName].apply(item, args); |
---|
484 | }); |
---|
485 | }, |
---|
486 | |
---|
487 | associate: function(keys){ |
---|
488 | var obj = {}, length = Math.min(this.length, keys.length); |
---|
489 | for (var i = 0; i < length; i++) obj[keys[i]] = this[i]; |
---|
490 | return obj; |
---|
491 | }, |
---|
492 | |
---|
493 | link: function(object){ |
---|
494 | var result = {}; |
---|
495 | for (var i = 0, l = this.length; i < l; i++){ |
---|
496 | for (var key in object){ |
---|
497 | if (object[key](this[i])){ |
---|
498 | result[key] = this[i]; |
---|
499 | delete object[key]; |
---|
500 | break; |
---|
501 | } |
---|
502 | } |
---|
503 | } |
---|
504 | return result; |
---|
505 | }, |
---|
506 | |
---|
507 | contains: function(item, from){ |
---|
508 | return this.indexOf(item, from) != -1; |
---|
509 | }, |
---|
510 | |
---|
511 | append: function(array){ |
---|
512 | this.push.apply(this, array); |
---|
513 | return this; |
---|
514 | }, |
---|
515 | |
---|
516 | getLast: function(){ |
---|
517 | return (this.length) ? this[this.length - 1] : null; |
---|
518 | }, |
---|
519 | |
---|
520 | getRandom: function(){ |
---|
521 | return (this.length) ? this[Number.random(0, this.length - 1)] : null; |
---|
522 | }, |
---|
523 | |
---|
524 | include: function(item){ |
---|
525 | if (!this.contains(item)) this.push(item); |
---|
526 | return this; |
---|
527 | }, |
---|
528 | |
---|
529 | combine: function(array){ |
---|
530 | for (var i = 0, l = array.length; i < l; i++) this.include(array[i]); |
---|
531 | return this; |
---|
532 | }, |
---|
533 | |
---|
534 | erase: function(item){ |
---|
535 | for (var i = this.length; i--;){ |
---|
536 | if (this[i] === item) this.splice(i, 1); |
---|
537 | } |
---|
538 | return this; |
---|
539 | }, |
---|
540 | |
---|
541 | empty: function(){ |
---|
542 | this.length = 0; |
---|
543 | return this; |
---|
544 | }, |
---|
545 | |
---|
546 | flatten: function(){ |
---|
547 | var array = []; |
---|
548 | for (var i = 0, l = this.length; i < l; i++){ |
---|
549 | var type = typeOf(this[i]); |
---|
550 | if (type == 'null') continue; |
---|
551 | array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]); |
---|
552 | } |
---|
553 | return array; |
---|
554 | }, |
---|
555 | |
---|
556 | pick: function(){ |
---|
557 | for (var i = 0, l = this.length; i < l; i++){ |
---|
558 | if (this[i] != null) return this[i]; |
---|
559 | } |
---|
560 | return null; |
---|
561 | }, |
---|
562 | |
---|
563 | hexToRgb: function(array){ |
---|
564 | if (this.length != 3) return null; |
---|
565 | var rgb = this.map(function(value){ |
---|
566 | if (value.length == 1) value += value; |
---|
567 | return value.toInt(16); |
---|
568 | }); |
---|
569 | return (array) ? rgb : 'rgb(' + rgb + ')'; |
---|
570 | }, |
---|
571 | |
---|
572 | rgbToHex: function(array){ |
---|
573 | if (this.length < 3) return null; |
---|
574 | if (this.length == 4 && this[3] == 0 && !array) return 'transparent'; |
---|
575 | var hex = []; |
---|
576 | for (var i = 0; i < 3; i++){ |
---|
577 | var bit = (this[i] - 0).toString(16); |
---|
578 | hex.push((bit.length == 1) ? '0' + bit : bit); |
---|
579 | } |
---|
580 | return (array) ? hex : '#' + hex.join(''); |
---|
581 | } |
---|
582 | |
---|
583 | }); |
---|
584 | |
---|
585 | |
---|
586 | |
---|
587 | |
---|
588 | /* |
---|
589 | --- |
---|
590 | |
---|
591 | name: String |
---|
592 | |
---|
593 | description: Contains String Prototypes like camelCase, capitalize, test, and toInt. |
---|
594 | |
---|
595 | license: MIT-style license. |
---|
596 | |
---|
597 | requires: Type |
---|
598 | |
---|
599 | provides: String |
---|
600 | |
---|
601 | ... |
---|
602 | */ |
---|
603 | |
---|
604 | String.implement({ |
---|
605 | |
---|
606 | test: function(regex, params){ |
---|
607 | return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this); |
---|
608 | }, |
---|
609 | |
---|
610 | contains: function(string, separator){ |
---|
611 | return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : String(this).indexOf(string) > -1; |
---|
612 | }, |
---|
613 | |
---|
614 | trim: function(){ |
---|
615 | return String(this).replace(/^\s+|\s+$/g, ''); |
---|
616 | }, |
---|
617 | |
---|
618 | clean: function(){ |
---|
619 | return String(this).replace(/\s+/g, ' ').trim(); |
---|
620 | }, |
---|
621 | |
---|
622 | camelCase: function(){ |
---|
623 | return String(this).replace(/-\D/g, function(match){ |
---|
624 | return match.charAt(1).toUpperCase(); |
---|
625 | }); |
---|
626 | }, |
---|
627 | |
---|
628 | hyphenate: function(){ |
---|
629 | return String(this).replace(/[A-Z]/g, function(match){ |
---|
630 | return ('-' + match.charAt(0).toLowerCase()); |
---|
631 | }); |
---|
632 | }, |
---|
633 | |
---|
634 | capitalize: function(){ |
---|
635 | return String(this).replace(/\b[a-z]/g, function(match){ |
---|
636 | return match.toUpperCase(); |
---|
637 | }); |
---|
638 | }, |
---|
639 | |
---|
640 | escapeRegExp: function(){ |
---|
641 | return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); |
---|
642 | }, |
---|
643 | |
---|
644 | toInt: function(base){ |
---|
645 | return parseInt(this, base || 10); |
---|
646 | }, |
---|
647 | |
---|
648 | toFloat: function(){ |
---|
649 | return parseFloat(this); |
---|
650 | }, |
---|
651 | |
---|
652 | hexToRgb: function(array){ |
---|
653 | var hex = String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); |
---|
654 | return (hex) ? hex.slice(1).hexToRgb(array) : null; |
---|
655 | }, |
---|
656 | |
---|
657 | rgbToHex: function(array){ |
---|
658 | var rgb = String(this).match(/\d{1,3}/g); |
---|
659 | return (rgb) ? rgb.rgbToHex(array) : null; |
---|
660 | }, |
---|
661 | |
---|
662 | substitute: function(object, regexp){ |
---|
663 | return String(this).replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){ |
---|
664 | if (match.charAt(0) == '\\') return match.slice(1); |
---|
665 | return (object[name] != null) ? object[name] : ''; |
---|
666 | }); |
---|
667 | } |
---|
668 | |
---|
669 | }); |
---|
670 | |
---|
671 | |
---|
672 | /* |
---|
673 | --- |
---|
674 | |
---|
675 | name: Number |
---|
676 | |
---|
677 | description: Contains Number Prototypes like limit, round, times, and ceil. |
---|
678 | |
---|
679 | license: MIT-style license. |
---|
680 | |
---|
681 | requires: Type |
---|
682 | |
---|
683 | provides: Number |
---|
684 | |
---|
685 | ... |
---|
686 | */ |
---|
687 | |
---|
688 | Number.implement({ |
---|
689 | |
---|
690 | limit: function(min, max){ |
---|
691 | return Math.min(max, Math.max(min, this)); |
---|
692 | }, |
---|
693 | |
---|
694 | round: function(precision){ |
---|
695 | precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0); |
---|
696 | return Math.round(this * precision) / precision; |
---|
697 | }, |
---|
698 | |
---|
699 | times: function(fn, bind){ |
---|
700 | for (var i = 0; i < this; i++) fn.call(bind, i, this); |
---|
701 | }, |
---|
702 | |
---|
703 | toFloat: function(){ |
---|
704 | return parseFloat(this); |
---|
705 | }, |
---|
706 | |
---|
707 | toInt: function(base){ |
---|
708 | return parseInt(this, base || 10); |
---|
709 | } |
---|
710 | |
---|
711 | }); |
---|
712 | |
---|
713 | Number.alias('each', 'times'); |
---|
714 | |
---|
715 | (function(math){ |
---|
716 | var methods = {}; |
---|
717 | math.each(function(name){ |
---|
718 | if (!Number[name]) methods[name] = function(){ |
---|
719 | return Math[name].apply(null, [this].concat(Array.from(arguments))); |
---|
720 | }; |
---|
721 | }); |
---|
722 | Number.implement(methods); |
---|
723 | })(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']); |
---|
724 | |
---|
725 | |
---|
726 | /* |
---|
727 | --- |
---|
728 | |
---|
729 | name: Function |
---|
730 | |
---|
731 | description: Contains Function Prototypes like create, bind, pass, and delay. |
---|
732 | |
---|
733 | license: MIT-style license. |
---|
734 | |
---|
735 | requires: Type |
---|
736 | |
---|
737 | provides: Function |
---|
738 | |
---|
739 | ... |
---|
740 | */ |
---|
741 | |
---|
742 | Function.extend({ |
---|
743 | |
---|
744 | attempt: function(){ |
---|
745 | for (var i = 0, l = arguments.length; i < l; i++){ |
---|
746 | try { |
---|
747 | return arguments[i](); |
---|
748 | } catch (e){} |
---|
749 | } |
---|
750 | return null; |
---|
751 | } |
---|
752 | |
---|
753 | }); |
---|
754 | |
---|
755 | Function.implement({ |
---|
756 | |
---|
757 | attempt: function(args, bind){ |
---|
758 | try { |
---|
759 | return this.apply(bind, Array.from(args)); |
---|
760 | } catch (e){} |
---|
761 | |
---|
762 | return null; |
---|
763 | }, |
---|
764 | |
---|
765 | /*<!ES5-bind>*/ |
---|
766 | bind: function(that){ |
---|
767 | var self = this, |
---|
768 | args = arguments.length > 1 ? Array.slice(arguments, 1) : null, |
---|
769 | F = function(){}; |
---|
770 | |
---|
771 | var bound = function(){ |
---|
772 | var context = that, length = arguments.length; |
---|
773 | if (this instanceof bound){ |
---|
774 | F.prototype = self.prototype; |
---|
775 | context = new F; |
---|
776 | } |
---|
777 | var result = (!args && !length) |
---|
778 | ? self.call(context) |
---|
779 | : self.apply(context, args && length ? args.concat(Array.slice(arguments)) : args || arguments); |
---|
780 | return context == that ? result : context; |
---|
781 | }; |
---|
782 | return bound; |
---|
783 | }, |
---|
784 | /*</!ES5-bind>*/ |
---|
785 | |
---|
786 | pass: function(args, bind){ |
---|
787 | var self = this; |
---|
788 | if (args != null) args = Array.from(args); |
---|
789 | return function(){ |
---|
790 | return self.apply(bind, args || arguments); |
---|
791 | }; |
---|
792 | }, |
---|
793 | |
---|
794 | delay: function(delay, bind, args){ |
---|
795 | return setTimeout(this.pass((args == null ? [] : args), bind), delay); |
---|
796 | }, |
---|
797 | |
---|
798 | periodical: function(periodical, bind, args){ |
---|
799 | return setInterval(this.pass((args == null ? [] : args), bind), periodical); |
---|
800 | } |
---|
801 | |
---|
802 | }); |
---|
803 | |
---|
804 | |
---|
805 | |
---|
806 | |
---|
807 | /* |
---|
808 | --- |
---|
809 | |
---|
810 | name: Object |
---|
811 | |
---|
812 | description: Object generic methods |
---|
813 | |
---|
814 | license: MIT-style license. |
---|
815 | |
---|
816 | requires: Type |
---|
817 | |
---|
818 | provides: [Object, Hash] |
---|
819 | |
---|
820 | ... |
---|
821 | */ |
---|
822 | |
---|
823 | (function(){ |
---|
824 | |
---|
825 | var hasOwnProperty = Object.prototype.hasOwnProperty; |
---|
826 | |
---|
827 | Object.extend({ |
---|
828 | |
---|
829 | subset: function(object, keys){ |
---|
830 | var results = {}; |
---|
831 | for (var i = 0, l = keys.length; i < l; i++){ |
---|
832 | var k = keys[i]; |
---|
833 | if (k in object) results[k] = object[k]; |
---|
834 | } |
---|
835 | return results; |
---|
836 | }, |
---|
837 | |
---|
838 | map: function(object, fn, bind){ |
---|
839 | var results = {}; |
---|
840 | for (var key in object){ |
---|
841 | if (hasOwnProperty.call(object, key)) results[key] = fn.call(bind, object[key], key, object); |
---|
842 | } |
---|
843 | return results; |
---|
844 | }, |
---|
845 | |
---|
846 | filter: function(object, fn, bind){ |
---|
847 | var results = {}; |
---|
848 | for (var key in object){ |
---|
849 | var value = object[key]; |
---|
850 | if (hasOwnProperty.call(object, key) && fn.call(bind, value, key, object)) results[key] = value; |
---|
851 | } |
---|
852 | return results; |
---|
853 | }, |
---|
854 | |
---|
855 | every: function(object, fn, bind){ |
---|
856 | for (var key in object){ |
---|
857 | if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return false; |
---|
858 | } |
---|
859 | return true; |
---|
860 | }, |
---|
861 | |
---|
862 | some: function(object, fn, bind){ |
---|
863 | for (var key in object){ |
---|
864 | if (hasOwnProperty.call(object, key) && fn.call(bind, object[key], key)) return true; |
---|
865 | } |
---|
866 | return false; |
---|
867 | }, |
---|
868 | |
---|
869 | keys: function(object){ |
---|
870 | var keys = []; |
---|
871 | for (var key in object){ |
---|
872 | if (hasOwnProperty.call(object, key)) keys.push(key); |
---|
873 | } |
---|
874 | return keys; |
---|
875 | }, |
---|
876 | |
---|
877 | values: function(object){ |
---|
878 | var values = []; |
---|
879 | for (var key in object){ |
---|
880 | if (hasOwnProperty.call(object, key)) values.push(object[key]); |
---|
881 | } |
---|
882 | return values; |
---|
883 | }, |
---|
884 | |
---|
885 | getLength: function(object){ |
---|
886 | return Object.keys(object).length; |
---|
887 | }, |
---|
888 | |
---|
889 | keyOf: function(object, value){ |
---|
890 | for (var key in object){ |
---|
891 | if (hasOwnProperty.call(object, key) && object[key] === value) return key; |
---|
892 | } |
---|
893 | return null; |
---|
894 | }, |
---|
895 | |
---|
896 | contains: function(object, value){ |
---|
897 | return Object.keyOf(object, value) != null; |
---|
898 | }, |
---|
899 | |
---|
900 | toQueryString: function(object, base){ |
---|
901 | var queryString = []; |
---|
902 | |
---|
903 | Object.each(object, function(value, key){ |
---|
904 | if (base) key = base + '[' + key + ']'; |
---|
905 | var result; |
---|
906 | switch (typeOf(value)){ |
---|
907 | case 'object': result = Object.toQueryString(value, key); break; |
---|
908 | case 'array': |
---|
909 | var qs = {}; |
---|
910 | value.each(function(val, i){ |
---|
911 | qs[i] = val; |
---|
912 | }); |
---|
913 | result = Object.toQueryString(qs, key); |
---|
914 | break; |
---|
915 | default: result = key + '=' + encodeURIComponent(value); |
---|
916 | } |
---|
917 | if (value != null) queryString.push(result); |
---|
918 | }); |
---|
919 | |
---|
920 | return queryString.join('&'); |
---|
921 | } |
---|
922 | |
---|
923 | }); |
---|
924 | |
---|
925 | })(); |
---|
926 | |
---|
927 | |
---|
928 | |
---|
929 | |
---|
930 | /* |
---|
931 | --- |
---|
932 | |
---|
933 | name: Browser |
---|
934 | |
---|
935 | description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash. |
---|
936 | |
---|
937 | license: MIT-style license. |
---|
938 | |
---|
939 | requires: [Array, Function, Number, String] |
---|
940 | |
---|
941 | provides: [Browser, Window, Document] |
---|
942 | |
---|
943 | ... |
---|
944 | */ |
---|
945 | |
---|
946 | (function(){ |
---|
947 | |
---|
948 | var document = this.document; |
---|
949 | var window = document.window = this; |
---|
950 | |
---|
951 | var ua = navigator.userAgent.toLowerCase(), |
---|
952 | platform = navigator.platform.toLowerCase(), |
---|
953 | UA = ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0], |
---|
954 | mode = UA[1] == 'ie' && document.documentMode; |
---|
955 | |
---|
956 | var Browser = this.Browser = { |
---|
957 | |
---|
958 | extend: Function.prototype.extend, |
---|
959 | |
---|
960 | name: (UA[1] == 'version') ? UA[3] : UA[1], |
---|
961 | |
---|
962 | version: mode || parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]), |
---|
963 | |
---|
964 | Platform: { |
---|
965 | name: ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0] |
---|
966 | }, |
---|
967 | |
---|
968 | Features: { |
---|
969 | xpath: !!(document.evaluate), |
---|
970 | air: !!(window.runtime), |
---|
971 | query: !!(document.querySelector), |
---|
972 | json: !!(window.JSON) |
---|
973 | }, |
---|
974 | |
---|
975 | Plugins: {} |
---|
976 | |
---|
977 | }; |
---|
978 | |
---|
979 | Browser[Browser.name] = true; |
---|
980 | Browser[Browser.name + parseInt(Browser.version, 10)] = true; |
---|
981 | Browser.Platform[Browser.Platform.name] = true; |
---|
982 | |
---|
983 | // Request |
---|
984 | |
---|
985 | Browser.Request = (function(){ |
---|
986 | |
---|
987 | var XMLHTTP = function(){ |
---|
988 | return new XMLHttpRequest(); |
---|
989 | }; |
---|
990 | |
---|
991 | var MSXML2 = function(){ |
---|
992 | return new ActiveXObject('MSXML2.XMLHTTP'); |
---|
993 | }; |
---|
994 | |
---|
995 | var MSXML = function(){ |
---|
996 | return new ActiveXObject('Microsoft.XMLHTTP'); |
---|
997 | }; |
---|
998 | |
---|
999 | return Function.attempt(function(){ |
---|
1000 | XMLHTTP(); |
---|
1001 | return XMLHTTP; |
---|
1002 | }, function(){ |
---|
1003 | MSXML2(); |
---|
1004 | return MSXML2; |
---|
1005 | }, function(){ |
---|
1006 | MSXML(); |
---|
1007 | return MSXML; |
---|
1008 | }); |
---|
1009 | |
---|
1010 | })(); |
---|
1011 | |
---|
1012 | Browser.Features.xhr = !!(Browser.Request); |
---|
1013 | |
---|
1014 | // Flash detection |
---|
1015 | |
---|
1016 | var version = (Function.attempt(function(){ |
---|
1017 | return navigator.plugins['Shockwave Flash'].description; |
---|
1018 | }, function(){ |
---|
1019 | return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); |
---|
1020 | }) || '0 r0').match(/\d+/g); |
---|
1021 | |
---|
1022 | Browser.Plugins.Flash = { |
---|
1023 | version: Number(version[0] || '0.' + version[1]) || 0, |
---|
1024 | build: Number(version[2]) || 0 |
---|
1025 | }; |
---|
1026 | |
---|
1027 | // String scripts |
---|
1028 | |
---|
1029 | Browser.exec = function(text){ |
---|
1030 | if (!text) return text; |
---|
1031 | if (window.execScript){ |
---|
1032 | window.execScript(text); |
---|
1033 | } else { |
---|
1034 | var script = document.createElement('script'); |
---|
1035 | script.setAttribute('type', 'text/javascript'); |
---|
1036 | script.text = text; |
---|
1037 | document.head.appendChild(script); |
---|
1038 | document.head.removeChild(script); |
---|
1039 | } |
---|
1040 | return text; |
---|
1041 | }; |
---|
1042 | |
---|
1043 | String.implement('stripScripts', function(exec){ |
---|
1044 | var scripts = ''; |
---|
1045 | var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){ |
---|
1046 | scripts += code + '\n'; |
---|
1047 | return ''; |
---|
1048 | }); |
---|
1049 | if (exec === true) Browser.exec(scripts); |
---|
1050 | else if (typeOf(exec) == 'function') exec(scripts, text); |
---|
1051 | return text; |
---|
1052 | }); |
---|
1053 | |
---|
1054 | // Window, Document |
---|
1055 | |
---|
1056 | Browser.extend({ |
---|
1057 | Document: this.Document, |
---|
1058 | Window: this.Window, |
---|
1059 | Element: this.Element, |
---|
1060 | Event: this.Event |
---|
1061 | }); |
---|
1062 | |
---|
1063 | this.Window = this.$constructor = new Type('Window', function(){}); |
---|
1064 | |
---|
1065 | this.$family = Function.from('window').hide(); |
---|
1066 | |
---|
1067 | Window.mirror(function(name, method){ |
---|
1068 | window[name] = method; |
---|
1069 | }); |
---|
1070 | |
---|
1071 | this.Document = document.$constructor = new Type('Document', function(){}); |
---|
1072 | |
---|
1073 | document.$family = Function.from('document').hide(); |
---|
1074 | |
---|
1075 | Document.mirror(function(name, method){ |
---|
1076 | document[name] = method; |
---|
1077 | }); |
---|
1078 | |
---|
1079 | document.html = document.documentElement; |
---|
1080 | if (!document.head) document.head = document.getElementsByTagName('head')[0]; |
---|
1081 | |
---|
1082 | if (document.execCommand) try { |
---|
1083 | document.execCommand("BackgroundImageCache", false, true); |
---|
1084 | } catch (e){} |
---|
1085 | |
---|
1086 | /*<ltIE9>*/ |
---|
1087 | if (this.attachEvent && !this.addEventListener){ |
---|
1088 | var unloadEvent = function(){ |
---|
1089 | this.detachEvent('onunload', unloadEvent); |
---|
1090 | document.head = document.html = document.window = null; |
---|
1091 | }; |
---|
1092 | this.attachEvent('onunload', unloadEvent); |
---|
1093 | } |
---|
1094 | |
---|
1095 | // IE fails on collections and <select>.options (refers to <select>) |
---|
1096 | var arrayFrom = Array.from; |
---|
1097 | try { |
---|
1098 | arrayFrom(document.html.childNodes); |
---|
1099 | } catch(e){ |
---|
1100 | Array.from = function(item){ |
---|
1101 | if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){ |
---|
1102 | var i = item.length, array = new Array(i); |
---|
1103 | while (i--) array[i] = item[i]; |
---|
1104 | return array; |
---|
1105 | } |
---|
1106 | return arrayFrom(item); |
---|
1107 | }; |
---|
1108 | |
---|
1109 | var prototype = Array.prototype, |
---|
1110 | slice = prototype.slice; |
---|
1111 | ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){ |
---|
1112 | var method = prototype[name]; |
---|
1113 | Array[name] = function(item){ |
---|
1114 | return method.apply(Array.from(item), slice.call(arguments, 1)); |
---|
1115 | }; |
---|
1116 | }); |
---|
1117 | } |
---|
1118 | /*</ltIE9>*/ |
---|
1119 | |
---|
1120 | |
---|
1121 | |
---|
1122 | })(); |
---|
1123 | |
---|
1124 | |
---|
1125 | /* |
---|
1126 | --- |
---|
1127 | |
---|
1128 | name: Event |
---|
1129 | |
---|
1130 | description: Contains the Event Type, to make the event object cross-browser. |
---|
1131 | |
---|
1132 | license: MIT-style license. |
---|
1133 | |
---|
1134 | requires: [Window, Document, Array, Function, String, Object] |
---|
1135 | |
---|
1136 | provides: Event |
---|
1137 | |
---|
1138 | ... |
---|
1139 | */ |
---|
1140 | |
---|
1141 | (function() { |
---|
1142 | |
---|
1143 | var _keys = {}; |
---|
1144 | |
---|
1145 | var DOMEvent = this.DOMEvent = new Type('DOMEvent', function(event, win){ |
---|
1146 | if (!win) win = window; |
---|
1147 | event = event || win.event; |
---|
1148 | if (event.$extended) return event; |
---|
1149 | this.event = event; |
---|
1150 | this.$extended = true; |
---|
1151 | this.shift = event.shiftKey; |
---|
1152 | this.control = event.ctrlKey; |
---|
1153 | this.alt = event.altKey; |
---|
1154 | this.meta = event.metaKey; |
---|
1155 | var type = this.type = event.type; |
---|
1156 | var target = event.target || event.srcElement; |
---|
1157 | while (target && target.nodeType == 3) target = target.parentNode; |
---|
1158 | this.target = document.id(target); |
---|
1159 | |
---|
1160 | if (type.indexOf('key') == 0){ |
---|
1161 | var code = this.code = (event.which || event.keyCode); |
---|
1162 | this.key = _keys[code]; |
---|
1163 | if (type == 'keydown'){ |
---|
1164 | if (code > 111 && code < 124) this.key = 'f' + (code - 111); |
---|
1165 | else if (code > 95 && code < 106) this.key = code - 96; |
---|
1166 | } |
---|
1167 | if (this.key == null) this.key = String.fromCharCode(code).toLowerCase(); |
---|
1168 | } else if (type == 'click' || type == 'dblclick' || type == 'contextmenu' || type == 'DOMMouseScroll' || type.indexOf('mouse') == 0){ |
---|
1169 | var doc = win.document; |
---|
1170 | doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; |
---|
1171 | this.page = { |
---|
1172 | x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft, |
---|
1173 | y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop |
---|
1174 | }; |
---|
1175 | this.client = { |
---|
1176 | x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX, |
---|
1177 | y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY |
---|
1178 | }; |
---|
1179 | if (type == 'DOMMouseScroll' || type == 'mousewheel') |
---|
1180 | this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3; |
---|
1181 | |
---|
1182 | this.rightClick = (event.which == 3 || event.button == 2); |
---|
1183 | if (type == 'mouseover' || type == 'mouseout'){ |
---|
1184 | var related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element']; |
---|
1185 | while (related && related.nodeType == 3) related = related.parentNode; |
---|
1186 | this.relatedTarget = document.id(related); |
---|
1187 | } |
---|
1188 | } else if (type.indexOf('touch') == 0 || type.indexOf('gesture') == 0){ |
---|
1189 | this.rotation = event.rotation; |
---|
1190 | this.scale = event.scale; |
---|
1191 | this.targetTouches = event.targetTouches; |
---|
1192 | this.changedTouches = event.changedTouches; |
---|
1193 | var touches = this.touches = event.touches; |
---|
1194 | if (touches && touches[0]){ |
---|
1195 | var touch = touches[0]; |
---|
1196 | this.page = {x: touch.pageX, y: touch.pageY}; |
---|
1197 | this.client = {x: touch.clientX, y: touch.clientY}; |
---|
1198 | } |
---|
1199 | } |
---|
1200 | |
---|
1201 | if (!this.client) this.client = {}; |
---|
1202 | if (!this.page) this.page = {}; |
---|
1203 | }); |
---|
1204 | |
---|
1205 | DOMEvent.implement({ |
---|
1206 | |
---|
1207 | stop: function(){ |
---|
1208 | return this.preventDefault().stopPropagation(); |
---|
1209 | }, |
---|
1210 | |
---|
1211 | stopPropagation: function(){ |
---|
1212 | if (this.event.stopPropagation) this.event.stopPropagation(); |
---|
1213 | else this.event.cancelBubble = true; |
---|
1214 | return this; |
---|
1215 | }, |
---|
1216 | |
---|
1217 | preventDefault: function(){ |
---|
1218 | if (this.event.preventDefault) this.event.preventDefault(); |
---|
1219 | else this.event.returnValue = false; |
---|
1220 | return this; |
---|
1221 | } |
---|
1222 | |
---|
1223 | }); |
---|
1224 | |
---|
1225 | DOMEvent.defineKey = function(code, key){ |
---|
1226 | _keys[code] = key; |
---|
1227 | return this; |
---|
1228 | }; |
---|
1229 | |
---|
1230 | DOMEvent.defineKeys = DOMEvent.defineKey.overloadSetter(true); |
---|
1231 | |
---|
1232 | DOMEvent.defineKeys({ |
---|
1233 | '38': 'up', '40': 'down', '37': 'left', '39': 'right', |
---|
1234 | '27': 'esc', '32': 'space', '8': 'backspace', '9': 'tab', |
---|
1235 | '46': 'delete', '13': 'enter' |
---|
1236 | }); |
---|
1237 | |
---|
1238 | })(); |
---|
1239 | |
---|
1240 | |
---|
1241 | |
---|
1242 | |
---|
1243 | |
---|
1244 | |
---|
1245 | /* |
---|
1246 | --- |
---|
1247 | |
---|
1248 | name: Class |
---|
1249 | |
---|
1250 | description: Contains the Class Function for easily creating, extending, and implementing reusable Classes. |
---|
1251 | |
---|
1252 | license: MIT-style license. |
---|
1253 | |
---|
1254 | requires: [Array, String, Function, Number] |
---|
1255 | |
---|
1256 | provides: Class |
---|
1257 | |
---|
1258 | ... |
---|
1259 | */ |
---|
1260 | |
---|
1261 | (function(){ |
---|
1262 | |
---|
1263 | var Class = this.Class = new Type('Class', function(params){ |
---|
1264 | if (instanceOf(params, Function)) params = {initialize: params}; |
---|
1265 | |
---|
1266 | var newClass = function(){ |
---|
1267 | reset(this); |
---|
1268 | if (newClass.$prototyping) return this; |
---|
1269 | this.$caller = null; |
---|
1270 | var value = (this.initialize) ? this.initialize.apply(this, arguments) : this; |
---|
1271 | this.$caller = this.caller = null; |
---|
1272 | return value; |
---|
1273 | }.extend(this).implement(params); |
---|
1274 | |
---|
1275 | newClass.$constructor = Class; |
---|
1276 | newClass.prototype.$constructor = newClass; |
---|
1277 | newClass.prototype.parent = parent; |
---|
1278 | |
---|
1279 | return newClass; |
---|
1280 | }); |
---|
1281 | |
---|
1282 | var parent = function(){ |
---|
1283 | if (!this.$caller) throw new Error('The method "parent" cannot be called.'); |
---|
1284 | var name = this.$caller.$name, |
---|
1285 | parent = this.$caller.$owner.parent, |
---|
1286 | previous = (parent) ? parent.prototype[name] : null; |
---|
1287 | if (!previous) throw new Error('The method "' + name + '" has no parent.'); |
---|
1288 | return previous.apply(this, arguments); |
---|
1289 | }; |
---|
1290 | |
---|
1291 | var reset = function(object){ |
---|
1292 | for (var key in object){ |
---|
1293 | var value = object[key]; |
---|
1294 | switch (typeOf(value)){ |
---|
1295 | case 'object': |
---|
1296 | var F = function(){}; |
---|
1297 | F.prototype = value; |
---|
1298 | object[key] = reset(new F); |
---|
1299 | break; |
---|
1300 | case 'array': object[key] = value.clone(); break; |
---|
1301 | } |
---|
1302 | } |
---|
1303 | return object; |
---|
1304 | }; |
---|
1305 | |
---|
1306 | var wrap = function(self, key, method){ |
---|
1307 | if (method.$origin) method = method.$origin; |
---|
1308 | var wrapper = function(){ |
---|
1309 | if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.'); |
---|
1310 | var caller = this.caller, current = this.$caller; |
---|
1311 | this.caller = current; this.$caller = wrapper; |
---|
1312 | var result = method.apply(this, arguments); |
---|
1313 | this.$caller = current; this.caller = caller; |
---|
1314 | return result; |
---|
1315 | }.extend({$owner: self, $origin: method, $name: key}); |
---|
1316 | return wrapper; |
---|
1317 | }; |
---|
1318 | |
---|
1319 | var implement = function(key, value, retain){ |
---|
1320 | if (Class.Mutators.hasOwnProperty(key)){ |
---|
1321 | value = Class.Mutators[key].call(this, value); |
---|
1322 | if (value == null) return this; |
---|
1323 | } |
---|
1324 | |
---|
1325 | if (typeOf(value) == 'function'){ |
---|
1326 | if (value.$hidden) return this; |
---|
1327 | this.prototype[key] = (retain) ? value : wrap(this, key, value); |
---|
1328 | } else { |
---|
1329 | Object.merge(this.prototype, key, value); |
---|
1330 | } |
---|
1331 | |
---|
1332 | return this; |
---|
1333 | }; |
---|
1334 | |
---|
1335 | var getInstance = function(klass){ |
---|
1336 | klass.$prototyping = true; |
---|
1337 | var proto = new klass; |
---|
1338 | delete klass.$prototyping; |
---|
1339 | return proto; |
---|
1340 | }; |
---|
1341 | |
---|
1342 | Class.implement('implement', implement.overloadSetter()); |
---|
1343 | |
---|
1344 | Class.Mutators = { |
---|
1345 | |
---|
1346 | Extends: function(parent){ |
---|
1347 | this.parent = parent; |
---|
1348 | this.prototype = getInstance(parent); |
---|
1349 | }, |
---|
1350 | |
---|
1351 | Implements: function(items){ |
---|
1352 | Array.from(items).each(function(item){ |
---|
1353 | var instance = new item; |
---|
1354 | for (var key in instance) implement.call(this, key, instance[key], true); |
---|
1355 | }, this); |
---|
1356 | } |
---|
1357 | }; |
---|
1358 | |
---|
1359 | })(); |
---|
1360 | |
---|
1361 | |
---|
1362 | /* |
---|
1363 | --- |
---|
1364 | |
---|
1365 | name: Class.Extras |
---|
1366 | |
---|
1367 | description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks. |
---|
1368 | |
---|
1369 | license: MIT-style license. |
---|
1370 | |
---|
1371 | requires: Class |
---|
1372 | |
---|
1373 | provides: [Class.Extras, Chain, Events, Options] |
---|
1374 | |
---|
1375 | ... |
---|
1376 | */ |
---|
1377 | |
---|
1378 | (function(){ |
---|
1379 | |
---|
1380 | this.Chain = new Class({ |
---|
1381 | |
---|
1382 | $chain: [], |
---|
1383 | |
---|
1384 | chain: function(){ |
---|
1385 | this.$chain.append(Array.flatten(arguments)); |
---|
1386 | return this; |
---|
1387 | }, |
---|
1388 | |
---|
1389 | callChain: function(){ |
---|
1390 | return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false; |
---|
1391 | }, |
---|
1392 | |
---|
1393 | clearChain: function(){ |
---|
1394 | this.$chain.empty(); |
---|
1395 | return this; |
---|
1396 | } |
---|
1397 | |
---|
1398 | }); |
---|
1399 | |
---|
1400 | var removeOn = function(string){ |
---|
1401 | return string.replace(/^on([A-Z])/, function(full, first){ |
---|
1402 | return first.toLowerCase(); |
---|
1403 | }); |
---|
1404 | }; |
---|
1405 | |
---|
1406 | this.Events = new Class({ |
---|
1407 | |
---|
1408 | $events: {}, |
---|
1409 | |
---|
1410 | addEvent: function(type, fn, internal){ |
---|
1411 | type = removeOn(type); |
---|
1412 | |
---|
1413 | |
---|
1414 | |
---|
1415 | this.$events[type] = (this.$events[type] || []).include(fn); |
---|
1416 | if (internal) fn.internal = true; |
---|
1417 | return this; |
---|
1418 | }, |
---|
1419 | |
---|
1420 | addEvents: function(events){ |
---|
1421 | for (var type in events) this.addEvent(type, events[type]); |
---|
1422 | return this; |
---|
1423 | }, |
---|
1424 | |
---|
1425 | fireEvent: function(type, args, delay){ |
---|
1426 | type = removeOn(type); |
---|
1427 | var events = this.$events[type]; |
---|
1428 | if (!events) return this; |
---|
1429 | args = Array.from(args); |
---|
1430 | events.each(function(fn){ |
---|
1431 | if (delay) fn.delay(delay, this, args); |
---|
1432 | else fn.apply(this, args); |
---|
1433 | }, this); |
---|
1434 | return this; |
---|
1435 | }, |
---|
1436 | |
---|
1437 | removeEvent: function(type, fn){ |
---|
1438 | type = removeOn(type); |
---|
1439 | var events = this.$events[type]; |
---|
1440 | if (events && !fn.internal){ |
---|
1441 | var index = events.indexOf(fn); |
---|
1442 | if (index != -1) delete events[index]; |
---|
1443 | } |
---|
1444 | return this; |
---|
1445 | }, |
---|
1446 | |
---|
1447 | removeEvents: function(events){ |
---|
1448 | var type; |
---|
1449 | if (typeOf(events) == 'object'){ |
---|
1450 | for (type in events) this.removeEvent(type, events[type]); |
---|
1451 | return this; |
---|
1452 | } |
---|
1453 | if (events) events = removeOn(events); |
---|
1454 | for (type in this.$events){ |
---|
1455 | if (events && events != type) continue; |
---|
1456 | var fns = this.$events[type]; |
---|
1457 | for (var i = fns.length; i--;) if (i in fns){ |
---|
1458 | this.removeEvent(type, fns[i]); |
---|
1459 | } |
---|
1460 | } |
---|
1461 | return this; |
---|
1462 | } |
---|
1463 | |
---|
1464 | }); |
---|
1465 | |
---|
1466 | this.Options = new Class({ |
---|
1467 | |
---|
1468 | setOptions: function(){ |
---|
1469 | var options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments)); |
---|
1470 | if (this.addEvent) for (var option in options){ |
---|
1471 | if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue; |
---|
1472 | this.addEvent(option, options[option]); |
---|
1473 | delete options[option]; |
---|
1474 | } |
---|
1475 | return this; |
---|
1476 | } |
---|
1477 | |
---|
1478 | }); |
---|
1479 | |
---|
1480 | })(); |
---|
1481 | |
---|
1482 | |
---|
1483 | /* |
---|
1484 | --- |
---|
1485 | name: Slick.Parser |
---|
1486 | description: Standalone CSS3 Selector parser |
---|
1487 | provides: Slick.Parser |
---|
1488 | ... |
---|
1489 | */ |
---|
1490 | |
---|
1491 | ;(function(){ |
---|
1492 | |
---|
1493 | var parsed, |
---|
1494 | separatorIndex, |
---|
1495 | combinatorIndex, |
---|
1496 | reversed, |
---|
1497 | cache = {}, |
---|
1498 | reverseCache = {}, |
---|
1499 | reUnescape = /\\/g; |
---|
1500 | |
---|
1501 | var parse = function(expression, isReversed){ |
---|
1502 | if (expression == null) return null; |
---|
1503 | if (expression.Slick === true) return expression; |
---|
1504 | expression = ('' + expression).replace(/^\s+|\s+$/g, ''); |
---|
1505 | reversed = !!isReversed; |
---|
1506 | var currentCache = (reversed) ? reverseCache : cache; |
---|
1507 | if (currentCache[expression]) return currentCache[expression]; |
---|
1508 | parsed = { |
---|
1509 | Slick: true, |
---|
1510 | expressions: [], |
---|
1511 | raw: expression, |
---|
1512 | reverse: function(){ |
---|
1513 | return parse(this.raw, true); |
---|
1514 | } |
---|
1515 | }; |
---|
1516 | separatorIndex = -1; |
---|
1517 | while (expression != (expression = expression.replace(regexp, parser))); |
---|
1518 | parsed.length = parsed.expressions.length; |
---|
1519 | return currentCache[parsed.raw] = (reversed) ? reverse(parsed) : parsed; |
---|
1520 | }; |
---|
1521 | |
---|
1522 | var reverseCombinator = function(combinator){ |
---|
1523 | if (combinator === '!') return ' '; |
---|
1524 | else if (combinator === ' ') return '!'; |
---|
1525 | else if ((/^!/).test(combinator)) return combinator.replace(/^!/, ''); |
---|
1526 | else return '!' + combinator; |
---|
1527 | }; |
---|
1528 | |
---|
1529 | var reverse = function(expression){ |
---|
1530 | var expressions = expression.expressions; |
---|
1531 | for (var i = 0; i < expressions.length; i++){ |
---|
1532 | var exp = expressions[i]; |
---|
1533 | var last = {parts: [], tag: '*', combinator: reverseCombinator(exp[0].combinator)}; |
---|
1534 | |
---|
1535 | for (var j = 0; j < exp.length; j++){ |
---|
1536 | var cexp = exp[j]; |
---|
1537 | if (!cexp.reverseCombinator) cexp.reverseCombinator = ' '; |
---|
1538 | cexp.combinator = cexp.reverseCombinator; |
---|
1539 | delete cexp.reverseCombinator; |
---|
1540 | } |
---|
1541 | |
---|
1542 | exp.reverse().push(last); |
---|
1543 | } |
---|
1544 | return expression; |
---|
1545 | }; |
---|
1546 | |
---|
1547 | var escapeRegExp = function(string){// Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevithan.com/regex/xregexp/> MIT License |
---|
1548 | return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, function(match){ |
---|
1549 | return '\\' + match; |
---|
1550 | }); |
---|
1551 | }; |
---|
1552 | |
---|
1553 | var regexp = new RegExp( |
---|
1554 | /* |
---|
1555 | #!/usr/bin/env ruby |
---|
1556 | puts "\t\t" + DATA.read.gsub(/\(\?x\)|\s+#.*$|\s+|\\$|\\n/,'') |
---|
1557 | __END__ |
---|
1558 | "(?x)^(?:\ |
---|
1559 | \\s* ( , ) \\s* # Separator \n\ |
---|
1560 | | \\s* ( <combinator>+ ) \\s* # Combinator \n\ |
---|
1561 | | ( \\s+ ) # CombinatorChildren \n\ |
---|
1562 | | ( <unicode>+ | \\* ) # Tag \n\ |
---|
1563 | | \\# ( <unicode>+ ) # ID \n\ |
---|
1564 | | \\. ( <unicode>+ ) # ClassName \n\ |
---|
1565 | | # Attribute \n\ |
---|
1566 | \\[ \ |
---|
1567 | \\s* (<unicode1>+) (?: \ |
---|
1568 | \\s* ([*^$!~|]?=) (?: \ |
---|
1569 | \\s* (?:\ |
---|
1570 | ([\"']?)(.*?)\\9 \ |
---|
1571 | )\ |
---|
1572 | ) \ |
---|
1573 | )? \\s* \ |
---|
1574 | \\](?!\\]) \n\ |
---|
1575 | | :+ ( <unicode>+ )(?:\ |
---|
1576 | \\( (?:\ |
---|
1577 | (?:([\"'])([^\\12]*)\\12)|((?:\\([^)]+\\)|[^()]*)+)\ |
---|
1578 | ) \\)\ |
---|
1579 | )?\ |
---|
1580 | )" |
---|
1581 | */ |
---|
1582 | "^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)" |
---|
1583 | .replace(/<combinator>/, '[' + escapeRegExp(">+~`!@$%^&={}\\;</") + ']') |
---|
1584 | .replace(/<unicode>/g, '(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])') |
---|
1585 | .replace(/<unicode1>/g, '(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])') |
---|
1586 | ); |
---|
1587 | |
---|
1588 | function parser( |
---|
1589 | rawMatch, |
---|
1590 | |
---|
1591 | separator, |
---|
1592 | combinator, |
---|
1593 | combinatorChildren, |
---|
1594 | |
---|
1595 | tagName, |
---|
1596 | id, |
---|
1597 | className, |
---|
1598 | |
---|
1599 | attributeKey, |
---|
1600 | attributeOperator, |
---|
1601 | attributeQuote, |
---|
1602 | attributeValue, |
---|
1603 | |
---|
1604 | pseudoMarker, |
---|
1605 | pseudoClass, |
---|
1606 | pseudoQuote, |
---|
1607 | pseudoClassQuotedValue, |
---|
1608 | pseudoClassValue |
---|
1609 | ){ |
---|
1610 | if (separator || separatorIndex === -1){ |
---|
1611 | parsed.expressions[++separatorIndex] = []; |
---|
1612 | combinatorIndex = -1; |
---|
1613 | if (separator) return ''; |
---|
1614 | } |
---|
1615 | |
---|
1616 | if (combinator || combinatorChildren || combinatorIndex === -1){ |
---|
1617 | combinator = combinator || ' '; |
---|
1618 | var currentSeparator = parsed.expressions[separatorIndex]; |
---|
1619 | if (reversed && currentSeparator[combinatorIndex]) |
---|
1620 | currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator); |
---|
1621 | currentSeparator[++combinatorIndex] = {combinator: combinator, tag: '*'}; |
---|
1622 | } |
---|
1623 | |
---|
1624 | var currentParsed = parsed.expressions[separatorIndex][combinatorIndex]; |
---|
1625 | |
---|
1626 | if (tagName){ |
---|
1627 | currentParsed.tag = tagName.replace(reUnescape, ''); |
---|
1628 | |
---|
1629 | } else if (id){ |
---|
1630 | currentParsed.id = id.replace(reUnescape, ''); |
---|
1631 | |
---|
1632 | } else if (className){ |
---|
1633 | className = className.replace(reUnescape, ''); |
---|
1634 | |
---|
1635 | if (!currentParsed.classList) currentParsed.classList = []; |
---|
1636 | if (!currentParsed.classes) currentParsed.classes = []; |
---|
1637 | currentParsed.classList.push(className); |
---|
1638 | currentParsed.classes.push({ |
---|
1639 | value: className, |
---|
1640 | regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)') |
---|
1641 | }); |
---|
1642 | |
---|
1643 | } else if (pseudoClass){ |
---|
1644 | pseudoClassValue = pseudoClassValue || pseudoClassQuotedValue; |
---|
1645 | pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null; |
---|
1646 | |
---|
1647 | if (!currentParsed.pseudos) currentParsed.pseudos = []; |
---|
1648 | currentParsed.pseudos.push({ |
---|
1649 | key: pseudoClass.replace(reUnescape, ''), |
---|
1650 | value: pseudoClassValue, |
---|
1651 | type: pseudoMarker.length == 1 ? 'class' : 'element' |
---|
1652 | }); |
---|
1653 | |
---|
1654 | } else if (attributeKey){ |
---|
1655 | attributeKey = attributeKey.replace(reUnescape, ''); |
---|
1656 | attributeValue = (attributeValue || '').replace(reUnescape, ''); |
---|
1657 | |
---|
1658 | var test, regexp; |
---|
1659 | |
---|
1660 | switch (attributeOperator){ |
---|
1661 | case '^=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) ); break; |
---|
1662 | case '$=' : regexp = new RegExp( escapeRegExp(attributeValue) +'$' ); break; |
---|
1663 | case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attributeValue) +'(\\s|$)' ); break; |
---|
1664 | case '|=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) +'(-|$)' ); break; |
---|
1665 | case '=' : test = function(value){ |
---|
1666 | return attributeValue == value; |
---|
1667 | }; break; |
---|
1668 | case '*=' : test = function(value){ |
---|
1669 | return value && value.indexOf(attributeValue) > -1; |
---|
1670 | }; break; |
---|
1671 | case '!=' : test = function(value){ |
---|
1672 | return attributeValue != value; |
---|
1673 | }; break; |
---|
1674 | default : test = function(value){ |
---|
1675 | return !!value; |
---|
1676 | }; |
---|
1677 | } |
---|
1678 | |
---|
1679 | if (attributeValue == '' && (/^[*$^]=$/).test(attributeOperator)) test = function(){ |
---|
1680 | return false; |
---|
1681 | }; |
---|
1682 | |
---|
1683 | if (!test) test = function(value){ |
---|
1684 | return value && regexp.test(value); |
---|
1685 | }; |
---|
1686 | |
---|
1687 | if (!currentParsed.attributes) currentParsed.attributes = []; |
---|
1688 | currentParsed.attributes.push({ |
---|
1689 | key: attributeKey, |
---|
1690 | operator: attributeOperator, |
---|
1691 | value: attributeValue, |
---|
1692 | test: test |
---|
1693 | }); |
---|
1694 | |
---|
1695 | } |
---|
1696 | |
---|
1697 | return ''; |
---|
1698 | }; |
---|
1699 | |
---|
1700 | // Slick NS |
---|
1701 | |
---|
1702 | var Slick = (this.Slick || {}); |
---|
1703 | |
---|
1704 | Slick.parse = function(expression){ |
---|
1705 | return parse(expression); |
---|
1706 | }; |
---|
1707 | |
---|
1708 | Slick.escapeRegExp = escapeRegExp; |
---|
1709 | |
---|
1710 | if (!this.Slick) this.Slick = Slick; |
---|
1711 | |
---|
1712 | }).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this); |
---|
1713 | |
---|
1714 | |
---|
1715 | /* |
---|
1716 | --- |
---|
1717 | name: Slick.Finder |
---|
1718 | description: The new, superfast css selector engine. |
---|
1719 | provides: Slick.Finder |
---|
1720 | requires: Slick.Parser |
---|
1721 | ... |
---|
1722 | */ |
---|
1723 | |
---|
1724 | ;(function(){ |
---|
1725 | |
---|
1726 | var local = {}, |
---|
1727 | featuresCache = {}, |
---|
1728 | toString = Object.prototype.toString; |
---|
1729 | |
---|
1730 | // Feature / Bug detection |
---|
1731 | |
---|
1732 | local.isNativeCode = function(fn){ |
---|
1733 | return (/\{\s*\[native code\]\s*\}/).test('' + fn); |
---|
1734 | }; |
---|
1735 | |
---|
1736 | local.isXML = function(document){ |
---|
1737 | return (!!document.xmlVersion) || (!!document.xml) || (toString.call(document) == '[object XMLDocument]') || |
---|
1738 | (document.nodeType == 9 && document.documentElement.nodeName != 'HTML'); |
---|
1739 | }; |
---|
1740 | |
---|
1741 | local.setDocument = function(document){ |
---|
1742 | |
---|
1743 | // convert elements / window arguments to document. if document cannot be extrapolated, the function returns. |
---|
1744 | var nodeType = document.nodeType; |
---|
1745 | if (nodeType == 9); // document |
---|
1746 | else if (nodeType) document = document.ownerDocument; // node |
---|
1747 | else if (document.navigator) document = document.document; // window |
---|
1748 | else return; |
---|
1749 | |
---|
1750 | // check if it's the old document |
---|
1751 | |
---|
1752 | if (this.document === document) return; |
---|
1753 | this.document = document; |
---|
1754 | |
---|
1755 | // check if we have done feature detection on this document before |
---|
1756 | |
---|
1757 | var root = document.documentElement, |
---|
1758 | rootUid = this.getUIDXML(root), |
---|
1759 | features = featuresCache[rootUid], |
---|
1760 | feature; |
---|
1761 | |
---|
1762 | if (features){ |
---|
1763 | for (feature in features){ |
---|
1764 | this[feature] = features[feature]; |
---|
1765 | } |
---|
1766 | return; |
---|
1767 | } |
---|
1768 | |
---|
1769 | features = featuresCache[rootUid] = {}; |
---|
1770 | |
---|
1771 | features.root = root; |
---|
1772 | features.isXMLDocument = this.isXML(document); |
---|
1773 | |
---|
1774 | features.brokenStarGEBTN |
---|
1775 | = features.starSelectsClosedQSA |
---|
1776 | = features.idGetsName |
---|
1777 | = features.brokenMixedCaseQSA |
---|
1778 | = features.brokenGEBCN |
---|
1779 | = features.brokenCheckedQSA |
---|
1780 | = features.brokenEmptyAttributeQSA |
---|
1781 | = features.isHTMLDocument |
---|
1782 | = features.nativeMatchesSelector |
---|
1783 | = false; |
---|
1784 | |
---|
1785 | var starSelectsClosed, starSelectsComments, |
---|
1786 | brokenSecondClassNameGEBCN, cachedGetElementsByClassName, |
---|
1787 | brokenFormAttributeGetter; |
---|
1788 | |
---|
1789 | var selected, id = 'slick_uniqueid'; |
---|
1790 | var testNode = document.createElement('div'); |
---|
1791 | |
---|
1792 | var testRoot = document.body || document.getElementsByTagName('body')[0] || root; |
---|
1793 | testRoot.appendChild(testNode); |
---|
1794 | |
---|
1795 | // on non-HTML documents innerHTML and getElementsById doesnt work properly |
---|
1796 | try { |
---|
1797 | testNode.innerHTML = '<a id="'+id+'"></a>'; |
---|
1798 | features.isHTMLDocument = !!document.getElementById(id); |
---|
1799 | } catch(e){}; |
---|
1800 | |
---|
1801 | if (features.isHTMLDocument){ |
---|
1802 | |
---|
1803 | testNode.style.display = 'none'; |
---|
1804 | |
---|
1805 | // IE returns comment nodes for getElementsByTagName('*') for some documents |
---|
1806 | testNode.appendChild(document.createComment('')); |
---|
1807 | starSelectsComments = (testNode.getElementsByTagName('*').length > 1); |
---|
1808 | |
---|
1809 | // IE returns closed nodes (EG:"</foo>") for getElementsByTagName('*') for some documents |
---|
1810 | try { |
---|
1811 | testNode.innerHTML = 'foo</foo>'; |
---|
1812 | selected = testNode.getElementsByTagName('*'); |
---|
1813 | starSelectsClosed = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/'); |
---|
1814 | } catch(e){}; |
---|
1815 | |
---|
1816 | features.brokenStarGEBTN = starSelectsComments || starSelectsClosed; |
---|
1817 | |
---|
1818 | // IE returns elements with the name instead of just id for getElementsById for some documents |
---|
1819 | try { |
---|
1820 | testNode.innerHTML = '<a name="'+ id +'"></a><b id="'+ id +'"></b>'; |
---|
1821 | features.idGetsName = document.getElementById(id) === testNode.firstChild; |
---|
1822 | } catch(e){}; |
---|
1823 | |
---|
1824 | if (testNode.getElementsByClassName){ |
---|
1825 | |
---|
1826 | // Safari 3.2 getElementsByClassName caches results |
---|
1827 | try { |
---|
1828 | testNode.innerHTML = '<a class="f"></a><a class="b"></a>'; |
---|
1829 | testNode.getElementsByClassName('b').length; |
---|
1830 | testNode.firstChild.className = 'b'; |
---|
1831 | cachedGetElementsByClassName = (testNode.getElementsByClassName('b').length != 2); |
---|
1832 | } catch(e){}; |
---|
1833 | |
---|
1834 | // Opera 9.6 getElementsByClassName doesnt detects the class if its not the first one |
---|
1835 | try { |
---|
1836 | testNode.innerHTML = '<a class="a"></a><a class="f b a"></a>'; |
---|
1837 | brokenSecondClassNameGEBCN = (testNode.getElementsByClassName('a').length != 2); |
---|
1838 | } catch(e){}; |
---|
1839 | |
---|
1840 | features.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN; |
---|
1841 | } |
---|
1842 | |
---|
1843 | if (testNode.querySelectorAll){ |
---|
1844 | // IE 8 returns closed nodes (EG:"</foo>") for querySelectorAll('*') for some documents |
---|
1845 | try { |
---|
1846 | testNode.innerHTML = 'foo</foo>'; |
---|
1847 | selected = testNode.querySelectorAll('*'); |
---|
1848 | features.starSelectsClosedQSA = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/'); |
---|
1849 | } catch(e){}; |
---|
1850 | |
---|
1851 | // Safari 3.2 querySelectorAll doesnt work with mixedcase on quirksmode |
---|
1852 | try { |
---|
1853 | testNode.innerHTML = '<a class="MiX"></a>'; |
---|
1854 | features.brokenMixedCaseQSA = !testNode.querySelectorAll('.MiX').length; |
---|
1855 | } catch(e){}; |
---|
1856 | |
---|
1857 | // Webkit and Opera dont return selected options on querySelectorAll |
---|
1858 | try { |
---|
1859 | testNode.innerHTML = '<select><option selected="selected">a</option></select>'; |
---|
1860 | features.brokenCheckedQSA = (testNode.querySelectorAll(':checked').length == 0); |
---|
1861 | } catch(e){}; |
---|
1862 | |
---|
1863 | // IE returns incorrect results for attr[*^$]="" selectors on querySelectorAll |
---|
1864 | try { |
---|
1865 | testNode.innerHTML = '<a class=""></a>'; |
---|
1866 | features.brokenEmptyAttributeQSA = (testNode.querySelectorAll('[class*=""]').length != 0); |
---|
1867 | } catch(e){}; |
---|
1868 | |
---|
1869 | } |
---|
1870 | |
---|
1871 | // IE6-7, if a form has an input of id x, form.getAttribute(x) returns a reference to the input |
---|
1872 | try { |
---|
1873 | testNode.innerHTML = '<form action="s"><input id="action"/></form>'; |
---|
1874 | brokenFormAttributeGetter = (testNode.firstChild.getAttribute('action') != 's'); |
---|
1875 | } catch(e){}; |
---|
1876 | |
---|
1877 | // native matchesSelector function |
---|
1878 | |
---|
1879 | features.nativeMatchesSelector = root.matchesSelector || /*root.msMatchesSelector ||*/ root.mozMatchesSelector || root.webkitMatchesSelector; |
---|
1880 | if (features.nativeMatchesSelector) try { |
---|
1881 | // if matchesSelector trows errors on incorrect sintaxes we can use it |
---|
1882 | features.nativeMatchesSelector.call(root, ':slick'); |
---|
1883 | features.nativeMatchesSelector = null; |
---|
1884 | } catch(e){}; |
---|
1885 | |
---|
1886 | } |
---|
1887 | |
---|
1888 | try { |
---|
1889 | root.slick_expando = 1; |
---|
1890 | delete root.slick_expando; |
---|
1891 | features.getUID = this.getUIDHTML; |
---|
1892 | } catch(e) { |
---|
1893 | features.getUID = this.getUIDXML; |
---|
1894 | } |
---|
1895 | |
---|
1896 | testRoot.removeChild(testNode); |
---|
1897 | testNode = selected = testRoot = null; |
---|
1898 | |
---|
1899 | // getAttribute |
---|
1900 | |
---|
1901 | features.getAttribute = (features.isHTMLDocument && brokenFormAttributeGetter) ? function(node, name){ |
---|
1902 | var method = this.attributeGetters[name]; |
---|
1903 | if (method) return method.call(node); |
---|
1904 | var attributeNode = node.getAttributeNode(name); |
---|
1905 | return (attributeNode) ? attributeNode.nodeValue : null; |
---|
1906 | } : function(node, name){ |
---|
1907 | var method = this.attributeGetters[name]; |
---|
1908 | return (method) ? method.call(node) : node.getAttribute(name); |
---|
1909 | }; |
---|
1910 | |
---|
1911 | // hasAttribute |
---|
1912 | |
---|
1913 | features.hasAttribute = (root && this.isNativeCode(root.hasAttribute)) ? function(node, attribute) { |
---|
1914 | return node.hasAttribute(attribute); |
---|
1915 | } : function(node, attribute) { |
---|
1916 | node = node.getAttributeNode(attribute); |
---|
1917 | return !!(node && (node.specified || node.nodeValue)); |
---|
1918 | }; |
---|
1919 | |
---|
1920 | // contains |
---|
1921 | // FIXME: Add specs: local.contains should be different for xml and html documents? |
---|
1922 | var nativeRootContains = root && this.isNativeCode(root.contains), |
---|
1923 | nativeDocumentContains = document && this.isNativeCode(document.contains); |
---|
1924 | |
---|
1925 | features.contains = (nativeRootContains && nativeDocumentContains) ? function(context, node){ |
---|
1926 | return context.contains(node); |
---|
1927 | } : (nativeRootContains && !nativeDocumentContains) ? function(context, node){ |
---|
1928 | // IE8 does not have .contains on document. |
---|
1929 | return context === node || ((context === document) ? document.documentElement : context).contains(node); |
---|
1930 | } : (root && root.compareDocumentPosition) ? function(context, node){ |
---|
1931 | return context === node || !!(context.compareDocumentPosition(node) & 16); |
---|
1932 | } : function(context, node){ |
---|
1933 | if (node) do { |
---|
1934 | if (node === context) return true; |
---|
1935 | } while ((node = node.parentNode)); |
---|
1936 | return false; |
---|
1937 | }; |
---|
1938 | |
---|
1939 | // document order sorting |
---|
1940 | // credits to Sizzle (http://sizzlejs.com/) |
---|
1941 | |
---|
1942 | features.documentSorter = (root.compareDocumentPosition) ? function(a, b){ |
---|
1943 | if (!a.compareDocumentPosition || !b.compareDocumentPosition) return 0; |
---|
1944 | return a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; |
---|
1945 | } : ('sourceIndex' in root) ? function(a, b){ |
---|
1946 | if (!a.sourceIndex || !b.sourceIndex) return 0; |
---|
1947 | return a.sourceIndex - b.sourceIndex; |
---|
1948 | } : (document.createRange) ? function(a, b){ |
---|
1949 | if (!a.ownerDocument || !b.ownerDocument) return 0; |
---|
1950 | var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); |
---|
1951 | aRange.setStart(a, 0); |
---|
1952 | aRange.setEnd(a, 0); |
---|
1953 | bRange.setStart(b, 0); |
---|
1954 | bRange.setEnd(b, 0); |
---|
1955 | return aRange.compareBoundaryPoints(Range.START_TO_END, bRange); |
---|
1956 | } : null ; |
---|
1957 | |
---|
1958 | root = null; |
---|
1959 | |
---|
1960 | for (feature in features){ |
---|
1961 | this[feature] = features[feature]; |
---|
1962 | } |
---|
1963 | }; |
---|
1964 | |
---|
1965 | // Main Method |
---|
1966 | |
---|
1967 | var reSimpleSelector = /^([#.]?)((?:[\w-]+|\*))$/, |
---|
1968 | reEmptyAttribute = /\[.+[*$^]=(?:""|'')?\]/, |
---|
1969 | qsaFailExpCache = {}; |
---|
1970 | |
---|
1971 | local.search = function(context, expression, append, first){ |
---|
1972 | |
---|
1973 | var found = this.found = (first) ? null : (append || []); |
---|
1974 | |
---|
1975 | if (!context) return found; |
---|
1976 | else if (context.navigator) context = context.document; // Convert the node from a window to a document |
---|
1977 | else if (!context.nodeType) return found; |
---|
1978 | |
---|
1979 | // setup |
---|
1980 | |
---|
1981 | var parsed, i, |
---|
1982 | uniques = this.uniques = {}, |
---|
1983 | hasOthers = !!(append && append.length), |
---|
1984 | contextIsDocument = (context.nodeType == 9); |
---|
1985 | |
---|
1986 | if (this.document !== (contextIsDocument ? context : context.ownerDocument)) this.setDocument(context); |
---|
1987 | |
---|
1988 | // avoid duplicating items already in the append array |
---|
1989 | if (hasOthers) for (i = found.length; i--;) uniques[this.getUID(found[i])] = true; |
---|
1990 | |
---|
1991 | // expression checks |
---|
1992 | |
---|
1993 | if (typeof expression == 'string'){ // expression is a string |
---|
1994 | |
---|
1995 | /*<simple-selectors-override>*/ |
---|
1996 | var simpleSelector = expression.match(reSimpleSelector); |
---|
1997 | simpleSelectors: if (simpleSelector) { |
---|
1998 | |
---|
1999 | var symbol = simpleSelector[1], |
---|
2000 | name = simpleSelector[2], |
---|
2001 | node, nodes; |
---|
2002 | |
---|
2003 | if (!symbol){ |
---|
2004 | |
---|
2005 | if (name == '*' && this.brokenStarGEBTN) break simpleSelectors; |
---|
2006 | nodes = context.getElementsByTagName(name); |
---|
2007 | if (first) return nodes[0] || null; |
---|
2008 | for (i = 0; node = nodes[i++];){ |
---|
2009 | if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); |
---|
2010 | } |
---|
2011 | |
---|
2012 | } else if (symbol == '#'){ |
---|
2013 | |
---|
2014 | if (!this.isHTMLDocument || !contextIsDocument) break simpleSelectors; |
---|
2015 | node = context.getElementById(name); |
---|
2016 | if (!node) return found; |
---|
2017 | if (this.idGetsName && node.getAttributeNode('id').nodeValue != name) break simpleSelectors; |
---|
2018 | if (first) return node || null; |
---|
2019 | if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); |
---|
2020 | |
---|
2021 | } else if (symbol == '.'){ |
---|
2022 | |
---|
2023 | if (!this.isHTMLDocument || ((!context.getElementsByClassName || this.brokenGEBCN) && context.querySelectorAll)) break simpleSelectors; |
---|
2024 | if (context.getElementsByClassName && !this.brokenGEBCN){ |
---|
2025 | nodes = context.getElementsByClassName(name); |
---|
2026 | if (first) return nodes[0] || null; |
---|
2027 | for (i = 0; node = nodes[i++];){ |
---|
2028 | if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); |
---|
2029 | } |
---|
2030 | } else { |
---|
2031 | var matchClass = new RegExp('(^|\\s)'+ Slick.escapeRegExp(name) +'(\\s|$)'); |
---|
2032 | nodes = context.getElementsByTagName('*'); |
---|
2033 | for (i = 0; node = nodes[i++];){ |
---|
2034 | className = node.className; |
---|
2035 | if (!(className && matchClass.test(className))) continue; |
---|
2036 | if (first) return node; |
---|
2037 | if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); |
---|
2038 | } |
---|
2039 | } |
---|
2040 | |
---|
2041 | } |
---|
2042 | |
---|
2043 | if (hasOthers) this.sort(found); |
---|
2044 | return (first) ? null : found; |
---|
2045 | |
---|
2046 | } |
---|
2047 | /*</simple-selectors-override>*/ |
---|
2048 | |
---|
2049 | /*<query-selector-override>*/ |
---|
2050 | querySelector: if (context.querySelectorAll) { |
---|
2051 | |
---|
2052 | if (!this.isHTMLDocument |
---|
2053 | || qsaFailExpCache[expression] |
---|
2054 | //TODO: only skip when expression is actually mixed case |
---|
2055 | || this.brokenMixedCaseQSA |
---|
2056 | || (this.brokenCheckedQSA && expression.indexOf(':checked') > -1) |
---|
2057 | || (this.brokenEmptyAttributeQSA && reEmptyAttribute.test(expression)) |
---|
2058 | || (!contextIsDocument //Abort when !contextIsDocument and... |
---|
2059 | // there are multiple expressions in the selector |
---|
2060 | // since we currently only fix non-document rooted QSA for single expression selectors |
---|
2061 | && expression.indexOf(',') > -1 |
---|
2062 | ) |
---|
2063 | || Slick.disableQSA |
---|
2064 | ) break querySelector; |
---|
2065 | |
---|
2066 | var _expression = expression, _context = context; |
---|
2067 | if (!contextIsDocument){ |
---|
2068 | // non-document rooted QSA |
---|
2069 | // credits to Andrew Dupont |
---|
2070 | var currentId = _context.getAttribute('id'), slickid = 'slickid__'; |
---|
2071 | _context.setAttribute('id', slickid); |
---|
2072 | _expression = '#' + slickid + ' ' + _expression; |
---|
2073 | context = _context.parentNode; |
---|
2074 | } |
---|
2075 | |
---|
2076 | try { |
---|
2077 | if (first) return context.querySelector(_expression) || null; |
---|
2078 | else nodes = context.querySelectorAll(_expression); |
---|
2079 | } catch(e) { |
---|
2080 | qsaFailExpCache[expression] = 1; |
---|
2081 | break querySelector; |
---|
2082 | } finally { |
---|
2083 | if (!contextIsDocument){ |
---|
2084 | if (currentId) _context.setAttribute('id', currentId); |
---|
2085 | else _context.removeAttribute('id'); |
---|
2086 | context = _context; |
---|
2087 | } |
---|
2088 | } |
---|
2089 | |
---|
2090 | if (this.starSelectsClosedQSA) for (i = 0; node = nodes[i++];){ |
---|
2091 | if (node.nodeName > '@' && !(hasOthers && uniques[this.getUID(node)])) found.push(node); |
---|
2092 | } else for (i = 0; node = nodes[i++];){ |
---|
2093 | if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); |
---|
2094 | } |
---|
2095 | |
---|
2096 | if (hasOthers) this.sort(found); |
---|
2097 | return found; |
---|
2098 | |
---|
2099 | } |
---|
2100 | /*</query-selector-override>*/ |
---|
2101 | |
---|
2102 | parsed = this.Slick.parse(expression); |
---|
2103 | if (!parsed.length) return found; |
---|
2104 | } else if (expression == null){ // there is no expression |
---|
2105 | return found; |
---|
2106 | } else if (expression.Slick){ // expression is a parsed Slick object |
---|
2107 | parsed = expression; |
---|
2108 | } else if (this.contains(context.documentElement || context, expression)){ // expression is a node |
---|
2109 | (found) ? found.push(expression) : found = expression; |
---|
2110 | return found; |
---|
2111 | } else { // other junk |
---|
2112 | return found; |
---|
2113 | } |
---|
2114 | |
---|
2115 | /*<pseudo-selectors>*//*<nth-pseudo-selectors>*/ |
---|
2116 | |
---|
2117 | // cache elements for the nth selectors |
---|
2118 | |
---|
2119 | this.posNTH = {}; |
---|
2120 | this.posNTHLast = {}; |
---|
2121 | this.posNTHType = {}; |
---|
2122 | this.posNTHTypeLast = {}; |
---|
2123 | |
---|
2124 | /*</nth-pseudo-selectors>*//*</pseudo-selectors>*/ |
---|
2125 | |
---|
2126 | // if append is null and there is only a single selector with one expression use pushArray, else use pushUID |
---|
2127 | this.push = (!hasOthers && (first || (parsed.length == 1 && parsed.expressions[0].length == 1))) ? this.pushArray : this.pushUID; |
---|
2128 | |
---|
2129 | if (found == null) found = []; |
---|
2130 | |
---|
2131 | // default engine |
---|
2132 | |
---|
2133 | var j, m, n; |
---|
2134 | var combinator, tag, id, classList, classes, attributes, pseudos; |
---|
2135 | var currentItems, currentExpression, currentBit, lastBit, expressions = parsed.expressions; |
---|
2136 | |
---|
2137 | search: for (i = 0; (currentExpression = expressions[i]); i++) for (j = 0; (currentBit = currentExpression[j]); j++){ |
---|
2138 | |
---|
2139 | combinator = 'combinator:' + currentBit.combinator; |
---|
2140 | if (!this[combinator]) continue search; |
---|
2141 | |
---|
2142 | tag = (this.isXMLDocument) ? currentBit.tag : currentBit.tag.toUpperCase(); |
---|
2143 | id = currentBit.id; |
---|
2144 | classList = currentBit.classList; |
---|
2145 | classes = currentBit.classes; |
---|
2146 | attributes = currentBit.attributes; |
---|
2147 | pseudos = currentBit.pseudos; |
---|
2148 | lastBit = (j === (currentExpression.length - 1)); |
---|
2149 | |
---|
2150 | this.bitUniques = {}; |
---|
2151 | |
---|
2152 | if (lastBit){ |
---|
2153 | this.uniques = uniques; |
---|
2154 | this.found = found; |
---|
2155 | } else { |
---|
2156 | this.uniques = {}; |
---|
2157 | this.found = []; |
---|
2158 | } |
---|
2159 | |
---|
2160 | if (j === 0){ |
---|
2161 | this[combinator](context, tag, id, classes, attributes, pseudos, classList); |
---|
2162 | if (first && lastBit && found.length) break search; |
---|
2163 | } else { |
---|
2164 | if (first && lastBit) for (m = 0, n = currentItems.length; m < n; m++){ |
---|
2165 | this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList); |
---|
2166 | if (found.length) break search; |
---|
2167 | } else for (m = 0, n = currentItems.length; m < n; m++) this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList); |
---|
2168 | } |
---|
2169 | |
---|
2170 | currentItems = this.found; |
---|
2171 | } |
---|
2172 | |
---|
2173 | // should sort if there are nodes in append and if you pass multiple expressions. |
---|
2174 | if (hasOthers || (parsed.expressions.length > 1)) this.sort(found); |
---|
2175 | |
---|
2176 | return (first) ? (found[0] || null) : found; |
---|
2177 | }; |
---|
2178 | |
---|
2179 | // Utils |
---|
2180 | |
---|
2181 | local.uidx = 1; |
---|
2182 | local.uidk = 'slick-uniqueid'; |
---|
2183 | |
---|
2184 | local.getUIDXML = function(node){ |
---|
2185 | var uid = node.getAttribute(this.uidk); |
---|
2186 | if (!uid){ |
---|
2187 | uid = this.uidx++; |
---|
2188 | node.setAttribute(this.uidk, uid); |
---|
2189 | } |
---|
2190 | return uid; |
---|
2191 | }; |
---|
2192 | |
---|
2193 | local.getUIDHTML = function(node){ |
---|
2194 | return node.uniqueNumber || (node.uniqueNumber = this.uidx++); |
---|
2195 | }; |
---|
2196 | |
---|
2197 | // sort based on the setDocument documentSorter method. |
---|
2198 | |
---|
2199 | local.sort = function(results){ |
---|
2200 | if (!this.documentSorter) return results; |
---|
2201 | results.sort(this.documentSorter); |
---|
2202 | return results; |
---|
2203 | }; |
---|
2204 | |
---|
2205 | /*<pseudo-selectors>*//*<nth-pseudo-selectors>*/ |
---|
2206 | |
---|
2207 | local.cacheNTH = {}; |
---|
2208 | |
---|
2209 | local.matchNTH = /^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/; |
---|
2210 | |
---|
2211 | local.parseNTHArgument = function(argument){ |
---|
2212 | var parsed = argument.match(this.matchNTH); |
---|
2213 | if (!parsed) return false; |
---|
2214 | var special = parsed[2] || false; |
---|
2215 | var a = parsed[1] || 1; |
---|
2216 | if (a == '-') a = -1; |
---|
2217 | var b = +parsed[3] || 0; |
---|
2218 | parsed = |
---|
2219 | (special == 'n') ? {a: a, b: b} : |
---|
2220 | (special == 'odd') ? {a: 2, b: 1} : |
---|
2221 | (special == 'even') ? {a: 2, b: 0} : {a: 0, b: a}; |
---|
2222 | |
---|
2223 | return (this.cacheNTH[argument] = parsed); |
---|
2224 | }; |
---|
2225 | |
---|
2226 | local.createNTHPseudo = function(child, sibling, positions, ofType){ |
---|
2227 | return function(node, argument){ |
---|
2228 | var uid = this.getUID(node); |
---|
2229 | if (!this[positions][uid]){ |
---|
2230 | var parent = node.parentNode; |
---|
2231 | if (!parent) return false; |
---|
2232 | var el = parent[child], count = 1; |
---|
2233 | if (ofType){ |
---|
2234 | var nodeName = node.nodeName; |
---|
2235 | do { |
---|
2236 | if (el.nodeName != nodeName) continue; |
---|
2237 | this[positions][this.getUID(el)] = count++; |
---|
2238 | } while ((el = el[sibling])); |
---|
2239 | } else { |
---|
2240 | do { |
---|
2241 | if (el.nodeType != 1) continue; |
---|
2242 | this[positions][this.getUID(el)] = count++; |
---|
2243 | } while ((el = el[sibling])); |
---|
2244 | } |
---|
2245 | } |
---|
2246 | argument = argument || 'n'; |
---|
2247 | var parsed = this.cacheNTH[argument] || this.parseNTHArgument(argument); |
---|
2248 | if (!parsed) return false; |
---|
2249 | var a = parsed.a, b = parsed.b, pos = this[positions][uid]; |
---|
2250 | if (a == 0) return b == pos; |
---|
2251 | if (a > 0){ |
---|
2252 | if (pos < b) return false; |
---|
2253 | } else { |
---|
2254 | if (b < pos) return false; |
---|
2255 | } |
---|
2256 | return ((pos - b) % a) == 0; |
---|
2257 | }; |
---|
2258 | }; |
---|
2259 | |
---|
2260 | /*</nth-pseudo-selectors>*//*</pseudo-selectors>*/ |
---|
2261 | |
---|
2262 | local.pushArray = function(node, tag, id, classes, attributes, pseudos){ |
---|
2263 | if (this.matchSelector(node, tag, id, classes, attributes, pseudos)) this.found.push(node); |
---|
2264 | }; |
---|
2265 | |
---|
2266 | local.pushUID = function(node, tag, id, classes, attributes, pseudos){ |
---|
2267 | var uid = this.getUID(node); |
---|
2268 | if (!this.uniques[uid] && this.matchSelector(node, tag, id, classes, attributes, pseudos)){ |
---|
2269 | this.uniques[uid] = true; |
---|
2270 | this.found.push(node); |
---|
2271 | } |
---|
2272 | }; |
---|
2273 | |
---|
2274 | local.matchNode = function(node, selector){ |
---|
2275 | if (this.isHTMLDocument && this.nativeMatchesSelector){ |
---|
2276 | try { |
---|
2277 | return this.nativeMatchesSelector.call(node, selector.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g, '[$1="$2"]')); |
---|
2278 | } catch(matchError) {} |
---|
2279 | } |
---|
2280 | |
---|
2281 | var parsed = this.Slick.parse(selector); |
---|
2282 | if (!parsed) return true; |
---|
2283 | |
---|
2284 | // simple (single) selectors |
---|
2285 | var expressions = parsed.expressions, simpleExpCounter = 0, i; |
---|
2286 | for (i = 0; (currentExpression = expressions[i]); i++){ |
---|
2287 | if (currentExpression.length == 1){ |
---|
2288 | var exp = currentExpression[0]; |
---|
2289 | if (this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.classes, exp.attributes, exp.pseudos)) return true; |
---|
2290 | simpleExpCounter++; |
---|
2291 | } |
---|
2292 | } |
---|
2293 | |
---|
2294 | if (simpleExpCounter == parsed.length) return false; |
---|
2295 | |
---|
2296 | var nodes = this.search(this.document, parsed), item; |
---|
2297 | for (i = 0; item = nodes[i++];){ |
---|
2298 | if (item === node) return true; |
---|
2299 | } |
---|
2300 | return false; |
---|
2301 | }; |
---|
2302 | |
---|
2303 | local.matchPseudo = function(node, name, argument){ |
---|
2304 | var pseudoName = 'pseudo:' + name; |
---|
2305 | if (this[pseudoName]) return this[pseudoName](node, argument); |
---|
2306 | var attribute = this.getAttribute(node, name); |
---|
2307 | return (argument) ? argument == attribute : !!attribute; |
---|
2308 | }; |
---|
2309 | |
---|
2310 | local.matchSelector = function(node, tag, id, classes, attributes, pseudos){ |
---|
2311 | if (tag){ |
---|
2312 | var nodeName = (this.isXMLDocument) ? node.nodeName : node.nodeName.toUpperCase(); |
---|
2313 | if (tag == '*'){ |
---|
2314 | if (nodeName < '@') return false; // Fix for comment nodes and closed nodes |
---|
2315 | } else { |
---|
2316 | if (nodeName != tag) return false; |
---|
2317 | } |
---|
2318 | } |
---|
2319 | |
---|
2320 | if (id && node.getAttribute('id') != id) return false; |
---|
2321 | |
---|
2322 | var i, part, cls; |
---|
2323 | if (classes) for (i = classes.length; i--;){ |
---|
2324 | cls = this.getAttribute(node, 'class'); |
---|
2325 | if (!(cls && classes[i].regexp.test(cls))) return false; |
---|
2326 | } |
---|
2327 | if (attributes) for (i = attributes.length; i--;){ |
---|
2328 | part = attributes[i]; |
---|
2329 | if (part.operator ? !part.test(this.getAttribute(node, part.key)) : !this.hasAttribute(node, part.key)) return false; |
---|
2330 | } |
---|
2331 | if (pseudos) for (i = pseudos.length; i--;){ |
---|
2332 | part = pseudos[i]; |
---|
2333 | if (!this.matchPseudo(node, part.key, part.value)) return false; |
---|
2334 | } |
---|
2335 | return true; |
---|
2336 | }; |
---|
2337 | |
---|
2338 | var combinators = { |
---|
2339 | |
---|
2340 | ' ': function(node, tag, id, classes, attributes, pseudos, classList){ // all child nodes, any level |
---|
2341 | |
---|
2342 | var i, item, children; |
---|
2343 | |
---|
2344 | if (this.isHTMLDocument){ |
---|
2345 | getById: if (id){ |
---|
2346 | item = this.document.getElementById(id); |
---|
2347 | if ((!item && node.all) || (this.idGetsName && item && item.getAttributeNode('id').nodeValue != id)){ |
---|
2348 | // all[id] returns all the elements with that name or id inside node |
---|
2349 | // if theres just one it will return the element, else it will be a collection |
---|
2350 | children = node.all[id]; |
---|
2351 | if (!children) return; |
---|
2352 | if (!children[0]) children = [children]; |
---|
2353 | for (i = 0; item = children[i++];){ |
---|
2354 | var idNode = item.getAttributeNode('id'); |
---|
2355 | if (idNode && idNode.nodeValue == id){ |
---|
2356 | this.push(item, tag, null, classes, attributes, pseudos); |
---|
2357 | break; |
---|
2358 | } |
---|
2359 | } |
---|
2360 | return; |
---|
2361 | } |
---|
2362 | if (!item){ |
---|
2363 | // if the context is in the dom we return, else we will try GEBTN, breaking the getById label |
---|
2364 | if (this.contains(this.root, node)) return; |
---|
2365 | else break getById; |
---|
2366 | } else if (this.document !== node && !this.contains(node, item)) return; |
---|
2367 | this.push(item, tag, null, classes, attributes, pseudos); |
---|
2368 | return; |
---|
2369 | } |
---|
2370 | getByClass: if (classes && node.getElementsByClassName && !this.brokenGEBCN){ |
---|
2371 | children = node.getElementsByClassName(classList.join(' ')); |
---|
2372 | if (!(children && children.length)) break getByClass; |
---|
2373 | for (i = 0; item = children[i++];) this.push(item, tag, id, null, attributes, pseudos); |
---|
2374 | return; |
---|
2375 | } |
---|
2376 | } |
---|
2377 | getByTag: { |
---|
2378 | children = node.getElementsByTagName(tag); |
---|
2379 | if (!(children && children.length)) break getByTag; |
---|
2380 | if (!this.brokenStarGEBTN) tag = null; |
---|
2381 | for (i = 0; item = children[i++];) this.push(item, tag, id, classes, attributes, pseudos); |
---|
2382 | } |
---|
2383 | }, |
---|
2384 | |
---|
2385 | '>': function(node, tag, id, classes, attributes, pseudos){ // direct children |
---|
2386 | if ((node = node.firstChild)) do { |
---|
2387 | if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); |
---|
2388 | } while ((node = node.nextSibling)); |
---|
2389 | }, |
---|
2390 | |
---|
2391 | '+': function(node, tag, id, classes, attributes, pseudos){ // next sibling |
---|
2392 | while ((node = node.nextSibling)) if (node.nodeType == 1){ |
---|
2393 | this.push(node, tag, id, classes, attributes, pseudos); |
---|
2394 | break; |
---|
2395 | } |
---|
2396 | }, |
---|
2397 | |
---|
2398 | '^': function(node, tag, id, classes, attributes, pseudos){ // first child |
---|
2399 | node = node.firstChild; |
---|
2400 | if (node){ |
---|
2401 | if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); |
---|
2402 | else this['combinator:+'](node, tag, id, classes, attributes, pseudos); |
---|
2403 | } |
---|
2404 | }, |
---|
2405 | |
---|
2406 | '~': function(node, tag, id, classes, attributes, pseudos){ // next siblings |
---|
2407 | while ((node = node.nextSibling)){ |
---|
2408 | if (node.nodeType != 1) continue; |
---|
2409 | var uid = this.getUID(node); |
---|
2410 | if (this.bitUniques[uid]) break; |
---|
2411 | this.bitUniques[uid] = true; |
---|
2412 | this.push(node, tag, id, classes, attributes, pseudos); |
---|
2413 | } |
---|
2414 | }, |
---|
2415 | |
---|
2416 | '++': function(node, tag, id, classes, attributes, pseudos){ // next sibling and previous sibling |
---|
2417 | this['combinator:+'](node, tag, id, classes, attributes, pseudos); |
---|
2418 | this['combinator:!+'](node, tag, id, classes, attributes, pseudos); |
---|
2419 | }, |
---|
2420 | |
---|
2421 | '~~': function(node, tag, id, classes, attributes, pseudos){ // next siblings and previous siblings |
---|
2422 | this['combinator:~'](node, tag, id, classes, attributes, pseudos); |
---|
2423 | this['combinator:!~'](node, tag, id, classes, attributes, pseudos); |
---|
2424 | }, |
---|
2425 | |
---|
2426 | '!': function(node, tag, id, classes, attributes, pseudos){ // all parent nodes up to document |
---|
2427 | while ((node = node.parentNode)) if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos); |
---|
2428 | }, |
---|
2429 | |
---|
2430 | '!>': function(node, tag, id, classes, attributes, pseudos){ // direct parent (one level) |
---|
2431 | node = node.parentNode; |
---|
2432 | if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos); |
---|
2433 | }, |
---|
2434 | |
---|
2435 | '!+': function(node, tag, id, classes, attributes, pseudos){ // previous sibling |
---|
2436 | while ((node = node.previousSibling)) if (node.nodeType == 1){ |
---|
2437 | this.push(node, tag, id, classes, attributes, pseudos); |
---|
2438 | break; |
---|
2439 | } |
---|
2440 | }, |
---|
2441 | |
---|
2442 | '!^': function(node, tag, id, classes, attributes, pseudos){ // last child |
---|
2443 | node = node.lastChild; |
---|
2444 | if (node){ |
---|
2445 | if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); |
---|
2446 | else this['combinator:!+'](node, tag, id, classes, attributes, pseudos); |
---|
2447 | } |
---|
2448 | }, |
---|
2449 | |
---|
2450 | '!~': function(node, tag, id, classes, attributes, pseudos){ // previous siblings |
---|
2451 | while ((node = node.previousSibling)){ |
---|
2452 | if (node.nodeType != 1) continue; |
---|
2453 | var uid = this.getUID(node); |
---|
2454 | if (this.bitUniques[uid]) break; |
---|
2455 | this.bitUniques[uid] = true; |
---|
2456 | this.push(node, tag, id, classes, attributes, pseudos); |
---|
2457 | } |
---|
2458 | } |
---|
2459 | |
---|
2460 | }; |
---|
2461 | |
---|
2462 | for (var c in combinators) local['combinator:' + c] = combinators[c]; |
---|
2463 | |
---|
2464 | var pseudos = { |
---|
2465 | |
---|
2466 | /*<pseudo-selectors>*/ |
---|
2467 | |
---|
2468 | 'empty': function(node){ |
---|
2469 | var child = node.firstChild; |
---|
2470 | return !(child && child.nodeType == 1) && !(node.innerText || node.textContent || '').length; |
---|
2471 | }, |
---|
2472 | |
---|
2473 | 'not': function(node, expression){ |
---|
2474 | return !this.matchNode(node, expression); |
---|
2475 | }, |
---|
2476 | |
---|
2477 | 'contains': function(node, text){ |
---|
2478 | return (node.innerText || node.textContent || '').indexOf(text) > -1; |
---|
2479 | }, |
---|
2480 | |
---|
2481 | 'first-child': function(node){ |
---|
2482 | while ((node = node.previousSibling)) if (node.nodeType == 1) return false; |
---|
2483 | return true; |
---|
2484 | }, |
---|
2485 | |
---|
2486 | 'last-child': function(node){ |
---|
2487 | while ((node = node.nextSibling)) if (node.nodeType == 1) return false; |
---|
2488 | return true; |
---|
2489 | }, |
---|
2490 | |
---|
2491 | 'only-child': function(node){ |
---|
2492 | var prev = node; |
---|
2493 | while ((prev = prev.previousSibling)) if (prev.nodeType == 1) return false; |
---|
2494 | var next = node; |
---|
2495 | while ((next = next.nextSibling)) if (next.nodeType == 1) return false; |
---|
2496 | return true; |
---|
2497 | }, |
---|
2498 | |
---|
2499 | /*<nth-pseudo-selectors>*/ |
---|
2500 | |
---|
2501 | 'nth-child': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTH'), |
---|
2502 | |
---|
2503 | 'nth-last-child': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHLast'), |
---|
2504 | |
---|
2505 | 'nth-of-type': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTHType', true), |
---|
2506 | |
---|
2507 | 'nth-last-of-type': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHTypeLast', true), |
---|
2508 | |
---|
2509 | 'index': function(node, index){ |
---|
2510 | return this['pseudo:nth-child'](node, '' + (index + 1)); |
---|
2511 | }, |
---|
2512 | |
---|
2513 | 'even': function(node){ |
---|
2514 | return this['pseudo:nth-child'](node, '2n'); |
---|
2515 | }, |
---|
2516 | |
---|
2517 | 'odd': function(node){ |
---|
2518 | return this['pseudo:nth-child'](node, '2n+1'); |
---|
2519 | }, |
---|
2520 | |
---|
2521 | /*</nth-pseudo-selectors>*/ |
---|
2522 | |
---|
2523 | /*<of-type-pseudo-selectors>*/ |
---|
2524 | |
---|
2525 | 'first-of-type': function(node){ |
---|
2526 | var nodeName = node.nodeName; |
---|
2527 | while ((node = node.previousSibling)) if (node.nodeName == nodeName) return false; |
---|
2528 | return true; |
---|
2529 | }, |
---|
2530 | |
---|
2531 | 'last-of-type': function(node){ |
---|
2532 | var nodeName = node.nodeName; |
---|
2533 | while ((node = node.nextSibling)) if (node.nodeName == nodeName) return false; |
---|
2534 | return true; |
---|
2535 | }, |
---|
2536 | |
---|
2537 | 'only-of-type': function(node){ |
---|
2538 | var prev = node, nodeName = node.nodeName; |
---|
2539 | while ((prev = prev.previousSibling)) if (prev.nodeName == nodeName) return false; |
---|
2540 | var next = node; |
---|
2541 | while ((next = next.nextSibling)) if (next.nodeName == nodeName) return false; |
---|
2542 | return true; |
---|
2543 | }, |
---|
2544 | |
---|
2545 | /*</of-type-pseudo-selectors>*/ |
---|
2546 | |
---|
2547 | // custom pseudos |
---|
2548 | |
---|
2549 | 'enabled': function(node){ |
---|
2550 | return !node.disabled; |
---|
2551 | }, |
---|
2552 | |
---|
2553 | 'disabled': function(node){ |
---|
2554 | return node.disabled; |
---|
2555 | }, |
---|
2556 | |
---|
2557 | 'checked': function(node){ |
---|
2558 | return node.checked || node.selected; |
---|
2559 | }, |
---|
2560 | |
---|
2561 | 'focus': function(node){ |
---|
2562 | return this.isHTMLDocument && this.document.activeElement === node && (node.href || node.type || this.hasAttribute(node, 'tabindex')); |
---|
2563 | }, |
---|
2564 | |
---|
2565 | 'root': function(node){ |
---|
2566 | return (node === this.root); |
---|
2567 | }, |
---|
2568 | |
---|
2569 | 'selected': function(node){ |
---|
2570 | return node.selected; |
---|
2571 | } |
---|
2572 | |
---|
2573 | /*</pseudo-selectors>*/ |
---|
2574 | }; |
---|
2575 | |
---|
2576 | for (var p in pseudos) local['pseudo:' + p] = pseudos[p]; |
---|
2577 | |
---|
2578 | // attributes methods |
---|
2579 | |
---|
2580 | var attributeGetters = local.attributeGetters = { |
---|
2581 | |
---|
2582 | 'for': function(){ |
---|
2583 | return ('htmlFor' in this) ? this.htmlFor : this.getAttribute('for'); |
---|
2584 | }, |
---|
2585 | |
---|
2586 | 'href': function(){ |
---|
2587 | return ('href' in this) ? this.getAttribute('href', 2) : this.getAttribute('href'); |
---|
2588 | }, |
---|
2589 | |
---|
2590 | 'style': function(){ |
---|
2591 | return (this.style) ? this.style.cssText : this.getAttribute('style'); |
---|
2592 | }, |
---|
2593 | |
---|
2594 | 'tabindex': function(){ |
---|
2595 | var attributeNode = this.getAttributeNode('tabindex'); |
---|
2596 | return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null; |
---|
2597 | }, |
---|
2598 | |
---|
2599 | 'type': function(){ |
---|
2600 | return this.getAttribute('type'); |
---|
2601 | }, |
---|
2602 | |
---|
2603 | 'maxlength': function(){ |
---|
2604 | var attributeNode = this.getAttributeNode('maxLength'); |
---|
2605 | return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null; |
---|
2606 | } |
---|
2607 | |
---|
2608 | }; |
---|
2609 | |
---|
2610 | attributeGetters.MAXLENGTH = attributeGetters.maxLength = attributeGetters.maxlength; |
---|
2611 | |
---|
2612 | // Slick |
---|
2613 | |
---|
2614 | var Slick = local.Slick = (this.Slick || {}); |
---|
2615 | |
---|
2616 | Slick.version = '1.1.7'; |
---|
2617 | |
---|
2618 | // Slick finder |
---|
2619 | |
---|
2620 | Slick.search = function(context, expression, append){ |
---|
2621 | return local.search(context, expression, append); |
---|
2622 | }; |
---|
2623 | |
---|
2624 | Slick.find = function(context, expression){ |
---|
2625 | return local.search(context, expression, null, true); |
---|
2626 | }; |
---|
2627 | |
---|
2628 | // Slick containment checker |
---|
2629 | |
---|
2630 | Slick.contains = function(container, node){ |
---|
2631 | local.setDocument(container); |
---|
2632 | return local.contains(container, node); |
---|
2633 | }; |
---|
2634 | |
---|
2635 | // Slick attribute getter |
---|
2636 | |
---|
2637 | Slick.getAttribute = function(node, name){ |
---|
2638 | local.setDocument(node); |
---|
2639 | return local.getAttribute(node, name); |
---|
2640 | }; |
---|
2641 | |
---|
2642 | Slick.hasAttribute = function(node, name){ |
---|
2643 | local.setDocument(node); |
---|
2644 | return local.hasAttribute(node, name); |
---|
2645 | }; |
---|
2646 | |
---|
2647 | // Slick matcher |
---|
2648 | |
---|
2649 | Slick.match = function(node, selector){ |
---|
2650 | if (!(node && selector)) return false; |
---|
2651 | if (!selector || selector === node) return true; |
---|
2652 | local.setDocument(node); |
---|
2653 | return local.matchNode(node, selector); |
---|
2654 | }; |
---|
2655 | |
---|
2656 | // Slick attribute accessor |
---|
2657 | |
---|
2658 | Slick.defineAttributeGetter = function(name, fn){ |
---|
2659 | local.attributeGetters[name] = fn; |
---|
2660 | return this; |
---|
2661 | }; |
---|
2662 | |
---|
2663 | Slick.lookupAttributeGetter = function(name){ |
---|
2664 | return local.attributeGetters[name]; |
---|
2665 | }; |
---|
2666 | |
---|
2667 | // Slick pseudo accessor |
---|
2668 | |
---|
2669 | Slick.definePseudo = function(name, fn){ |
---|
2670 | local['pseudo:' + name] = function(node, argument){ |
---|
2671 | return fn.call(node, argument); |
---|
2672 | }; |
---|
2673 | return this; |
---|
2674 | }; |
---|
2675 | |
---|
2676 | Slick.lookupPseudo = function(name){ |
---|
2677 | var pseudo = local['pseudo:' + name]; |
---|
2678 | if (pseudo) return function(argument){ |
---|
2679 | return pseudo.call(this, argument); |
---|
2680 | }; |
---|
2681 | return null; |
---|
2682 | }; |
---|
2683 | |
---|
2684 | // Slick overrides accessor |
---|
2685 | |
---|
2686 | Slick.override = function(regexp, fn){ |
---|
2687 | local.override(regexp, fn); |
---|
2688 | return this; |
---|
2689 | }; |
---|
2690 | |
---|
2691 | Slick.isXML = local.isXML; |
---|
2692 | |
---|
2693 | Slick.uidOf = function(node){ |
---|
2694 | return local.getUIDHTML(node); |
---|
2695 | }; |
---|
2696 | |
---|
2697 | if (!this.Slick) this.Slick = Slick; |
---|
2698 | |
---|
2699 | }).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this); |
---|
2700 | |
---|
2701 | |
---|
2702 | /* |
---|
2703 | --- |
---|
2704 | |
---|
2705 | name: Element |
---|
2706 | |
---|
2707 | description: One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements. |
---|
2708 | |
---|
2709 | license: MIT-style license. |
---|
2710 | |
---|
2711 | requires: [Window, Document, Array, String, Function, Object, Number, Slick.Parser, Slick.Finder] |
---|
2712 | |
---|
2713 | provides: [Element, Elements, $, $$, Iframe, Selectors] |
---|
2714 | |
---|
2715 | ... |
---|
2716 | */ |
---|
2717 | |
---|
2718 | var Element = function(tag, props){ |
---|
2719 | var konstructor = Element.Constructors[tag]; |
---|
2720 | if (konstructor) return konstructor(props); |
---|
2721 | if (typeof tag != 'string') return document.id(tag).set(props); |
---|
2722 | |
---|
2723 | if (!props) props = {}; |
---|
2724 | |
---|
2725 | if (!(/^[\w-]+$/).test(tag)){ |
---|
2726 | var parsed = Slick.parse(tag).expressions[0][0]; |
---|
2727 | tag = (parsed.tag == '*') ? 'div' : parsed.tag; |
---|
2728 | if (parsed.id && props.id == null) props.id = parsed.id; |
---|
2729 | |
---|
2730 | var attributes = parsed.attributes; |
---|
2731 | if (attributes) for (var attr, i = 0, l = attributes.length; i < l; i++){ |
---|
2732 | attr = attributes[i]; |
---|
2733 | if (props[attr.key] != null) continue; |
---|
2734 | |
---|
2735 | if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value; |
---|
2736 | else if (!attr.value && !attr.operator) props[attr.key] = true; |
---|
2737 | } |
---|
2738 | |
---|
2739 | if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' '); |
---|
2740 | } |
---|
2741 | |
---|
2742 | return document.newElement(tag, props); |
---|
2743 | }; |
---|
2744 | |
---|
2745 | |
---|
2746 | if (Browser.Element){ |
---|
2747 | Element.prototype = Browser.Element.prototype; |
---|
2748 | // IE8 and IE9 require the wrapping. |
---|
2749 | Element.prototype._fireEvent = (function(fireEvent){ |
---|
2750 | return function(type, event){ |
---|
2751 | return fireEvent.call(this, type, event); |
---|
2752 | }; |
---|
2753 | })(Element.prototype.fireEvent); |
---|
2754 | } |
---|
2755 | |
---|
2756 | new Type('Element', Element).mirror(function(name){ |
---|
2757 | if (Array.prototype[name]) return; |
---|
2758 | |
---|
2759 | var obj = {}; |
---|
2760 | obj[name] = function(){ |
---|
2761 | var results = [], args = arguments, elements = true; |
---|
2762 | for (var i = 0, l = this.length; i < l; i++){ |
---|
2763 | var element = this[i], result = results[i] = element[name].apply(element, args); |
---|
2764 | elements = (elements && typeOf(result) == 'element'); |
---|
2765 | } |
---|
2766 | return (elements) ? new Elements(results) : results; |
---|
2767 | }; |
---|
2768 | |
---|
2769 | Elements.implement(obj); |
---|
2770 | }); |
---|
2771 | |
---|
2772 | if (!Browser.Element){ |
---|
2773 | Element.parent = Object; |
---|
2774 | |
---|
2775 | Element.Prototype = { |
---|
2776 | '$constructor': Element, |
---|
2777 | '$family': Function.from('element').hide() |
---|
2778 | }; |
---|
2779 | |
---|
2780 | Element.mirror(function(name, method){ |
---|
2781 | Element.Prototype[name] = method; |
---|
2782 | }); |
---|
2783 | } |
---|
2784 | |
---|
2785 | Element.Constructors = {}; |
---|
2786 | |
---|
2787 | |
---|
2788 | |
---|
2789 | var IFrame = new Type('IFrame', function(){ |
---|
2790 | var params = Array.link(arguments, { |
---|
2791 | properties: Type.isObject, |
---|
2792 | iframe: function(obj){ |
---|
2793 | return (obj != null); |
---|
2794 | } |
---|
2795 | }); |
---|
2796 | |
---|
2797 | var props = params.properties || {}, iframe; |
---|
2798 | if (params.iframe) iframe = document.id(params.iframe); |
---|
2799 | var onload = props.onload || function(){}; |
---|
2800 | delete props.onload; |
---|
2801 | props.id = props.name = [props.id, props.name, iframe ? (iframe.id || iframe.name) : 'IFrame_' + String.uniqueID()].pick(); |
---|
2802 | iframe = new Element(iframe || 'iframe', props); |
---|
2803 | |
---|
2804 | var onLoad = function(){ |
---|
2805 | onload.call(iframe.contentWindow); |
---|
2806 | }; |
---|
2807 | |
---|
2808 | if (window.frames[props.id]) onLoad(); |
---|
2809 | else iframe.addListener('load', onLoad); |
---|
2810 | return iframe; |
---|
2811 | }); |
---|
2812 | |
---|
2813 | var Elements = this.Elements = function(nodes){ |
---|
2814 | if (nodes && nodes.length){ |
---|
2815 | var uniques = {}, node; |
---|
2816 | for (var i = 0; node = nodes[i++];){ |
---|
2817 | var uid = Slick.uidOf(node); |
---|
2818 | if (!uniques[uid]){ |
---|
2819 | uniques[uid] = true; |
---|
2820 | this.push(node); |
---|
2821 | } |
---|
2822 | } |
---|
2823 | } |
---|
2824 | }; |
---|
2825 | |
---|
2826 | Elements.prototype = {length: 0}; |
---|
2827 | Elements.parent = Array; |
---|
2828 | |
---|
2829 | new Type('Elements', Elements).implement({ |
---|
2830 | |
---|
2831 | filter: function(filter, bind){ |
---|
2832 | if (!filter) return this; |
---|
2833 | return new Elements(Array.filter(this, (typeOf(filter) == 'string') ? function(item){ |
---|
2834 | return item.match(filter); |
---|
2835 | } : filter, bind)); |
---|
2836 | }.protect(), |
---|
2837 | |
---|
2838 | push: function(){ |
---|
2839 | var length = this.length; |
---|
2840 | for (var i = 0, l = arguments.length; i < l; i++){ |
---|
2841 | var item = document.id(arguments[i]); |
---|
2842 | if (item) this[length++] = item; |
---|
2843 | } |
---|
2844 | return (this.length = length); |
---|
2845 | }.protect(), |
---|
2846 | |
---|
2847 | unshift: function(){ |
---|
2848 | var items = []; |
---|
2849 | for (var i = 0, l = arguments.length; i < l; i++){ |
---|
2850 | var item = document.id(arguments[i]); |
---|
2851 | if (item) items.push(item); |
---|
2852 | } |
---|
2853 | return Array.prototype.unshift.apply(this, items); |
---|
2854 | }.protect(), |
---|
2855 | |
---|
2856 | concat: function(){ |
---|
2857 | var newElements = new Elements(this); |
---|
2858 | for (var i = 0, l = arguments.length; i < l; i++){ |
---|
2859 | var item = arguments[i]; |
---|
2860 | if (Type.isEnumerable(item)) newElements.append(item); |
---|
2861 | else newElements.push(item); |
---|
2862 | } |
---|
2863 | return newElements; |
---|
2864 | }.protect(), |
---|
2865 | |
---|
2866 | append: function(collection){ |
---|
2867 | for (var i = 0, l = collection.length; i < l; i++) this.push(collection[i]); |
---|
2868 | return this; |
---|
2869 | }.protect(), |
---|
2870 | |
---|
2871 | empty: function(){ |
---|
2872 | while (this.length) delete this[--this.length]; |
---|
2873 | return this; |
---|
2874 | }.protect() |
---|
2875 | |
---|
2876 | }); |
---|
2877 | |
---|
2878 | |
---|
2879 | |
---|
2880 | (function(){ |
---|
2881 | |
---|
2882 | // FF, IE |
---|
2883 | var splice = Array.prototype.splice, object = {'0': 0, '1': 1, length: 2}; |
---|
2884 | |
---|
2885 | splice.call(object, 1, 1); |
---|
2886 | if (object[1] == 1) Elements.implement('splice', function(){ |
---|
2887 | var length = this.length; |
---|
2888 | var result = splice.apply(this, arguments); |
---|
2889 | while (length >= this.length) delete this[length--]; |
---|
2890 | return result; |
---|
2891 | }.protect()); |
---|
2892 | |
---|
2893 | Array.forEachMethod(function(method, name){ |
---|
2894 | Elements.implement(name, method); |
---|
2895 | }); |
---|
2896 | |
---|
2897 | Array.mirror(Elements); |
---|
2898 | |
---|
2899 | /*<ltIE8>*/ |
---|
2900 | var createElementAcceptsHTML; |
---|
2901 | try { |
---|
2902 | createElementAcceptsHTML = (document.createElement('<input name=x>').name == 'x'); |
---|
2903 | } catch (e){} |
---|
2904 | |
---|
2905 | var escapeQuotes = function(html){ |
---|
2906 | return ('' + html).replace(/&/g, '&').replace(/"/g, '"'); |
---|
2907 | }; |
---|
2908 | /*</ltIE8>*/ |
---|
2909 | |
---|
2910 | Document.implement({ |
---|
2911 | |
---|
2912 | newElement: function(tag, props){ |
---|
2913 | if (props && props.checked != null) props.defaultChecked = props.checked; |
---|
2914 | /*<ltIE8>*/// Fix for readonly name and type properties in IE < 8 |
---|
2915 | if (createElementAcceptsHTML && props){ |
---|
2916 | tag = '<' + tag; |
---|
2917 | if (props.name) tag += ' name="' + escapeQuotes(props.name) + '"'; |
---|
2918 | if (props.type) tag += ' type="' + escapeQuotes(props.type) + '"'; |
---|
2919 | tag += '>'; |
---|
2920 | delete props.name; |
---|
2921 | delete props.type; |
---|
2922 | } |
---|
2923 | /*</ltIE8>*/ |
---|
2924 | return this.id(this.createElement(tag)).set(props); |
---|
2925 | } |
---|
2926 | |
---|
2927 | }); |
---|
2928 | |
---|
2929 | })(); |
---|
2930 | |
---|
2931 | (function(){ |
---|
2932 | |
---|
2933 | Slick.uidOf(window); |
---|
2934 | Slick.uidOf(document); |
---|
2935 | |
---|
2936 | Document.implement({ |
---|
2937 | |
---|
2938 | newTextNode: function(text){ |
---|
2939 | return this.createTextNode(text); |
---|
2940 | }, |
---|
2941 | |
---|
2942 | getDocument: function(){ |
---|
2943 | return this; |
---|
2944 | }, |
---|
2945 | |
---|
2946 | getWindow: function(){ |
---|
2947 | return this.window; |
---|
2948 | }, |
---|
2949 | |
---|
2950 | id: (function(){ |
---|
2951 | |
---|
2952 | var types = { |
---|
2953 | |
---|
2954 | string: function(id, nocash, doc){ |
---|
2955 | id = Slick.find(doc, '#' + id.replace(/(\W)/g, '\\$1')); |
---|
2956 | return (id) ? types.element(id, nocash) : null; |
---|
2957 | }, |
---|
2958 | |
---|
2959 | element: function(el, nocash){ |
---|
2960 | Slick.uidOf(el); |
---|
2961 | if (!nocash && !el.$family && !(/^(?:object|embed)$/i).test(el.tagName)){ |
---|
2962 | var fireEvent = el.fireEvent; |
---|
2963 | // wrapping needed in IE7, or else crash |
---|
2964 | el._fireEvent = function(type, event){ |
---|
2965 | return fireEvent(type, event); |
---|
2966 | }; |
---|
2967 | Object.append(el, Element.Prototype); |
---|
2968 | } |
---|
2969 | return el; |
---|
2970 | }, |
---|
2971 | |
---|
2972 | object: function(obj, nocash, doc){ |
---|
2973 | if (obj.toElement) return types.element(obj.toElement(doc), nocash); |
---|
2974 | return null; |
---|
2975 | } |
---|
2976 | |
---|
2977 | }; |
---|
2978 | |
---|
2979 | types.textnode = types.whitespace = types.window = types.document = function(zero){ |
---|
2980 | return zero; |
---|
2981 | }; |
---|
2982 | |
---|
2983 | return function(el, nocash, doc){ |
---|
2984 | if (el && el.$family && el.uniqueNumber) return el; |
---|
2985 | var type = typeOf(el); |
---|
2986 | return (types[type]) ? types[type](el, nocash, doc || document) : null; |
---|
2987 | }; |
---|
2988 | |
---|
2989 | })() |
---|
2990 | |
---|
2991 | }); |
---|
2992 | |
---|
2993 | if (window.$ == null) Window.implement('$', function(el, nc){ |
---|
2994 | return document.id(el, nc, this.document); |
---|
2995 | }); |
---|
2996 | |
---|
2997 | Window.implement({ |
---|
2998 | |
---|
2999 | getDocument: function(){ |
---|
3000 | return this.document; |
---|
3001 | }, |
---|
3002 | |
---|
3003 | getWindow: function(){ |
---|
3004 | return this; |
---|
3005 | } |
---|
3006 | |
---|
3007 | }); |
---|
3008 | |
---|
3009 | [Document, Element].invoke('implement', { |
---|
3010 | |
---|
3011 | getElements: function(expression){ |
---|
3012 | return Slick.search(this, expression, new Elements); |
---|
3013 | }, |
---|
3014 | |
---|
3015 | getElement: function(expression){ |
---|
3016 | return document.id(Slick.find(this, expression)); |
---|
3017 | } |
---|
3018 | |
---|
3019 | }); |
---|
3020 | |
---|
3021 | var contains = {contains: function(element){ |
---|
3022 | return Slick.contains(this, element); |
---|
3023 | }}; |
---|
3024 | |
---|
3025 | if (!document.contains) Document.implement(contains); |
---|
3026 | if (!document.createElement('div').contains) Element.implement(contains); |
---|
3027 | |
---|
3028 | |
---|
3029 | |
---|
3030 | // tree walking |
---|
3031 | |
---|
3032 | var injectCombinator = function(expression, combinator){ |
---|
3033 | if (!expression) return combinator; |
---|
3034 | |
---|
3035 | expression = Object.clone(Slick.parse(expression)); |
---|
3036 | |
---|
3037 | var expressions = expression.expressions; |
---|
3038 | for (var i = expressions.length; i--;) |
---|
3039 | expressions[i][0].combinator = combinator; |
---|
3040 | |
---|
3041 | return expression; |
---|
3042 | }; |
---|
3043 | |
---|
3044 | Object.forEach({ |
---|
3045 | getNext: '~', |
---|
3046 | getPrevious: '!~', |
---|
3047 | getParent: '!' |
---|
3048 | }, function(combinator, method){ |
---|
3049 | Element.implement(method, function(expression){ |
---|
3050 | return this.getElement(injectCombinator(expression, combinator)); |
---|
3051 | }); |
---|
3052 | }); |
---|
3053 | |
---|
3054 | Object.forEach({ |
---|
3055 | getAllNext: '~', |
---|
3056 | getAllPrevious: '!~', |
---|
3057 | getSiblings: '~~', |
---|
3058 | getChildren: '>', |
---|
3059 | getParents: '!' |
---|
3060 | }, function(combinator, method){ |
---|
3061 | Element.implement(method, function(expression){ |
---|
3062 | return this.getElements(injectCombinator(expression, combinator)); |
---|
3063 | }); |
---|
3064 | }); |
---|
3065 | |
---|
3066 | Element.implement({ |
---|
3067 | |
---|
3068 | getFirst: function(expression){ |
---|
3069 | return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]); |
---|
3070 | }, |
---|
3071 | |
---|
3072 | getLast: function(expression){ |
---|
3073 | return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast()); |
---|
3074 | }, |
---|
3075 | |
---|
3076 | getWindow: function(){ |
---|
3077 | return this.ownerDocument.window; |
---|
3078 | }, |
---|
3079 | |
---|
3080 | getDocument: function(){ |
---|
3081 | return this.ownerDocument; |
---|
3082 | }, |
---|
3083 | |
---|
3084 | getElementById: function(id){ |
---|
3085 | return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1'))); |
---|
3086 | }, |
---|
3087 | |
---|
3088 | match: function(expression){ |
---|
3089 | return !expression || Slick.match(this, expression); |
---|
3090 | } |
---|
3091 | |
---|
3092 | }); |
---|
3093 | |
---|
3094 | |
---|
3095 | |
---|
3096 | if (window.$$ == null) Window.implement('$$', function(selector){ |
---|
3097 | if (arguments.length == 1){ |
---|
3098 | if (typeof selector == 'string') return Slick.search(this.document, selector, new Elements); |
---|
3099 | else if (Type.isEnumerable(selector)) return new Elements(selector); |
---|
3100 | } |
---|
3101 | return new Elements(arguments); |
---|
3102 | }); |
---|
3103 | |
---|
3104 | // Inserters |
---|
3105 | |
---|
3106 | var inserters = { |
---|
3107 | |
---|
3108 | before: function(context, element){ |
---|
3109 | var parent = element.parentNode; |
---|
3110 | if (parent) parent.insertBefore(context, element); |
---|
3111 | }, |
---|
3112 | |
---|
3113 | after: function(context, element){ |
---|
3114 | var parent = element.parentNode; |
---|
3115 | if (parent) parent.insertBefore(context, element.nextSibling); |
---|
3116 | }, |
---|
3117 | |
---|
3118 | bottom: function(context, element){ |
---|
3119 | element.appendChild(context); |
---|
3120 | }, |
---|
3121 | |
---|
3122 | top: function(context, element){ |
---|
3123 | element.insertBefore(context, element.firstChild); |
---|
3124 | } |
---|
3125 | |
---|
3126 | }; |
---|
3127 | |
---|
3128 | inserters.inside = inserters.bottom; |
---|
3129 | |
---|
3130 | |
---|
3131 | |
---|
3132 | // getProperty / setProperty |
---|
3133 | |
---|
3134 | var propertyGetters = {}, propertySetters = {}; |
---|
3135 | |
---|
3136 | // properties |
---|
3137 | |
---|
3138 | var properties = {}; |
---|
3139 | Array.forEach([ |
---|
3140 | 'type', 'value', 'defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', |
---|
3141 | 'frameBorder', 'rowSpan', 'tabIndex', 'useMap' |
---|
3142 | ], function(property){ |
---|
3143 | properties[property.toLowerCase()] = property; |
---|
3144 | }); |
---|
3145 | |
---|
3146 | properties.html = 'innerHTML'; |
---|
3147 | properties.text = (document.createElement('div').textContent == null) ? 'innerText': 'textContent'; |
---|
3148 | |
---|
3149 | Object.forEach(properties, function(real, key){ |
---|
3150 | propertySetters[key] = function(node, value){ |
---|
3151 | node[real] = value; |
---|
3152 | }; |
---|
3153 | propertyGetters[key] = function(node){ |
---|
3154 | return node[real]; |
---|
3155 | }; |
---|
3156 | }); |
---|
3157 | |
---|
3158 | // Booleans |
---|
3159 | |
---|
3160 | var bools = [ |
---|
3161 | 'compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', |
---|
3162 | 'disabled', 'readOnly', 'multiple', 'selected', 'noresize', |
---|
3163 | 'defer', 'defaultChecked', 'autofocus', 'controls', 'autoplay', |
---|
3164 | 'loop' |
---|
3165 | ]; |
---|
3166 | |
---|
3167 | var booleans = {}; |
---|
3168 | Array.forEach(bools, function(bool){ |
---|
3169 | var lower = bool.toLowerCase(); |
---|
3170 | booleans[lower] = bool; |
---|
3171 | propertySetters[lower] = function(node, value){ |
---|
3172 | node[bool] = !!value; |
---|
3173 | }; |
---|
3174 | propertyGetters[lower] = function(node){ |
---|
3175 | return !!node[bool]; |
---|
3176 | }; |
---|
3177 | }); |
---|
3178 | |
---|
3179 | // Special cases |
---|
3180 | |
---|
3181 | Object.append(propertySetters, { |
---|
3182 | |
---|
3183 | 'class': function(node, value){ |
---|
3184 | ('className' in node) ? node.className = (value || '') : node.setAttribute('class', value); |
---|
3185 | }, |
---|
3186 | |
---|
3187 | 'for': function(node, value){ |
---|
3188 | ('htmlFor' in node) ? node.htmlFor = value : node.setAttribute('for', value); |
---|
3189 | }, |
---|
3190 | |
---|
3191 | 'style': function(node, value){ |
---|
3192 | (node.style) ? node.style.cssText = value : node.setAttribute('style', value); |
---|
3193 | }, |
---|
3194 | |
---|
3195 | 'value': function(node, value){ |
---|
3196 | node.value = (value != null) ? value : ''; |
---|
3197 | } |
---|
3198 | |
---|
3199 | }); |
---|
3200 | |
---|
3201 | propertyGetters['class'] = function(node){ |
---|
3202 | return ('className' in node) ? node.className || null : node.getAttribute('class'); |
---|
3203 | }; |
---|
3204 | |
---|
3205 | /* <webkit> */ |
---|
3206 | var el = document.createElement('button'); |
---|
3207 | // IE sets type as readonly and throws |
---|
3208 | try { el.type = 'button'; } catch(e){} |
---|
3209 | if (el.type != 'button') propertySetters.type = function(node, value){ |
---|
3210 | node.setAttribute('type', value); |
---|
3211 | }; |
---|
3212 | el = null; |
---|
3213 | /* </webkit> */ |
---|
3214 | |
---|
3215 | /*<IE>*/ |
---|
3216 | var input = document.createElement('input'); |
---|
3217 | input.value = 't'; |
---|
3218 | input.type = 'submit'; |
---|
3219 | if (input.value != 't') propertySetters.type = function(node, type){ |
---|
3220 | var value = node.value; |
---|
3221 | node.type = type; |
---|
3222 | node.value = value; |
---|
3223 | }; |
---|
3224 | input = null; |
---|
3225 | /*</IE>*/ |
---|
3226 | |
---|
3227 | /* getProperty, setProperty */ |
---|
3228 | |
---|
3229 | /* <ltIE9> */ |
---|
3230 | var pollutesGetAttribute = (function(div){ |
---|
3231 | div.random = 'attribute'; |
---|
3232 | return (div.getAttribute('random') == 'attribute'); |
---|
3233 | })(document.createElement('div')); |
---|
3234 | |
---|
3235 | /* <ltIE9> */ |
---|
3236 | |
---|
3237 | Element.implement({ |
---|
3238 | |
---|
3239 | setProperty: function(name, value){ |
---|
3240 | var setter = propertySetters[name.toLowerCase()]; |
---|
3241 | if (setter){ |
---|
3242 | setter(this, value); |
---|
3243 | } else { |
---|
3244 | /* <ltIE9> */ |
---|
3245 | if (pollutesGetAttribute) var attributeWhiteList = this.retrieve('$attributeWhiteList', {}); |
---|
3246 | /* </ltIE9> */ |
---|
3247 | |
---|
3248 | if (value == null){ |
---|
3249 | this.removeAttribute(name); |
---|
3250 | /* <ltIE9> */ |
---|
3251 | if (pollutesGetAttribute) delete attributeWhiteList[name]; |
---|
3252 | /* </ltIE9> */ |
---|
3253 | } else { |
---|
3254 | this.setAttribute(name, '' + value); |
---|
3255 | /* <ltIE9> */ |
---|
3256 | if (pollutesGetAttribute) attributeWhiteList[name] = true; |
---|
3257 | /* </ltIE9> */ |
---|
3258 | } |
---|
3259 | } |
---|
3260 | return this; |
---|
3261 | }, |
---|
3262 | |
---|
3263 | setProperties: function(attributes){ |
---|
3264 | for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]); |
---|
3265 | return this; |
---|
3266 | }, |
---|
3267 | |
---|
3268 | getProperty: function(name){ |
---|
3269 | var getter = propertyGetters[name.toLowerCase()]; |
---|
3270 | if (getter) return getter(this); |
---|
3271 | /* <ltIE9> */ |
---|
3272 | if (pollutesGetAttribute){ |
---|
3273 | var attr = this.getAttributeNode(name), attributeWhiteList = this.retrieve('$attributeWhiteList', {}); |
---|
3274 | if (!attr) return null; |
---|
3275 | if (attr.expando && !attributeWhiteList[name]){ |
---|
3276 | var outer = this.outerHTML; |
---|
3277 | // segment by the opening tag and find mention of attribute name |
---|
3278 | if (outer.substr(0, outer.search(/\/?['"]?>(?![^<]*<['"])/)).indexOf(name) < 0) return null; |
---|
3279 | attributeWhiteList[name] = true; |
---|
3280 | } |
---|
3281 | } |
---|
3282 | /* </ltIE9> */ |
---|
3283 | var result = Slick.getAttribute(this, name); |
---|
3284 | return (!result && !Slick.hasAttribute(this, name)) ? null : result; |
---|
3285 | }, |
---|
3286 | |
---|
3287 | getProperties: function(){ |
---|
3288 | var args = Array.from(arguments); |
---|
3289 | return args.map(this.getProperty, this).associate(args); |
---|
3290 | }, |
---|
3291 | |
---|
3292 | removeProperty: function(name){ |
---|
3293 | return this.setProperty(name, null); |
---|
3294 | }, |
---|
3295 | |
---|
3296 | removeProperties: function(){ |
---|
3297 | Array.each(arguments, this.removeProperty, this); |
---|
3298 | return this; |
---|
3299 | }, |
---|
3300 | |
---|
3301 | set: function(prop, value){ |
---|
3302 | var property = Element.Properties[prop]; |
---|
3303 | (property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value); |
---|
3304 | }.overloadSetter(), |
---|
3305 | |
---|
3306 | get: function(prop){ |
---|
3307 | var property = Element.Properties[prop]; |
---|
3308 | return (property && property.get) ? property.get.apply(this) : this.getProperty(prop); |
---|
3309 | }.overloadGetter(), |
---|
3310 | |
---|
3311 | erase: function(prop){ |
---|
3312 | var property = Element.Properties[prop]; |
---|
3313 | (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop); |
---|
3314 | return this; |
---|
3315 | }, |
---|
3316 | |
---|
3317 | hasClass: function(className){ |
---|
3318 | return this.className.clean().contains(className, ' '); |
---|
3319 | }, |
---|
3320 | |
---|
3321 | addClass: function(className){ |
---|
3322 | if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean(); |
---|
3323 | return this; |
---|
3324 | }, |
---|
3325 | |
---|
3326 | removeClass: function(className){ |
---|
3327 | this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1'); |
---|
3328 | return this; |
---|
3329 | }, |
---|
3330 | |
---|
3331 | toggleClass: function(className, force){ |
---|
3332 | if (force == null) force = !this.hasClass(className); |
---|
3333 | return (force) ? this.addClass(className) : this.removeClass(className); |
---|
3334 | }, |
---|
3335 | |
---|
3336 | adopt: function(){ |
---|
3337 | var parent = this, fragment, elements = Array.flatten(arguments), length = elements.length; |
---|
3338 | if (length > 1) parent = fragment = document.createDocumentFragment(); |
---|
3339 | |
---|
3340 | for (var i = 0; i < length; i++){ |
---|
3341 | var element = document.id(elements[i], true); |
---|
3342 | if (element) parent.appendChild(element); |
---|
3343 | } |
---|
3344 | |
---|
3345 | if (fragment) this.appendChild(fragment); |
---|
3346 | |
---|
3347 | return this; |
---|
3348 | }, |
---|
3349 | |
---|
3350 | appendText: function(text, where){ |
---|
3351 | return this.grab(this.getDocument().newTextNode(text), where); |
---|
3352 | }, |
---|
3353 | |
---|
3354 | grab: function(el, where){ |
---|
3355 | inserters[where || 'bottom'](document.id(el, true), this); |
---|
3356 | return this; |
---|
3357 | }, |
---|
3358 | |
---|
3359 | inject: function(el, where){ |
---|
3360 | inserters[where || 'bottom'](this, document.id(el, true)); |
---|
3361 | return this; |
---|
3362 | }, |
---|
3363 | |
---|
3364 | replaces: function(el){ |
---|
3365 | el = document.id(el, true); |
---|
3366 | el.parentNode.replaceChild(this, el); |
---|
3367 | return this; |
---|
3368 | }, |
---|
3369 | |
---|
3370 | wraps: function(el, where){ |
---|
3371 | el = document.id(el, true); |
---|
3372 | return this.replaces(el).grab(el, where); |
---|
3373 | }, |
---|
3374 | |
---|
3375 | getSelected: function(){ |
---|
3376 | this.selectedIndex; // Safari 3.2.1 |
---|
3377 | return new Elements(Array.from(this.options).filter(function(option){ |
---|
3378 | return option.selected; |
---|
3379 | })); |
---|
3380 | }, |
---|
3381 | |
---|
3382 | toQueryString: function(){ |
---|
3383 | var queryString = []; |
---|
3384 | this.getElements('input, select, textarea').each(function(el){ |
---|
3385 | var type = el.type; |
---|
3386 | if (!el.name || el.disabled || type == 'submit' || type == 'reset' || type == 'file' || type == 'image') return; |
---|
3387 | |
---|
3388 | var value = (el.get('tag') == 'select') ? el.getSelected().map(function(opt){ |
---|
3389 | // IE |
---|
3390 | return document.id(opt).get('value'); |
---|
3391 | }) : ((type == 'radio' || type == 'checkbox') && !el.checked) ? null : el.get('value'); |
---|
3392 | |
---|
3393 | Array.from(value).each(function(val){ |
---|
3394 | if (typeof val != 'undefined') queryString.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(val)); |
---|
3395 | }); |
---|
3396 | }); |
---|
3397 | return queryString.join('&'); |
---|
3398 | } |
---|
3399 | |
---|
3400 | }); |
---|
3401 | |
---|
3402 | var collected = {}, storage = {}; |
---|
3403 | |
---|
3404 | var get = function(uid){ |
---|
3405 | return (storage[uid] || (storage[uid] = {})); |
---|
3406 | }; |
---|
3407 | |
---|
3408 | var clean = function(item){ |
---|
3409 | var uid = item.uniqueNumber; |
---|
3410 | if (item.removeEvents) item.removeEvents(); |
---|
3411 | if (item.clearAttributes) item.clearAttributes(); |
---|
3412 | if (uid != null){ |
---|
3413 | delete collected[uid]; |
---|
3414 | delete storage[uid]; |
---|
3415 | } |
---|
3416 | return item; |
---|
3417 | }; |
---|
3418 | |
---|
3419 | var formProps = {input: 'checked', option: 'selected', textarea: 'value'}; |
---|
3420 | |
---|
3421 | Element.implement({ |
---|
3422 | |
---|
3423 | destroy: function(){ |
---|
3424 | var children = clean(this).getElementsByTagName('*'); |
---|
3425 | Array.each(children, clean); |
---|
3426 | Element.dispose(this); |
---|
3427 | return null; |
---|
3428 | }, |
---|
3429 | |
---|
3430 | empty: function(){ |
---|
3431 | Array.from(this.childNodes).each(Element.dispose); |
---|
3432 | return this; |
---|
3433 | }, |
---|
3434 | |
---|
3435 | dispose: function(){ |
---|
3436 | return (this.parentNode) ? this.parentNode.removeChild(this) : this; |
---|
3437 | }, |
---|
3438 | |
---|
3439 | clone: function(contents, keepid){ |
---|
3440 | contents = contents !== false; |
---|
3441 | var clone = this.cloneNode(contents), ce = [clone], te = [this], i; |
---|
3442 | |
---|
3443 | if (contents){ |
---|
3444 | ce.append(Array.from(clone.getElementsByTagName('*'))); |
---|
3445 | te.append(Array.from(this.getElementsByTagName('*'))); |
---|
3446 | } |
---|
3447 | |
---|
3448 | for (i = ce.length; i--;){ |
---|
3449 | var node = ce[i], element = te[i]; |
---|
3450 | if (!keepid) node.removeAttribute('id'); |
---|
3451 | /*<ltIE9>*/ |
---|
3452 | if (node.clearAttributes){ |
---|
3453 | node.clearAttributes(); |
---|
3454 | node.mergeAttributes(element); |
---|
3455 | node.removeAttribute('uniqueNumber'); |
---|
3456 | if (node.options){ |
---|
3457 | var no = node.options, eo = element.options; |
---|
3458 | for (var j = no.length; j--;) no[j].selected = eo[j].selected; |
---|
3459 | } |
---|
3460 | } |
---|
3461 | /*</ltIE9>*/ |
---|
3462 | var prop = formProps[element.tagName.toLowerCase()]; |
---|
3463 | if (prop && element[prop]) node[prop] = element[prop]; |
---|
3464 | } |
---|
3465 | |
---|
3466 | /*<ltIE9>*/ |
---|
3467 | if (Browser.ie){ |
---|
3468 | var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object'); |
---|
3469 | for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML; |
---|
3470 | } |
---|
3471 | /*</ltIE9>*/ |
---|
3472 | return document.id(clone); |
---|
3473 | } |
---|
3474 | |
---|
3475 | }); |
---|
3476 | |
---|
3477 | [Element, Window, Document].invoke('implement', { |
---|
3478 | |
---|
3479 | addListener: function(type, fn){ |
---|
3480 | if (type == 'unload'){ |
---|
3481 | var old = fn, self = this; |
---|
3482 | fn = function(){ |
---|
3483 | self.removeListener('unload', fn); |
---|
3484 | old(); |
---|
3485 | }; |
---|
3486 | } else { |
---|
3487 | collected[Slick.uidOf(this)] = this; |
---|
3488 | } |
---|
3489 | if (this.addEventListener) this.addEventListener(type, fn, !!arguments[2]); |
---|
3490 | else this.attachEvent('on' + type, fn); |
---|
3491 | return this; |
---|
3492 | }, |
---|
3493 | |
---|
3494 | removeListener: function(type, fn){ |
---|
3495 | if (this.removeEventListener) this.removeEventListener(type, fn, !!arguments[2]); |
---|
3496 | else this.detachEvent('on' + type, fn); |
---|
3497 | return this; |
---|
3498 | }, |
---|
3499 | |
---|
3500 | retrieve: function(property, dflt){ |
---|
3501 | var storage = get(Slick.uidOf(this)), prop = storage[property]; |
---|
3502 | if (dflt != null && prop == null) prop = storage[property] = dflt; |
---|
3503 | return prop != null ? prop : null; |
---|
3504 | }, |
---|
3505 | |
---|
3506 | store: function(property, value){ |
---|
3507 | var storage = get(Slick.uidOf(this)); |
---|
3508 | storage[property] = value; |
---|
3509 | return this; |
---|
3510 | }, |
---|
3511 | |
---|
3512 | eliminate: function(property){ |
---|
3513 | var storage = get(Slick.uidOf(this)); |
---|
3514 | delete storage[property]; |
---|
3515 | return this; |
---|
3516 | } |
---|
3517 | |
---|
3518 | }); |
---|
3519 | |
---|
3520 | /*<ltIE9>*/ |
---|
3521 | if (window.attachEvent && !window.addEventListener) window.addListener('unload', function(){ |
---|
3522 | Object.each(collected, clean); |
---|
3523 | if (window.CollectGarbage) CollectGarbage(); |
---|
3524 | }); |
---|
3525 | /*</ltIE9>*/ |
---|
3526 | |
---|
3527 | Element.Properties = {}; |
---|
3528 | |
---|
3529 | |
---|
3530 | |
---|
3531 | Element.Properties.style = { |
---|
3532 | |
---|
3533 | set: function(style){ |
---|
3534 | this.style.cssText = style; |
---|
3535 | }, |
---|
3536 | |
---|
3537 | get: function(){ |
---|
3538 | return this.style.cssText; |
---|
3539 | }, |
---|
3540 | |
---|
3541 | erase: function(){ |
---|
3542 | this.style.cssText = ''; |
---|
3543 | } |
---|
3544 | |
---|
3545 | }; |
---|
3546 | |
---|
3547 | Element.Properties.tag = { |
---|
3548 | |
---|
3549 | get: function(){ |
---|
3550 | return this.tagName.toLowerCase(); |
---|
3551 | } |
---|
3552 | |
---|
3553 | }; |
---|
3554 | |
---|
3555 | Element.Properties.html = { |
---|
3556 | |
---|
3557 | set: function(html){ |
---|
3558 | if (html == null) html = ''; |
---|
3559 | else if (typeOf(html) == 'array') html = html.join(''); |
---|
3560 | this.innerHTML = html; |
---|
3561 | }, |
---|
3562 | |
---|
3563 | erase: function(){ |
---|
3564 | this.innerHTML = ''; |
---|
3565 | } |
---|
3566 | |
---|
3567 | }; |
---|
3568 | |
---|
3569 | /*<ltIE9>*/ |
---|
3570 | // technique by jdbarlett - http://jdbartlett.com/innershiv/ |
---|
3571 | var div = document.createElement('div'); |
---|
3572 | div.innerHTML = '<nav></nav>'; |
---|
3573 | var supportsHTML5Elements = (div.childNodes.length == 1); |
---|
3574 | if (!supportsHTML5Elements){ |
---|
3575 | var tags = 'abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video'.split(' '), |
---|
3576 | fragment = document.createDocumentFragment(), l = tags.length; |
---|
3577 | while (l--) fragment.createElement(tags[l]); |
---|
3578 | } |
---|
3579 | div = null; |
---|
3580 | /*</ltIE9>*/ |
---|
3581 | |
---|
3582 | /*<IE>*/ |
---|
3583 | var supportsTableInnerHTML = Function.attempt(function(){ |
---|
3584 | var table = document.createElement('table'); |
---|
3585 | table.innerHTML = '<tr><td></td></tr>'; |
---|
3586 | return true; |
---|
3587 | }); |
---|
3588 | |
---|
3589 | /*<ltFF4>*/ |
---|
3590 | var tr = document.createElement('tr'), html = '<td></td>'; |
---|
3591 | tr.innerHTML = html; |
---|
3592 | var supportsTRInnerHTML = (tr.innerHTML == html); |
---|
3593 | tr = null; |
---|
3594 | /*</ltFF4>*/ |
---|
3595 | |
---|
3596 | if (!supportsTableInnerHTML || !supportsTRInnerHTML || !supportsHTML5Elements){ |
---|
3597 | |
---|
3598 | Element.Properties.html.set = (function(set){ |
---|
3599 | |
---|
3600 | var translations = { |
---|
3601 | table: [1, '<table>', '</table>'], |
---|
3602 | select: [1, '<select>', '</select>'], |
---|
3603 | tbody: [2, '<table><tbody>', '</tbody></table>'], |
---|
3604 | tr: [3, '<table><tbody><tr>', '</tr></tbody></table>'] |
---|
3605 | }; |
---|
3606 | |
---|
3607 | translations.thead = translations.tfoot = translations.tbody; |
---|
3608 | |
---|
3609 | return function(html){ |
---|
3610 | var wrap = translations[this.get('tag')]; |
---|
3611 | if (!wrap && !supportsHTML5Elements) wrap = [0, '', '']; |
---|
3612 | if (!wrap) return set.call(this, html); |
---|
3613 | |
---|
3614 | var level = wrap[0], wrapper = document.createElement('div'), target = wrapper; |
---|
3615 | if (!supportsHTML5Elements) fragment.appendChild(wrapper); |
---|
3616 | wrapper.innerHTML = [wrap[1], html, wrap[2]].flatten().join(''); |
---|
3617 | while (level--) target = target.firstChild; |
---|
3618 | this.empty().adopt(target.childNodes); |
---|
3619 | if (!supportsHTML5Elements) fragment.removeChild(wrapper); |
---|
3620 | wrapper = null; |
---|
3621 | }; |
---|
3622 | |
---|
3623 | })(Element.Properties.html.set); |
---|
3624 | } |
---|
3625 | /*</IE>*/ |
---|
3626 | |
---|
3627 | /*<ltIE9>*/ |
---|
3628 | var testForm = document.createElement('form'); |
---|
3629 | testForm.innerHTML = '<select><option>s</option></select>'; |
---|
3630 | |
---|
3631 | if (testForm.firstChild.value != 's') Element.Properties.value = { |
---|
3632 | |
---|
3633 | set: function(value){ |
---|
3634 | var tag = this.get('tag'); |
---|
3635 | if (tag != 'select') return this.setProperty('value', value); |
---|
3636 | var options = this.getElements('option'); |
---|
3637 | for (var i = 0; i < options.length; i++){ |
---|
3638 | var option = options[i], |
---|
3639 | attr = option.getAttributeNode('value'), |
---|
3640 | optionValue = (attr && attr.specified) ? option.value : option.get('text'); |
---|
3641 | if (optionValue == value) return option.selected = true; |
---|
3642 | } |
---|
3643 | }, |
---|
3644 | |
---|
3645 | get: function(){ |
---|
3646 | var option = this, tag = option.get('tag'); |
---|
3647 | |
---|
3648 | if (tag != 'select' && tag != 'option') return this.getProperty('value'); |
---|
3649 | |
---|
3650 | if (tag == 'select' && !(option = option.getSelected()[0])) return ''; |
---|
3651 | |
---|
3652 | var attr = option.getAttributeNode('value'); |
---|
3653 | return (attr && attr.specified) ? option.value : option.get('text'); |
---|
3654 | } |
---|
3655 | |
---|
3656 | }; |
---|
3657 | testForm = null; |
---|
3658 | /*</ltIE9>*/ |
---|
3659 | |
---|
3660 | /*<IE>*/ |
---|
3661 | if (document.createElement('div').getAttributeNode('id')) Element.Properties.id = { |
---|
3662 | set: function(id){ |
---|
3663 | this.id = this.getAttributeNode('id').value = id; |
---|
3664 | }, |
---|
3665 | get: function(){ |
---|
3666 | return this.id || null; |
---|
3667 | }, |
---|
3668 | erase: function(){ |
---|
3669 | this.id = this.getAttributeNode('id').value = ''; |
---|
3670 | } |
---|
3671 | }; |
---|
3672 | /*</IE>*/ |
---|
3673 | |
---|
3674 | })(); |
---|
3675 | |
---|
3676 | |
---|
3677 | /* |
---|
3678 | --- |
---|
3679 | |
---|
3680 | name: Element.Style |
---|
3681 | |
---|
3682 | description: Contains methods for interacting with the styles of Elements in a fashionable way. |
---|
3683 | |
---|
3684 | license: MIT-style license. |
---|
3685 | |
---|
3686 | requires: Element |
---|
3687 | |
---|
3688 | provides: Element.Style |
---|
3689 | |
---|
3690 | ... |
---|
3691 | */ |
---|
3692 | |
---|
3693 | (function(){ |
---|
3694 | |
---|
3695 | var html = document.html; |
---|
3696 | |
---|
3697 | //<ltIE9> |
---|
3698 | // Check for oldIE, which does not remove styles when they're set to null |
---|
3699 | var el = document.createElement('div'); |
---|
3700 | el.style.color = 'red'; |
---|
3701 | el.style.color = null; |
---|
3702 | var doesNotRemoveStyles = el.style.color == 'red'; |
---|
3703 | el = null; |
---|
3704 | //</ltIE9> |
---|
3705 | |
---|
3706 | Element.Properties.styles = {set: function(styles){ |
---|
3707 | this.setStyles(styles); |
---|
3708 | }}; |
---|
3709 | |
---|
3710 | var hasOpacity = (html.style.opacity != null), |
---|
3711 | hasFilter = (html.style.filter != null), |
---|
3712 | reAlpha = /alpha\(opacity=([\d.]+)\)/i; |
---|
3713 | |
---|
3714 | var setVisibility = function(element, opacity){ |
---|
3715 | element.store('$opacity', opacity); |
---|
3716 | element.style.visibility = opacity > 0 || opacity == null ? 'visible' : 'hidden'; |
---|
3717 | }; |
---|
3718 | |
---|
3719 | var setOpacity = (hasOpacity ? function(element, opacity){ |
---|
3720 | element.style.opacity = opacity; |
---|
3721 | } : (hasFilter ? function(element, opacity){ |
---|
3722 | var style = element.style; |
---|
3723 | if (!element.currentStyle || !element.currentStyle.hasLayout) style.zoom = 1; |
---|
3724 | if (opacity == null || opacity == 1) opacity = ''; |
---|
3725 | else opacity = 'alpha(opacity=' + (opacity * 100).limit(0, 100).round() + ')'; |
---|
3726 | var filter = style.filter || element.getComputedStyle('filter') || ''; |
---|
3727 | style.filter = reAlpha.test(filter) ? filter.replace(reAlpha, opacity) : filter + opacity; |
---|
3728 | if (!style.filter) style.removeAttribute('filter'); |
---|
3729 | } : setVisibility)); |
---|
3730 | |
---|
3731 | var getOpacity = (hasOpacity ? function(element){ |
---|
3732 | var opacity = element.style.opacity || element.getComputedStyle('opacity'); |
---|
3733 | return (opacity == '') ? 1 : opacity.toFloat(); |
---|
3734 | } : (hasFilter ? function(element){ |
---|
3735 | var filter = (element.style.filter || element.getComputedStyle('filter')), |
---|
3736 | opacity; |
---|
3737 | if (filter) opacity = filter.match(reAlpha); |
---|
3738 | return (opacity == null || filter == null) ? 1 : (opacity[1] / 100); |
---|
3739 | } : function(element){ |
---|
3740 | var opacity = element.retrieve('$opacity'); |
---|
3741 | if (opacity == null) opacity = (element.style.visibility == 'hidden' ? 0 : 1); |
---|
3742 | return opacity; |
---|
3743 | })); |
---|
3744 | |
---|
3745 | var floatName = (html.style.cssFloat == null) ? 'styleFloat' : 'cssFloat'; |
---|
3746 | |
---|
3747 | Element.implement({ |
---|
3748 | |
---|
3749 | getComputedStyle: function(property){ |
---|
3750 | if (this.currentStyle) return this.currentStyle[property.camelCase()]; |
---|
3751 | var defaultView = Element.getDocument(this).defaultView, |
---|
3752 | computed = defaultView ? defaultView.getComputedStyle(this, null) : null; |
---|
3753 | return (computed) ? computed.getPropertyValue((property == floatName) ? 'float' : property.hyphenate()) : null; |
---|
3754 | }, |
---|
3755 | |
---|
3756 | setStyle: function(property, value){ |
---|
3757 | if (property == 'opacity'){ |
---|
3758 | if (value != null) value = parseFloat(value); |
---|
3759 | setOpacity(this, value); |
---|
3760 | return this; |
---|
3761 | } |
---|
3762 | property = (property == 'float' ? floatName : property).camelCase(); |
---|
3763 | if (typeOf(value) != 'string'){ |
---|
3764 | var map = (Element.Styles[property] || '@').split(' '); |
---|
3765 | value = Array.from(value).map(function(val, i){ |
---|
3766 | if (!map[i]) return ''; |
---|
3767 | return (typeOf(val) == 'number') ? map[i].replace('@', Math.round(val)) : val; |
---|
3768 | }).join(' '); |
---|
3769 | } else if (value == String(Number(value))){ |
---|
3770 | value = Math.round(value); |
---|
3771 | } |
---|
3772 | this.style[property] = value; |
---|
3773 | //<ltIE9> |
---|
3774 | if ((value == '' || value == null) && doesNotRemoveStyles && this.style.removeAttribute){ |
---|
3775 | this.style.removeAttribute(property); |
---|
3776 | } |
---|
3777 | //</ltIE9> |
---|
3778 | return this; |
---|
3779 | }, |
---|
3780 | |
---|
3781 | getStyle: function(property){ |
---|
3782 | if (property == 'opacity') return getOpacity(this); |
---|
3783 | property = (property == 'float' ? floatName : property).camelCase(); |
---|
3784 | var result = this.style[property]; |
---|
3785 | if (!result || property == 'zIndex'){ |
---|
3786 | result = []; |
---|
3787 | for (var style in Element.ShortStyles){ |
---|
3788 | if (property != style) continue; |
---|
3789 | for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s)); |
---|
3790 | return result.join(' '); |
---|
3791 | } |
---|
3792 | result = this.getComputedStyle(property); |
---|
3793 | } |
---|
3794 | if (result){ |
---|
3795 | result = String(result); |
---|
3796 | var color = result.match(/rgba?\([\d\s,]+\)/); |
---|
3797 | if (color) result = result.replace(color[0], color[0].rgbToHex()); |
---|
3798 | } |
---|
3799 | if (Browser.opera || Browser.ie){ |
---|
3800 | if ((/^(height|width)$/).test(property) && !(/px$/.test(result))){ |
---|
3801 | var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0; |
---|
3802 | values.each(function(value){ |
---|
3803 | size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt(); |
---|
3804 | }, this); |
---|
3805 | return this['offset' + property.capitalize()] - size + 'px'; |
---|
3806 | } |
---|
3807 | if (Browser.ie && (/^border(.+)Width|margin|padding/).test(property) && isNaN(parseFloat(result))){ |
---|
3808 | return '0px'; |
---|
3809 | } |
---|
3810 | } |
---|
3811 | return result; |
---|
3812 | }, |
---|
3813 | |
---|
3814 | setStyles: function(styles){ |
---|
3815 | for (var style in styles) this.setStyle(style, styles[style]); |
---|
3816 | return this; |
---|
3817 | }, |
---|
3818 | |
---|
3819 | getStyles: function(){ |
---|
3820 | var result = {}; |
---|
3821 | Array.flatten(arguments).each(function(key){ |
---|
3822 | result[key] = this.getStyle(key); |
---|
3823 | }, this); |
---|
3824 | return result; |
---|
3825 | } |
---|
3826 | |
---|
3827 | }); |
---|
3828 | |
---|
3829 | Element.Styles = { |
---|
3830 | left: '@px', top: '@px', bottom: '@px', right: '@px', |
---|
3831 | width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px', |
---|
3832 | backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)', |
---|
3833 | fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)', |
---|
3834 | margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)', |
---|
3835 | borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)', |
---|
3836 | zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@' |
---|
3837 | }; |
---|
3838 | |
---|
3839 | |
---|
3840 | |
---|
3841 | |
---|
3842 | |
---|
3843 | Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}}; |
---|
3844 | |
---|
3845 | ['Top', 'Right', 'Bottom', 'Left'].each(function(direction){ |
---|
3846 | var Short = Element.ShortStyles; |
---|
3847 | var All = Element.Styles; |
---|
3848 | ['margin', 'padding'].each(function(style){ |
---|
3849 | var sd = style + direction; |
---|
3850 | Short[style][sd] = All[sd] = '@px'; |
---|
3851 | }); |
---|
3852 | var bd = 'border' + direction; |
---|
3853 | Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)'; |
---|
3854 | var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color'; |
---|
3855 | Short[bd] = {}; |
---|
3856 | Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px'; |
---|
3857 | Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@'; |
---|
3858 | Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)'; |
---|
3859 | }); |
---|
3860 | |
---|
3861 | })(); |
---|
3862 | |
---|
3863 | |
---|
3864 | /* |
---|
3865 | --- |
---|
3866 | |
---|
3867 | name: Element.Event |
---|
3868 | |
---|
3869 | description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events, if necessary. |
---|
3870 | |
---|
3871 | license: MIT-style license. |
---|
3872 | |
---|
3873 | requires: [Element, Event] |
---|
3874 | |
---|
3875 | provides: Element.Event |
---|
3876 | |
---|
3877 | ... |
---|
3878 | */ |
---|
3879 | |
---|
3880 | (function(){ |
---|
3881 | |
---|
3882 | Element.Properties.events = {set: function(events){ |
---|
3883 | this.addEvents(events); |
---|
3884 | }}; |
---|
3885 | |
---|
3886 | [Element, Window, Document].invoke('implement', { |
---|
3887 | |
---|
3888 | addEvent: function(type, fn){ |
---|
3889 | var events = this.retrieve('events', {}); |
---|
3890 | if (!events[type]) events[type] = {keys: [], values: []}; |
---|
3891 | if (events[type].keys.contains(fn)) return this; |
---|
3892 | events[type].keys.push(fn); |
---|
3893 | var realType = type, |
---|
3894 | custom = Element.Events[type], |
---|
3895 | condition = fn, |
---|
3896 | self = this; |
---|
3897 | if (custom){ |
---|
3898 | if (custom.onAdd) custom.onAdd.call(this, fn, type); |
---|
3899 | if (custom.condition){ |
---|
3900 | condition = function(event){ |
---|
3901 | if (custom.condition.call(this, event, type)) return fn.call(this, event); |
---|
3902 | return true; |
---|
3903 | }; |
---|
3904 | } |
---|
3905 | if (custom.base) realType = Function.from(custom.base).call(this, type); |
---|
3906 | } |
---|
3907 | var defn = function(){ |
---|
3908 | return fn.call(self); |
---|
3909 | }; |
---|
3910 | var nativeEvent = Element.NativeEvents[realType]; |
---|
3911 | if (nativeEvent){ |
---|
3912 | if (nativeEvent == 2){ |
---|
3913 | defn = function(event){ |
---|
3914 | event = new DOMEvent(event, self.getWindow()); |
---|
3915 | if (condition.call(self, event) === false) event.stop(); |
---|
3916 | }; |
---|
3917 | } |
---|
3918 | this.addListener(realType, defn, arguments[2]); |
---|
3919 | } |
---|
3920 | events[type].values.push(defn); |
---|
3921 | return this; |
---|
3922 | }, |
---|
3923 | |
---|
3924 | removeEvent: function(type, fn){ |
---|
3925 | var events = this.retrieve('events'); |
---|
3926 | if (!events || !events[type]) return this; |
---|
3927 | var list = events[type]; |
---|
3928 | var index = list.keys.indexOf(fn); |
---|
3929 | if (index == -1) return this; |
---|
3930 | var value = list.values[index]; |
---|
3931 | delete list.keys[index]; |
---|
3932 | delete list.values[index]; |
---|
3933 | var custom = Element.Events[type]; |
---|
3934 | if (custom){ |
---|
3935 | if (custom.onRemove) custom.onRemove.call(this, fn, type); |
---|
3936 | if (custom.base) type = Function.from(custom.base).call(this, type); |
---|
3937 | } |
---|
3938 | return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this; |
---|
3939 | }, |
---|
3940 | |
---|
3941 | addEvents: function(events){ |
---|
3942 | for (var event in events) this.addEvent(event, events[event]); |
---|
3943 | return this; |
---|
3944 | }, |
---|
3945 | |
---|
3946 | removeEvents: function(events){ |
---|
3947 | var type; |
---|
3948 | if (typeOf(events) == 'object'){ |
---|
3949 | for (type in events) this.removeEvent(type, events[type]); |
---|
3950 | return this; |
---|
3951 | } |
---|
3952 | var attached = this.retrieve('events'); |
---|
3953 | if (!attached) return this; |
---|
3954 | if (!events){ |
---|
3955 | for (type in attached) this.removeEvents(type); |
---|
3956 | this.eliminate('events'); |
---|
3957 | } else if (attached[events]){ |
---|
3958 | attached[events].keys.each(function(fn){ |
---|
3959 | this.removeEvent(events, fn); |
---|
3960 | }, this); |
---|
3961 | delete attached[events]; |
---|
3962 | } |
---|
3963 | return this; |
---|
3964 | }, |
---|
3965 | |
---|
3966 | fireEvent: function(type, args, delay){ |
---|
3967 | var events = this.retrieve('events'); |
---|
3968 | if (!events || !events[type]) return this; |
---|
3969 | args = Array.from(args); |
---|
3970 | |
---|
3971 | events[type].keys.each(function(fn){ |
---|
3972 | if (delay) fn.delay(delay, this, args); |
---|
3973 | else fn.apply(this, args); |
---|
3974 | }, this); |
---|
3975 | return this; |
---|
3976 | }, |
---|
3977 | |
---|
3978 | cloneEvents: function(from, type){ |
---|
3979 | from = document.id(from); |
---|
3980 | var events = from.retrieve('events'); |
---|
3981 | if (!events) return this; |
---|
3982 | if (!type){ |
---|
3983 | for (var eventType in events) this.cloneEvents(from, eventType); |
---|
3984 | } else if (events[type]){ |
---|
3985 | events[type].keys.each(function(fn){ |
---|
3986 | this.addEvent(type, fn); |
---|
3987 | }, this); |
---|
3988 | } |
---|
3989 | return this; |
---|
3990 | } |
---|
3991 | |
---|
3992 | }); |
---|
3993 | |
---|
3994 | Element.NativeEvents = { |
---|
3995 | click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons |
---|
3996 | mousewheel: 2, DOMMouseScroll: 2, //mouse wheel |
---|
3997 | mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement |
---|
3998 | keydown: 2, keypress: 2, keyup: 2, //keyboard |
---|
3999 | orientationchange: 2, // mobile |
---|
4000 | touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch |
---|
4001 | gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture |
---|
4002 | focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, paste: 2, input: 2, //form elements |
---|
4003 | load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window |
---|
4004 | error: 1, abort: 1, scroll: 1 //misc |
---|
4005 | }; |
---|
4006 | |
---|
4007 | Element.Events = {mousewheel: { |
---|
4008 | base: (Browser.firefox) ? 'DOMMouseScroll' : 'mousewheel' |
---|
4009 | }}; |
---|
4010 | |
---|
4011 | if ('onmouseenter' in document.documentElement){ |
---|
4012 | Element.NativeEvents.mouseenter = Element.NativeEvents.mouseleave = 2; |
---|
4013 | } else { |
---|
4014 | var check = function(event){ |
---|
4015 | var related = event.relatedTarget; |
---|
4016 | if (related == null) return true; |
---|
4017 | if (!related) return false; |
---|
4018 | return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related)); |
---|
4019 | }; |
---|
4020 | |
---|
4021 | Element.Events.mouseenter = { |
---|
4022 | base: 'mouseover', |
---|
4023 | condition: check |
---|
4024 | }; |
---|
4025 | |
---|
4026 | Element.Events.mouseleave = { |
---|
4027 | base: 'mouseout', |
---|
4028 | condition: check |
---|
4029 | }; |
---|
4030 | } |
---|
4031 | |
---|
4032 | /*<ltIE9>*/ |
---|
4033 | if (!window.addEventListener){ |
---|
4034 | Element.NativeEvents.propertychange = 2; |
---|
4035 | Element.Events.change = { |
---|
4036 | base: function(){ |
---|
4037 | var type = this.type; |
---|
4038 | return (this.get('tag') == 'input' && (type == 'radio' || type == 'checkbox')) ? 'propertychange' : 'change' |
---|
4039 | }, |
---|
4040 | condition: function(event){ |
---|
4041 | return this.type != 'radio' || (event.event.propertyName == 'checked' && this.checked); |
---|
4042 | } |
---|
4043 | } |
---|
4044 | } |
---|
4045 | /*</ltIE9>*/ |
---|
4046 | |
---|
4047 | |
---|
4048 | |
---|
4049 | })(); |
---|
4050 | |
---|
4051 | |
---|
4052 | /* |
---|
4053 | --- |
---|
4054 | |
---|
4055 | name: Element.Delegation |
---|
4056 | |
---|
4057 | description: Extends the Element native object to include the delegate method for more efficient event management. |
---|
4058 | |
---|
4059 | license: MIT-style license. |
---|
4060 | |
---|
4061 | requires: [Element.Event] |
---|
4062 | |
---|
4063 | provides: [Element.Delegation] |
---|
4064 | |
---|
4065 | ... |
---|
4066 | */ |
---|
4067 | |
---|
4068 | (function(){ |
---|
4069 | |
---|
4070 | var eventListenerSupport = !!window.addEventListener; |
---|
4071 | |
---|
4072 | Element.NativeEvents.focusin = Element.NativeEvents.focusout = 2; |
---|
4073 | |
---|
4074 | var bubbleUp = function(self, match, fn, event, target){ |
---|
4075 | while (target && target != self){ |
---|
4076 | if (match(target, event)) return fn.call(target, event, target); |
---|
4077 | target = document.id(target.parentNode); |
---|
4078 | } |
---|
4079 | }; |
---|
4080 | |
---|
4081 | var map = { |
---|
4082 | mouseenter: { |
---|
4083 | base: 'mouseover' |
---|
4084 | }, |
---|
4085 | mouseleave: { |
---|
4086 | base: 'mouseout' |
---|
4087 | }, |
---|
4088 | focus: { |
---|
4089 | base: 'focus' + (eventListenerSupport ? '' : 'in'), |
---|
4090 | capture: true |
---|
4091 | }, |
---|
4092 | blur: { |
---|
4093 | base: eventListenerSupport ? 'blur' : 'focusout', |
---|
4094 | capture: true |
---|
4095 | } |
---|
4096 | }; |
---|
4097 | |
---|
4098 | /*<ltIE9>*/ |
---|
4099 | var _key = '$delegation:'; |
---|
4100 | var formObserver = function(type){ |
---|
4101 | |
---|
4102 | return { |
---|
4103 | |
---|
4104 | base: 'focusin', |
---|
4105 | |
---|
4106 | remove: function(self, uid){ |
---|
4107 | var list = self.retrieve(_key + type + 'listeners', {})[uid]; |
---|
4108 | if (list && list.forms) for (var i = list.forms.length; i--;){ |
---|
4109 | list.forms[i].removeEvent(type, list.fns[i]); |
---|
4110 | } |
---|
4111 | }, |
---|
4112 | |
---|
4113 | listen: function(self, match, fn, event, target, uid){ |
---|
4114 | var form = (target.get('tag') == 'form') ? target : event.target.getParent('form'); |
---|
4115 | if (!form) return; |
---|
4116 | |
---|
4117 | var listeners = self.retrieve(_key + type + 'listeners', {}), |
---|
4118 | listener = listeners[uid] || {forms: [], fns: []}, |
---|
4119 | forms = listener.forms, fns = listener.fns; |
---|
4120 | |
---|
4121 | if (forms.indexOf(form) != -1) return; |
---|
4122 | forms.push(form); |
---|
4123 | |
---|
4124 | var _fn = function(event){ |
---|
4125 | bubbleUp(self, match, fn, event, target); |
---|
4126 | }; |
---|
4127 | form.addEvent(type, _fn); |
---|
4128 | fns.push(_fn); |
---|
4129 | |
---|
4130 | listeners[uid] = listener; |
---|
4131 | self.store(_key + type + 'listeners', listeners); |
---|
4132 | } |
---|
4133 | }; |
---|
4134 | }; |
---|
4135 | |
---|
4136 | var inputObserver = function(type){ |
---|
4137 | return { |
---|
4138 | base: 'focusin', |
---|
4139 | listen: function(self, match, fn, event, target){ |
---|
4140 | var events = {blur: function(){ |
---|
4141 | this.removeEvents(events); |
---|
4142 | }}; |
---|
4143 | events[type] = function(event){ |
---|
4144 | bubbleUp(self, match, fn, event, target); |
---|
4145 | }; |
---|
4146 | event.target.addEvents(events); |
---|
4147 | } |
---|
4148 | }; |
---|
4149 | }; |
---|
4150 | |
---|
4151 | if (!eventListenerSupport) Object.append(map, { |
---|
4152 | submit: formObserver('submit'), |
---|
4153 | reset: formObserver('reset'), |
---|
4154 | change: inputObserver('change'), |
---|
4155 | select: inputObserver('select') |
---|
4156 | }); |
---|
4157 | /*</ltIE9>*/ |
---|
4158 | |
---|
4159 | var proto = Element.prototype, |
---|
4160 | addEvent = proto.addEvent, |
---|
4161 | removeEvent = proto.removeEvent; |
---|
4162 | |
---|
4163 | var relay = function(old, method){ |
---|
4164 | return function(type, fn, useCapture){ |
---|
4165 | if (type.indexOf(':relay') == -1) return old.call(this, type, fn, useCapture); |
---|
4166 | var parsed = Slick.parse(type).expressions[0][0]; |
---|
4167 | if (parsed.pseudos[0].key != 'relay') return old.call(this, type, fn, useCapture); |
---|
4168 | var newType = parsed.tag; |
---|
4169 | parsed.pseudos.slice(1).each(function(pseudo){ |
---|
4170 | newType += ':' + pseudo.key + (pseudo.value ? '(' + pseudo.value + ')' : ''); |
---|
4171 | }); |
---|
4172 | old.call(this, type, fn); |
---|
4173 | return method.call(this, newType, parsed.pseudos[0].value, fn); |
---|
4174 | }; |
---|
4175 | }; |
---|
4176 | |
---|
4177 | var delegation = { |
---|
4178 | |
---|
4179 | addEvent: function(type, match, fn){ |
---|
4180 | var storage = this.retrieve('$delegates', {}), stored = storage[type]; |
---|
4181 | if (stored) for (var _uid in stored){ |
---|
4182 | if (stored[_uid].fn == fn && stored[_uid].match == match) return this; |
---|
4183 | } |
---|
4184 | |
---|
4185 | var _type = type, _match = match, _fn = fn, _map = map[type] || {}; |
---|
4186 | type = _map.base || _type; |
---|
4187 | |
---|
4188 | match = function(target){ |
---|
4189 | return Slick.match(target, _match); |
---|
4190 | }; |
---|
4191 | |
---|
4192 | var elementEvent = Element.Events[_type]; |
---|
4193 | if (elementEvent && elementEvent.condition){ |
---|
4194 | var __match = match, condition = elementEvent.condition; |
---|
4195 | match = function(target, event){ |
---|
4196 | return __match(target, event) && condition.call(target, event, type); |
---|
4197 | }; |
---|
4198 | } |
---|
4199 | |
---|
4200 | var self = this, uid = String.uniqueID(); |
---|
4201 | var delegator = _map.listen ? function(event, target){ |
---|
4202 | if (!target && event && event.target) target = event.target; |
---|
4203 | if (target) _map.listen(self, match, fn, event, target, uid); |
---|
4204 | } : function(event, target){ |
---|
4205 | if (!target && event && event.target) target = event.target; |
---|
4206 | if (target) bubbleUp(self, match, fn, event, target); |
---|
4207 | }; |
---|
4208 | |
---|
4209 | if (!stored) stored = {}; |
---|
4210 | stored[uid] = { |
---|
4211 | match: _match, |
---|
4212 | fn: _fn, |
---|
4213 | delegator: delegator |
---|
4214 | }; |
---|
4215 | storage[_type] = stored; |
---|
4216 | return addEvent.call(this, type, delegator, _map.capture); |
---|
4217 | }, |
---|
4218 | |
---|
4219 | removeEvent: function(type, match, fn, _uid){ |
---|
4220 | var storage = this.retrieve('$delegates', {}), stored = storage[type]; |
---|
4221 | if (!stored) return this; |
---|
4222 | |
---|
4223 | if (_uid){ |
---|
4224 | var _type = type, delegator = stored[_uid].delegator, _map = map[type] || {}; |
---|
4225 | type = _map.base || _type; |
---|
4226 | if (_map.remove) _map.remove(this, _uid); |
---|
4227 | delete stored[_uid]; |
---|
4228 | storage[_type] = stored; |
---|
4229 | return removeEvent.call(this, type, delegator); |
---|
4230 | } |
---|
4231 | |
---|
4232 | var __uid, s; |
---|
4233 | if (fn) for (__uid in stored){ |
---|
4234 | s = stored[__uid]; |
---|
4235 | if (s.match == match && s.fn == fn) return delegation.removeEvent.call(this, type, match, fn, __uid); |
---|
4236 | } else for (__uid in stored){ |
---|
4237 | s = stored[__uid]; |
---|
4238 | if (s.match == match) delegation.removeEvent.call(this, type, match, s.fn, __uid); |
---|
4239 | } |
---|
4240 | return this; |
---|
4241 | } |
---|
4242 | |
---|
4243 | }; |
---|
4244 | |
---|
4245 | [Element, Window, Document].invoke('implement', { |
---|
4246 | addEvent: relay(addEvent, delegation.addEvent), |
---|
4247 | removeEvent: relay(removeEvent, delegation.removeEvent) |
---|
4248 | }); |
---|
4249 | |
---|
4250 | })(); |
---|
4251 | |
---|
4252 | |
---|
4253 | /* |
---|
4254 | --- |
---|
4255 | |
---|
4256 | name: Element.Dimensions |
---|
4257 | |
---|
4258 | description: Contains methods to work with size, scroll, or positioning of Elements and the window object. |
---|
4259 | |
---|
4260 | license: MIT-style license. |
---|
4261 | |
---|
4262 | credits: |
---|
4263 | - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html). |
---|
4264 | - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html). |
---|
4265 | |
---|
4266 | requires: [Element, Element.Style] |
---|
4267 | |
---|
4268 | provides: [Element.Dimensions] |
---|
4269 | |
---|
4270 | ... |
---|
4271 | */ |
---|
4272 | |
---|
4273 | (function(){ |
---|
4274 | |
---|
4275 | var element = document.createElement('div'), |
---|
4276 | child = document.createElement('div'); |
---|
4277 | element.style.height = '0'; |
---|
4278 | element.appendChild(child); |
---|
4279 | var brokenOffsetParent = (child.offsetParent === element); |
---|
4280 | element = child = null; |
---|
4281 | |
---|
4282 | var isOffset = function(el){ |
---|
4283 | return styleString(el, 'position') != 'static' || isBody(el); |
---|
4284 | }; |
---|
4285 | |
---|
4286 | var isOffsetStatic = function(el){ |
---|
4287 | return isOffset(el) || (/^(?:table|td|th)$/i).test(el.tagName); |
---|
4288 | }; |
---|
4289 | |
---|
4290 | Element.implement({ |
---|
4291 | |
---|
4292 | scrollTo: function(x, y){ |
---|
4293 | if (isBody(this)){ |
---|
4294 | this.getWindow().scrollTo(x, y); |
---|
4295 | } else { |
---|
4296 | this.scrollLeft = x; |
---|
4297 | this.scrollTop = y; |
---|
4298 | } |
---|
4299 | return this; |
---|
4300 | }, |
---|
4301 | |
---|
4302 | getSize: function(){ |
---|
4303 | if (isBody(this)) return this.getWindow().getSize(); |
---|
4304 | return {x: this.offsetWidth, y: this.offsetHeight}; |
---|
4305 | }, |
---|
4306 | |
---|
4307 | getScrollSize: function(){ |
---|
4308 | if (isBody(this)) return this.getWindow().getScrollSize(); |
---|
4309 | return {x: this.scrollWidth, y: this.scrollHeight}; |
---|
4310 | }, |
---|
4311 | |
---|
4312 | getScroll: function(){ |
---|
4313 | if (isBody(this)) return this.getWindow().getScroll(); |
---|
4314 | return {x: this.scrollLeft, y: this.scrollTop}; |
---|
4315 | }, |
---|
4316 | |
---|
4317 | getScrolls: function(){ |
---|
4318 | var element = this.parentNode, position = {x: 0, y: 0}; |
---|
4319 | while (element && !isBody(element)){ |
---|
4320 | position.x += element.scrollLeft; |
---|
4321 | position.y += element.scrollTop; |
---|
4322 | element = element.parentNode; |
---|
4323 | } |
---|
4324 | return position; |
---|
4325 | }, |
---|
4326 | |
---|
4327 | getOffsetParent: brokenOffsetParent ? function(){ |
---|
4328 | var element = this; |
---|
4329 | if (isBody(element) || styleString(element, 'position') == 'fixed') return null; |
---|
4330 | |
---|
4331 | var isOffsetCheck = (styleString(element, 'position') == 'static') ? isOffsetStatic : isOffset; |
---|
4332 | while ((element = element.parentNode)){ |
---|
4333 | if (isOffsetCheck(element)) return element; |
---|
4334 | } |
---|
4335 | return null; |
---|
4336 | } : function(){ |
---|
4337 | var element = this; |
---|
4338 | if (isBody(element) || styleString(element, 'position') == 'fixed') return null; |
---|
4339 | |
---|
4340 | try { |
---|
4341 | return element.offsetParent; |
---|
4342 | } catch(e) {} |
---|
4343 | return null; |
---|
4344 | }, |
---|
4345 | |
---|
4346 | getOffsets: function(){ |
---|
4347 | if (this.getBoundingClientRect && !Browser.Platform.ios){ |
---|
4348 | var bound = this.getBoundingClientRect(), |
---|
4349 | html = document.id(this.getDocument().documentElement), |
---|
4350 | htmlScroll = html.getScroll(), |
---|
4351 | elemScrolls = this.getScrolls(), |
---|
4352 | isFixed = (styleString(this, 'position') == 'fixed'); |
---|
4353 | |
---|
4354 | return { |
---|
4355 | x: bound.left.toInt() + elemScrolls.x + ((isFixed) ? 0 : htmlScroll.x) - html.clientLeft, |
---|
4356 | y: bound.top.toInt() + elemScrolls.y + ((isFixed) ? 0 : htmlScroll.y) - html.clientTop |
---|
4357 | }; |
---|
4358 | } |
---|
4359 | |
---|
4360 | var element = this, position = {x: 0, y: 0}; |
---|
4361 | if (isBody(this)) return position; |
---|
4362 | |
---|
4363 | while (element && !isBody(element)){ |
---|
4364 | position.x += element.offsetLeft; |
---|
4365 | position.y += element.offsetTop; |
---|
4366 | |
---|
4367 | if (Browser.firefox){ |
---|
4368 | if (!borderBox(element)){ |
---|
4369 | position.x += leftBorder(element); |
---|
4370 | position.y += topBorder(element); |
---|
4371 | } |
---|
4372 | var parent = element.parentNode; |
---|
4373 | if (parent && styleString(parent, 'overflow') != 'visible'){ |
---|
4374 | position.x += leftBorder(parent); |
---|
4375 | position.y += topBorder(parent); |
---|
4376 | } |
---|
4377 | } else if (element != this && Browser.safari){ |
---|
4378 | position.x += leftBorder(element); |
---|
4379 | position.y += topBorder(element); |
---|
4380 | } |
---|
4381 | |
---|
4382 | element = element.offsetParent; |
---|
4383 | } |
---|
4384 | if (Browser.firefox && !borderBox(this)){ |
---|
4385 | position.x -= leftBorder(this); |
---|
4386 | position.y -= topBorder(this); |
---|
4387 | } |
---|
4388 | return position; |
---|
4389 | }, |
---|
4390 | |
---|
4391 | getPosition: function(relative){ |
---|
4392 | var offset = this.getOffsets(), |
---|
4393 | scroll = this.getScrolls(); |
---|
4394 | var position = { |
---|
4395 | x: offset.x - scroll.x, |
---|
4396 | y: offset.y - scroll.y |
---|
4397 | }; |
---|
4398 | |
---|
4399 | if (relative && (relative = document.id(relative))){ |
---|
4400 | var relativePosition = relative.getPosition(); |
---|
4401 | return {x: position.x - relativePosition.x - leftBorder(relative), y: position.y - relativePosition.y - topBorder(relative)}; |
---|
4402 | } |
---|
4403 | return position; |
---|
4404 | }, |
---|
4405 | |
---|
4406 | getCoordinates: function(element){ |
---|
4407 | if (isBody(this)) return this.getWindow().getCoordinates(); |
---|
4408 | var position = this.getPosition(element), |
---|
4409 | size = this.getSize(); |
---|
4410 | var obj = { |
---|
4411 | left: position.x, |
---|
4412 | top: position.y, |
---|
4413 | width: size.x, |
---|
4414 | height: size.y |
---|
4415 | }; |
---|
4416 | obj.right = obj.left + obj.width; |
---|
4417 | obj.bottom = obj.top + obj.height; |
---|
4418 | return obj; |
---|
4419 | }, |
---|
4420 | |
---|
4421 | computePosition: function(obj){ |
---|
4422 | return { |
---|
4423 | left: obj.x - styleNumber(this, 'margin-left'), |
---|
4424 | top: obj.y - styleNumber(this, 'margin-top') |
---|
4425 | }; |
---|
4426 | }, |
---|
4427 | |
---|
4428 | setPosition: function(obj){ |
---|
4429 | return this.setStyles(this.computePosition(obj)); |
---|
4430 | } |
---|
4431 | |
---|
4432 | }); |
---|
4433 | |
---|
4434 | |
---|
4435 | [Document, Window].invoke('implement', { |
---|
4436 | |
---|
4437 | getSize: function(){ |
---|
4438 | var doc = getCompatElement(this); |
---|
4439 | return {x: doc.clientWidth, y: doc.clientHeight}; |
---|
4440 | }, |
---|
4441 | |
---|
4442 | getScroll: function(){ |
---|
4443 | var win = this.getWindow(), doc = getCompatElement(this); |
---|
4444 | return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop}; |
---|
4445 | }, |
---|
4446 | |
---|
4447 | getScrollSize: function(){ |
---|
4448 | var doc = getCompatElement(this), |
---|
4449 | min = this.getSize(), |
---|
4450 | body = this.getDocument().body; |
---|
4451 | |
---|
4452 | return {x: Math.max(doc.scrollWidth, body.scrollWidth, min.x), y: Math.max(doc.scrollHeight, body.scrollHeight, min.y)}; |
---|
4453 | }, |
---|
4454 | |
---|
4455 | getPosition: function(){ |
---|
4456 | return {x: 0, y: 0}; |
---|
4457 | }, |
---|
4458 | |
---|
4459 | getCoordinates: function(){ |
---|
4460 | var size = this.getSize(); |
---|
4461 | return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x}; |
---|
4462 | } |
---|
4463 | |
---|
4464 | }); |
---|
4465 | |
---|
4466 | // private methods |
---|
4467 | |
---|
4468 | var styleString = Element.getComputedStyle; |
---|
4469 | |
---|
4470 | function styleNumber(element, style){ |
---|
4471 | return styleString(element, style).toInt() || 0; |
---|
4472 | } |
---|
4473 | |
---|
4474 | function borderBox(element){ |
---|
4475 | return styleString(element, '-moz-box-sizing') == 'border-box'; |
---|
4476 | } |
---|
4477 | |
---|
4478 | function topBorder(element){ |
---|
4479 | return styleNumber(element, 'border-top-width'); |
---|
4480 | } |
---|
4481 | |
---|
4482 | function leftBorder(element){ |
---|
4483 | return styleNumber(element, 'border-left-width'); |
---|
4484 | } |
---|
4485 | |
---|
4486 | function isBody(element){ |
---|
4487 | return (/^(?:body|html)$/i).test(element.tagName); |
---|
4488 | } |
---|
4489 | |
---|
4490 | function getCompatElement(element){ |
---|
4491 | var doc = element.getDocument(); |
---|
4492 | return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; |
---|
4493 | } |
---|
4494 | |
---|
4495 | })(); |
---|
4496 | |
---|
4497 | //aliases |
---|
4498 | Element.alias({position: 'setPosition'}); //compatability |
---|
4499 | |
---|
4500 | [Window, Document, Element].invoke('implement', { |
---|
4501 | |
---|
4502 | getHeight: function(){ |
---|
4503 | return this.getSize().y; |
---|
4504 | }, |
---|
4505 | |
---|
4506 | getWidth: function(){ |
---|
4507 | return this.getSize().x; |
---|
4508 | }, |
---|
4509 | |
---|
4510 | getScrollTop: function(){ |
---|
4511 | return this.getScroll().y; |
---|
4512 | }, |
---|
4513 | |
---|
4514 | getScrollLeft: function(){ |
---|
4515 | return this.getScroll().x; |
---|
4516 | }, |
---|
4517 | |
---|
4518 | getScrollHeight: function(){ |
---|
4519 | return this.getScrollSize().y; |
---|
4520 | }, |
---|
4521 | |
---|
4522 | getScrollWidth: function(){ |
---|
4523 | return this.getScrollSize().x; |
---|
4524 | }, |
---|
4525 | |
---|
4526 | getTop: function(){ |
---|
4527 | return this.getPosition().y; |
---|
4528 | }, |
---|
4529 | |
---|
4530 | getLeft: function(){ |
---|
4531 | return this.getPosition().x; |
---|
4532 | } |
---|
4533 | |
---|
4534 | }); |
---|
4535 | |
---|
4536 | |
---|
4537 | /* |
---|
4538 | --- |
---|
4539 | |
---|
4540 | name: Fx |
---|
4541 | |
---|
4542 | description: Contains the basic animation logic to be extended by all other Fx Classes. |
---|
4543 | |
---|
4544 | license: MIT-style license. |
---|
4545 | |
---|
4546 | requires: [Chain, Events, Options] |
---|
4547 | |
---|
4548 | provides: Fx |
---|
4549 | |
---|
4550 | ... |
---|
4551 | */ |
---|
4552 | |
---|
4553 | (function(){ |
---|
4554 | |
---|
4555 | var Fx = this.Fx = new Class({ |
---|
4556 | |
---|
4557 | Implements: [Chain, Events, Options], |
---|
4558 | |
---|
4559 | options: { |
---|
4560 | /* |
---|
4561 | onStart: nil, |
---|
4562 | onCancel: nil, |
---|
4563 | onComplete: nil, |
---|
4564 | */ |
---|
4565 | fps: 60, |
---|
4566 | unit: false, |
---|
4567 | duration: 500, |
---|
4568 | frames: null, |
---|
4569 | frameSkip: true, |
---|
4570 | link: 'ignore' |
---|
4571 | }, |
---|
4572 | |
---|
4573 | initialize: function(options){ |
---|
4574 | this.subject = this.subject || this; |
---|
4575 | this.setOptions(options); |
---|
4576 | }, |
---|
4577 | |
---|
4578 | getTransition: function(){ |
---|
4579 | return function(p){ |
---|
4580 | return -(Math.cos(Math.PI * p) - 1) / 2; |
---|
4581 | }; |
---|
4582 | }, |
---|
4583 | |
---|
4584 | step: function(now){ |
---|
4585 | if (this.options.frameSkip){ |
---|
4586 | var diff = (this.time != null) ? (now - this.time) : 0, frames = diff / this.frameInterval; |
---|
4587 | this.time = now; |
---|
4588 | this.frame += frames; |
---|
4589 | } else { |
---|
4590 | this.frame++; |
---|
4591 | } |
---|
4592 | |
---|
4593 | if (this.frame < this.frames){ |
---|
4594 | var delta = this.transition(this.frame / this.frames); |
---|
4595 | this.set(this.compute(this.from, this.to, delta)); |
---|
4596 | } else { |
---|
4597 | this.frame = this.frames; |
---|
4598 | this.set(this.compute(this.from, this.to, 1)); |
---|
4599 | this.stop(); |
---|
4600 | } |
---|
4601 | }, |
---|
4602 | |
---|
4603 | set: function(now){ |
---|
4604 | return now; |
---|
4605 | }, |
---|
4606 | |
---|
4607 | compute: function(from, to, delta){ |
---|
4608 | return Fx.compute(from, to, delta); |
---|
4609 | }, |
---|
4610 | |
---|
4611 | check: function(){ |
---|
4612 | if (!this.isRunning()) return true; |
---|
4613 | switch (this.options.link){ |
---|
4614 | case 'cancel': this.cancel(); return true; |
---|
4615 | case 'chain': this.chain(this.caller.pass(arguments, this)); return false; |
---|
4616 | } |
---|
4617 | return false; |
---|
4618 | }, |
---|
4619 | |
---|
4620 | start: function(from, to){ |
---|
4621 | if (!this.check(from, to)) return this; |
---|
4622 | this.from = from; |
---|
4623 | this.to = to; |
---|
4624 | this.frame = (this.options.frameSkip) ? 0 : -1; |
---|
4625 | this.time = null; |
---|
4626 | this.transition = this.getTransition(); |
---|
4627 | var frames = this.options.frames, fps = this.options.fps, duration = this.options.duration; |
---|
4628 | this.duration = Fx.Durations[duration] || duration.toInt(); |
---|
4629 | this.frameInterval = 1000 / fps; |
---|
4630 | this.frames = frames || Math.round(this.duration / this.frameInterval); |
---|
4631 | this.fireEvent('start', this.subject); |
---|
4632 | pushInstance.call(this, fps); |
---|
4633 | return this; |
---|
4634 | }, |
---|
4635 | |
---|
4636 | stop: function(){ |
---|
4637 | if (this.isRunning()){ |
---|
4638 | this.time = null; |
---|
4639 | pullInstance.call(this, this.options.fps); |
---|
4640 | if (this.frames == this.frame){ |
---|
4641 | this.fireEvent('complete', this.subject); |
---|
4642 | if (!this.callChain()) this.fireEvent('chainComplete', this.subject); |
---|
4643 | } else { |
---|
4644 | this.fireEvent('stop', this.subject); |
---|
4645 | } |
---|
4646 | } |
---|
4647 | return this; |
---|
4648 | }, |
---|
4649 | |
---|
4650 | cancel: function(){ |
---|
4651 | if (this.isRunning()){ |
---|
4652 | this.time = null; |
---|
4653 | pullInstance.call(this, this.options.fps); |
---|
4654 | this.frame = this.frames; |
---|
4655 | this.fireEvent('cancel', this.subject).clearChain(); |
---|
4656 | } |
---|
4657 | return this; |
---|
4658 | }, |
---|
4659 | |
---|
4660 | pause: function(){ |
---|
4661 | if (this.isRunning()){ |
---|
4662 | this.time = null; |
---|
4663 | pullInstance.call(this, this.options.fps); |
---|
4664 | } |
---|
4665 | return this; |
---|
4666 | }, |
---|
4667 | |
---|
4668 | resume: function(){ |
---|
4669 | if ((this.frame < this.frames) && !this.isRunning()) pushInstance.call(this, this.options.fps); |
---|
4670 | return this; |
---|
4671 | }, |
---|
4672 | |
---|
4673 | isRunning: function(){ |
---|
4674 | var list = instances[this.options.fps]; |
---|
4675 | return list && list.contains(this); |
---|
4676 | } |
---|
4677 | |
---|
4678 | }); |
---|
4679 | |
---|
4680 | Fx.compute = function(from, to, delta){ |
---|
4681 | return (to - from) * delta + from; |
---|
4682 | }; |
---|
4683 | |
---|
4684 | Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000}; |
---|
4685 | |
---|
4686 | // global timers |
---|
4687 | |
---|
4688 | var instances = {}, timers = {}; |
---|
4689 | |
---|
4690 | var loop = function(){ |
---|
4691 | var now = Date.now(); |
---|
4692 | for (var i = this.length; i--;){ |
---|
4693 | var instance = this[i]; |
---|
4694 | if (instance) instance.step(now); |
---|
4695 | } |
---|
4696 | }; |
---|
4697 | |
---|
4698 | var pushInstance = function(fps){ |
---|
4699 | var list = instances[fps] || (instances[fps] = []); |
---|
4700 | list.push(this); |
---|
4701 | if (!timers[fps]) timers[fps] = loop.periodical(Math.round(1000 / fps), list); |
---|
4702 | }; |
---|
4703 | |
---|
4704 | var pullInstance = function(fps){ |
---|
4705 | var list = instances[fps]; |
---|
4706 | if (list){ |
---|
4707 | list.erase(this); |
---|
4708 | if (!list.length && timers[fps]){ |
---|
4709 | delete instances[fps]; |
---|
4710 | timers[fps] = clearInterval(timers[fps]); |
---|
4711 | } |
---|
4712 | } |
---|
4713 | }; |
---|
4714 | |
---|
4715 | })(); |
---|
4716 | |
---|
4717 | |
---|
4718 | /* |
---|
4719 | --- |
---|
4720 | |
---|
4721 | name: Fx.CSS |
---|
4722 | |
---|
4723 | description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements. |
---|
4724 | |
---|
4725 | license: MIT-style license. |
---|
4726 | |
---|
4727 | requires: [Fx, Element.Style] |
---|
4728 | |
---|
4729 | provides: Fx.CSS |
---|
4730 | |
---|
4731 | ... |
---|
4732 | */ |
---|
4733 | |
---|
4734 | Fx.CSS = new Class({ |
---|
4735 | |
---|
4736 | Extends: Fx, |
---|
4737 | |
---|
4738 | //prepares the base from/to object |
---|
4739 | |
---|
4740 | prepare: function(element, property, values){ |
---|
4741 | values = Array.from(values); |
---|
4742 | var from = values[0], to = values[1]; |
---|
4743 | if (to == null){ |
---|
4744 | to = from; |
---|
4745 | from = element.getStyle(property); |
---|
4746 | var unit = this.options.unit; |
---|
4747 | // adapted from: https://github.com/ryanmorr/fx/blob/master/fx.js#L299 |
---|
4748 | if (unit && from.slice(-unit.length) != unit && parseFloat(from) != 0){ |
---|
4749 | element.setStyle(property, to + unit); |
---|
4750 | var value = element.getComputedStyle(property); |
---|
4751 | // IE and Opera support pixelLeft or pixelWidth |
---|
4752 | if (!(/px$/.test(value))){ |
---|
4753 | value = element.style[('pixel-' + property).camelCase()]; |
---|
4754 | if (value == null){ |
---|
4755 | // adapted from Dean Edwards' http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 |
---|
4756 | var left = element.style.left; |
---|
4757 | element.style.left = to + unit; |
---|
4758 | value = element.style.pixelLeft; |
---|
4759 | element.style.left = left; |
---|
4760 | } |
---|
4761 | } |
---|
4762 | from = (to || 1) / (parseFloat(value) || 1) * (parseFloat(from) || 0); |
---|
4763 | element.setStyle(property, from + unit); |
---|
4764 | } |
---|
4765 | } |
---|
4766 | return {from: this.parse(from), to: this.parse(to)}; |
---|
4767 | }, |
---|
4768 | |
---|
4769 | //parses a value into an array |
---|
4770 | |
---|
4771 | parse: function(value){ |
---|
4772 | value = Function.from(value)(); |
---|
4773 | value = (typeof value == 'string') ? value.split(' ') : Array.from(value); |
---|
4774 | return value.map(function(val){ |
---|
4775 | val = String(val); |
---|
4776 | var found = false; |
---|
4777 | Object.each(Fx.CSS.Parsers, function(parser, key){ |
---|
4778 | if (found) return; |
---|
4779 | var parsed = parser.parse(val); |
---|
4780 | if (parsed || parsed === 0) found = {value: parsed, parser: parser}; |
---|
4781 | }); |
---|
4782 | found = found || {value: val, parser: Fx.CSS.Parsers.String}; |
---|
4783 | return found; |
---|
4784 | }); |
---|
4785 | }, |
---|
4786 | |
---|
4787 | //computes by a from and to prepared objects, using their parsers. |
---|
4788 | |
---|
4789 | compute: function(from, to, delta){ |
---|
4790 | var computed = []; |
---|
4791 | (Math.min(from.length, to.length)).times(function(i){ |
---|
4792 | computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser}); |
---|
4793 | }); |
---|
4794 | computed.$family = Function.from('fx:css:value'); |
---|
4795 | return computed; |
---|
4796 | }, |
---|
4797 | |
---|
4798 | //serves the value as settable |
---|
4799 | |
---|
4800 | serve: function(value, unit){ |
---|
4801 | if (typeOf(value) != 'fx:css:value') value = this.parse(value); |
---|
4802 | var returned = []; |
---|
4803 | value.each(function(bit){ |
---|
4804 | returned = returned.concat(bit.parser.serve(bit.value, unit)); |
---|
4805 | }); |
---|
4806 | return returned; |
---|
4807 | }, |
---|
4808 | |
---|
4809 | //renders the change to an element |
---|
4810 | |
---|
4811 | render: function(element, property, value, unit){ |
---|
4812 | element.setStyle(property, this.serve(value, unit)); |
---|
4813 | }, |
---|
4814 | |
---|
4815 | //searches inside the page css to find the values for a selector |
---|
4816 | |
---|
4817 | search: function(selector){ |
---|
4818 | if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector]; |
---|
4819 | var to = {}, selectorTest = new RegExp('^' + selector.escapeRegExp() + '$'); |
---|
4820 | Array.each(document.styleSheets, function(sheet, j){ |
---|
4821 | var href = sheet.href; |
---|
4822 | if (href && href.contains('://') && !href.contains(document.domain)) return; |
---|
4823 | var rules = sheet.rules || sheet.cssRules; |
---|
4824 | Array.each(rules, function(rule, i){ |
---|
4825 | if (!rule.style) return; |
---|
4826 | var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){ |
---|
4827 | return m.toLowerCase(); |
---|
4828 | }) : null; |
---|
4829 | if (!selectorText || !selectorTest.test(selectorText)) return; |
---|
4830 | Object.each(Element.Styles, function(value, style){ |
---|
4831 | if (!rule.style[style] || Element.ShortStyles[style]) return; |
---|
4832 | value = String(rule.style[style]); |
---|
4833 | to[style] = ((/^rgb/).test(value)) ? value.rgbToHex() : value; |
---|
4834 | }); |
---|
4835 | }); |
---|
4836 | }); |
---|
4837 | return Fx.CSS.Cache[selector] = to; |
---|
4838 | } |
---|
4839 | |
---|
4840 | }); |
---|
4841 | |
---|
4842 | Fx.CSS.Cache = {}; |
---|
4843 | |
---|
4844 | Fx.CSS.Parsers = { |
---|
4845 | |
---|
4846 | Color: { |
---|
4847 | parse: function(value){ |
---|
4848 | if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true); |
---|
4849 | return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false; |
---|
4850 | }, |
---|
4851 | compute: function(from, to, delta){ |
---|
4852 | return from.map(function(value, i){ |
---|
4853 | return Math.round(Fx.compute(from[i], to[i], delta)); |
---|
4854 | }); |
---|
4855 | }, |
---|
4856 | serve: function(value){ |
---|
4857 | return value.map(Number); |
---|
4858 | } |
---|
4859 | }, |
---|
4860 | |
---|
4861 | Number: { |
---|
4862 | parse: parseFloat, |
---|
4863 | compute: Fx.compute, |
---|
4864 | serve: function(value, unit){ |
---|
4865 | return (unit) ? value + unit : value; |
---|
4866 | } |
---|
4867 | }, |
---|
4868 | |
---|
4869 | String: { |
---|
4870 | parse: Function.from(false), |
---|
4871 | compute: function(zero, one){ |
---|
4872 | return one; |
---|
4873 | }, |
---|
4874 | serve: function(zero){ |
---|
4875 | return zero; |
---|
4876 | } |
---|
4877 | } |
---|
4878 | |
---|
4879 | }; |
---|
4880 | |
---|
4881 | |
---|
4882 | |
---|
4883 | |
---|
4884 | /* |
---|
4885 | --- |
---|
4886 | |
---|
4887 | name: Fx.Tween |
---|
4888 | |
---|
4889 | description: Formerly Fx.Style, effect to transition any CSS property for an element. |
---|
4890 | |
---|
4891 | license: MIT-style license. |
---|
4892 | |
---|
4893 | requires: Fx.CSS |
---|
4894 | |
---|
4895 | provides: [Fx.Tween, Element.fade, Element.highlight] |
---|
4896 | |
---|
4897 | ... |
---|
4898 | */ |
---|
4899 | |
---|
4900 | Fx.Tween = new Class({ |
---|
4901 | |
---|
4902 | Extends: Fx.CSS, |
---|
4903 | |
---|
4904 | initialize: function(element, options){ |
---|
4905 | this.element = this.subject = document.id(element); |
---|
4906 | this.parent(options); |
---|
4907 | }, |
---|
4908 | |
---|
4909 | set: function(property, now){ |
---|
4910 | if (arguments.length == 1){ |
---|
4911 | now = property; |
---|
4912 | property = this.property || this.options.property; |
---|
4913 | } |
---|
4914 | this.render(this.element, property, now, this.options.unit); |
---|
4915 | return this; |
---|
4916 | }, |
---|
4917 | |
---|
4918 | start: function(property, from, to){ |
---|
4919 | if (!this.check(property, from, to)) return this; |
---|
4920 | var args = Array.flatten(arguments); |
---|
4921 | this.property = this.options.property || args.shift(); |
---|
4922 | var parsed = this.prepare(this.element, this.property, args); |
---|
4923 | return this.parent(parsed.from, parsed.to); |
---|
4924 | } |
---|
4925 | |
---|
4926 | }); |
---|
4927 | |
---|
4928 | Element.Properties.tween = { |
---|
4929 | |
---|
4930 | set: function(options){ |
---|
4931 | this.get('tween').cancel().setOptions(options); |
---|
4932 | return this; |
---|
4933 | }, |
---|
4934 | |
---|
4935 | get: function(){ |
---|
4936 | var tween = this.retrieve('tween'); |
---|
4937 | if (!tween){ |
---|
4938 | tween = new Fx.Tween(this, {link: 'cancel'}); |
---|
4939 | this.store('tween', tween); |
---|
4940 | } |
---|
4941 | return tween; |
---|
4942 | } |
---|
4943 | |
---|
4944 | }; |
---|
4945 | |
---|
4946 | Element.implement({ |
---|
4947 | |
---|
4948 | tween: function(property, from, to){ |
---|
4949 | this.get('tween').start(property, from, to); |
---|
4950 | return this; |
---|
4951 | }, |
---|
4952 | |
---|
4953 | fade: function(how){ |
---|
4954 | var fade = this.get('tween'), method, args = ['opacity'].append(arguments), toggle; |
---|
4955 | if (args[1] == null) args[1] = 'toggle'; |
---|
4956 | switch (args[1]){ |
---|
4957 | case 'in': method = 'start'; args[1] = 1; break; |
---|
4958 | case 'out': method = 'start'; args[1] = 0; break; |
---|
4959 | case 'show': method = 'set'; args[1] = 1; break; |
---|
4960 | case 'hide': method = 'set'; args[1] = 0; break; |
---|
4961 | case 'toggle': |
---|
4962 | var flag = this.retrieve('fade:flag', this.getStyle('opacity') == 1); |
---|
4963 | method = 'start'; |
---|
4964 | args[1] = flag ? 0 : 1; |
---|
4965 | this.store('fade:flag', !flag); |
---|
4966 | toggle = true; |
---|
4967 | break; |
---|
4968 | default: method = 'start'; |
---|
4969 | } |
---|
4970 | if (!toggle) this.eliminate('fade:flag'); |
---|
4971 | fade[method].apply(fade, args); |
---|
4972 | var to = args[args.length - 1]; |
---|
4973 | if (method == 'set' || to != 0) this.setStyle('visibility', to == 0 ? 'hidden' : 'visible'); |
---|
4974 | else fade.chain(function(){ |
---|
4975 | this.element.setStyle('visibility', 'hidden'); |
---|
4976 | this.callChain(); |
---|
4977 | }); |
---|
4978 | return this; |
---|
4979 | }, |
---|
4980 | |
---|
4981 | highlight: function(start, end){ |
---|
4982 | if (!end){ |
---|
4983 | end = this.retrieve('highlight:original', this.getStyle('background-color')); |
---|
4984 | end = (end == 'transparent') ? '#fff' : end; |
---|
4985 | } |
---|
4986 | var tween = this.get('tween'); |
---|
4987 | tween.start('background-color', start || '#ffff88', end).chain(function(){ |
---|
4988 | this.setStyle('background-color', this.retrieve('highlight:original')); |
---|
4989 | tween.callChain(); |
---|
4990 | }.bind(this)); |
---|
4991 | return this; |
---|
4992 | } |
---|
4993 | |
---|
4994 | }); |
---|
4995 | |
---|
4996 | |
---|
4997 | /* |
---|
4998 | --- |
---|
4999 | |
---|
5000 | name: Fx.Morph |
---|
5001 | |
---|
5002 | description: Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules. |
---|
5003 | |
---|
5004 | license: MIT-style license. |
---|
5005 | |
---|
5006 | requires: Fx.CSS |
---|
5007 | |
---|
5008 | provides: Fx.Morph |
---|
5009 | |
---|
5010 | ... |
---|
5011 | */ |
---|
5012 | |
---|
5013 | Fx.Morph = new Class({ |
---|
5014 | |
---|
5015 | Extends: Fx.CSS, |
---|
5016 | |
---|
5017 | initialize: function(element, options){ |
---|
5018 | this.element = this.subject = document.id(element); |
---|
5019 | this.parent(options); |
---|
5020 | }, |
---|
5021 | |
---|
5022 | set: function(now){ |
---|
5023 | if (typeof now == 'string') now = this.search(now); |
---|
5024 | for (var p in now) this.render(this.element, p, now[p], this.options.unit); |
---|
5025 | return this; |
---|
5026 | }, |
---|
5027 | |
---|
5028 | compute: function(from, to, delta){ |
---|
5029 | var now = {}; |
---|
5030 | for (var p in from) now[p] = this.parent(from[p], to[p], delta); |
---|
5031 | return now; |
---|
5032 | }, |
---|
5033 | |
---|
5034 | start: function(properties){ |
---|
5035 | if (!this.check(properties)) return this; |
---|
5036 | if (typeof properties == 'string') properties = this.search(properties); |
---|
5037 | var from = {}, to = {}; |
---|
5038 | for (var p in properties){ |
---|
5039 | var parsed = this.prepare(this.element, p, properties[p]); |
---|
5040 | from[p] = parsed.from; |
---|
5041 | to[p] = parsed.to; |
---|
5042 | } |
---|
5043 | return this.parent(from, to); |
---|
5044 | } |
---|
5045 | |
---|
5046 | }); |
---|
5047 | |
---|
5048 | Element.Properties.morph = { |
---|
5049 | |
---|
5050 | set: function(options){ |
---|
5051 | this.get('morph').cancel().setOptions(options); |
---|
5052 | return this; |
---|
5053 | }, |
---|
5054 | |
---|
5055 | get: function(){ |
---|
5056 | var morph = this.retrieve('morph'); |
---|
5057 | if (!morph){ |
---|
5058 | morph = new Fx.Morph(this, {link: 'cancel'}); |
---|
5059 | this.store('morph', morph); |
---|
5060 | } |
---|
5061 | return morph; |
---|
5062 | } |
---|
5063 | |
---|
5064 | }; |
---|
5065 | |
---|
5066 | Element.implement({ |
---|
5067 | |
---|
5068 | morph: function(props){ |
---|
5069 | this.get('morph').start(props); |
---|
5070 | return this; |
---|
5071 | } |
---|
5072 | |
---|
5073 | }); |
---|
5074 | |
---|
5075 | |
---|
5076 | /* |
---|
5077 | --- |
---|
5078 | |
---|
5079 | name: Fx.Transitions |
---|
5080 | |
---|
5081 | description: Contains a set of advanced transitions to be used with any of the Fx Classes. |
---|
5082 | |
---|
5083 | license: MIT-style license. |
---|
5084 | |
---|
5085 | credits: |
---|
5086 | - Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools. |
---|
5087 | |
---|
5088 | requires: Fx |
---|
5089 | |
---|
5090 | provides: Fx.Transitions |
---|
5091 | |
---|
5092 | ... |
---|
5093 | */ |
---|
5094 | |
---|
5095 | Fx.implement({ |
---|
5096 | |
---|
5097 | getTransition: function(){ |
---|
5098 | var trans = this.options.transition || Fx.Transitions.Sine.easeInOut; |
---|
5099 | if (typeof trans == 'string'){ |
---|
5100 | var data = trans.split(':'); |
---|
5101 | trans = Fx.Transitions; |
---|
5102 | trans = trans[data[0]] || trans[data[0].capitalize()]; |
---|
5103 | if (data[1]) trans = trans['ease' + data[1].capitalize() + (data[2] ? data[2].capitalize() : '')]; |
---|
5104 | } |
---|
5105 | return trans; |
---|
5106 | } |
---|
5107 | |
---|
5108 | }); |
---|
5109 | |
---|
5110 | Fx.Transition = function(transition, params){ |
---|
5111 | params = Array.from(params); |
---|
5112 | var easeIn = function(pos){ |
---|
5113 | return transition(pos, params); |
---|
5114 | }; |
---|
5115 | return Object.append(easeIn, { |
---|
5116 | easeIn: easeIn, |
---|
5117 | easeOut: function(pos){ |
---|
5118 | return 1 - transition(1 - pos, params); |
---|
5119 | }, |
---|
5120 | easeInOut: function(pos){ |
---|
5121 | return (pos <= 0.5 ? transition(2 * pos, params) : (2 - transition(2 * (1 - pos), params))) / 2; |
---|
5122 | } |
---|
5123 | }); |
---|
5124 | }; |
---|
5125 | |
---|
5126 | Fx.Transitions = { |
---|
5127 | |
---|
5128 | linear: function(zero){ |
---|
5129 | return zero; |
---|
5130 | } |
---|
5131 | |
---|
5132 | }; |
---|
5133 | |
---|
5134 | |
---|
5135 | |
---|
5136 | Fx.Transitions.extend = function(transitions){ |
---|
5137 | for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]); |
---|
5138 | }; |
---|
5139 | |
---|
5140 | Fx.Transitions.extend({ |
---|
5141 | |
---|
5142 | Pow: function(p, x){ |
---|
5143 | return Math.pow(p, x && x[0] || 6); |
---|
5144 | }, |
---|
5145 | |
---|
5146 | Expo: function(p){ |
---|
5147 | return Math.pow(2, 8 * (p - 1)); |
---|
5148 | }, |
---|
5149 | |
---|
5150 | Circ: function(p){ |
---|
5151 | return 1 - Math.sin(Math.acos(p)); |
---|
5152 | }, |
---|
5153 | |
---|
5154 | Sine: function(p){ |
---|
5155 | return 1 - Math.cos(p * Math.PI / 2); |
---|
5156 | }, |
---|
5157 | |
---|
5158 | Back: function(p, x){ |
---|
5159 | x = x && x[0] || 1.618; |
---|
5160 | return Math.pow(p, 2) * ((x + 1) * p - x); |
---|
5161 | }, |
---|
5162 | |
---|
5163 | Bounce: function(p){ |
---|
5164 | var value; |
---|
5165 | for (var a = 0, b = 1; 1; a += b, b /= 2){ |
---|
5166 | if (p >= (7 - 4 * a) / 11){ |
---|
5167 | value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2); |
---|
5168 | break; |
---|
5169 | } |
---|
5170 | } |
---|
5171 | return value; |
---|
5172 | }, |
---|
5173 | |
---|
5174 | Elastic: function(p, x){ |
---|
5175 | return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x && x[0] || 1) / 3); |
---|
5176 | } |
---|
5177 | |
---|
5178 | }); |
---|
5179 | |
---|
5180 | ['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){ |
---|
5181 | Fx.Transitions[transition] = new Fx.Transition(function(p){ |
---|
5182 | return Math.pow(p, i + 2); |
---|
5183 | }); |
---|
5184 | }); |
---|
5185 | |
---|
5186 | |
---|
5187 | /* |
---|
5188 | --- |
---|
5189 | |
---|
5190 | name: Request |
---|
5191 | |
---|
5192 | description: Powerful all purpose Request Class. Uses XMLHTTPRequest. |
---|
5193 | |
---|
5194 | license: MIT-style license. |
---|
5195 | |
---|
5196 | requires: [Object, Element, Chain, Events, Options, Browser] |
---|
5197 | |
---|
5198 | provides: Request |
---|
5199 | |
---|
5200 | ... |
---|
5201 | */ |
---|
5202 | |
---|
5203 | (function(){ |
---|
5204 | |
---|
5205 | var empty = function(){}, |
---|
5206 | progressSupport = ('onprogress' in new Browser.Request); |
---|
5207 | |
---|
5208 | var Request = this.Request = new Class({ |
---|
5209 | |
---|
5210 | Implements: [Chain, Events, Options], |
---|
5211 | |
---|
5212 | options: {/* |
---|
5213 | onRequest: function(){}, |
---|
5214 | onLoadstart: function(event, xhr){}, |
---|
5215 | onProgress: function(event, xhr){}, |
---|
5216 | onComplete: function(){}, |
---|
5217 | onCancel: function(){}, |
---|
5218 | onSuccess: function(responseText, responseXML){}, |
---|
5219 | onFailure: function(xhr){}, |
---|
5220 | onException: function(headerName, value){}, |
---|
5221 | onTimeout: function(){}, |
---|
5222 | user: '', |
---|
5223 | password: '',*/ |
---|
5224 | url: '', |
---|
5225 | data: '', |
---|
5226 | headers: { |
---|
5227 | 'X-Requested-With': 'XMLHttpRequest', |
---|
5228 | 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' |
---|
5229 | }, |
---|
5230 | async: true, |
---|
5231 | format: false, |
---|
5232 | method: 'post', |
---|
5233 | link: 'ignore', |
---|
5234 | isSuccess: null, |
---|
5235 | emulation: true, |
---|
5236 | urlEncoded: true, |
---|
5237 | encoding: 'utf-8', |
---|
5238 | evalScripts: false, |
---|
5239 | evalResponse: false, |
---|
5240 | timeout: 0, |
---|
5241 | noCache: false |
---|
5242 | }, |
---|
5243 | |
---|
5244 | initialize: function(options){ |
---|
5245 | this.xhr = new Browser.Request(); |
---|
5246 | this.setOptions(options); |
---|
5247 | this.headers = this.options.headers; |
---|
5248 | }, |
---|
5249 | |
---|
5250 | onStateChange: function(){ |
---|
5251 | var xhr = this.xhr; |
---|
5252 | if (xhr.readyState != 4 || !this.running) return; |
---|
5253 | this.running = false; |
---|
5254 | this.status = 0; |
---|
5255 | Function.attempt(function(){ |
---|
5256 | var status = xhr.status; |
---|
5257 | this.status = (status == 1223) ? 204 : status; |
---|
5258 | }.bind(this)); |
---|
5259 | xhr.onreadystatechange = empty; |
---|
5260 | if (progressSupport) xhr.onprogress = xhr.onloadstart = empty; |
---|
5261 | clearTimeout(this.timer); |
---|
5262 | |
---|
5263 | this.response = {text: this.xhr.responseText || '', xml: this.xhr.responseXML}; |
---|
5264 | if (this.options.isSuccess.call(this, this.status)) |
---|
5265 | this.success(this.response.text, this.response.xml); |
---|
5266 | else |
---|
5267 | this.failure(); |
---|
5268 | }, |
---|
5269 | |
---|
5270 | isSuccess: function(){ |
---|
5271 | var status = this.status; |
---|
5272 | return (status >= 200 && status < 300); |
---|
5273 | }, |
---|
5274 | |
---|
5275 | isRunning: function(){ |
---|
5276 | return !!this.running; |
---|
5277 | }, |
---|
5278 | |
---|
5279 | processScripts: function(text){ |
---|
5280 | if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return Browser.exec(text); |
---|
5281 | return text.stripScripts(this.options.evalScripts); |
---|
5282 | }, |
---|
5283 | |
---|
5284 | success: function(text, xml){ |
---|
5285 | this.onSuccess(this.processScripts(text), xml); |
---|
5286 | }, |
---|
5287 | |
---|
5288 | onSuccess: function(){ |
---|
5289 | this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain(); |
---|
5290 | }, |
---|
5291 | |
---|
5292 | failure: function(){ |
---|
5293 | this.onFailure(); |
---|
5294 | }, |
---|
5295 | |
---|
5296 | onFailure: function(){ |
---|
5297 | this.fireEvent('complete').fireEvent('failure', this.xhr); |
---|
5298 | }, |
---|
5299 | |
---|
5300 | loadstart: function(event){ |
---|
5301 | this.fireEvent('loadstart', [event, this.xhr]); |
---|
5302 | }, |
---|
5303 | |
---|
5304 | progress: function(event){ |
---|
5305 | this.fireEvent('progress', [event, this.xhr]); |
---|
5306 | }, |
---|
5307 | |
---|
5308 | timeout: function(){ |
---|
5309 | this.fireEvent('timeout', this.xhr); |
---|
5310 | }, |
---|
5311 | |
---|
5312 | setHeader: function(name, value){ |
---|
5313 | this.headers[name] = value; |
---|
5314 | return this; |
---|
5315 | }, |
---|
5316 | |
---|
5317 | getHeader: function(name){ |
---|
5318 | return Function.attempt(function(){ |
---|
5319 | return this.xhr.getResponseHeader(name); |
---|
5320 | }.bind(this)); |
---|
5321 | }, |
---|
5322 | |
---|
5323 | check: function(){ |
---|
5324 | if (!this.running) return true; |
---|
5325 | switch (this.options.link){ |
---|
5326 | case 'cancel': this.cancel(); return true; |
---|
5327 | case 'chain': this.chain(this.caller.pass(arguments, this)); return false; |
---|
5328 | } |
---|
5329 | return false; |
---|
5330 | }, |
---|
5331 | |
---|
5332 | send: function(options){ |
---|
5333 | if (!this.check(options)) return this; |
---|
5334 | |
---|
5335 | this.options.isSuccess = this.options.isSuccess || this.isSuccess; |
---|
5336 | this.running = true; |
---|
5337 | |
---|
5338 | var type = typeOf(options); |
---|
5339 | if (type == 'string' || type == 'element') options = {data: options}; |
---|
5340 | |
---|
5341 | var old = this.options; |
---|
5342 | options = Object.append({data: old.data, url: old.url, method: old.method}, options); |
---|
5343 | var data = options.data, url = String(options.url), method = options.method.toLowerCase(); |
---|
5344 | |
---|
5345 | switch (typeOf(data)){ |
---|
5346 | case 'element': data = document.id(data).toQueryString(); break; |
---|
5347 | case 'object': case 'hash': data = Object.toQueryString(data); |
---|
5348 | } |
---|
5349 | |
---|
5350 | if (this.options.format){ |
---|
5351 | var format = 'format=' + this.options.format; |
---|
5352 | data = (data) ? format + '&' + data : format; |
---|
5353 | } |
---|
5354 | |
---|
5355 | if (this.options.emulation && !['get', 'post'].contains(method)){ |
---|
5356 | var _method = '_method=' + method; |
---|
5357 | data = (data) ? _method + '&' + data : _method; |
---|
5358 | method = 'post'; |
---|
5359 | } |
---|
5360 | |
---|
5361 | if (this.options.urlEncoded && ['post', 'put'].contains(method)){ |
---|
5362 | var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : ''; |
---|
5363 | this.headers['Content-type'] = 'application/x-www-form-urlencoded' + encoding; |
---|
5364 | } |
---|
5365 | |
---|
5366 | if (!url) url = document.location.pathname; |
---|
5367 | |
---|
5368 | var trimPosition = url.lastIndexOf('/'); |
---|
5369 | if (trimPosition > -1 && (trimPosition = url.indexOf('#')) > -1) url = url.substr(0, trimPosition); |
---|
5370 | |
---|
5371 | if (this.options.noCache) |
---|
5372 | url += (url.contains('?') ? '&' : '?') + String.uniqueID(); |
---|
5373 | |
---|
5374 | if (data && method == 'get'){ |
---|
5375 | url += (url.contains('?') ? '&' : '?') + data; |
---|
5376 | data = null; |
---|
5377 | } |
---|
5378 | |
---|
5379 | var xhr = this.xhr; |
---|
5380 | if (progressSupport){ |
---|
5381 | xhr.onloadstart = this.loadstart.bind(this); |
---|
5382 | xhr.onprogress = this.progress.bind(this); |
---|
5383 | } |
---|
5384 | |
---|
5385 | xhr.open(method.toUpperCase(), url, this.options.async, this.options.user, this.options.password); |
---|
5386 | if (this.options.user && 'withCredentials' in xhr) xhr.withCredentials = true; |
---|
5387 | |
---|
5388 | xhr.onreadystatechange = this.onStateChange.bind(this); |
---|
5389 | |
---|
5390 | Object.each(this.headers, function(value, key){ |
---|
5391 | try { |
---|
5392 | xhr.setRequestHeader(key, value); |
---|
5393 | } catch (e){ |
---|
5394 | this.fireEvent('exception', [key, value]); |
---|
5395 | } |
---|
5396 | }, this); |
---|
5397 | |
---|
5398 | this.fireEvent('request'); |
---|
5399 | xhr.send(data); |
---|
5400 | if (!this.options.async) this.onStateChange(); |
---|
5401 | else if (this.options.timeout) this.timer = this.timeout.delay(this.options.timeout, this); |
---|
5402 | return this; |
---|
5403 | }, |
---|
5404 | |
---|
5405 | cancel: function(){ |
---|
5406 | if (!this.running) return this; |
---|
5407 | this.running = false; |
---|
5408 | var xhr = this.xhr; |
---|
5409 | xhr.abort(); |
---|
5410 | clearTimeout(this.timer); |
---|
5411 | xhr.onreadystatechange = empty; |
---|
5412 | if (progressSupport) xhr.onprogress = xhr.onloadstart = empty; |
---|
5413 | this.xhr = new Browser.Request(); |
---|
5414 | this.fireEvent('cancel'); |
---|
5415 | return this; |
---|
5416 | } |
---|
5417 | |
---|
5418 | }); |
---|
5419 | |
---|
5420 | var methods = {}; |
---|
5421 | ['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){ |
---|
5422 | methods[method] = function(data){ |
---|
5423 | var object = { |
---|
5424 | method: method |
---|
5425 | }; |
---|
5426 | if (data != null) object.data = data; |
---|
5427 | return this.send(object); |
---|
5428 | }; |
---|
5429 | }); |
---|
5430 | |
---|
5431 | Request.implement(methods); |
---|
5432 | |
---|
5433 | Element.Properties.send = { |
---|
5434 | |
---|
5435 | set: function(options){ |
---|
5436 | var send = this.get('send').cancel(); |
---|
5437 | send.setOptions(options); |
---|
5438 | return this; |
---|
5439 | }, |
---|
5440 | |
---|
5441 | get: function(){ |
---|
5442 | var send = this.retrieve('send'); |
---|
5443 | if (!send){ |
---|
5444 | send = new Request({ |
---|
5445 | data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action') |
---|
5446 | }); |
---|
5447 | this.store('send', send); |
---|
5448 | } |
---|
5449 | return send; |
---|
5450 | } |
---|
5451 | |
---|
5452 | }; |
---|
5453 | |
---|
5454 | Element.implement({ |
---|
5455 | |
---|
5456 | send: function(url){ |
---|
5457 | var sender = this.get('send'); |
---|
5458 | sender.send({data: this, url: url || sender.options.url}); |
---|
5459 | return this; |
---|
5460 | } |
---|
5461 | |
---|
5462 | }); |
---|
5463 | |
---|
5464 | })(); |
---|
5465 | |
---|
5466 | |
---|
5467 | /* |
---|
5468 | --- |
---|
5469 | |
---|
5470 | name: Request.HTML |
---|
5471 | |
---|
5472 | description: Extends the basic Request Class with additional methods for interacting with HTML responses. |
---|
5473 | |
---|
5474 | license: MIT-style license. |
---|
5475 | |
---|
5476 | requires: [Element, Request] |
---|
5477 | |
---|
5478 | provides: Request.HTML |
---|
5479 | |
---|
5480 | ... |
---|
5481 | */ |
---|
5482 | |
---|
5483 | Request.HTML = new Class({ |
---|
5484 | |
---|
5485 | Extends: Request, |
---|
5486 | |
---|
5487 | options: { |
---|
5488 | update: false, |
---|
5489 | append: false, |
---|
5490 | evalScripts: true, |
---|
5491 | filter: false, |
---|
5492 | headers: { |
---|
5493 | Accept: 'text/html, application/xml, text/xml, */*' |
---|
5494 | } |
---|
5495 | }, |
---|
5496 | |
---|
5497 | success: function(text){ |
---|
5498 | var options = this.options, response = this.response; |
---|
5499 | |
---|
5500 | response.html = text.stripScripts(function(script){ |
---|
5501 | response.javascript = script; |
---|
5502 | }); |
---|
5503 | |
---|
5504 | var match = response.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i); |
---|
5505 | if (match) response.html = match[1]; |
---|
5506 | var temp = new Element('div').set('html', response.html); |
---|
5507 | |
---|
5508 | response.tree = temp.childNodes; |
---|
5509 | response.elements = temp.getElements(options.filter || '*'); |
---|
5510 | |
---|
5511 | if (options.filter) response.tree = response.elements; |
---|
5512 | if (options.update){ |
---|
5513 | var update = document.id(options.update).empty(); |
---|
5514 | if (options.filter) update.adopt(response.elements); |
---|
5515 | else update.set('html', response.html); |
---|
5516 | } else if (options.append){ |
---|
5517 | var append = document.id(options.append); |
---|
5518 | if (options.filter) response.elements.reverse().inject(append); |
---|
5519 | else append.adopt(temp.getChildren()); |
---|
5520 | } |
---|
5521 | if (options.evalScripts) Browser.exec(response.javascript); |
---|
5522 | |
---|
5523 | this.onSuccess(response.tree, response.elements, response.html, response.javascript); |
---|
5524 | } |
---|
5525 | |
---|
5526 | }); |
---|
5527 | |
---|
5528 | Element.Properties.load = { |
---|
5529 | |
---|
5530 | set: function(options){ |
---|
5531 | var load = this.get('load').cancel(); |
---|
5532 | load.setOptions(options); |
---|
5533 | return this; |
---|
5534 | }, |
---|
5535 | |
---|
5536 | get: function(){ |
---|
5537 | var load = this.retrieve('load'); |
---|
5538 | if (!load){ |
---|
5539 | load = new Request.HTML({data: this, link: 'cancel', update: this, method: 'get'}); |
---|
5540 | this.store('load', load); |
---|
5541 | } |
---|
5542 | return load; |
---|
5543 | } |
---|
5544 | |
---|
5545 | }; |
---|
5546 | |
---|
5547 | Element.implement({ |
---|
5548 | |
---|
5549 | load: function(){ |
---|
5550 | this.get('load').send(Array.link(arguments, {data: Type.isObject, url: Type.isString})); |
---|
5551 | return this; |
---|
5552 | } |
---|
5553 | |
---|
5554 | }); |
---|
5555 | |
---|
5556 | |
---|
5557 | /* |
---|
5558 | --- |
---|
5559 | |
---|
5560 | name: JSON |
---|
5561 | |
---|
5562 | description: JSON encoder and decoder. |
---|
5563 | |
---|
5564 | license: MIT-style license. |
---|
5565 | |
---|
5566 | SeeAlso: <http://www.json.org/> |
---|
5567 | |
---|
5568 | requires: [Array, String, Number, Function] |
---|
5569 | |
---|
5570 | provides: JSON |
---|
5571 | |
---|
5572 | ... |
---|
5573 | */ |
---|
5574 | |
---|
5575 | if (typeof JSON == 'undefined') this.JSON = {}; |
---|
5576 | |
---|
5577 | |
---|
5578 | |
---|
5579 | (function(){ |
---|
5580 | |
---|
5581 | var special = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'}; |
---|
5582 | |
---|
5583 | var escape = function(chr){ |
---|
5584 | return special[chr] || '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4); |
---|
5585 | }; |
---|
5586 | |
---|
5587 | JSON.validate = function(string){ |
---|
5588 | string = string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). |
---|
5589 | replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). |
---|
5590 | replace(/(?:^|:|,)(?:\s*\[)+/g, ''); |
---|
5591 | |
---|
5592 | return (/^[\],:{}\s]*$/).test(string); |
---|
5593 | }; |
---|
5594 | |
---|
5595 | JSON.encode = JSON.stringify ? function(obj){ |
---|
5596 | return JSON.stringify(obj); |
---|
5597 | } : function(obj){ |
---|
5598 | if (obj && obj.toJSON) obj = obj.toJSON(); |
---|
5599 | |
---|
5600 | switch (typeOf(obj)){ |
---|
5601 | case 'string': |
---|
5602 | return '"' + obj.replace(/[\x00-\x1f\\"]/g, escape) + '"'; |
---|
5603 | case 'array': |
---|
5604 | return '[' + obj.map(JSON.encode).clean() + ']'; |
---|
5605 | case 'object': case 'hash': |
---|
5606 | var string = []; |
---|
5607 | Object.each(obj, function(value, key){ |
---|
5608 | var json = JSON.encode(value); |
---|
5609 | if (json) string.push(JSON.encode(key) + ':' + json); |
---|
5610 | }); |
---|
5611 | return '{' + string + '}'; |
---|
5612 | case 'number': case 'boolean': return '' + obj; |
---|
5613 | case 'null': return 'null'; |
---|
5614 | } |
---|
5615 | |
---|
5616 | return null; |
---|
5617 | }; |
---|
5618 | |
---|
5619 | JSON.decode = function(string, secure){ |
---|
5620 | if (!string || typeOf(string) != 'string') return null; |
---|
5621 | |
---|
5622 | if (secure || JSON.secure){ |
---|
5623 | if (JSON.parse) return JSON.parse(string); |
---|
5624 | if (!JSON.validate(string)) throw new Error('JSON could not decode the input; security is enabled and the value is not secure.'); |
---|
5625 | } |
---|
5626 | |
---|
5627 | return eval('(' + string + ')'); |
---|
5628 | }; |
---|
5629 | |
---|
5630 | })(); |
---|
5631 | |
---|
5632 | |
---|
5633 | /* |
---|
5634 | --- |
---|
5635 | |
---|
5636 | name: Request.JSON |
---|
5637 | |
---|
5638 | description: Extends the basic Request Class with additional methods for sending and receiving JSON data. |
---|
5639 | |
---|
5640 | license: MIT-style license. |
---|
5641 | |
---|
5642 | requires: [Request, JSON] |
---|
5643 | |
---|
5644 | provides: Request.JSON |
---|
5645 | |
---|
5646 | ... |
---|
5647 | */ |
---|
5648 | |
---|
5649 | Request.JSON = new Class({ |
---|
5650 | |
---|
5651 | Extends: Request, |
---|
5652 | |
---|
5653 | options: { |
---|
5654 | /*onError: function(text, error){},*/ |
---|
5655 | secure: true |
---|
5656 | }, |
---|
5657 | |
---|
5658 | initialize: function(options){ |
---|
5659 | this.parent(options); |
---|
5660 | Object.append(this.headers, { |
---|
5661 | 'Accept': 'application/json', |
---|
5662 | 'X-Request': 'JSON' |
---|
5663 | }); |
---|
5664 | }, |
---|
5665 | |
---|
5666 | success: function(text){ |
---|
5667 | var json; |
---|
5668 | try { |
---|
5669 | json = this.response.json = JSON.decode(text, this.options.secure); |
---|
5670 | } catch (error){ |
---|
5671 | this.fireEvent('error', [text, error]); |
---|
5672 | return; |
---|
5673 | } |
---|
5674 | if (json == null) this.onFailure(); |
---|
5675 | else this.onSuccess(json, text); |
---|
5676 | } |
---|
5677 | |
---|
5678 | }); |
---|
5679 | |
---|
5680 | |
---|
5681 | /* |
---|
5682 | --- |
---|
5683 | |
---|
5684 | name: DOMReady |
---|
5685 | |
---|
5686 | description: Contains the custom event domready. |
---|
5687 | |
---|
5688 | license: MIT-style license. |
---|
5689 | |
---|
5690 | requires: [Browser, Element, Element.Event] |
---|
5691 | |
---|
5692 | provides: [DOMReady, DomReady] |
---|
5693 | |
---|
5694 | ... |
---|
5695 | */ |
---|
5696 | |
---|
5697 | (function(window, document){ |
---|
5698 | |
---|
5699 | var ready, |
---|
5700 | loaded, |
---|
5701 | checks = [], |
---|
5702 | shouldPoll, |
---|
5703 | timer, |
---|
5704 | testElement = document.createElement('div'); |
---|
5705 | |
---|
5706 | var domready = function(){ |
---|
5707 | clearTimeout(timer); |
---|
5708 | if (ready) return; |
---|
5709 | Browser.loaded = ready = true; |
---|
5710 | document.removeListener('DOMContentLoaded', domready).removeListener('readystatechange', check); |
---|
5711 | |
---|
5712 | document.fireEvent('domready'); |
---|
5713 | window.fireEvent('domready'); |
---|
5714 | }; |
---|
5715 | |
---|
5716 | var check = function(){ |
---|
5717 | for (var i = checks.length; i--;) if (checks[i]()){ |
---|
5718 | domready(); |
---|
5719 | return true; |
---|
5720 | } |
---|
5721 | return false; |
---|
5722 | }; |
---|
5723 | |
---|
5724 | var poll = function(){ |
---|
5725 | clearTimeout(timer); |
---|
5726 | if (!check()) timer = setTimeout(poll, 10); |
---|
5727 | }; |
---|
5728 | |
---|
5729 | document.addListener('DOMContentLoaded', domready); |
---|
5730 | |
---|
5731 | /*<ltIE8>*/ |
---|
5732 | // doScroll technique by Diego Perini http://javascript.nwbox.com/IEContentLoaded/ |
---|
5733 | // testElement.doScroll() throws when the DOM is not ready, only in the top window |
---|
5734 | var doScrollWorks = function(){ |
---|
5735 | try { |
---|
5736 | testElement.doScroll(); |
---|
5737 | return true; |
---|
5738 | } catch (e){} |
---|
5739 | return false; |
---|
5740 | }; |
---|
5741 | // If doScroll works already, it can't be used to determine domready |
---|
5742 | // e.g. in an iframe |
---|
5743 | if (testElement.doScroll && !doScrollWorks()){ |
---|
5744 | checks.push(doScrollWorks); |
---|
5745 | shouldPoll = true; |
---|
5746 | } |
---|
5747 | /*</ltIE8>*/ |
---|
5748 | |
---|
5749 | if (document.readyState) checks.push(function(){ |
---|
5750 | var state = document.readyState; |
---|
5751 | return (state == 'loaded' || state == 'complete'); |
---|
5752 | }); |
---|
5753 | |
---|
5754 | if ('onreadystatechange' in document) document.addListener('readystatechange', check); |
---|
5755 | else shouldPoll = true; |
---|
5756 | |
---|
5757 | if (shouldPoll) poll(); |
---|
5758 | |
---|
5759 | Element.Events.domready = { |
---|
5760 | onAdd: function(fn){ |
---|
5761 | if (ready) fn.call(this); |
---|
5762 | } |
---|
5763 | }; |
---|
5764 | |
---|
5765 | // Make sure that domready fires before load |
---|
5766 | Element.Events.load = { |
---|
5767 | base: 'load', |
---|
5768 | onAdd: function(fn){ |
---|
5769 | if (loaded && this == window) fn.call(this); |
---|
5770 | }, |
---|
5771 | condition: function(){ |
---|
5772 | if (this == window){ |
---|
5773 | domready(); |
---|
5774 | delete Element.Events.load; |
---|
5775 | } |
---|
5776 | return true; |
---|
5777 | } |
---|
5778 | }; |
---|
5779 | |
---|
5780 | // This is based on the custom load event |
---|
5781 | window.addEvent('load', function(){ |
---|
5782 | loaded = true; |
---|
5783 | }); |
---|
5784 | |
---|
5785 | })(window, document); |
---|
5786 | |
---|
5787 | |
---|
5788 | /* |
---|
5789 | --- |
---|
5790 | |
---|
5791 | name: Swiff |
---|
5792 | |
---|
5793 | description: Wrapper for embedding SWF movies. Supports External Interface Communication. |
---|
5794 | |
---|
5795 | license: MIT-style license. |
---|
5796 | |
---|
5797 | credits: |
---|
5798 | - Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject. |
---|
5799 | |
---|
5800 | requires: [Options, Object, Element] |
---|
5801 | |
---|
5802 | provides: Swiff |
---|
5803 | |
---|
5804 | ... |
---|
5805 | */ |
---|
5806 | |
---|
5807 | (function(){ |
---|
5808 | |
---|
5809 | var Swiff = this.Swiff = new Class({ |
---|
5810 | |
---|
5811 | Implements: Options, |
---|
5812 | |
---|
5813 | options: { |
---|
5814 | id: null, |
---|
5815 | height: 1, |
---|
5816 | width: 1, |
---|
5817 | container: null, |
---|
5818 | properties: {}, |
---|
5819 | params: { |
---|
5820 | quality: 'high', |
---|
5821 | allowScriptAccess: 'always', |
---|
5822 | wMode: 'window', |
---|
5823 | swLiveConnect: true |
---|
5824 | }, |
---|
5825 | callBacks: {}, |
---|
5826 | vars: {} |
---|
5827 | }, |
---|
5828 | |
---|
5829 | toElement: function(){ |
---|
5830 | return this.object; |
---|
5831 | }, |
---|
5832 | |
---|
5833 | initialize: function(path, options){ |
---|
5834 | this.instance = 'Swiff_' + String.uniqueID(); |
---|
5835 | |
---|
5836 | this.setOptions(options); |
---|
5837 | options = this.options; |
---|
5838 | var id = this.id = options.id || this.instance; |
---|
5839 | var container = document.id(options.container); |
---|
5840 | |
---|
5841 | Swiff.CallBacks[this.instance] = {}; |
---|
5842 | |
---|
5843 | var params = options.params, vars = options.vars, callBacks = options.callBacks; |
---|
5844 | var properties = Object.append({height: options.height, width: options.width}, options.properties); |
---|
5845 | |
---|
5846 | var self = this; |
---|
5847 | |
---|
5848 | for (var callBack in callBacks){ |
---|
5849 | Swiff.CallBacks[this.instance][callBack] = (function(option){ |
---|
5850 | return function(){ |
---|
5851 | return option.apply(self.object, arguments); |
---|
5852 | }; |
---|
5853 | })(callBacks[callBack]); |
---|
5854 | vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack; |
---|
5855 | } |
---|
5856 | |
---|
5857 | params.flashVars = Object.toQueryString(vars); |
---|
5858 | if (Browser.ie){ |
---|
5859 | properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'; |
---|
5860 | params.movie = path; |
---|
5861 | } else { |
---|
5862 | properties.type = 'application/x-shockwave-flash'; |
---|
5863 | } |
---|
5864 | properties.data = path; |
---|
5865 | |
---|
5866 | var build = '<object id="' + id + '"'; |
---|
5867 | for (var property in properties) build += ' ' + property + '="' + properties[property] + '"'; |
---|
5868 | build += '>'; |
---|
5869 | for (var param in params){ |
---|
5870 | if (params[param]) build += '<param name="' + param + '" value="' + params[param] + '" />'; |
---|
5871 | } |
---|
5872 | build += '</object>'; |
---|
5873 | this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild; |
---|
5874 | }, |
---|
5875 | |
---|
5876 | replaces: function(element){ |
---|
5877 | element = document.id(element, true); |
---|
5878 | element.parentNode.replaceChild(this.toElement(), element); |
---|
5879 | return this; |
---|
5880 | }, |
---|
5881 | |
---|
5882 | inject: function(element){ |
---|
5883 | document.id(element, true).appendChild(this.toElement()); |
---|
5884 | return this; |
---|
5885 | }, |
---|
5886 | |
---|
5887 | remote: function(){ |
---|
5888 | return Swiff.remote.apply(Swiff, [this.toElement()].append(arguments)); |
---|
5889 | } |
---|
5890 | |
---|
5891 | }); |
---|
5892 | |
---|
5893 | Swiff.CallBacks = {}; |
---|
5894 | |
---|
5895 | Swiff.remote = function(obj, fn){ |
---|
5896 | var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + '</invoke>'); |
---|
5897 | return eval(rs); |
---|
5898 | }; |
---|
5899 | |
---|
5900 | })(); |
---|
5901 | |
---|