├── Demos
├── custom-event.js
├── demo.css
├── index.html
├── mootools-core.js
├── pinch.html
├── style.css
├── swipe.html
└── touchhold.html
├── LICENSE
├── README.md
├── Source
├── Browser
│ ├── Features.Touch.js
│ └── Mobile.js
├── Desktop
│ └── Mouse.js
└── Touch
│ ├── Click.js
│ ├── Pinch.js
│ ├── Swipe.js
│ ├── Touch.js
│ └── Touchhold.js
└── package.yml
/Demos/custom-event.js:
--------------------------------------------------------------------------------
1 | /*
2 | ---
3 |
4 | name: Element.defineCustomEvent
5 |
6 | description: Allows to create custom events based on other custom events.
7 |
8 | authors: Christoph Pojer (@cpojer)
9 |
10 | license: MIT-style license.
11 |
12 | requires: [Core/Element.Event]
13 |
14 | provides: Element.defineCustomEvent
15 |
16 | ...
17 | */
18 |
19 | (function(){
20 |
21 | [Element, Window, Document].invoke('implement', {hasEvent: function(event){
22 | var events = this.retrieve('events'),
23 | list = (events && events[event]) ? events[event].values : null;
24 | if (list){
25 | for (var i = list.length; i--;) if (i in list){
26 | return true;
27 | }
28 | }
29 | return false;
30 | }});
31 |
32 | var wrap = function(custom, method, extended, name){
33 | method = custom[method];
34 | extended = custom[extended];
35 |
36 | return function(fn, customName){
37 | if (!customName) customName = name;
38 |
39 | if (extended && !this.hasEvent(customName)) extended.call(this, fn, customName);
40 | if (method) method.call(this, fn, customName);
41 | };
42 | };
43 |
44 | var inherit = function(custom, base, method, name){
45 | return function(fn, customName){
46 | base[method].call(this, fn, customName || name);
47 | custom[method].call(this, fn, customName || name);
48 | };
49 | };
50 |
51 | var events = Element.Events;
52 |
53 | Element.defineCustomEvent = function(name, custom){
54 |
55 | var base = events[custom.base];
56 |
57 | custom.onAdd = wrap(custom, 'onAdd', 'onSetup', name);
58 | custom.onRemove = wrap(custom, 'onRemove', 'onTeardown', name);
59 |
60 | events[name] = base ? Object.append({}, custom, {
61 |
62 | base: base.base,
63 |
64 | condition: function(event){
65 | return (!base.condition || base.condition.call(this, event)) &&
66 | (!custom.condition || custom.condition.call(this, event));
67 | },
68 |
69 | onAdd: inherit(custom, base, 'onAdd', name),
70 | onRemove: inherit(custom, base, 'onRemove', name)
71 |
72 | }) : custom;
73 |
74 | return this;
75 |
76 | };
77 |
78 | var loop = function(name){
79 | var method = 'on' + name.capitalize();
80 | Element[name + 'CustomEvents'] = function(){
81 | Object.each(events, function(event, name){
82 | if (event[method]) event[method].call(event, name);
83 | });
84 | };
85 | return loop;
86 | };
87 |
88 | loop('enable')('disable');
89 |
90 | })();
91 |
92 |
--------------------------------------------------------------------------------
/Demos/demo.css:
--------------------------------------------------------------------------------
1 | body > div {
2 | float: left;
3 | }
4 |
5 | div#more {
6 | width: 150px;
7 |
8 | font-weight: bold;
9 | }
10 |
11 | div#more span {
12 | font-size: 1.2em;
13 | }
14 |
--------------------------------------------------------------------------------
/Demos/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MooTools Mobile
5 |
6 |
7 |
8 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
83 |
84 |
85 |
92 |
93 |
94 |
95 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/Demos/mootools-core.js:
--------------------------------------------------------------------------------
1 | /*
2 | ---
3 |
4 | name: Core
5 |
6 | description: The heart of MooTools.
7 |
8 | license: MIT-style license.
9 |
10 | copyright: Copyright (c) 2006-2010 [Valerio Proietti](http://mad4milk.net/).
11 |
12 | authors: The MooTools production team (http://mootools.net/developers/)
13 |
14 | inspiration:
15 | - 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)
16 | - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php)
17 |
18 | provides: [Core, MooTools, Type, typeOf, instanceOf, Native]
19 |
20 | ...
21 | */
22 |
23 | (function(){
24 |
25 | this.MooTools = {
26 | version: '1.3dev',
27 | build: '0a7aeabbbac5bc23b021b4c1aa9ba722c40e303d'
28 | };
29 |
30 | // typeOf, instanceOf
31 |
32 | var typeOf = this.typeOf = function(item){
33 | if (item == null) return 'null';
34 | if (item.$family) return item.$family();
35 |
36 | if (item.nodeName){
37 | if (item.nodeType == 1) return 'element';
38 | if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace';
39 | } else if (typeof item.length == 'number'){
40 | if (item.callee) return 'arguments';
41 | if ('item' in item) return 'collection';
42 | }
43 |
44 | return typeof item;
45 | };
46 |
47 | var instanceOf = this.instanceOf = function(item, object){
48 | if (item == null) return false;
49 | var constructor = item.$constructor || item.constructor;
50 | while (constructor){
51 | if (constructor === object) return true;
52 | constructor = constructor.parent;
53 | }
54 | return item instanceof object;
55 | };
56 |
57 | // Function overloading
58 |
59 | var Function = this.Function;
60 |
61 | var enumerables = true;
62 | for (var i in {toString: 1}) enumerables = null;
63 | if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor'];
64 |
65 | Function.prototype.overloadSetter = function(usePlural){
66 | var self = this;
67 | return function(a, b){
68 | if (a == null) return this;
69 | if (usePlural || typeof a != 'string'){
70 | for (var k in a) self.call(this, k, a[k]);
71 | if (enumerables) for (var i = enumerables.length; i--;){
72 | k = enumerables[i];
73 | if (a.hasOwnProperty(k)) self.call(this, k, a[k]);
74 | }
75 | } else {
76 | self.call(this, a, b);
77 | }
78 | return this;
79 | };
80 | };
81 |
82 | Function.prototype.overloadGetter = function(usePlural){
83 | var self = this;
84 | return function(a){
85 | var args, result;
86 | if (usePlural || typeof a != 'string') args = a;
87 | else if (arguments.length > 1) args = arguments;
88 | if (args){
89 | result = {};
90 | for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]);
91 | } else {
92 | result = self.call(this, a);
93 | }
94 | return result;
95 | };
96 | };
97 |
98 | Function.prototype.extend = function(key, value){
99 | this[key] = value;
100 | }.overloadSetter();
101 |
102 | Function.prototype.implement = function(key, value){
103 | this.prototype[key] = value;
104 | }.overloadSetter();
105 |
106 | // From
107 |
108 | var slice = Array.prototype.slice;
109 |
110 | Function.from = function(item){
111 | return (typeOf(item) == 'function') ? item : function(){
112 | return item;
113 | };
114 | };
115 |
116 | Array.from = function(item){
117 | if (item == null) return [];
118 | return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item];
119 | };
120 |
121 | Number.from = function(item){
122 | var number = parseFloat(item);
123 | return isFinite(number) ? number : null;
124 | };
125 |
126 | String.from = function(item){
127 | return item + '';
128 | };
129 |
130 | // hide, protect
131 |
132 | Function.implement({
133 |
134 | hide: function(){
135 | this.$hidden = true;
136 | return this;
137 | },
138 |
139 | protect: function(){
140 | this.$protected = true;
141 | return this;
142 | }
143 |
144 | });
145 |
146 | // Type
147 |
148 | var Type = this.Type = function(name, object){
149 | if (name){
150 | var lower = name.toLowerCase();
151 | var typeCheck = function(item){
152 | return (typeOf(item) == lower);
153 | };
154 |
155 | Type['is' + name] = typeCheck;
156 | if (object != null){
157 | object.prototype.$family = (function(){
158 | return lower;
159 | }).hide();
160 |
161 | }
162 | }
163 |
164 | if (object == null) return null;
165 |
166 | object.extend(this);
167 | object.$constructor = Type;
168 | object.prototype.$constructor = object;
169 |
170 | return object;
171 | };
172 |
173 | var toString = Object.prototype.toString;
174 |
175 | Type.isEnumerable = function(item){
176 | return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' );
177 | };
178 |
179 | var hooks = {};
180 |
181 | var hooksOf = function(object){
182 | var type = typeOf(object.prototype);
183 | return hooks[type] || (hooks[type] = []);
184 | };
185 |
186 | var implement = function(name, method){
187 | if (method && method.$hidden) return this;
188 |
189 | var hooks = hooksOf(this);
190 |
191 | for (var i = 0; i < hooks.length; i++){
192 | var hook = hooks[i];
193 | if (typeOf(hook) == 'type') implement.call(hook, name, method);
194 | else hook.call(this, name, method);
195 | }
196 |
197 | var previous = this.prototype[name];
198 | if (previous == null || !previous.$protected) this.prototype[name] = method;
199 |
200 | if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){
201 | return method.apply(item, slice.call(arguments, 1));
202 | });
203 |
204 | return this;
205 | };
206 |
207 | var extend = function(name, method){
208 | if (method && method.$hidden) return this;
209 | var previous = this[name];
210 | if (previous == null || !previous.$protected) this[name] = method;
211 | return this;
212 | };
213 |
214 | Type.implement({
215 |
216 | implement: implement.overloadSetter(),
217 |
218 | extend: extend.overloadSetter(),
219 |
220 | alias: function(name, existing){
221 | implement.call(this, name, this.prototype[existing]);
222 | }.overloadSetter(),
223 |
224 | mirror: function(hook){
225 | hooksOf(this).push(hook);
226 | return this;
227 | }
228 |
229 | });
230 |
231 | new Type('Type', Type);
232 |
233 | // Default Types
234 |
235 | var force = function(name, object, methods){
236 | var isType = (object != Object),
237 | prototype = object.prototype;
238 |
239 | if (isType) object = new Type(name, object);
240 |
241 | for (var i = 0, l = methods.length; i < l; i++){
242 | var key = methods[i],
243 | generic = object[key],
244 | proto = prototype[key];
245 |
246 | if (generic) generic.protect();
247 |
248 | if (isType && proto){
249 | delete prototype[key];
250 | prototype[key] = proto.protect();
251 | }
252 | }
253 |
254 | if (isType) object.implement(prototype);
255 |
256 | return force;
257 | };
258 |
259 | force('String', String, [
260 | 'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search',
261 | 'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase'
262 | ])('Array', Array, [
263 | 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice',
264 | 'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight'
265 | ])('Number', Number, [
266 | 'toExponential', 'toFixed', 'toLocaleString', 'toPrecision'
267 | ])('Function', Function, [
268 | 'apply', 'call', 'bind'
269 | ])('RegExp', RegExp, [
270 | 'exec', 'test'
271 | ])('Object', Object, [
272 | 'create', 'defineProperty', 'defineProperties', 'keys',
273 | 'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames',
274 | 'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen'
275 | ])('Date', Date, ['now']);
276 |
277 | Object.extend = extend.overloadSetter();
278 |
279 | Date.extend('now', function(){
280 | return +(new Date);
281 | });
282 |
283 | new Type('Boolean', Boolean);
284 |
285 | // fixes NaN returning as Number
286 |
287 | Number.prototype.$family = function(){
288 | return isFinite(this) ? 'number' : 'null';
289 | }.hide();
290 |
291 | // Number.random
292 |
293 | Number.extend('random', function(min, max){
294 | return Math.floor(Math.random() * (max - min + 1) + min);
295 | });
296 |
297 | // forEach, each
298 |
299 | Object.extend('forEach', function(object, fn, bind){
300 | for (var key in object){
301 | if (object.hasOwnProperty(key)) fn.call(bind, object[key], key, object);
302 | }
303 | });
304 |
305 | Object.each = Object.forEach;
306 |
307 | Array.implement({
308 |
309 | forEach: function(fn, bind){
310 | for (var i = 0, l = this.length; i < l; i++){
311 | if (i in this) fn.call(bind, this[i], i, this);
312 | }
313 | },
314 |
315 | each: function(fn, bind){
316 | Array.forEach(this, fn, bind);
317 | return this;
318 | }
319 |
320 | });
321 |
322 | // Array & Object cloning, Object merging and appending
323 |
324 | var cloneOf = function(item){
325 | switch (typeOf(item)){
326 | case 'array': return item.clone();
327 | case 'object': return Object.clone(item);
328 | default: return item;
329 | }
330 | };
331 |
332 | Array.implement('clone', function(){
333 | var i = this.length, clone = new Array(i);
334 | while (i--) clone[i] = cloneOf(this[i]);
335 | return clone;
336 | });
337 |
338 | var mergeOne = function(source, key, current){
339 | switch (typeOf(current)){
340 | case 'object':
341 | if (typeOf(source[key]) == 'object') Object.merge(source[key], current);
342 | else source[key] = Object.clone(current);
343 | break;
344 | case 'array': source[key] = current.clone(); break;
345 | default: source[key] = current;
346 | }
347 | return source;
348 | };
349 |
350 | Object.extend({
351 |
352 | merge: function(source, k, v){
353 | if (typeOf(k) == 'string') return mergeOne(source, k, v);
354 | for (var i = 1, l = arguments.length; i < l; i++){
355 | var object = arguments[i];
356 | for (var key in object) mergeOne(source, key, object[key]);
357 | }
358 | return source;
359 | },
360 |
361 | clone: function(object){
362 | var clone = {};
363 | for (var key in object) clone[key] = cloneOf(object[key]);
364 | return clone;
365 | },
366 |
367 | append: function(original){
368 | for (var i = 1, l = arguments.length; i < l; i++){
369 | var extended = arguments[i] || {};
370 | for (var key in extended) original[key] = extended[key];
371 | }
372 | return original;
373 | }
374 |
375 | });
376 |
377 | // Object-less types
378 |
379 | ['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){
380 | new Type(name);
381 | });
382 |
383 | // Unique ID
384 |
385 | var UID = Date.now();
386 |
387 | String.extend('generateUID', function(){
388 | return (UID++).toString(36);
389 | });
390 |
391 |
392 |
393 | })();
394 |
395 |
396 | /*
397 | ---
398 |
399 | name: Array
400 |
401 | description: Contains Array Prototypes like each, contains, and erase.
402 |
403 | license: MIT-style license.
404 |
405 | requires: Type
406 |
407 | provides: Array
408 |
409 | ...
410 | */
411 |
412 | Array.implement({
413 |
414 | invoke: function(methodName){
415 | var args = Array.slice(arguments, 1);
416 | return this.map(function(item){
417 | return item[methodName].apply(item, args);
418 | });
419 | },
420 |
421 | every: function(fn, bind){
422 | for (var i = 0, l = this.length; i < l; i++){
423 | if ((i in this) && !fn.call(bind, this[i], i, this)) return false;
424 | }
425 | return true;
426 | },
427 |
428 | filter: function(fn, bind){
429 | var results = [];
430 | for (var i = 0, l = this.length; i < l; i++){
431 | if ((i in this) && fn.call(bind, this[i], i, this)) results.push(this[i]);
432 | }
433 | return results;
434 | },
435 |
436 | clean: function(){
437 | return this.filter(function(item){
438 | return item != null;
439 | });
440 | },
441 |
442 | indexOf: function(item, from){
443 | var len = this.length;
444 | for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
445 | if (this[i] === item) return i;
446 | }
447 | return -1;
448 | },
449 |
450 | map: function(fn, bind){
451 | var results = [];
452 | for (var i = 0, l = this.length; i < l; i++){
453 | if (i in this) results[i] = fn.call(bind, this[i], i, this);
454 | }
455 | return results;
456 | },
457 |
458 | some: function(fn, bind){
459 | for (var i = 0, l = this.length; i < l; i++){
460 | if ((i in this) && fn.call(bind, this[i], i, this)) return true;
461 | }
462 | return false;
463 | },
464 |
465 | associate: function(keys){
466 | var obj = {}, length = Math.min(this.length, keys.length);
467 | for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
468 | return obj;
469 | },
470 |
471 | link: function(object){
472 | var result = {};
473 | for (var i = 0, l = this.length; i < l; i++){
474 | for (var key in object){
475 | if (object[key](this[i])){
476 | result[key] = this[i];
477 | delete object[key];
478 | break;
479 | }
480 | }
481 | }
482 | return result;
483 | },
484 |
485 | contains: function(item, from){
486 | return this.indexOf(item, from) != -1;
487 | },
488 |
489 | append: function(array){
490 | this.push.apply(this, array);
491 | return this;
492 | },
493 |
494 | getLast: function(){
495 | return (this.length) ? this[this.length - 1] : null;
496 | },
497 |
498 | getRandom: function(){
499 | return (this.length) ? this[Number.random(0, this.length - 1)] : null;
500 | },
501 |
502 | include: function(item){
503 | if (!this.contains(item)) this.push(item);
504 | return this;
505 | },
506 |
507 | combine: function(array){
508 | for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
509 | return this;
510 | },
511 |
512 | erase: function(item){
513 | for (var i = this.length; i--;){
514 | if (this[i] === item) this.splice(i, 1);
515 | }
516 | return this;
517 | },
518 |
519 | empty: function(){
520 | this.length = 0;
521 | return this;
522 | },
523 |
524 | flatten: function(){
525 | var array = [];
526 | for (var i = 0, l = this.length; i < l; i++){
527 | var type = typeOf(this[i]);
528 | if (type == 'null') continue;
529 | array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]);
530 | }
531 | return array;
532 | },
533 |
534 | pick: function(){
535 | for (var i = 0, l = this.length; i < l; i++){
536 | if (this[i] != null) return this[i];
537 | }
538 | return null;
539 | },
540 |
541 | hexToRgb: function(array){
542 | if (this.length != 3) return null;
543 | var rgb = this.map(function(value){
544 | if (value.length == 1) value += value;
545 | return value.toInt(16);
546 | });
547 | return (array) ? rgb : 'rgb(' + rgb + ')';
548 | },
549 |
550 | rgbToHex: function(array){
551 | if (this.length < 3) return null;
552 | if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
553 | var hex = [];
554 | for (var i = 0; i < 3; i++){
555 | var bit = (this[i] - 0).toString(16);
556 | hex.push((bit.length == 1) ? '0' + bit : bit);
557 | }
558 | return (array) ? hex : '#' + hex.join('');
559 | }
560 |
561 | });
562 |
563 |
564 |
565 |
566 | /*
567 | ---
568 |
569 | name: String
570 |
571 | description: Contains String Prototypes like camelCase, capitalize, test, and toInt.
572 |
573 | license: MIT-style license.
574 |
575 | requires: Type
576 |
577 | provides: String
578 |
579 | ...
580 | */
581 |
582 | String.implement({
583 |
584 | test: function(regex, params){
585 | return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this);
586 | },
587 |
588 | contains: function(string, separator){
589 | return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1;
590 | },
591 |
592 | trim: function(){
593 | return this.replace(/^\s+|\s+$/g, '');
594 | },
595 |
596 | clean: function(){
597 | return this.replace(/\s+/g, ' ').trim();
598 | },
599 |
600 | camelCase: function(){
601 | return this.replace(/-\D/g, function(match){
602 | return match.charAt(1).toUpperCase();
603 | });
604 | },
605 |
606 | hyphenate: function(){
607 | return this.replace(/[A-Z]/g, function(match){
608 | return ('-' + match.charAt(0).toLowerCase());
609 | });
610 | },
611 |
612 | capitalize: function(){
613 | return this.replace(/\b[a-z]/g, function(match){
614 | return match.toUpperCase();
615 | });
616 | },
617 |
618 | escapeRegExp: function(){
619 | return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
620 | },
621 |
622 | toInt: function(base){
623 | return parseInt(this, base || 10);
624 | },
625 |
626 | toFloat: function(){
627 | return parseFloat(this);
628 | },
629 |
630 | hexToRgb: function(array){
631 | var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
632 | return (hex) ? hex.slice(1).hexToRgb(array) : null;
633 | },
634 |
635 | rgbToHex: function(array){
636 | var rgb = this.match(/\d{1,3}/g);
637 | return (rgb) ? rgb.rgbToHex(array) : null;
638 | },
639 |
640 | substitute: function(object, regexp){
641 | return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){
642 | if (match.charAt(0) == '\\') return match.slice(1);
643 | return (object[name] != null) ? object[name] : '';
644 | });
645 | }
646 |
647 | });
648 |
649 |
650 | /*
651 | ---
652 |
653 | name: Function
654 |
655 | description: Contains Function Prototypes like create, bind, pass, and delay.
656 |
657 | license: MIT-style license.
658 |
659 | requires: Type
660 |
661 | provides: Function
662 |
663 | ...
664 | */
665 |
666 | Function.extend({
667 |
668 | attempt: function(){
669 | for (var i = 0, l = arguments.length; i < l; i++){
670 | try {
671 | return arguments[i]();
672 | } catch (e){}
673 | }
674 | return null;
675 | }
676 |
677 | });
678 |
679 | Function.implement({
680 |
681 | attempt: function(args, bind){
682 | try {
683 | return this.apply(bind, Array.from(args));
684 | } catch (e){}
685 |
686 | return null;
687 | },
688 |
689 | bind: function(bind){
690 | var self = this,
691 | args = (arguments.length > 1) ? Array.slice(arguments, 1) : null;
692 |
693 | return function(){
694 | if (!args && !arguments.length) return self.call(bind);
695 | if (args && arguments.length) return self.apply(bind, args.concat(Array.from(arguments)));
696 | return self.apply(bind, args || arguments);
697 | };
698 | },
699 |
700 | pass: function(args, bind){
701 | var self = this;
702 | if (args != null) args = Array.from(args);
703 | return function(){
704 | return self.apply(bind, args || arguments);
705 | };
706 | },
707 |
708 | delay: function(delay, bind, args){
709 | return setTimeout(this.pass(args, bind), delay);
710 | },
711 |
712 | periodical: function(periodical, bind, args){
713 | return setInterval(this.pass(args, bind), periodical);
714 | }
715 |
716 | });
717 |
718 |
719 |
720 |
721 | /*
722 | ---
723 |
724 | name: Number
725 |
726 | description: Contains Number Prototypes like limit, round, times, and ceil.
727 |
728 | license: MIT-style license.
729 |
730 | requires: Type
731 |
732 | provides: Number
733 |
734 | ...
735 | */
736 |
737 | Number.implement({
738 |
739 | limit: function(min, max){
740 | return Math.min(max, Math.max(min, this));
741 | },
742 |
743 | round: function(precision){
744 | precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0);
745 | return Math.round(this * precision) / precision;
746 | },
747 |
748 | times: function(fn, bind){
749 | for (var i = 0; i < this; i++) fn.call(bind, i, this);
750 | },
751 |
752 | toFloat: function(){
753 | return parseFloat(this);
754 | },
755 |
756 | toInt: function(base){
757 | return parseInt(this, base || 10);
758 | }
759 |
760 | });
761 |
762 | Number.alias('each', 'times');
763 |
764 | (function(math){
765 | var methods = {};
766 | math.each(function(name){
767 | if (!Number[name]) methods[name] = function(){
768 | return Math[name].apply(null, [this].concat(Array.from(arguments)));
769 | };
770 | });
771 | Number.implement(methods);
772 | })(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);
773 |
774 |
775 | /*
776 | ---
777 |
778 | name: Class
779 |
780 | description: Contains the Class Function for easily creating, extending, and implementing reusable Classes.
781 |
782 | license: MIT-style license.
783 |
784 | requires: [Array, String, Function, Number]
785 |
786 | provides: Class
787 |
788 | ...
789 | */
790 |
791 | (function(){
792 |
793 | var Class = this.Class = new Type('Class', function(params){
794 | if (instanceOf(params, Function)) params = {initialize: params};
795 |
796 | var newClass = function(){
797 | reset(this);
798 | if (newClass.$prototyping) return this;
799 | this.$caller = null;
800 | var value = (this.initialize) ? this.initialize.apply(this, arguments) : this;
801 | this.$caller = this.caller = null;
802 | return value;
803 | }.extend(this).implement(params);
804 |
805 | newClass.$constructor = Class;
806 | newClass.prototype.$constructor = newClass;
807 | newClass.prototype.parent = parent;
808 |
809 | return newClass;
810 | });
811 |
812 | var parent = function(){
813 | if (!this.$caller) throw new Error('The method "parent" cannot be called.');
814 | var name = this.$caller.$name,
815 | parent = this.$caller.$owner.parent,
816 | previous = (parent) ? parent.prototype[name] : null;
817 | if (!previous) throw new Error('The method "' + name + '" has no parent.');
818 | return previous.apply(this, arguments);
819 | };
820 |
821 | var reset = function(object){
822 | for (var key in object){
823 | var value = object[key];
824 | switch (typeOf(value)){
825 | case 'object':
826 | var F = function(){};
827 | F.prototype = value;
828 | object[key] = reset(new F);
829 | break;
830 | case 'array': object[key] = value.clone(); break;
831 | }
832 | }
833 | return object;
834 | };
835 |
836 | var wrap = function(self, key, method){
837 | if (method.$origin) method = method.$origin;
838 | var wrapper = function(){
839 | if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.');
840 | var caller = this.caller, current = this.$caller;
841 | this.caller = current; this.$caller = wrapper;
842 | var result = method.apply(this, arguments);
843 | this.$caller = current; this.caller = caller;
844 | return result;
845 | }.extend({$owner: self, $origin: method, $name: key});
846 | return wrapper;
847 | };
848 |
849 | var implement = function(key, value, retain){
850 | if (Class.Mutators.hasOwnProperty(key)){
851 | value = Class.Mutators[key].call(this, value);
852 | if (value == null) return this;
853 | }
854 |
855 | if (typeOf(value) == 'function'){
856 | if (value.$hidden) return this;
857 | this.prototype[key] = (retain) ? value : wrap(this, key, value);
858 | } else {
859 | Object.merge(this.prototype, key, value);
860 | }
861 |
862 | return this;
863 | };
864 |
865 | var getInstance = function(klass){
866 | klass.$prototyping = true;
867 | var proto = new klass;
868 | delete klass.$prototyping;
869 | return proto;
870 | };
871 |
872 | Class.implement('implement', implement.overloadSetter());
873 |
874 | Class.Mutators = {
875 |
876 | Extends: function(parent){
877 | this.parent = parent;
878 | this.prototype = getInstance(parent);
879 | },
880 |
881 | Implements: function(items){
882 | Array.from(items).each(function(item){
883 | var instance = new item;
884 | for (var key in instance) implement.call(this, key, instance[key], true);
885 | }, this);
886 | }
887 | };
888 |
889 | })();
890 |
891 |
892 | /*
893 | ---
894 |
895 | name: Class.Extras
896 |
897 | description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks.
898 |
899 | license: MIT-style license.
900 |
901 | requires: Class
902 |
903 | provides: [Class.Extras, Chain, Events, Options]
904 |
905 | ...
906 | */
907 |
908 | (function(){
909 |
910 | this.Chain = new Class({
911 |
912 | $chain: [],
913 |
914 | chain: function(){
915 | this.$chain.append(Array.flatten(arguments));
916 | return this;
917 | },
918 |
919 | callChain: function(){
920 | return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false;
921 | },
922 |
923 | clearChain: function(){
924 | this.$chain.empty();
925 | return this;
926 | }
927 |
928 | });
929 |
930 | var removeOn = function(string){
931 | return string.replace(/^on([A-Z])/, function(full, first){
932 | return first.toLowerCase();
933 | });
934 | };
935 |
936 | this.Events = new Class({
937 |
938 | $events: {},
939 |
940 | addEvent: function(type, fn, internal){
941 | type = removeOn(type);
942 |
943 |
944 |
945 | this.$events[type] = (this.$events[type] || []).include(fn);
946 | if (internal) fn.internal = true;
947 | return this;
948 | },
949 |
950 | addEvents: function(events){
951 | for (var type in events) this.addEvent(type, events[type]);
952 | return this;
953 | },
954 |
955 | fireEvent: function(type, args, delay){
956 | type = removeOn(type);
957 | var events = this.$events[type];
958 | if (!events) return this;
959 | args = Array.from(args);
960 | events.each(function(fn){
961 | if (delay) fn.delay(delay, this, args);
962 | else fn.apply(this, args);
963 | }, this);
964 | return this;
965 | },
966 |
967 | removeEvent: function(type, fn){
968 | type = removeOn(type);
969 | var events = this.$events[type];
970 | if (events && !fn.internal){
971 | var index = events.indexOf(fn);
972 | if (index != -1) delete events[index];
973 | }
974 | return this;
975 | },
976 |
977 | removeEvents: function(events){
978 | var type;
979 | if (typeOf(events) == 'object'){
980 | for (type in events) this.removeEvent(type, events[type]);
981 | return this;
982 | }
983 | if (events) events = removeOn(events);
984 | for (type in this.$events){
985 | if (events && events != type) continue;
986 | var fns = this.$events[type];
987 | for (var i = fns.length; i--;) this.removeEvent(type, fns[i]);
988 | }
989 | return this;
990 | }
991 |
992 | });
993 |
994 | this.Options = new Class({
995 |
996 | setOptions: function(){
997 | var options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments));
998 | if (!this.addEvent) return this;
999 | for (var option in options){
1000 | if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
1001 | this.addEvent(option, options[option]);
1002 | delete options[option];
1003 | }
1004 | return this;
1005 | }
1006 |
1007 | });
1008 |
1009 | })();
1010 |
1011 |
1012 | /*
1013 | ---
1014 |
1015 | name: Browser
1016 |
1017 | description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash.
1018 |
1019 | license: MIT-style license.
1020 |
1021 | requires: [Array, Function, Number, String]
1022 |
1023 | provides: [Browser, Window, Document]
1024 |
1025 | ...
1026 | */
1027 |
1028 | (function(){
1029 |
1030 | var document = this.document;
1031 | var window = document.window = this;
1032 |
1033 | var UID = 1;
1034 |
1035 | this.$uid = (window.ActiveXObject) ? function(item){
1036 | return (item.uid || (item.uid = [UID++]))[0];
1037 | } : function(item){
1038 | return item.uid || (item.uid = UID++);
1039 | };
1040 |
1041 | $uid(window);
1042 | $uid(document);
1043 |
1044 | var ua = navigator.userAgent.toLowerCase(),
1045 | platform = navigator.platform.toLowerCase(),
1046 | UA = ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0],
1047 | mode = UA[1] == 'ie' && document.documentMode;
1048 |
1049 | var Browser = this.Browser = {
1050 |
1051 | extend: Function.prototype.extend,
1052 |
1053 | name: (UA[1] == 'version') ? UA[3] : UA[1],
1054 |
1055 | version: mode || parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]),
1056 |
1057 | Platform: {
1058 | name: ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0]
1059 | },
1060 |
1061 | Features: {
1062 | xpath: !!(document.evaluate),
1063 | air: !!(window.runtime),
1064 | query: !!(document.querySelector),
1065 | json: !!(window.JSON)
1066 | },
1067 |
1068 | Plugins: {}
1069 |
1070 | };
1071 |
1072 | Browser[Browser.name] = true;
1073 | Browser[Browser.name + parseInt(Browser.version, 10)] = true;
1074 | Browser.Platform[Browser.Platform.name] = true;
1075 |
1076 | // Request
1077 |
1078 | Browser.Request = (function(){
1079 |
1080 | var XMLHTTP = function(){
1081 | return new XMLHttpRequest();
1082 | };
1083 |
1084 | var MSXML2 = function(){
1085 | return new ActiveXObject('MSXML2.XMLHTTP');
1086 | };
1087 |
1088 | var MSXML = function(){
1089 | return new ActiveXObject('Microsoft.XMLHTTP');
1090 | };
1091 |
1092 | return Function.attempt(function(){
1093 | XMLHTTP();
1094 | return XMLHTTP;
1095 | }, function(){
1096 | MSXML2();
1097 | return MSXML2;
1098 | }, function(){
1099 | MSXML();
1100 | return MSXML;
1101 | });
1102 |
1103 | })();
1104 |
1105 | Browser.Features.xhr = !!(Browser.Request);
1106 |
1107 | // Flash detection
1108 |
1109 | var version = (Function.attempt(function(){
1110 | return navigator.plugins['Shockwave Flash'].description;
1111 | }, function(){
1112 | return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
1113 | }) || '0 r0').match(/\d+/g);
1114 |
1115 | Browser.Plugins.Flash = {
1116 | version: Number(version[0] || '0.' + version[1]) || 0,
1117 | build: Number(version[2]) || 0
1118 | };
1119 |
1120 | // String scripts
1121 |
1122 | Browser.exec = function(text){
1123 | if (!text) return text;
1124 | if (window.execScript){
1125 | window.execScript(text);
1126 | } else {
1127 | var script = document.createElement('script');
1128 | script.setAttribute('type', 'text/javascript');
1129 | script.text = text;
1130 | document.head.appendChild(script);
1131 | document.head.removeChild(script);
1132 | }
1133 | return text;
1134 | };
1135 |
1136 | String.implement('stripScripts', function(exec){
1137 | var scripts = '';
1138 | var text = this.replace(/
25 |
26 |
27 |
28 |
29 |
30 |
31 |
47 |
48 |
49 |
56 |
57 | Pinch
58 |
59 |
60 |