atomjs-rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ source "http://rubygems.org"
2
+ gemspec
3
+
4
+ gem 'sqlite3'
5
+
6
+ group :assets do
7
+ gem 'sass-rails', ">= 3.1.0"
8
+ gem 'coffee-rails', ">= 3.1.0"
9
+ gem 'uglifier'
10
+ end
11
+
12
+ gem 'jquery-rails'
13
+
14
+ group :test do
15
+ gem 'turn', :require => false
16
+ gem 'rspec-rails'
17
+ gem 'capybara', '>= 2.0.3'
18
+ gem 'capybara-webkit', :git => 'git@github.com:thoughtbot/capybara-webkit.git'
19
+ end
@@ -0,0 +1,20 @@
1
+ Copyright 2012 http://rocketscience.it <demerest@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,46 @@
1
+ # atomjs-rails [![Build Status](https://secure.travis-ci.org/tanraya/atomjs-rails.png)](http://travis-ci.org/tanraya/atomjs-rails)
2
+
3
+ Atom javascript library prepared for using with Rails 3.1+
4
+
5
+ ## What is Atom?
6
+
7
+ Atom is compact JavaScript framework oriented on modern browsers, which allows to support quite broad list of features without keeping a lot of cruft necessary to implement them in old browsers.
8
+
9
+ Supported browsers:
10
+
11
+ * Firefox 3.5+
12
+ * Google Chrome
13
+ * Safari 4+
14
+ * Opera 10+
15
+ * Internet Explorer 9+
16
+ * Mobile Safari
17
+ * Android Browser
18
+ * Opera Mobile
19
+
20
+ Atom github repo: https://github.com/theshock/atomjs
21
+
22
+ ## Installation
23
+
24
+ First, put this line in your `Gemfile`:
25
+
26
+ ```ruby
27
+ gem 'atomjs-rails'
28
+ ```
29
+
30
+ Then run `bundle install` to update your application's bundle.
31
+
32
+ Now you need to edit your `app/assets/javascripts/application.js` file and add the following line:
33
+
34
+ ```javascript
35
+ //= require atom
36
+ ```
37
+
38
+ And you're done!
39
+
40
+ ## Usage
41
+
42
+ See docs [Docs folder](https://github.com/theshock/atomjs/tree/master/Docs/En) for description of Atom core and bundled plugins.
43
+
44
+ ## License
45
+
46
+ [The MIT License](https://github.com/tanraya/atomjs-rails/blob/master/MIT-LICENSE)
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,5 @@
1
+ if defined? Rails && Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR >= 1
2
+ require "atomjs-rails/engine"
3
+ else
4
+ puts "You should use Rails 3.1 and higher with atomjs-rails!"
5
+ end
@@ -0,0 +1,4 @@
1
+ module AtomjsRails
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,4918 @@
1
+
2
+ /*
3
+ ---
4
+
5
+ name: "AtomJS"
6
+
7
+ license:
8
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
9
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
10
+
11
+ authors:
12
+ - Pavel Ponomarenko aka Shock <shocksilien@gmail.com>
13
+
14
+ inspiration:
15
+ - "[JQuery](http://jquery.com)"
16
+ - "[MooTools](http://mootools.net)"
17
+
18
+ ...
19
+ */
20
+
21
+ (function (Object, Array, undefined) { // AtomJS
22
+ // Safari 5 bug:
23
+ // 'use strict';
24
+
25
+ var
26
+ toString = Object.prototype.toString,
27
+ hasOwn = Object.prototype.hasOwnProperty,
28
+ slice = Array .prototype.slice,
29
+ atom = this.atom = function () {
30
+ if (atom.initialize) return atom.initialize.apply(this, arguments);
31
+ };
32
+
33
+ atom.global = this;
34
+
35
+ /*
36
+ ---
37
+
38
+ name: "JavaScript 1.8.5"
39
+
40
+ description: "JavaScript 1.8.5 Compatiblity."
41
+
42
+ license:
43
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
44
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
45
+
46
+ inspiration:
47
+ - "[JQuery](http://jquery.com)"
48
+ - "[MooTools](http://mootools.net)"
49
+
50
+ provides: js185
51
+
52
+ ...
53
+ */
54
+
55
+ // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
56
+ if (!Function.prototype.bind) {
57
+ Function.prototype.bind = function(context /*, arg1, arg2... */) {
58
+ if (typeof this !== "function") throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
59
+
60
+ var args = slice.call(arguments, 1),
61
+ toBind = this,
62
+ Nop = function () {},
63
+ Bound = function () {
64
+ var isInstance;
65
+ // Opera & Safari bug fixed. I must fix it in right way
66
+ // TypeError: Second argument to 'instanceof' does not implement [[HasInstance]]
67
+ try {
68
+ isInstance = this instanceof Nop;
69
+ } catch (ignored) {
70
+ // console.log( 'bind error', Nop.prototype );
71
+ isInstance = false;
72
+ }
73
+ return toBind.apply(
74
+ isInstance ? this : ( context || {} ),
75
+ args.concat( slice.call(arguments) )
76
+ );
77
+ };
78
+ Nop.prototype = toBind.prototype;
79
+ Bound.prototype = new Nop();
80
+ return Bound;
81
+ };
82
+ }
83
+
84
+ // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys
85
+ if (!Object.keys) (function (has) {
86
+
87
+ Object.keys = function(obj) {
88
+ if (obj !== Object(obj)) throw new TypeError('Object.keys called on non-object');
89
+
90
+ var keys = [], i;
91
+ for (i in obj) if (has.call(obj, i)) keys.push(i);
92
+ return keys;
93
+ };
94
+ })({}.hasOwnProperty);
95
+
96
+ // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
97
+ if (!Array.isArray) {
98
+ Array.isArray = function(o) {
99
+ return o && toString.call(o) === '[object Array]';
100
+ };
101
+ }
102
+
103
+ // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/create
104
+ if (!Object.create) {
105
+ Object.create = function (o) {
106
+ if (arguments.length > 1) {
107
+ throw new Error('Object.create implementation only accepts the first parameter.');
108
+ }
109
+ function F() {}
110
+ F.prototype = o;
111
+ return new F();
112
+ };
113
+ }
114
+
115
+ if (!String.prototype.trim) {
116
+ String.prototype.trim = function () {
117
+ return this.replace(/^\s+|\s+$/g, '');
118
+ }
119
+ }
120
+
121
+ if (!String.prototype.trimLeft) {
122
+ String.prototype.trimLeft = function () {
123
+ return this.replace(/^\s+/, '');
124
+ }
125
+ }
126
+
127
+ if (!String.prototype.trimRight) {
128
+ String.prototype.trimRight = function () {
129
+ return this.replace(/\s+$/g, '');
130
+ }
131
+ }
132
+
133
+ /*
134
+ ---
135
+
136
+ name: "Core"
137
+
138
+ description: "The core of AtomJS."
139
+
140
+ license:
141
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
142
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
143
+
144
+ inspiration:
145
+ - "[JQuery](http://jquery.com)"
146
+ - "[MooTools](http://mootools.net)"
147
+
148
+ provides: Core
149
+
150
+ requires:
151
+ - js185
152
+
153
+ ...
154
+ */
155
+
156
+ function coreIsFunction (item) {
157
+ return item && toString.call(item) == '[object Function]';
158
+ }
159
+
160
+ function coreObjectize (properties, value) {
161
+ if (typeof properties != 'object') {
162
+ var key = properties;
163
+ properties = {};
164
+ if (key != null) {
165
+ properties[key] = value;
166
+ }
167
+ }
168
+ return properties;
169
+ }
170
+
171
+ function coreContains (array, element) {
172
+ return array.indexOf(element) >= 0;
173
+ }
174
+
175
+ function includeUnique(array, element) {
176
+ if (!coreContains(array, element)) {
177
+ array.push(element);
178
+ }
179
+ return array;
180
+ }
181
+
182
+ function coreEraseOne(array, element) {
183
+ element = array.indexOf(element);
184
+ if (element != -1) {
185
+ array.splice( element, 1 );
186
+ }
187
+ return array;
188
+ }
189
+
190
+ function coreEraseAll(array, element) {
191
+ for (var i = array.length; i--;) {
192
+ if (array[i] == element) {
193
+ array.splice( i, 1 );
194
+ }
195
+ }
196
+ return array;
197
+ }
198
+ function coreToArray (elem) { return slice.call(elem) }
199
+ function coreIsArrayLike (item) {
200
+ return item && (Array.isArray(item) || (
201
+ typeof item != 'string' &&
202
+ !coreIsFunction(item) &&
203
+ typeof item.nodeName != 'string' &&
204
+ typeof item.length == 'number'
205
+ ));
206
+ }
207
+ function coreAppend(target, source) {
208
+ if (source) for (var key in source) if (hasOwn.call(source, key)) {
209
+ target[key] = source[key];
210
+ }
211
+ return target;
212
+ }
213
+
214
+ new function () {
215
+
216
+ function ensureObjectSetter (fn) {
217
+ return function (properties, value) {
218
+ return fn.call(this, coreObjectize(properties, value))
219
+ }
220
+ }
221
+ function overloadSetter (fn) {
222
+ return function (properties, value) {
223
+ properties = coreObjectize(properties, value);
224
+ for (var i in properties) fn.call( this, i, properties[i] );
225
+ return this;
226
+ };
227
+ }
228
+ function overloadGetter (fn, ignoreEmpty) {
229
+ return function (properties) {
230
+ if (Array.isArray(properties)) {
231
+ var result = {}, name, value;
232
+ for (var i = properties.length; i--;) {
233
+ name = properties[i];
234
+ value = fn.call(this, name);
235
+ if (!ignoreEmpty || typeof value !== 'undefined') {
236
+ result[name] = value;
237
+ }
238
+ }
239
+ return result;
240
+ }
241
+ return fn.call(this, properties);
242
+ };
243
+ }
244
+ /**
245
+ * Returns function that calls callbacks.get
246
+ * if first parameter is primitive & second parameter is undefined
247
+ * object.attr('name') - get
248
+ * object.attr('name', 'value') - set
249
+ * object.attr({name: 'value'}) - set
250
+ * @param {Object} callbacks
251
+ * @param {Function} callbacks.get
252
+ * @param {Function} callbacks.set
253
+ */
254
+ function slickAccessor (callbacks) {
255
+ var setter = atom.core.overloadSetter(callbacks.set);
256
+
257
+ return function (properties, value) {
258
+ if (typeof value === 'undefined' && typeof properties !== 'object') {
259
+ return callbacks.get.call(this, properties);
260
+ } else {
261
+ return setter.call(this, properties, value);
262
+ }
263
+ };
264
+ }
265
+
266
+ atom.core = {
267
+ isFunction: coreIsFunction,
268
+ objectize : coreObjectize,
269
+ contains : coreContains,
270
+ eraseOne : coreEraseOne,
271
+ eraseAll : coreEraseAll,
272
+ toArray : coreToArray,
273
+ append : coreAppend,
274
+ isArrayLike : coreIsArrayLike,
275
+ includeUnique : includeUnique,
276
+ slickAccessor : slickAccessor,
277
+ overloadSetter: overloadSetter,
278
+ overloadGetter: overloadGetter,
279
+ ensureObjectSetter: ensureObjectSetter
280
+ };
281
+
282
+ /** @deprecated - use atom.core.toArray instead */
283
+ atom.toArray = coreToArray;
284
+ /** @deprecated - use console-cap instead: https://github.com/theshock/console-cap/ */
285
+ atom.log = function () { throw new Error('deprecated') };
286
+ /** @deprecated - use atom.core.isArrayLike instead */
287
+ atom.isArrayLike = coreIsArrayLike;
288
+ /** @deprecated - use atom.core.append instead */
289
+ atom.append = coreAppend;
290
+
291
+ };
292
+
293
+ /*
294
+ ---
295
+
296
+ name: "Accessors"
297
+
298
+ description: "Implementing accessors"
299
+
300
+ license:
301
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
302
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
303
+
304
+ requires:
305
+ - Core
306
+
307
+ provides: accessors
308
+
309
+ ...
310
+ */
311
+
312
+ (function (Object) {
313
+ var standard = !!Object.getOwnPropertyDescriptor, nonStandard = !!{}.__defineGetter__;
314
+
315
+ if (!standard && !nonStandard) throw new Error('Accessors are not supported');
316
+
317
+ var lookup = nonStandard ?
318
+ function (from, key, bool) {
319
+ var g = from.__lookupGetter__(key), s = from.__lookupSetter__(key), has = !!(g || s);
320
+
321
+ if (bool) return has;
322
+
323
+ return has ? { get: g, set: s } : null;
324
+ } :
325
+ function (from, key, bool) {
326
+ var descriptor = Object.getOwnPropertyDescriptor(from, key);
327
+ if (!descriptor) {
328
+ // try to find accessors according to chain of prototypes
329
+ var proto = Object.getPrototypeOf(from);
330
+ if (proto) return atom.accessors.lookup(proto, key, bool);
331
+ } else if ( descriptor.set || descriptor.get ) {
332
+ if (bool) return true;
333
+
334
+ return {
335
+ set: descriptor.set,
336
+ get: descriptor.get
337
+ };
338
+ }
339
+ return bool ? false : null;
340
+ }; /* lookup */
341
+
342
+ var define = nonStandard ?
343
+ function (object, prop, descriptor) {
344
+ if (descriptor) {
345
+ if (descriptor.get) object.__defineGetter__(prop, descriptor.get);
346
+ if (descriptor.set) object.__defineSetter__(prop, descriptor.set);
347
+ }
348
+ return object;
349
+ } :
350
+ function (object, prop, descriptor) {
351
+ if (descriptor) {
352
+ var desc = {
353
+ get: descriptor.get,
354
+ set: descriptor.set,
355
+ configurable: true,
356
+ enumerable: true
357
+ };
358
+ Object.defineProperty(object, prop, desc);
359
+ }
360
+ return object;
361
+ };
362
+
363
+ atom.accessors = {
364
+ lookup: lookup,
365
+ define: function (object, prop, descriptor) {
366
+ if (typeof prop == 'object') {
367
+ for (var i in prop) define(object, i, prop[i]);
368
+ } else {
369
+ define(object, prop, descriptor);
370
+ }
371
+ return object;
372
+ },
373
+ has: function (object, key) {
374
+ return atom.accessors.lookup(object, key, true);
375
+ },
376
+ inherit: function (from, to, key) {
377
+ var a = atom.accessors.lookup(from, key);
378
+
379
+ if ( a ) {
380
+ atom.accessors.define(to, key, a);
381
+ return true;
382
+ }
383
+ return false;
384
+ }
385
+ };
386
+ })(Object);
387
+
388
+ /*
389
+ ---
390
+
391
+ name: "Dom"
392
+
393
+ description: "todo"
394
+
395
+ license:
396
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
397
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
398
+
399
+ requires:
400
+ - Core
401
+ - accessors
402
+
403
+ inspiration:
404
+ - "[JQuery](http://jquery.org)"
405
+
406
+ provides: dom
407
+
408
+ ...
409
+ */
410
+ (function (window, document) {
411
+ var
412
+ regexp = {
413
+ Tag : /^[-_a-z0-9]+$/i,
414
+ Class: /^\.[-_a-z0-9]+$/i,
415
+ Id : /^#[-_a-z0-9]+$/i
416
+ },
417
+ isArray = Array.isArray,
418
+ prevent = function (e) {
419
+ e.preventDefault();
420
+ return false;
421
+ },
422
+ ignoreCssPostfix = {
423
+ zIndex: true,
424
+ fontWeight: true,
425
+ opacity: true,
426
+ zoom: true,
427
+ lineHeight: true
428
+ },
429
+ domReady = false,
430
+ onDomReady = [],
431
+ camelCase = function (str) {
432
+ return String(str).replace(/-\D/g, function(match){
433
+ return match[1].toUpperCase();
434
+ });
435
+ },
436
+ hyphenate = function (str) {
437
+ return String(str).replace(/[A-Z]/g, function(match){
438
+ return '-' + match[0].toLowerCase();
439
+ });
440
+ },
441
+ readyCallback = function () {
442
+ if (domReady) return;
443
+
444
+ domReady = true;
445
+
446
+ for (var i = 0; i < onDomReady.length;) {
447
+ onDomReady[i++]();
448
+ }
449
+
450
+ onDomReady = [];
451
+ },
452
+ findParentByLevel = function (elem, level) {
453
+ if (level == null || level < 0) level = 1;
454
+
455
+ if (!elem || level <= 0) return atom.dom(elem);
456
+
457
+ return findParentByLevel(elem.parentNode, level-1);
458
+ };
459
+
460
+ document.addEventListener('DOMContentLoaded', readyCallback, false);
461
+ window.addEventListener('load', readyCallback, false);
462
+
463
+ var Dom = function (sel, context) {
464
+ if (! (this instanceof Dom)) {
465
+ return new Dom(sel, context);
466
+ }
467
+
468
+ if (!arguments.length) {
469
+ this.elems = [document];
470
+ return this;
471
+ }
472
+
473
+ if (!context && sel === 'body') {
474
+ this.elems = [document.body];
475
+ return this;
476
+ }
477
+
478
+ if (context !== undefined) {
479
+ return new Dom(context || document).find(sel);
480
+ }
481
+ context = context || document;
482
+
483
+ if (typeof sel == 'function' && !(sel instanceof Dom)) {
484
+ // onDomReady
485
+ var fn = sel.bind(this, atom, Dom);
486
+ domReady ? setTimeout(fn, 1) : onDomReady.push(fn);
487
+ return this;
488
+ }
489
+
490
+ var elems = this.elems =
491
+ sel == window ? [ document ]
492
+ : sel instanceof Dom ? coreToArray(sel.elems)
493
+ : coreIsArrayLike(sel) ? coreToArray(sel)
494
+ : typeof sel == 'string' ? Dom.query(context, sel)
495
+ : Dom.find(context, sel);
496
+
497
+ if (elems.length == 1 && elems[0] == null) {
498
+ elems.length = 0;
499
+ }
500
+
501
+ return this;
502
+ };
503
+ coreAppend(Dom, {
504
+ query : function (context, sel) {
505
+ return sel.match(regexp.Id) ? [(context.getElementById ? context : document).getElementById(sel.substr(1))] :
506
+ sel.match(regexp.Class) ? coreToArray(context.getElementsByClassName(sel.substr(1))) :
507
+ sel.match(regexp.Tag) ? coreToArray(context.getElementsByTagName (sel)) :
508
+ coreToArray(context.querySelectorAll (sel));
509
+ },
510
+ find: function (context, sel) {
511
+ if (!sel) return context == null ? [] : [context];
512
+
513
+ var result = sel.nodeName ? [sel]
514
+ : typeof sel == 'string' ? Dom.query(context, sel) : [context];
515
+ return (result.length == 1 && result[0] == null) ? [] : result;
516
+ },
517
+ create: function (tagName, attr) {
518
+ var elem = new Dom(document.createElement(tagName));
519
+ if (attr) elem.attr(attr);
520
+ return elem;
521
+ },
522
+ isElement: function (node) {
523
+ return !!(node && node.nodeName);
524
+ }
525
+ });
526
+ Dom.prototype = {
527
+ get length() {
528
+ return this.elems ? this.elems.length : 0;
529
+ },
530
+ get body() {
531
+ return this.find('body');
532
+ },
533
+ get first() {
534
+ return this.elems[0];
535
+ },
536
+ get : function (index) {
537
+ return this.elems[Number(index) || 0];
538
+ },
539
+ parent : function(step) {
540
+ return findParentByLevel(this.first, step);
541
+ },
542
+ contains: function (child) {
543
+ var parent = this.first;
544
+ child = atom.dom(child).first;
545
+ if ( child ) while ( child = child.parentNode ) {
546
+ if( child == parent ) {
547
+ return true;
548
+ }
549
+ }
550
+ return false;
551
+ },
552
+ filter: function (selector) {
553
+ var property = null;
554
+ // speed optimization for "tag" & "id" filtering
555
+ if (selector.match(regexp.Tag)) {
556
+ selector = selector.toUpperCase();
557
+ property = 'tagName';
558
+ } else if (selector.match(regexp.Id)) {
559
+ selector = selector.substr(1).toUpperCase();
560
+ property = 'id';
561
+ }
562
+
563
+ return new Dom(this.elems.filter(function (elem) {
564
+ if (property) {
565
+ return elem[property].toUpperCase() == selector;
566
+ } else {
567
+ return elem.parentNode && coreToArray(
568
+ elem.parentNode.querySelectorAll(selector)
569
+ ).indexOf(elem) >= 0;
570
+ }
571
+ }));
572
+ },
573
+ is: function (selector) {
574
+ return this.filter(selector).length > 0;
575
+ },
576
+ html : function (value) {
577
+ if (value != null) {
578
+ this.first.innerHTML = value;
579
+ return this;
580
+ } else {
581
+ return this.first.innerHTML;
582
+ }
583
+ },
584
+ text : function (value) {
585
+ var property = document.body.innerText == null ? 'textContent' : 'innerText';
586
+ if (value == null) {
587
+ return this.first[property];
588
+ }
589
+ this.first[property] = value;
590
+ return this;
591
+ },
592
+ create : function (tagName, index, attr) {
593
+ if (typeof index == 'object') {
594
+ attr = index;
595
+ index = 0;
596
+ }
597
+ atom.dom.create(tagName, attr).appendTo( this.get(index) );
598
+ return this;
599
+ },
600
+ each : function (fn) {
601
+ this.elems.forEach(fn.bind(this));
602
+ return this;
603
+ },
604
+ attr : atom.core.slickAccessor({
605
+ get: function (name) {
606
+ return this.first.getAttribute(name);
607
+ },
608
+ set: function (name, value) {
609
+ var e = this.elems, i = e.length;
610
+ while (i--) {
611
+ e[i].setAttribute(name, value)
612
+ }
613
+ }
614
+ }),
615
+ css : atom.core.slickAccessor({
616
+ get: function (name) {
617
+ return window.getComputedStyle(this.first, "").getPropertyValue(hyphenate(name));
618
+ },
619
+ set: function (name, value) {
620
+ var e = this.elems, i = e.length;
621
+ while (i--) {
622
+ if (typeof value == 'number' && !ignoreCssPostfix[name]) {
623
+ value += 'px';
624
+ }
625
+ e[i].style[camelCase(name)] = value;
626
+ }
627
+ }
628
+ }),
629
+
630
+ bind : atom.core.overloadSetter(function (event, callback) {
631
+ if (callback === false) callback = prevent;
632
+
633
+ this.each(function (elem) {
634
+ if (elem == document && event == 'load') elem = window;
635
+ elem.addEventListener(event, callback, false);
636
+ });
637
+
638
+ return this;
639
+ }),
640
+ unbind : atom.core.overloadSetter(function (event, callback) {
641
+ if (callback === false) callback = prevent;
642
+
643
+ this.each(function (elem) {
644
+ if (elem == document && event == 'load') elem = window;
645
+ elem.removeEventListener(event, callback, false);
646
+ });
647
+
648
+ return this;
649
+ }),
650
+ delegate : function (selector, event, fn) {
651
+ return this.bind(event, function (e) {
652
+ if (new Dom(e.target).is(selector)) {
653
+ fn.apply(this, arguments);
654
+ }
655
+ });
656
+ },
657
+ wrap : function (wrapper) {
658
+ wrapper = new Dom(wrapper).first;
659
+ return this.replaceWith(wrapper).appendTo(wrapper);
660
+ },
661
+ replaceWith: function (element) {
662
+ var obj = this.first;
663
+ element = Dom(element).first;
664
+ obj.parentNode.replaceChild(element, obj);
665
+ return this;
666
+ },
667
+ find : function (selector) {
668
+ var result = [];
669
+ this.each(function (elem) {
670
+ var i = 0,
671
+ found = Dom.find(elem, selector),
672
+ l = found.length;
673
+ while (i < l) includeUnique(result, found[i++]);
674
+ });
675
+ return new Dom(result);
676
+ },
677
+ appendTo : function (to) {
678
+ var fr = document.createDocumentFragment();
679
+ this.each(function (elem) {
680
+ fr.appendChild(elem);
681
+ });
682
+ Dom(to).first.appendChild(fr);
683
+ return this;
684
+ },
685
+ appendBefore: function (elem) {
686
+ var fr = document.createDocumentFragment();
687
+ this.each(function (elem) {
688
+ fr.appendChild(elem);
689
+ });
690
+ Dom(elem).parent().first.insertBefore(fr, Dom(elem).first);
691
+ return this;
692
+ },
693
+ appendAfter: function (elem) {
694
+ var parent = Dom(elem).parent().first;
695
+ var next = Dom(elem).first.nextSibling;
696
+ var fr = document.createDocumentFragment();
697
+ this.each(function (elem) {
698
+ fr.appendChild(elem);
699
+ });
700
+
701
+ if (next) {
702
+ parent.insertBefore(fr, next);
703
+ } else {
704
+ parent.appendChild(fr);
705
+ }
706
+
707
+ return this;
708
+ },
709
+ /** @private */
710
+ manipulateClass: function (classNames, fn) {
711
+ if (!classNames) return this;
712
+ if (!isArray(classNames)) classNames = [classNames];
713
+
714
+ return this.each(function (elem) {
715
+ var i, all = elem.className.split(/\s+/);
716
+
717
+ for (i = classNames.length; i--;) {
718
+ fn.call(this, all, classNames[i]);
719
+ }
720
+
721
+ elem.className = all.join(' ').trim();
722
+ });
723
+ },
724
+ addClass: function (classNames) {
725
+ return this.manipulateClass(classNames, includeUnique);
726
+ },
727
+ removeClass: function (classNames) {
728
+ return this.manipulateClass(classNames, coreEraseAll);
729
+ },
730
+ toggleClass: function(classNames) {
731
+ return this.manipulateClass(classNames, function (all, c) {
732
+ var i = all.indexOf(c);
733
+ if (i === -1) {
734
+ all.push(c);
735
+ } else {
736
+ all.splice(i, 1);
737
+ }
738
+ });
739
+ },
740
+ hasClass: function(classNames) {
741
+ if (!classNames) return this;
742
+ if (!isArray(classNames)) classNames = [classNames];
743
+
744
+ var result = false;
745
+ this.each(function (elem) {
746
+ if (result) return;
747
+
748
+ var i = classNames.length,
749
+ all = elem.className.split(/\s+/);
750
+
751
+ while (i--) if (!coreContains(all, classNames[i])) {
752
+ return;
753
+ }
754
+
755
+ result = true;
756
+ });
757
+ return result;
758
+ },
759
+ offset: function () {
760
+ var element = this.first;
761
+ if (element.offsetX != null) {
762
+ return { x: element.offsetX, y: element.offsetY };
763
+ }
764
+
765
+ var box = element.getBoundingClientRect(),
766
+ body = document.body,
767
+ docElem = document.documentElement,
768
+ scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft,
769
+ scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop,
770
+ clientLeft = docElem.clientLeft || body.clientLeft || 0,
771
+ clientTop = docElem.clientTop || body.clientTop || 0;
772
+
773
+ return {
774
+ x: Math.round(box.left + scrollLeft - clientLeft),
775
+ y: Math.round(box.top + scrollTop - clientTop )
776
+ };
777
+ },
778
+ clone: function (deep) {
779
+ var i = 0, elements = [];
780
+
781
+ if (deep == null) deep = true;
782
+
783
+ for (; i < this.elems.length; i++) {
784
+ elements.push(this.elems[i].cloneNode(deep));
785
+ }
786
+
787
+ return atom.dom(elements);
788
+ },
789
+ empty: function () {
790
+ return this.each(function (elem) {
791
+ while (elem.hasChildNodes()) {
792
+ elem.removeChild( elem.firstChild );
793
+ }
794
+ });
795
+ },
796
+ log : function () {
797
+ console.log('atom.dom: ', this.elems);
798
+ return this;
799
+ },
800
+ destroy : function () {
801
+ return this.each(function (elem) {
802
+ elem.parentNode.removeChild(elem);
803
+ });
804
+ },
805
+ constructor: Dom
806
+ };
807
+
808
+ atom.dom = Dom;
809
+ }(window, window.document));
810
+
811
+
812
+ /*
813
+ ---
814
+
815
+ name: "CoreExtended"
816
+
817
+ description: "Extended core of AtomJS - extend, implements, clone, typeOf"
818
+
819
+ license:
820
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
821
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
822
+
823
+ inspiration:
824
+ - "[JQuery](http://jquery.com)"
825
+ - "[MooTools](http://mootools.net)"
826
+
827
+ provides: CoreExtended
828
+
829
+ requires:
830
+ - js185
831
+ - Core
832
+
833
+ ...
834
+ */
835
+
836
+ new function () {
837
+
838
+ function innerExtend (proto) {
839
+ return function (elem, from) {
840
+ if (from == null) {
841
+ from = elem;
842
+ elem = atom;
843
+ }
844
+
845
+ var ext = proto ? elem.prototype : elem,
846
+ accessors = atom.accessors && atom.accessors.inherit;
847
+
848
+ for (var i in from) if (i != 'constructor') {
849
+ if ( accessors && accessors(from, ext, i) ) continue;
850
+
851
+ ext[i] = clone(from[i]);
852
+ }
853
+ return elem;
854
+ };
855
+ }
856
+
857
+ function typeOf (item) {
858
+ if (item == null) return 'null';
859
+
860
+ var string = toString.call(item);
861
+ for (var i in typeOf.types) if (i == string) return typeOf.types[i];
862
+
863
+ if (item.nodeName){
864
+ if (item.nodeType == 1) return 'element';
865
+ if (item.nodeType == 3) return /\S/.test(item.nodeValue) ? 'textnode' : 'whitespace';
866
+ }
867
+
868
+ var type = typeof item;
869
+
870
+ if (item && type == 'object') {
871
+ if (atom.Class && item instanceof atom.Class) return 'class';
872
+ if (coreIsArrayLike(item)) return 'arguments';
873
+ }
874
+
875
+ return type;
876
+ }
877
+
878
+ typeOf.types = {};
879
+ ['Boolean', 'Number', 'String', 'Function', 'Array', 'Date', 'RegExp', 'Class'].forEach(function(name) {
880
+ typeOf.types['[object ' + name + ']'] = name.toLowerCase();
881
+ });
882
+
883
+
884
+ function clone (object) {
885
+ var type = typeOf(object);
886
+ return type in clone.types ? clone.types[type](object) : object;
887
+ }
888
+ clone.types = {
889
+ 'array': function (array) {
890
+ var i = array.length, c = new Array(i);
891
+ while (i--) c[i] = clone(array[i]);
892
+ return c;
893
+ },
894
+ 'class':function (object) {
895
+ return typeof object.clone == 'function' ?
896
+ object.clone() : object;
897
+ },
898
+ 'object': function (object) {
899
+ if (typeof object.clone == 'function') return object.clone();
900
+
901
+ var c = {}, accessors = atom.accessors && atom.accessors.inherit;
902
+ for (var key in object) {
903
+ if (accessors && accessors(object, c, key)) continue;
904
+ c[key] = clone(object[key]);
905
+ }
906
+ return c;
907
+ }
908
+ };
909
+
910
+ atom.core.extend = innerExtend(false);
911
+ atom.core.implement = innerExtend(true);
912
+ atom.core.typeOf = typeOf;
913
+ atom.core.clone = clone;
914
+
915
+ atom.extend = atom.core.extend;
916
+ atom.implement = atom.core.implement;
917
+ atom.typeOf = atom.core.typeOf;
918
+ atom.clone = atom.core.clone;
919
+
920
+ };
921
+
922
+ /*
923
+ ---
924
+
925
+ name: "Ajax"
926
+
927
+ description: "todo"
928
+
929
+ license:
930
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
931
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
932
+
933
+ requires:
934
+ - Core
935
+ - CoreExtended
936
+
937
+ provides: ajax
938
+
939
+ ...
940
+ */
941
+
942
+ (function () {
943
+ var extend = atom.core.extend, emptyFn = function () {};
944
+
945
+ var ajax = function (userConfig) {
946
+ var data, config, method, req, url;
947
+ config = {};
948
+ extend(config, ajax.defaultProps);
949
+ extend(config, userConfig);
950
+ config.headers = {};
951
+ extend(config.headers, ajax.defaultHeaders);
952
+ extend(config.headers, userConfig.headers);
953
+
954
+ data = ajax.stringify( config.data );
955
+ req = new XMLHttpRequest();
956
+ url = config.url;
957
+ method = config.method.toUpperCase();
958
+ if (method == 'GET' && data) {
959
+ url += (url.indexOf( '?' ) == -1 ? '?' : '&') + data;
960
+ }
961
+ if (!config.cache) {
962
+ url += (url.indexOf( '?' ) == -1 ? '?' : '&') + '_no_cache=' + Date.now();
963
+ }
964
+ req.onreadystatechange = ajax.onready(req, config);
965
+ req.open(method, url, true);
966
+ for (var i in config.headers) {
967
+ req.setRequestHeader(i, config.headers[i]);
968
+ }
969
+ req.send( method == 'POST' && data ? data : null );
970
+ };
971
+
972
+ ajax.stringify = function (object) {
973
+ if (!object) return '';
974
+ if (typeof object == 'string' || typeof object == 'number') return String( object );
975
+
976
+ var array = [], e = encodeURIComponent;
977
+ for (var i in object) if (object.hasOwnProperty(i)) {
978
+ array.push( e(i) + '=' + e(object[i]) );
979
+ }
980
+ return array.join('&');
981
+ };
982
+
983
+ ajax.defaultProps = {
984
+ interval: 0,
985
+ type : 'plain',
986
+ method : 'post',
987
+ data : {},
988
+ headers : {},
989
+ cache : false,
990
+ url : location.href,
991
+ onLoad : emptyFn,
992
+ onError : emptyFn
993
+ };
994
+
995
+ ajax.defaultHeaders = {
996
+ 'X-Requested-With': 'XMLHttpRequest',
997
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
998
+ };
999
+ /** @type {function} */
1000
+ ajax.onready = function (req, config) {
1001
+ return function (e) {
1002
+ if (req.readyState == 4) {
1003
+ if (req.status != 200) return config.onError(e);
1004
+
1005
+ var result = req.responseText;
1006
+ if (config.type.toLowerCase() == 'json') {
1007
+ result = JSON.parse(result);
1008
+ }
1009
+ if (config.interval > 0) setTimeout(function () {
1010
+ atom.ajax(config);
1011
+ }, config.interval * 1000);
1012
+ config.onLoad(result);
1013
+ }
1014
+ };
1015
+ };
1016
+
1017
+ atom.ajax = ajax;
1018
+ })();
1019
+
1020
+
1021
+ /*
1022
+ ---
1023
+
1024
+ name: "Ajax.Dom"
1025
+
1026
+ description: todo
1027
+
1028
+ license:
1029
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
1030
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
1031
+
1032
+ requires:
1033
+ - Core
1034
+ - dom
1035
+ - ajax
1036
+
1037
+ provides: ajax.dom
1038
+
1039
+ ...
1040
+ */
1041
+
1042
+ atom.dom.prototype.ajax = function (config) {
1043
+ config = coreAppend({}, config);
1044
+
1045
+ var $dom = this;
1046
+
1047
+ if (config.onLoad ) {
1048
+ config.onLoad = config.onLoad.bind($dom);
1049
+ } else {
1050
+ config.onLoad = function (r) { $dom.first.innerHTML = r };
1051
+ }
1052
+ if (config.onError) config.onError = config.onError.bind($dom);
1053
+
1054
+ atom.ajax(config);
1055
+ return $dom;
1056
+ };
1057
+
1058
+
1059
+ /*
1060
+ ---
1061
+
1062
+ name: "Cookie"
1063
+
1064
+ description: "todo"
1065
+
1066
+ license:
1067
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
1068
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
1069
+
1070
+ requires:
1071
+ - Core
1072
+
1073
+ provides: cookie
1074
+
1075
+ ...
1076
+ */
1077
+
1078
+ atom.cookie = {
1079
+ get: function (name) {
1080
+ var matches = document.cookie.match(new RegExp(
1081
+ "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
1082
+ ));
1083
+ return matches ? decodeURIComponent(matches[1]) : null;
1084
+ },
1085
+ set: function (name, value, options) {
1086
+ options = options || {};
1087
+ var exp = options.expires;
1088
+ if (exp) {
1089
+ if (typeof exp == 'number') {
1090
+ exp = new Date(exp * 1000 + Date.now());
1091
+ }
1092
+ if (exp.toUTCString) {
1093
+ exp = exp.toUTCString();
1094
+ }
1095
+ options.expires = exp;
1096
+ }
1097
+
1098
+ var cookie = [name + "=" + encodeURIComponent(value)];
1099
+ for (var o in options) cookie.push(
1100
+ options[o] === true ? o : o + "=" + options[o]
1101
+ );
1102
+ document.cookie = cookie.join('; ');
1103
+
1104
+ return atom.cookie;
1105
+ },
1106
+ del: function (name) {
1107
+ return atom.cookie.set(name, '', { expires: -1 });
1108
+ }
1109
+ };
1110
+
1111
+ /*
1112
+ ---
1113
+
1114
+ name: "Frame"
1115
+
1116
+ description: "Provides cross-browser interface for requestAnimationFrame"
1117
+
1118
+ license:
1119
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
1120
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
1121
+
1122
+ requires:
1123
+ - Core
1124
+
1125
+ provides: frame
1126
+
1127
+ ...
1128
+ */
1129
+ (function () {
1130
+
1131
+ var previous,
1132
+ started = false,
1133
+ callbacks = [],
1134
+ remove = [],
1135
+ frameTime = 16, // 62 fps
1136
+ // we'll switch to real `requestAnimationFrame` here
1137
+ // when all browsers will be ready
1138
+ requestAnimationFrame = function (callback) {
1139
+ window.setTimeout(callback, frameTime);
1140
+ };
1141
+
1142
+ function startAnimation () {
1143
+ if (!started) {
1144
+ previous = Date.now();
1145
+ requestAnimationFrame(frame);
1146
+ started = true;
1147
+ }
1148
+ }
1149
+
1150
+ function invokeFrame () {
1151
+ var fn, i, l,
1152
+ now = Date.now(),
1153
+ // 1 sec is max time for frame to avoid some bugs with too large time
1154
+ delta = Math.min(now - previous, 1000);
1155
+
1156
+ for (i = 0, l = remove.length; i < l; i++) {
1157
+ coreEraseOne(callbacks, remove[i]);
1158
+ }
1159
+ remove.length = 0;
1160
+
1161
+ for (i = 0, l = callbacks.length; i < l; i++) {
1162
+ fn = callbacks[i];
1163
+ // one of previous calls can remove our fn
1164
+ if (remove.indexOf(fn) == -1) {
1165
+ fn.call(null, delta);
1166
+ }
1167
+ }
1168
+
1169
+ previous = now;
1170
+ }
1171
+
1172
+ function frame() {
1173
+ requestAnimationFrame(frame);
1174
+
1175
+ if (callbacks.length == 0) {
1176
+ remove.length = 0;
1177
+ previous = Date.now();
1178
+ } else invokeFrame();
1179
+ }
1180
+
1181
+ atom.frame = {
1182
+ add: function (fn) {
1183
+ startAnimation();
1184
+ includeUnique(callbacks, fn);
1185
+ },
1186
+ // we dont want to fragmentate callbacks, so remove only before frame started
1187
+ remove: function (fn) {
1188
+ if (started) includeUnique(remove, fn);
1189
+ }
1190
+ };
1191
+
1192
+ }());
1193
+
1194
+ /*
1195
+ ---
1196
+
1197
+ name: "PointerLock"
1198
+
1199
+ description: "Provides cross-browser interface for locking pointer"
1200
+
1201
+ license:
1202
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
1203
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
1204
+
1205
+ requires:
1206
+ - Core
1207
+
1208
+ provides: PointerLock
1209
+
1210
+ ...
1211
+ */
1212
+ (function (document) {
1213
+
1214
+ var prefix =
1215
+ 'pointerLockElement' in document ? '':
1216
+ 'mozPointerLockElement' in document ? 'moz':
1217
+ 'webkitPointerLockElement' in document ? 'webkit': null;
1218
+
1219
+ function PointerLock (supports) {
1220
+ this.supports = supports;
1221
+ }
1222
+
1223
+ if (prefix == null) {
1224
+ PointerLock.prototype = {
1225
+ locked : function () { return false },
1226
+ request : function () {},
1227
+ exit : function () {}
1228
+ };
1229
+ } else {
1230
+
1231
+ function p (string) {
1232
+ return prefix ? prefix + string :
1233
+ string[0].toLowerCase() + string.substr(1);
1234
+ }
1235
+
1236
+ function isLocked (element) {
1237
+ return document[p('PointerLockElement')] === element;
1238
+ }
1239
+
1240
+ document.addEventListener("mousemove", function onMove (e) {
1241
+ if (lockedElement && isLocked(lockedElement)) {
1242
+ e.movementX = e[p('MovementX')] || 0;
1243
+ e.movementY = e[p('MovementY')] || 0;
1244
+
1245
+ callback && callback(e);
1246
+ }
1247
+ }, false);
1248
+
1249
+
1250
+ var lockedElement = false, callback = null;
1251
+
1252
+ PointerLock.prototype = {
1253
+ locked: function (element) {
1254
+ return isLocked(element || lockedElement);
1255
+ },
1256
+ request: function (element, fn) {
1257
+ lockedElement = element;
1258
+ callback = fn;
1259
+ element[p('RequestPointerLock')]();
1260
+ },
1261
+ exit: function () {
1262
+ lockedElement = null;
1263
+ callback = null;
1264
+ document[p('ExitPointerLock')]();
1265
+ }
1266
+ };
1267
+ }
1268
+
1269
+ atom.pointerLock = new PointerLock(prefix != null);
1270
+
1271
+ }(document));
1272
+
1273
+ /*
1274
+ ---
1275
+
1276
+ name: "Uri"
1277
+
1278
+ description: "Port of parseUri function"
1279
+
1280
+ license: "MIT License"
1281
+
1282
+ author: "Steven Levithan <stevenlevithan.com>"
1283
+
1284
+ requires:
1285
+ - Core
1286
+
1287
+ provides: uri
1288
+
1289
+ ...
1290
+ */
1291
+ new function () {
1292
+
1293
+ var uri = function (str) {
1294
+ var o = atom.uri.options,
1295
+ m = o.parser.exec(str || window.location.href),
1296
+ uri = {},
1297
+ i = 14;
1298
+
1299
+ while (i--) uri[o.key[i]] = m[i] || "";
1300
+
1301
+ uri[o.q.name] = {};
1302
+ uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
1303
+ if ($1) uri[o.q.name][$1] = $2;
1304
+ });
1305
+
1306
+ return uri;
1307
+ };
1308
+ uri.options = {
1309
+ key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
1310
+ q: {
1311
+ name: "queryKey",
1312
+ parser: /(?:^|&)([^&=]*)=?([^&]*)/g
1313
+ },
1314
+ parser: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
1315
+ };
1316
+
1317
+ atom.uri = uri;
1318
+
1319
+ };
1320
+
1321
+ /*
1322
+ ---
1323
+
1324
+ name: "Class"
1325
+
1326
+ description: "Contains the Class Function for easily creating, extending, and implementing reusable Classes."
1327
+
1328
+ license:
1329
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
1330
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
1331
+
1332
+ requires:
1333
+ - Core
1334
+ - CoreExtended
1335
+ - accessors
1336
+ - Array
1337
+
1338
+ inspiration:
1339
+ - "[MooTools](http://mootools.net)"
1340
+
1341
+ provides: Class
1342
+
1343
+ deprected: "Use declare instead"
1344
+
1345
+ ...
1346
+ */
1347
+
1348
+
1349
+ (function(atom){
1350
+
1351
+ var typeOf = atom.core.typeOf,
1352
+ extend = atom.core.extend,
1353
+ accessors = atom.accessors.inherit,
1354
+ prototype = 'prototype',
1355
+ lambda = function (value) { return function () { return value; }},
1356
+ prototyping = false;
1357
+
1358
+ var Class = function (params) {
1359
+ if (prototyping) return this;
1360
+
1361
+ if (typeof params == 'function' && typeOf(params) == 'function') params = { initialize: params };
1362
+
1363
+ var Constructor = function(){
1364
+ if (this instanceof Constructor) {
1365
+ if (prototyping) return this;
1366
+ return this.initialize ? this.initialize.apply(this, arguments) : this;
1367
+ } else {
1368
+ return Constructor.invoke.apply(Constructor, arguments);
1369
+ }
1370
+ };
1371
+ extend(Constructor, Class);
1372
+ Constructor.prototype = getInstance(Class);
1373
+
1374
+ Constructor
1375
+ .implement(params, false)
1376
+ .reserved(true, {
1377
+ parent: parent,
1378
+ self : Constructor
1379
+ })
1380
+ .reserved({
1381
+ factory : function() {
1382
+ function Factory(args) { return Constructor.apply(this, args); }
1383
+ Factory.prototype = Constructor.prototype;
1384
+ return function(args) { return new Factory(args || []); }
1385
+ }()
1386
+ });
1387
+
1388
+ Constructor.prototype.constructor = Constructor;
1389
+
1390
+ return Constructor;
1391
+ };
1392
+
1393
+ var parent = function(){
1394
+ if (!this.$caller) throw new Error('The method «parent» cannot be called.');
1395
+ var name = this.$caller.$name,
1396
+ parent = this.$caller.$owner.parent,
1397
+ previous = parent && parent.prototype[name];
1398
+ if (!previous) throw new Error('The method «' + name + '» has no parent.');
1399
+ return previous.apply(this, arguments);
1400
+ };
1401
+
1402
+ var wrap = function(self, key, method){
1403
+ // if method is already wrapped
1404
+ if (method.$origin) method = method.$origin;
1405
+
1406
+ var wrapper = function() {
1407
+ if (!this || this == atom.global) throw new TypeError('Context lost');
1408
+ if (method.$protected && !this.$caller) throw new Error('The method «' + key + '» is protected.');
1409
+ var current = this.$caller;
1410
+ this.$caller = wrapper;
1411
+ var result = method.apply(this, arguments);
1412
+ this.$caller = current;
1413
+ return result;
1414
+ };
1415
+ wrapper.$owner = self;
1416
+ wrapper.$origin = method;
1417
+ wrapper.$name = key;
1418
+
1419
+ return wrapper;
1420
+ };
1421
+
1422
+ var getInstance = function(Class){
1423
+ if (atom.declare && Class instanceof atom.declare) {
1424
+ return atom.declare.config.methods.proto(Class);
1425
+ }
1426
+
1427
+ prototyping = true;
1428
+ var proto = new Class;
1429
+ prototyping = false;
1430
+ return proto;
1431
+ };
1432
+
1433
+ Class.extend = function (name, fn) {
1434
+ if (typeof name == 'string') {
1435
+ var object = {};
1436
+ object[name] = fn;
1437
+ } else {
1438
+ object = name;
1439
+ }
1440
+
1441
+ for (var i in object) if (!accessors(object, this, i)) {
1442
+ this[i] = object[i];
1443
+ }
1444
+ return this;
1445
+ };
1446
+
1447
+ Class.extend({
1448
+ implement: function(name, fn, retain){
1449
+ if (typeof name == 'string') {
1450
+ var params = {};
1451
+ params[name] = fn;
1452
+ } else {
1453
+ params = name;
1454
+ retain = fn;
1455
+ }
1456
+
1457
+ for (var key in params) {
1458
+ if (!accessors(params, this.prototype, key)) {
1459
+ var value = params[key];
1460
+
1461
+ if (Class.Mutators.hasOwnProperty(key)){
1462
+ value = Class.Mutators[key].call(this, value);
1463
+ if (value == null) continue;
1464
+ }
1465
+
1466
+ if (typeof value == 'function' && typeOf(value) == 'function'){
1467
+ if (value.$origin) value = value.$origin;
1468
+ if (value.$hidden == 'next') {
1469
+ value.$hidden = true
1470
+ } else if (value.$hidden) {
1471
+ continue;
1472
+ }
1473
+ this.prototype[key] = (retain) ? value : wrap(this, key, value);
1474
+ } else {
1475
+ this.prototype[key] = atom.clone(value);
1476
+ }
1477
+ }
1478
+ }
1479
+ return this;
1480
+ },
1481
+ mixin: function () {
1482
+ Array.from(arguments).forEach(function (item) {
1483
+ this.implement(getInstance(item));
1484
+ }.bind(this));
1485
+ return this;
1486
+ },
1487
+ reserved: function (toProto, props) { // use careful !!
1488
+ if (arguments.length == 1) {
1489
+ props = toProto;
1490
+ toProto = false;
1491
+ }
1492
+ var target = toProto ? this.prototype : this;
1493
+ for (var name in props) {
1494
+ atom.accessors.define(target, name, { get: lambda(props[name]) });
1495
+ }
1496
+ return this;
1497
+ },
1498
+ isInstance: function (object) {
1499
+ return object instanceof this;
1500
+ },
1501
+ invoke: function () {
1502
+ return this.factory( arguments );
1503
+ },
1504
+ Mutators: {
1505
+ Extends: function(parent){
1506
+ if (parent == null) throw new TypeError('Cant extends from null');
1507
+ this.extend(parent).reserved({ parent: parent });
1508
+ this.prototype = getInstance(parent);
1509
+ },
1510
+
1511
+ Implements: function(items){
1512
+ this.mixin.apply(this, Array.from(items));
1513
+ },
1514
+
1515
+ Static: function(properties) {
1516
+ this.extend(properties);
1517
+ }
1518
+ },
1519
+ abstractMethod: function () {
1520
+ throw new Error('Abstract Method «' + this.$caller.$name + '» called');
1521
+ },
1522
+ protectedMethod: function (fn) {
1523
+ return extend(fn, { $protected: true });
1524
+ },
1525
+ hiddenMethod: function (fn) {
1526
+ return extend(fn, { $hidden: 'next' });
1527
+ }
1528
+ });
1529
+
1530
+ Class.abstractMethod.$abstract = true;
1531
+ atom.Class = Class;
1532
+
1533
+ })(atom);
1534
+
1535
+ /*
1536
+ ---
1537
+
1538
+ name: "Class.BindAll"
1539
+
1540
+ description: ""
1541
+
1542
+ license:
1543
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
1544
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
1545
+
1546
+ requires:
1547
+ - Core
1548
+ - Class
1549
+
1550
+ inspiration:
1551
+ - "[MooTools](http://mootools.net)"
1552
+
1553
+ provides: Class.BindAll
1554
+
1555
+ ...
1556
+ */
1557
+
1558
+ atom.Class.bindAll = function (object, methods) {
1559
+ if (typeof methods == 'string') {
1560
+ if (
1561
+ methods != '$caller' &&
1562
+ !atom.accessors.has(object, methods) &&
1563
+ coreIsFunction(object[methods])
1564
+ ) {
1565
+ object[methods] = object[methods].bind( object );
1566
+ }
1567
+ } else if (methods) {
1568
+ for (i = methods.length; i--;) atom.Class.bindAll( object, methods[i] );
1569
+ } else {
1570
+ for (var i in object) atom.Class.bindAll( object, i );
1571
+ }
1572
+ return object;
1573
+ };
1574
+
1575
+ /*
1576
+ ---
1577
+
1578
+ name: "Class.Events"
1579
+
1580
+ description: ""
1581
+
1582
+ license:
1583
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
1584
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
1585
+
1586
+ requires:
1587
+ - Core
1588
+ - Class
1589
+
1590
+ inspiration:
1591
+ - "[MooTools](http://mootools.net)"
1592
+
1593
+ provides: Class.Events
1594
+
1595
+ ...
1596
+ */
1597
+
1598
+ new function () {
1599
+
1600
+ var Class = atom.Class;
1601
+
1602
+ var fire = function (name, fn, args) {
1603
+ var result = fn.apply(this, Array.from(args || []));
1604
+ if (typeof result == 'string' && result.toLowerCase() == 'removeevent') {
1605
+ this.removeEvent(name, fn);
1606
+ }
1607
+ };
1608
+
1609
+ var removeOn = function(string){
1610
+ return (string || '').replace(/^on([A-Z])/, function(full, first){
1611
+ return first.toLowerCase();
1612
+ });
1613
+ };
1614
+
1615
+ var initEvents = function (object, reset) {
1616
+ if (reset || !object._events) object._events = { $ready: {} };
1617
+ };
1618
+
1619
+ var nextTick = function (fn) {
1620
+ nextTick.fn.push(fn);
1621
+ if (!nextTick.id) {
1622
+ nextTick.id = function () {
1623
+ nextTick.reset().invoke();
1624
+ }.delay(1);
1625
+ }
1626
+ };
1627
+ nextTick.reset = function () {
1628
+ var fn = nextTick.fn;
1629
+ nextTick.fn = [];
1630
+ nextTick.id = 0;
1631
+ return fn;
1632
+ };
1633
+ nextTick.reset();
1634
+
1635
+ coreAppend(Class, {
1636
+ Events: Class({
1637
+ addEvent: function(name, fn) {
1638
+ initEvents(this);
1639
+
1640
+ var i, l, onfinish = [];
1641
+ if (arguments.length == 1 && typeof name != 'string') {
1642
+ for (i in name) {
1643
+ this.addEvent(i, name[i]);
1644
+ }
1645
+ } else if (Array.isArray(name)) {
1646
+ for (i = 0, l = name.length; i < l; i++) {
1647
+ this.addEvent(name[i], fn);
1648
+ }
1649
+ } else {
1650
+ name = removeOn(name);
1651
+ if (name == '$ready') {
1652
+ throw new TypeError('Event name «$ready» is reserved');
1653
+ } else if (!fn) {
1654
+ throw new TypeError('Function is empty');
1655
+ } else {
1656
+ Object.ifEmpty(this._events, name, []);
1657
+
1658
+ this._events[name].include(fn);
1659
+
1660
+ var ready = this._events.$ready[name];
1661
+ if (ready) fire.apply(this, [name, fn, ready, onfinish]);
1662
+ onfinish.invoke();
1663
+ }
1664
+ }
1665
+ return this;
1666
+ },
1667
+ removeEvent: function (name, fn) {
1668
+ if (!arguments.length) {
1669
+ initEvents( this, true );
1670
+ return this;
1671
+ }
1672
+
1673
+ initEvents(this);
1674
+
1675
+ if (Array.isArray(name)) {
1676
+ for (var i = name.length; i--;) {
1677
+ this.removeEvent(name[i], fn);
1678
+ }
1679
+ } else if (arguments.length == 1 && typeof name != 'string') {
1680
+ for (i in name) {
1681
+ this.removeEvent(i, name[i]);
1682
+ }
1683
+ } else {
1684
+ name = removeOn(name);
1685
+ if (name == '$ready') {
1686
+ throw new TypeError('Event name «$ready» is reserved');
1687
+ } else if (arguments.length == 1) {
1688
+ this._events[name] = [];
1689
+ } else if (name in this._events) {
1690
+ this._events[name].erase(fn);
1691
+ }
1692
+ }
1693
+ return this;
1694
+ },
1695
+ isEventAdded: function (name) {
1696
+ initEvents(this);
1697
+
1698
+ var e = this._events[name];
1699
+ return !!(e && e.length);
1700
+ },
1701
+ fireEvent: function (name, args) {
1702
+ initEvents(this);
1703
+
1704
+ name = removeOn(name);
1705
+ // we should prevent skipping next event on removing this in different fireEvents
1706
+ var funcs = atom.clone(this._events[name]);
1707
+ if (funcs) {
1708
+ var l = funcs.length,
1709
+ i = 0;
1710
+ for (;i < l; i++) fire.call(this, name, funcs[i], args || []);
1711
+ }
1712
+ return this;
1713
+ },
1714
+ readyEvent: function (name, args) {
1715
+ initEvents(this);
1716
+
1717
+ nextTick(function () {
1718
+ name = removeOn(name);
1719
+ this._events.$ready[name] = args || [];
1720
+ this.fireEvent(name, args || []);
1721
+ }.bind(this));
1722
+ return this;
1723
+ }
1724
+ })
1725
+ });
1726
+
1727
+ };
1728
+
1729
+ /*
1730
+ ---
1731
+
1732
+ name: "Class.Mutators.Generators"
1733
+
1734
+ description: "Provides Generators mutator"
1735
+
1736
+ license:
1737
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
1738
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
1739
+
1740
+ authors:
1741
+ - "Shock <shocksilien@gmail.com>"
1742
+
1743
+ requires:
1744
+ - Core
1745
+ - accessors
1746
+ - Class
1747
+
1748
+ provides: Class.Mutators.Generators
1749
+
1750
+ ...
1751
+ */
1752
+
1753
+ new function () {
1754
+
1755
+ var getter = function (key, fn) {
1756
+ return function() {
1757
+ var pr = '_' + key, obj = this;
1758
+ return pr in obj ? obj[pr] : (obj[pr] = fn.call(obj));
1759
+ };
1760
+ };
1761
+
1762
+ atom.Class.Mutators.Generators = function(properties) {
1763
+ atom.Class.Mutators.Generators.init(this, properties);
1764
+ };
1765
+
1766
+ atom.Class.Mutators.Generators.init = function (Class, properties) {
1767
+ for (var i in properties) atom.accessors.define(Class.prototype, i, { get: getter(i, properties[i]) });
1768
+ };
1769
+
1770
+ };
1771
+
1772
+ /*
1773
+ ---
1774
+
1775
+ name: "Class.Options"
1776
+
1777
+ description: ""
1778
+
1779
+ license:
1780
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
1781
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
1782
+
1783
+ requires:
1784
+ - Core
1785
+ - Class
1786
+
1787
+ inspiration:
1788
+ - "[MooTools](http://mootools.net)"
1789
+
1790
+ provides: Class.Options
1791
+
1792
+ ...
1793
+ */
1794
+
1795
+ atom.Class.Options = atom.Class({
1796
+ options: {},
1797
+ fastSetOptions: false,
1798
+ setOptions: function(){
1799
+ if (!this.options) {
1800
+ this.options = {};
1801
+ } else if (this.options == this.self.prototype.options) {
1802
+ // it shouldn't be link to static options
1803
+ if (this.fastSetOptions) {
1804
+ this.options = coreAppend({}, this.options);
1805
+ } else {
1806
+ this.options = atom.clone(this.options);
1807
+ }
1808
+ }
1809
+ var options = this.options;
1810
+
1811
+ for (var a = arguments, i = 0, l = a.length; i < l; i++) {
1812
+ if (typeof a[i] == 'object') {
1813
+ if (this.fastSetOptions) {
1814
+ coreAppend(options, a[i]);
1815
+ } else {
1816
+ atom.extend(options, a[i]);
1817
+ }
1818
+ }
1819
+ }
1820
+
1821
+ if (this.addEvent) for (var option in options){
1822
+ if (atom.typeOf(options[option]) == 'function' && (/^on[A-Z]/).test(option)) {
1823
+ this.addEvent(option, options[option]);
1824
+ delete options[option];
1825
+ }
1826
+ }
1827
+ return this;
1828
+ }
1829
+ });
1830
+
1831
+ /*
1832
+ ---
1833
+
1834
+ name: "Declare"
1835
+
1836
+ description: "Contains the Class Function for easily creating, extending, and implementing reusable Classes."
1837
+
1838
+ license:
1839
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
1840
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
1841
+
1842
+ requires:
1843
+ - Core
1844
+ - accessors
1845
+
1846
+ provides: declare
1847
+
1848
+ ...
1849
+ */
1850
+
1851
+ var declare = (function(atom){
1852
+
1853
+ var
1854
+ declare, methods,
1855
+ accessors = atom.accessors.inherit,
1856
+ factory = false,
1857
+ prototyping = false,
1858
+ mutators = [];
1859
+
1860
+ declare = function (declareName, Parent, params) {
1861
+ if (prototyping) return this;
1862
+
1863
+ params = methods.prepareParams(declareName, Parent, params);
1864
+
1865
+ // line break for more user-friendly debug string
1866
+ var Constructor = function ()
1867
+ { return methods.construct.call(this, Constructor, arguments) };
1868
+
1869
+ // <debug> - should be removed on production
1870
+ if (params.name) {
1871
+ Constructor = new Function('con', 'return {"' + params.name + '": ' +
1872
+ function(){ return con.apply(this, arguments) }
1873
+ + '}["' + params.name + '"];')(Constructor);
1874
+ }
1875
+ // </debug>
1876
+
1877
+ for (var i = 0, l = mutators.length; i < l; i++) {
1878
+ mutators[i].fn( Constructor, params[mutators[i].name] );
1879
+ }
1880
+
1881
+ Constructor.prototype.constructor = Constructor;
1882
+
1883
+ if (params.declareName) methods.define( params.declareName, Constructor );
1884
+
1885
+ return Constructor;
1886
+ };
1887
+
1888
+ declare.prototype.bindMethods = function (methods) {
1889
+ var i;
1890
+
1891
+ if (typeof methods == 'string') {
1892
+ if (typeof this[methods] == 'function') {
1893
+ this[methods] = this[methods].bind(this);
1894
+ }
1895
+ return this;
1896
+ }
1897
+
1898
+ if (!methods) {
1899
+ for (i in this) this.bindMethods(i);
1900
+ return this;
1901
+ }
1902
+
1903
+ for (i = methods.length; i--;) this.bindMethods( methods[i] );
1904
+ return this;
1905
+ };
1906
+
1907
+ declare.prototype.toString = function () {
1908
+ return '[object ' + (this.constructor.NAME || 'Declare') + ']';
1909
+ };
1910
+
1911
+ declare.NAME = 'atom.declare';
1912
+
1913
+ declare.invoke = function () {
1914
+ return this.factory( arguments );
1915
+ };
1916
+
1917
+ declare.own = function (properties) {
1918
+ methods.addTo(this, properties, this.NAME + '.');
1919
+ return this;
1920
+ };
1921
+
1922
+ declare.factory = function (args) {
1923
+ factory = true;
1924
+ return new this(args);
1925
+ };
1926
+
1927
+ declare.castArguments = function (args) {
1928
+ if (args == null) return null;
1929
+
1930
+ var constructor = this;
1931
+
1932
+ return (args != null && args[0] && args[0] instanceof constructor) ?
1933
+ args[0] : args instanceof constructor ? args : new constructor( args );
1934
+ };
1935
+
1936
+ methods = {
1937
+ define: function (path, value) {
1938
+ var key, part, target = atom.global;
1939
+
1940
+ path = path.split('.');
1941
+ key = path.pop();
1942
+
1943
+ while (path.length) {
1944
+ part = path.shift();
1945
+ if (!target[part]) {
1946
+ target = target[part] = {};
1947
+ } else {
1948
+ target = target[part];
1949
+ }
1950
+ }
1951
+
1952
+ target[key] = value;
1953
+ },
1954
+ mixin: function (target, items) {
1955
+ if (!Array.isArray(items)) items = [ items ];
1956
+ for (var i = 0, l = items.length; i < l; i++) {
1957
+ methods.addTo( target.prototype, methods.proto(items[i]) );
1958
+ }
1959
+ return this;
1960
+ },
1961
+ addTo: function (target, source, name) {
1962
+ var i, property;
1963
+ if (source) for (i in source) if (source.hasOwnProperty(i)) {
1964
+ if (!accessors(source, target, i) && source[i] != declare.config) {
1965
+ property = source[i];
1966
+ if (coreIsFunction(property)) {
1967
+ if (name) property.path = name + i;
1968
+ if (!property.previous && coreIsFunction(target[i])) {
1969
+ property.previous = target[i];
1970
+ }
1971
+ }
1972
+ target[i] = property;
1973
+ }
1974
+ }
1975
+ return target;
1976
+ },
1977
+ prepareParams: function (declareName, Parent, params) {
1978
+ if (typeof declareName != 'string') {
1979
+ params = Parent;
1980
+ Parent = declareName;
1981
+ declareName = null;
1982
+ }
1983
+
1984
+ if (params == null && typeof Parent != 'function') {
1985
+ params = Parent;
1986
+ Parent = null;
1987
+ }
1988
+
1989
+ if (!params ) params = {};
1990
+ if (!params.prototype ) params = { prototype: params };
1991
+ if (!params.name ) params.name = declareName;
1992
+ if (!params.declareName ) params.declareName = declareName;
1993
+ if (!params.parent && Parent) params.parent = Parent;
1994
+
1995
+ if (!params.prototype.initialize) {
1996
+ params.prototype.initialize = function () {
1997
+ if (!params.parent) return;
1998
+ return params.parent.prototype.initialize.apply(this, arguments);
1999
+ };
2000
+ }
2001
+ return params;
2002
+ },
2003
+ proto: function (Fn) {
2004
+ prototyping = true;
2005
+ var result = new Fn;
2006
+ prototyping = false;
2007
+ return result;
2008
+ },
2009
+ construct: function (Constructor, args) {
2010
+ if (factory) {
2011
+ args = args[0];
2012
+ factory = false;
2013
+ }
2014
+
2015
+ if (prototyping) return this;
2016
+
2017
+ if (this instanceof Constructor) {
2018
+ if (Constructor.NAME) this.Constructor = Constructor.NAME;
2019
+ return this.initialize.apply(this, args);
2020
+ } else {
2021
+ return Constructor.invoke.apply(Constructor, args);
2022
+ }
2023
+ }
2024
+ };
2025
+
2026
+ declare.config = {
2027
+ methods: methods,
2028
+ mutator: atom.core.overloadSetter(function (name, fn) {
2029
+ mutators.push({ name: name, fn: fn });
2030
+ return this;
2031
+ })
2032
+ };
2033
+
2034
+ declare.config
2035
+ .mutator( 'parent', function (Constructor, parent) {
2036
+ parent = parent || declare;
2037
+ methods.addTo( Constructor, parent );
2038
+ Constructor.prototype = methods.proto( parent );
2039
+ Constructor.Parent = parent;
2040
+ })
2041
+ .mutator( 'mixin', function (Constructor, mixins) {
2042
+ if (mixins) methods.mixin( Constructor, mixins );
2043
+ })
2044
+ .mutator( 'name', function (Constructor, name) {
2045
+ if (!name) return;
2046
+ Constructor.NAME = name;
2047
+ })
2048
+ .mutator( 'own', function (Constructor, properties) {
2049
+ Constructor.own(properties);
2050
+ })
2051
+ .mutator( 'prototype', function (Constructor, properties) {
2052
+ methods.addTo(Constructor.prototype, properties, Constructor.NAME + '#');
2053
+ });
2054
+
2055
+ return atom.declare = declare;
2056
+
2057
+ })(atom);
2058
+
2059
+ /*
2060
+ ---
2061
+
2062
+ name: "Transition"
2063
+
2064
+ description: ""
2065
+
2066
+ license:
2067
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
2068
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
2069
+
2070
+ requires:
2071
+ - Core
2072
+ - declare
2073
+
2074
+ inspiration:
2075
+ - "[MooTools](http://mootools.net)"
2076
+
2077
+ provides: Transition
2078
+
2079
+ ...
2080
+ */
2081
+
2082
+ atom.Transition = function (method, noEase) {
2083
+ var easeIn = function (progress) {
2084
+ return method(progress);
2085
+ };
2086
+
2087
+ if (noEase) {
2088
+ return coreAppend( easeIn, {
2089
+ easeIn : easeIn,
2090
+ easeOut : easeIn,
2091
+ easeInOut: easeIn
2092
+ });
2093
+ }
2094
+
2095
+ return coreAppend( easeIn, {
2096
+ easeIn: easeIn,
2097
+ easeOut: function(progress){
2098
+ return 1 - method(1 - progress);
2099
+ },
2100
+ easeInOut: function(progress){
2101
+ if (progress > 0.5) {
2102
+ return ( 2 - method(2 * (1 - progress)) ) /2
2103
+ } else {
2104
+ return method(2 * progress)/2;
2105
+ }
2106
+ }
2107
+ });
2108
+ };
2109
+
2110
+ atom.Transition.set = atom.core.overloadSetter(function (id, fn) {
2111
+ atom.Transition[id] = atom.Transition(fn);
2112
+ });
2113
+
2114
+ atom.Transition.get = function (fn) {
2115
+ if (typeof fn != 'string') return fn;
2116
+ var method = fn.split('-')[0], ease = 'easeInOut', In, Out;
2117
+ if (method != fn) {
2118
+ In = fn.indexOf('-in' ) > 0;
2119
+ Out = fn.indexOf('-out') > 0;
2120
+ if (In ^ Out) {
2121
+ if (In ) ease = 'easeIn';
2122
+ if (Out) ease = 'easeOut';
2123
+ }
2124
+ }
2125
+ method = method[0].toUpperCase() + method.substr(1);
2126
+ if (!atom.Transition[method]) {
2127
+ throw new Error('No Transition method: ' + method);
2128
+ }
2129
+ return atom.Transition[method][ease];
2130
+ };
2131
+
2132
+ atom.Transition.Linear = atom.Transition(function(p) { return p }, true);
2133
+
2134
+ atom.Transition.set({
2135
+ Expo: function(p){
2136
+ return Math.pow(2, 8 * (p - 1));
2137
+ },
2138
+
2139
+ Circ: function(p){
2140
+ return 1 - Math.sin(Math.acos(p));
2141
+ },
2142
+
2143
+ Sine: function(p){
2144
+ return 1 - Math.cos(p * Math.PI / 2);
2145
+ },
2146
+
2147
+ Back: function(p){
2148
+ var x = 1.618;
2149
+ return Math.pow(p, 2) * ((x + 1) * p - x);
2150
+ },
2151
+
2152
+ Bounce: function(p){
2153
+ var value, a = 0, b = 1;
2154
+ for (;;){
2155
+ if (p >= (7 - 4 * a) / 11){
2156
+ value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2);
2157
+ break;
2158
+ }
2159
+ a += b, b /= 2
2160
+ }
2161
+ return value;
2162
+ },
2163
+
2164
+ Elastic: function(p){
2165
+ return Math.pow(2, 10 * --p) * Math.cos(12 * p);
2166
+ }
2167
+
2168
+ });
2169
+
2170
+ ['Quad', 'Cubic', 'Quart', 'Quint'].forEach(function(transition, i){
2171
+ atom.Transition.set(transition, function(p){
2172
+ return Math.pow(p, i + 2);
2173
+ });
2174
+ });
2175
+
2176
+ /*
2177
+ ---
2178
+
2179
+ name: "Events"
2180
+
2181
+ description: ""
2182
+
2183
+ license:
2184
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
2185
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
2186
+
2187
+ requires:
2188
+ - Core
2189
+ - declare
2190
+
2191
+ inspiration:
2192
+ - "[MooTools](http://mootools.net)"
2193
+
2194
+ provides: Events
2195
+
2196
+ ...
2197
+ */
2198
+
2199
+ /** @class atom.Events */
2200
+ declare( 'atom.Events', {
2201
+
2202
+ /** @constructs */
2203
+ initialize: function (context) {
2204
+ this.context = context || this;
2205
+ this.locked = [];
2206
+ this.events = {};
2207
+ this.actions = {};
2208
+ this.readyList = {};
2209
+ },
2210
+
2211
+ /**
2212
+ * @param {String} name
2213
+ * @return Boolean
2214
+ */
2215
+ exists: function (name) {
2216
+ var array = this.events[this.removeOn( name )];
2217
+ return !!(array && array.length);
2218
+ },
2219
+
2220
+ /**
2221
+ * @param {String} name
2222
+ * @param {Function} callback
2223
+ * @return Boolean
2224
+ */
2225
+ add: function (name, callback) {
2226
+ this.run( 'addOne', name, callback );
2227
+ return this;
2228
+ },
2229
+
2230
+ /**
2231
+ * @param {String} name
2232
+ * @param {Function} [callback]
2233
+ * @return Boolean
2234
+ */
2235
+ remove: function (name, callback) {
2236
+ if (typeof name == 'string' && !callback) {
2237
+ this.removeAll( name );
2238
+ } else {
2239
+ this.run( 'removeOne', name, callback );
2240
+ }
2241
+ return this;
2242
+ },
2243
+
2244
+ /**
2245
+ * @param {String} name
2246
+ * @param {Array} args
2247
+ * @return atom.Events
2248
+ */
2249
+ fire: function (name, args) {
2250
+ args = args ? slice.call( args ) : [];
2251
+ name = this.removeOn( name );
2252
+
2253
+ this.locked.push(name);
2254
+ var i = 0, l, events = this.events[name];
2255
+ if (events) for (l = events.length; i < l; i++) {
2256
+ events[i].apply( this.context, args );
2257
+ }
2258
+ this.unlock( name );
2259
+ return this;
2260
+ },
2261
+
2262
+ /**
2263
+ * @param {String} name
2264
+ * @param {Array} [args=null]
2265
+ * @return atom.Events
2266
+ */
2267
+ ready: function (name, args) {
2268
+ name = this.removeOn( name );
2269
+ this.locked.push(name);
2270
+ if (name in this.readyList) {
2271
+ throw new Error( 'Event «'+name+'» is ready' );
2272
+ }
2273
+ this.readyList[name] = args;
2274
+ this.fire(name, args);
2275
+ this.removeAll(name);
2276
+ this.unlock( name );
2277
+ return this;
2278
+ },
2279
+
2280
+ /**
2281
+ * @param {String} name
2282
+ * @param {Array} [args=null]
2283
+ * @return atom.Events
2284
+ */
2285
+ ensureReady: function (name, args) {
2286
+ if (!(name in this.readyList)) {
2287
+ this.ready(name, args);
2288
+ }
2289
+ return this;
2290
+ },
2291
+
2292
+
2293
+ // only private are below
2294
+
2295
+ /** @private */
2296
+ context: null,
2297
+ /** @private */
2298
+ events: {},
2299
+ /** @private */
2300
+ readyList: {},
2301
+ /** @private */
2302
+ locked: [],
2303
+ /** @private */
2304
+ actions: {},
2305
+
2306
+ /** @private */
2307
+ removeOn: function (name) {
2308
+ return (name || '').replace(/^on([A-Z])/, function(full, first){
2309
+ return first.toLowerCase();
2310
+ });
2311
+ },
2312
+ /** @private */
2313
+ removeAll: function (name) {
2314
+ var events = this.events[name];
2315
+ if (events) for (var i = events.length; i--;) {
2316
+ this.removeOne( name, events[i] );
2317
+ }
2318
+ },
2319
+ /** @private */
2320
+ unlock: function (name) {
2321
+ var action,
2322
+ all = this.actions[name],
2323
+ index = this.locked.indexOf( name );
2324
+
2325
+ this.locked.splice(index, 1);
2326
+
2327
+ if (all) for (index = 0; index < all.length; index++) {
2328
+ action = all[index];
2329
+
2330
+ this[action.method]( name, action.callback );
2331
+ }
2332
+ },
2333
+ /** @private */
2334
+ run: function (method, name, callback) {
2335
+ var i = 0, l = 0;
2336
+
2337
+ if (Array.isArray(name)) {
2338
+ for (i = 0, l = name.length; i < l; i++) {
2339
+ this[method](name[i], callback);
2340
+ }
2341
+ } else if (typeof name == 'object') {
2342
+ for (i in name) {
2343
+ this[method](i, name[i]);
2344
+ }
2345
+ } else if (typeof name == 'string') {
2346
+ this[method](name, callback);
2347
+ } else {
2348
+ throw new TypeError( 'Wrong arguments in Events.' + method );
2349
+ }
2350
+ },
2351
+ /** @private */
2352
+ register: function (name, method, callback) {
2353
+ var actions = this.actions;
2354
+ if (!actions[name]) {
2355
+ actions[name] = [];
2356
+ }
2357
+ actions[name].push({ method: method, callback: callback })
2358
+ },
2359
+ /** @private */
2360
+ addOne: function (name, callback) {
2361
+ var events, ready, context;
2362
+
2363
+ name = this.removeOn( name );
2364
+
2365
+ if (this.locked.indexOf(name) == -1) {
2366
+ ready = this.readyList[name];
2367
+ if (ready) {
2368
+ context = this.context;
2369
+ setTimeout(function () {
2370
+ callback.apply(context, ready);
2371
+ }, 0);
2372
+ return this;
2373
+ } else {
2374
+ events = this.events;
2375
+ if (!events[name]) {
2376
+ events[name] = [callback];
2377
+ } else {
2378
+ events[name].push(callback);
2379
+ }
2380
+ }
2381
+ } else {
2382
+ this.register(name, 'addOne', callback);
2383
+ }
2384
+ },
2385
+ /** @private */
2386
+ removeOne: function (name, callback) {
2387
+ name = this.removeOn( name );
2388
+
2389
+ if (this.locked.indexOf(name) == -1) {
2390
+ var events = this.events[name], i = events.length;
2391
+ while (i--) if (events[i] == callback) {
2392
+ events.splice(i, 1);
2393
+ }
2394
+ } else {
2395
+ this.register(name, 'removeOne', callback);
2396
+ }
2397
+ }
2398
+ });
2399
+
2400
+ // local alias
2401
+ var Events = atom.Events;
2402
+
2403
+ /*
2404
+ ---
2405
+
2406
+ name: "Settings"
2407
+
2408
+ description: ""
2409
+
2410
+ license:
2411
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
2412
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
2413
+
2414
+ requires:
2415
+ - declare
2416
+
2417
+ provides: Settings
2418
+
2419
+ ...
2420
+ */
2421
+
2422
+ /** @class atom.Settings */
2423
+ declare( 'atom.Settings', {
2424
+ /** @private */
2425
+ recursive: false,
2426
+
2427
+ /** @private */
2428
+ values: {},
2429
+
2430
+ /**
2431
+ * @constructs
2432
+ * @param {Object} [initialValues]
2433
+ */
2434
+ initialize: function (initialValues) {
2435
+ this.values = {};
2436
+
2437
+ if (initialValues) this.set(initialValues);
2438
+ },
2439
+
2440
+ /**
2441
+ * @param {atom.Events} events
2442
+ * @return atom.Options
2443
+ */
2444
+ addEvents: function (events) {
2445
+ this.events = events;
2446
+ return this.invokeEvents();
2447
+ },
2448
+
2449
+ /**
2450
+ * @param {string|Array} name
2451
+ */
2452
+ get: function (name, defaultValue) {
2453
+ if (Array.isArray(name)) return this.subset(name, defaultValue);
2454
+
2455
+ return name in this.values ? this.values[name] : defaultValue;
2456
+ },
2457
+
2458
+ /**
2459
+ * @test
2460
+ * @param {object} target
2461
+ * @param {string[]} names
2462
+ * @return {atom.Settings}
2463
+ */
2464
+ properties: function (target, names) {
2465
+ if (typeof names == 'string') {
2466
+ names = names.split(' ');
2467
+ }
2468
+
2469
+ this['properties.names' ] = names;
2470
+ this['properties.target'] = target;
2471
+
2472
+ for (var i in this.values) if (this.values.hasOwnProperty(i)) {
2473
+ if (names.indexOf(i) >= 0) {
2474
+ target[i] = this.values[i];
2475
+ }
2476
+ }
2477
+
2478
+ return this;
2479
+ },
2480
+
2481
+ subset: function (names, defaultValue) {
2482
+ var i, values = {};
2483
+
2484
+ for (i = names.length; i--;) {
2485
+ values[names[i]] = this.get( names[i], defaultValue );
2486
+ }
2487
+
2488
+ return values;
2489
+ },
2490
+
2491
+ /**
2492
+ * @param {Object} options
2493
+ * @return atom.Options
2494
+ */
2495
+ set: function (options, value) {
2496
+ var i,
2497
+ values = this.values,
2498
+ target = this['properties.target'],
2499
+ names = this['properties.names'];
2500
+
2501
+ options = this.prepareOptions(options, value);
2502
+
2503
+ for (i in options) if (options.hasOwnProperty(i)) {
2504
+ value = options[i];
2505
+ if (values[i] != value) {
2506
+ values[i] = value;
2507
+ if (target && names.indexOf(i) >= 0) {
2508
+ target[i] = values[i];
2509
+ }
2510
+ }
2511
+ }
2512
+
2513
+ this.invokeEvents();
2514
+
2515
+ return this;
2516
+ },
2517
+
2518
+ /** @private */
2519
+ prepareOptions: function (options, value) {
2520
+ if (typeof options == 'string') {
2521
+ var i = options;
2522
+ options = {};
2523
+ options[i] = value;
2524
+ } else if (options instanceof this.constructor) {
2525
+ options = options.values;
2526
+ }
2527
+ return options;
2528
+ },
2529
+
2530
+ /**
2531
+ * @param {String} name
2532
+ * @return atom.Options
2533
+ */
2534
+ unset: function (name) {
2535
+ delete this.values[name];
2536
+ return this;
2537
+ },
2538
+
2539
+ /** @private */
2540
+ invokeEvents: function () {
2541
+ if (!this.events) return this;
2542
+
2543
+ var values = this.values, name, option;
2544
+ for (name in values) if (values.hasOwnProperty(name)) {
2545
+ option = values[name];
2546
+ if (this.isInvokable(name, option)) {
2547
+ this.events.add(name, option);
2548
+ this.unset(name);
2549
+ }
2550
+ }
2551
+ return this;
2552
+ },
2553
+
2554
+ /** @private */
2555
+ isInvokable: function (name, option) {
2556
+ return name &&
2557
+ option &&
2558
+ coreIsFunction(option) &&
2559
+ (/^on[A-Z]/).test(name);
2560
+ }
2561
+ });
2562
+
2563
+ var Settings = atom.Settings;
2564
+
2565
+ /*
2566
+ ---
2567
+
2568
+ name: "Types.Object"
2569
+
2570
+ description: "Object generic methods"
2571
+
2572
+ license:
2573
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
2574
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
2575
+
2576
+ requires:
2577
+ - Core
2578
+
2579
+ provides: Types.Object
2580
+
2581
+ ...
2582
+ */
2583
+
2584
+ atom.object = {
2585
+ append: function (target, source1, source2) {
2586
+ for (var i = 1, l = arguments.length; i < l; i++) {
2587
+ atom.core.append(target, arguments[i]);
2588
+ }
2589
+ return target;
2590
+ },
2591
+ invert: function (object) {
2592
+ var newObj = {};
2593
+ for (var i in object) newObj[object[i]] = i;
2594
+ return newObj;
2595
+ },
2596
+ collect: function (obj, props, Default) {
2597
+ var newObj = {};
2598
+ props.forEach(function (i){
2599
+ newObj[i] = i in obj ? obj[i] : Default;
2600
+ });
2601
+ return newObj;
2602
+ },
2603
+ values: function (obj) {
2604
+ var values = [];
2605
+ for (var i in obj) values.push(obj[i]);
2606
+ return values;
2607
+ },
2608
+ isDefined: function (obj) {
2609
+ return typeof obj !== 'undefined';
2610
+ },
2611
+ isReal: function (obj) {
2612
+ return obj || obj === 0;
2613
+ },
2614
+ map: function (obj, fn) {
2615
+ var mapped = {};
2616
+ for (var i in obj) if (obj.hasOwnProperty(i)) {
2617
+ mapped[i] = fn( obj[i], i, obj );
2618
+ }
2619
+ return mapped;
2620
+ },
2621
+ max: function (obj) {
2622
+ var max = null, key = null;
2623
+ for (var i in obj) if (max == null || obj[i] > max) {
2624
+ key = i;
2625
+ max = obj[i];
2626
+ }
2627
+ return key;
2628
+ },
2629
+ min: function (obj) {
2630
+ var min = null, key = null;
2631
+ for (var i in obj) if (min == null || obj[i] < min) {
2632
+ key = i;
2633
+ min = obj[i];
2634
+ }
2635
+ return key;
2636
+ },
2637
+ deepEquals: function (first, second) {
2638
+ if (!first || (typeof first) !== (typeof second)) return false;
2639
+
2640
+ for (var i in first) {
2641
+ var f = first[i], s = second[i];
2642
+ if (typeof f === 'object') {
2643
+ if (!s || !Object.deepEquals(f, s)) return false;
2644
+ } else if (f !== s) {
2645
+ return false;
2646
+ }
2647
+ }
2648
+
2649
+ for (i in second) if (!(i in first)) return false;
2650
+
2651
+ return true;
2652
+ },
2653
+ isEmpty: function (object) {
2654
+ return Object.keys(object).length == 0;
2655
+ },
2656
+ ifEmpty: function (object, key, defaultValue) {
2657
+ if (!(key in object)) {
2658
+ object[key] = defaultValue;
2659
+ }
2660
+ return object;
2661
+ },
2662
+ path: {
2663
+ parts: function (path, delimiter) {
2664
+ return Array.isArray(path) ? path : String(path).split( delimiter || '.' );
2665
+ },
2666
+ get: function (object, path, delimiter) {
2667
+ if (!path) return object;
2668
+
2669
+ path = Object.path.parts( path, delimiter );
2670
+
2671
+ for (var i = 0; i < path.length; i++) {
2672
+ if (object != null && path[i] in object) {
2673
+ object = object[path[i]];
2674
+ } else {
2675
+ return;
2676
+ }
2677
+ }
2678
+
2679
+ return object;
2680
+ },
2681
+ set: function (object, path, value, delimiter) {
2682
+ path = Object.path.parts( path, delimiter );
2683
+
2684
+ var key = path.pop();
2685
+
2686
+ while (path.length) {
2687
+ var current = path.shift();
2688
+ if (object[current]) {
2689
+ object = object[current];
2690
+ } else {
2691
+ object = object[current] = {};
2692
+ }
2693
+ }
2694
+
2695
+ object[key] = value;
2696
+ }
2697
+ }
2698
+ };
2699
+
2700
+ /*
2701
+ ---
2702
+
2703
+ name: "Animatable"
2704
+
2705
+ description: "Provides Color class"
2706
+
2707
+ license:
2708
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
2709
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
2710
+
2711
+ requires:
2712
+ - Core
2713
+ - declare
2714
+ - frame
2715
+ - Transition
2716
+ - Events
2717
+ - Settings
2718
+ - Types.Object
2719
+
2720
+ provides: Animatable
2721
+
2722
+ ...
2723
+ */
2724
+
2725
+ /** @class atom.Animatable */
2726
+ declare( 'atom.Animatable', {
2727
+
2728
+ element: null,
2729
+
2730
+ initialize: function (callbacks, context) {
2731
+ this.bindMethods('animate');
2732
+ this.context = context || null;
2733
+
2734
+ if (!callbacks) throw new TypeError( 'callbacks cant be null' );
2735
+
2736
+ this.animations = [];
2737
+ if (this.isValidCallbacks(callbacks)) {
2738
+ this.callbacks = callbacks;
2739
+ } else {
2740
+ this.callbacks = this.getDefaultCallbacks(callbacks);
2741
+ }
2742
+ },
2743
+
2744
+ get current () {
2745
+ return this.animations[0];
2746
+ },
2747
+
2748
+ /**
2749
+ * Binded to `Animatable`
2750
+ * @returns {atom.Animatable.Animation}
2751
+ */
2752
+ animate: atom.core.ensureObjectSetter(function (properties) {
2753
+ return this.next(new atom.Animatable.Animation(this, properties));
2754
+ }),
2755
+
2756
+ stop: function (all) {
2757
+ var current = this.current;
2758
+ if (current) {
2759
+ if (all) this.animations.length = 0;
2760
+ current.destroy('stop');
2761
+ }
2762
+ return this;
2763
+ },
2764
+
2765
+ /** @private */
2766
+ getDefaultCallbacks: function (element) {
2767
+ return {
2768
+ get: function (property) {
2769
+ return atom.object.path.get(element, property);
2770
+ },
2771
+ set: atom.core.overloadSetter(function (property, value) {
2772
+ return atom.object.path.set(element, property, value);
2773
+ })
2774
+ };
2775
+ },
2776
+ /** @private */
2777
+ isValidCallbacks: function (callbacks) {
2778
+ return typeof callbacks == 'object' &&
2779
+ Object.keys(callbacks).length == 2 &&
2780
+ coreIsFunction(callbacks.set) &&
2781
+ coreIsFunction(callbacks.get);
2782
+ },
2783
+
2784
+ /** @private */
2785
+ animations: null,
2786
+
2787
+ /** @private */
2788
+ next: function (animation) {
2789
+ var queue = this.animations;
2790
+ if (animation) {
2791
+ queue.push(animation);
2792
+ if (queue.length == 1) {
2793
+ this.launch(animation);
2794
+ }
2795
+ } else if (queue.length) {
2796
+ this.launch(this.current);
2797
+ }
2798
+ return animation;
2799
+ },
2800
+ /** @private */
2801
+ launch: function (animation) {
2802
+ var queue = this.animations, animatable = this;
2803
+ animation.events.add('destroy', function remove () {
2804
+ queue.splice(queue.indexOf(animation), 1);
2805
+ animation.events.remove('destroy', remove);
2806
+ animatable.next();
2807
+ });
2808
+ animation.start();
2809
+ },
2810
+ /** @private */
2811
+ get: function (name) {
2812
+ return this.callbacks.get.apply(this.context, arguments);
2813
+ },
2814
+ /** @private */
2815
+ set: function (name, value) {
2816
+ return this.callbacks.set.apply(this.context, arguments);
2817
+ }
2818
+ });
2819
+
2820
+ /** @class atom.Animatable.Animation */
2821
+ declare( 'atom.Animatable.Animation', {
2822
+ /** @property {atom.Animatable} */
2823
+ animatable: null,
2824
+
2825
+ /**
2826
+ * initial values of properties
2827
+ * @property {Object}
2828
+ */
2829
+ initial: null,
2830
+
2831
+ /**
2832
+ * target values of properties
2833
+ * @property {Object}
2834
+ */
2835
+ target: null,
2836
+
2837
+ initialize: function (animatable, settings) {
2838
+ this.bindMethods([ 'tick', 'start' ]);
2839
+
2840
+ if (!settings.props) settings = {props: settings};
2841
+ this.events = new atom.Events(animatable);
2842
+ this.settings = new atom.Settings({
2843
+ fn : 'linear',
2844
+ time: 500
2845
+ })
2846
+ .set(settings)
2847
+ .addEvents(this.events);
2848
+ this.animatable = animatable;
2849
+ this.transition = atom.Transition.get(this.settings.get('fn'));
2850
+ this.allTime = this.settings.get('time');
2851
+ this.target = this.settings.get('props');
2852
+ },
2853
+
2854
+ start: function () {
2855
+ this.initial = this.fetchInitialValues();
2856
+ this.delta = this.countValuesDelta();
2857
+ this.timeLeft = this.allTime;
2858
+ this.events.fire( 'start', [ this ]);
2859
+ atom.frame.add(this.tick);
2860
+ return this;
2861
+ },
2862
+
2863
+ /** @private */
2864
+ countValuesDelta: function () {
2865
+ var initial = this.initial;
2866
+ return atom.object.map(this.target, function (value, key) {
2867
+ var start = initial[key];
2868
+ if (atom.Color && start instanceof atom.Color) {
2869
+ return start.diff( new atom.Color(value) );
2870
+ } else {
2871
+ return value - start;
2872
+ }
2873
+ });
2874
+ },
2875
+
2876
+ /** @private */
2877
+ fetchInitialValues: function () {
2878
+ var animatable = this.animatable;
2879
+ return atom.object.map(this.target, function (value, key) {
2880
+ var v = animatable.get(key);
2881
+ if (atom.Color && atom.Color.isColorString(value) || value instanceof atom.Color) {
2882
+ if (!v) {
2883
+ v = new atom.Color(value);
2884
+ v.alpha = 0;
2885
+ return v;
2886
+ }
2887
+ return new atom.Color(v);
2888
+ } else if (isNaN(v)) {
2889
+ throw new Error('value is not animatable: ' + v);
2890
+ } else {
2891
+ return v;
2892
+ }
2893
+ });
2894
+ },
2895
+
2896
+ /** @private */
2897
+ changeValues: function (progress) {
2898
+ var delta = this.delta, animatable = this.animatable, initial, target;
2899
+ for (var i in delta) if (delta.hasOwnProperty(i)) {
2900
+ if (progress == null) {
2901
+ target = this.target[i];
2902
+ animatable.set( i,
2903
+ atom.Color && target instanceof atom.Color
2904
+ ? target.toString() : target
2905
+ );
2906
+ } else {
2907
+ initial = this.initial[i];
2908
+ animatable.set( i,
2909
+ atom.Color && initial instanceof atom.Color ?
2910
+ initial.clone().move(delta[i].clone().mul(progress)).toString() :
2911
+ initial + delta[i] * progress
2912
+ );
2913
+ }
2914
+ }
2915
+ },
2916
+
2917
+ /** @private */
2918
+ tick: function (time) {
2919
+ var lastTick = time >= this.timeLeft;
2920
+ this.timeLeft = lastTick ? 0 : this.timeLeft - time;
2921
+
2922
+ this.changeValues(this.transition(
2923
+ lastTick ? 1 : (this.allTime - this.timeLeft) / this.allTime
2924
+ ));
2925
+ this.events.fire( 'tick', [ this ]);
2926
+
2927
+ if (lastTick) this.destroy('complete');
2928
+ },
2929
+
2930
+ destroy: function (type) {
2931
+ if (!type) type = 'error';
2932
+ this.events.fire( type, [ this ]);
2933
+ this.events.fire( 'destroy', [ this ]);
2934
+ atom.frame.remove(this.tick);
2935
+ return this;
2936
+ }
2937
+ });
2938
+
2939
+ if (atom.dom) (function (animatable) {
2940
+ var accessors = {
2941
+ get: function (name) {
2942
+ var value = this.css(name);
2943
+ return atom.Color && atom.Color.isColorString(value) ? value : parseFloat(value);
2944
+ },
2945
+ set: function (name, value) {
2946
+ this.css(name, value);
2947
+ }
2948
+ };
2949
+
2950
+ atom.dom.prototype.animate = atom.core.ensureObjectSetter(function (params) {
2951
+ this.each(function (elem) {
2952
+ if (!elem[animatable]) {
2953
+ elem[animatable] = new atom.Animatable(accessors, atom.dom(elem));
2954
+ }
2955
+ elem[animatable].animate(params);
2956
+ });
2957
+ return this
2958
+ });
2959
+
2960
+ atom.dom.prototype.stopAnimation = function (force) {
2961
+ this.each(function (elem) {
2962
+ if (elem[animatable]) {
2963
+ elem[animatable].stop(force);
2964
+ }
2965
+ });
2966
+ return this;
2967
+ };
2968
+ })('atom.animatable');
2969
+
2970
+ /*
2971
+ ---
2972
+
2973
+ name: "ClassCompat"
2974
+
2975
+ description: "Contains the Class Function for easily creating, extending, and implementing reusable Classes."
2976
+
2977
+ license:
2978
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
2979
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
2980
+
2981
+ requires:
2982
+ - Core
2983
+ - CoreExtended
2984
+ - declare
2985
+
2986
+ provides: ClassCompat
2987
+ ...
2988
+ */
2989
+
2990
+ declare( 'atom.Settings.Mixin',
2991
+ /** @deprecated */
2992
+ {
2993
+ /**
2994
+ * @private
2995
+ * @property atom.Settings
2996
+ */
2997
+ settings: null,
2998
+ options : {},
2999
+
3000
+ setOptions: function (options) {
3001
+ if (!this.settings) {
3002
+ this.settings = new atom.Settings(
3003
+ atom.clone(this.options || {})
3004
+ );
3005
+ this.options = this.settings.values;
3006
+ }
3007
+
3008
+ for (var i = 0; i < arguments.length; i++) {
3009
+ this.settings.set(arguments[i]);
3010
+ }
3011
+
3012
+ return this;
3013
+ }
3014
+ });
3015
+
3016
+ declare( 'atom.Events.Mixin', new function () {
3017
+ var init = function () {
3018
+ var events = this.__events;
3019
+ if (!events) events = this.__events = new atom.Events(this);
3020
+ if (this._events) {
3021
+ for (var name in this._events) if (name != '$ready') {
3022
+ this._events[name].forEach(function (fn) {
3023
+ events.add(name, fn);
3024
+ });
3025
+ }
3026
+ }
3027
+ return events;
3028
+ };
3029
+
3030
+ var method = function (method, useReturn) {
3031
+ return function () {
3032
+ var result, events = init.call(this);
3033
+
3034
+ result = events[method].apply( events, arguments );
3035
+ return useReturn ? result : this;
3036
+ }
3037
+ };
3038
+
3039
+ return {
3040
+ get events ( ) { return init.call(this); },
3041
+ set events (e) { this.__events = e; },
3042
+ isEventAdded: method( 'exists', true ),
3043
+ addEvent : method( 'add' , false ),
3044
+ removeEvent : method( 'remove', false ),
3045
+ fireEvent : method( 'fire' , false ),
3046
+ readyEvent : method( 'ready' , false )
3047
+ };
3048
+ });
3049
+
3050
+ /*
3051
+ ---
3052
+
3053
+ name: "Types.Number"
3054
+
3055
+ description: "Contains number-manipulation methods like limit, round, times, and ceil."
3056
+
3057
+ license:
3058
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
3059
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
3060
+
3061
+ requires:
3062
+ - Core
3063
+
3064
+ provides: Types.Number
3065
+
3066
+ ...
3067
+ */
3068
+
3069
+ atom.number = {
3070
+ randomFloat: function (max, min) {
3071
+ return Math.random() * (max - min) + min;
3072
+ },
3073
+ random : function (min, max) {
3074
+ return Math.floor(Math.random() * (max - min + 1) + min);
3075
+ },
3076
+ between: function (number, n1, n2, equals) {
3077
+ number = Number(number);
3078
+ n1 = Number(n1);
3079
+ n2 = Number(n2);
3080
+ return (n1 <= n2) && (
3081
+ (equals == 'L' && number == n1) ||
3082
+ (equals == 'R' && number == n2) ||
3083
+ (number > n1 && number < n2) ||
3084
+ ([true,'LR','RL'].indexOf(equals) != -1 && (n1 == number || n2 == number))
3085
+ );
3086
+ },
3087
+ equals : function (number, to, accuracy) {
3088
+ if (accuracy == null) accuracy = 8;
3089
+ return number.toFixed(accuracy) == to.toFixed(accuracy);
3090
+ },
3091
+ limit: function(number, min, max){
3092
+ var bottom = Math.max(min, Number(number));
3093
+ return max != null ? Math.min(max, bottom) : bottom;
3094
+ },
3095
+ round: function(number, precision){
3096
+ if (!precision) return Math.round(number);
3097
+
3098
+ if (precision < 0) {
3099
+ precision = Number( Math.pow(10, precision).toFixed( -precision ) );
3100
+ } else {
3101
+ precision = Math.pow(10, precision);
3102
+ }
3103
+ return Math.round(number * precision) / precision;
3104
+ },
3105
+ stop: function(num) {
3106
+ num = Number(num);
3107
+ if (num) {
3108
+ clearInterval(num);
3109
+ clearTimeout (num);
3110
+ }
3111
+ return this;
3112
+ }
3113
+ };
3114
+
3115
+ /*
3116
+ ---
3117
+
3118
+ name: "Types.Array"
3119
+
3120
+ description: "Contains array-manipulation methods like include, contains, and erase."
3121
+
3122
+ license:
3123
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
3124
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
3125
+
3126
+ requires:
3127
+ - Core
3128
+ - Types.Number
3129
+
3130
+ provides: Types.Array
3131
+
3132
+ ...
3133
+ */
3134
+
3135
+ atom.array = {
3136
+ /**
3137
+ * Checks if arguments is array
3138
+ * @param {Array} array
3139
+ * @returns {boolean}
3140
+ */
3141
+ is: function (array) {
3142
+ return Array.isArray(array);
3143
+ },
3144
+ /**
3145
+ * Creates rangearray
3146
+ * @param {int} from
3147
+ * @param {int} to
3148
+ * @param {int} [step=1] - should be
3149
+ * @returns {int[]}
3150
+ */
3151
+ range: function (from, to, step) {
3152
+ from = Number(from);
3153
+ to = Number(to );
3154
+ step = Number(step);
3155
+
3156
+ if (typeof from != 'number') throw new TypeError( '`from` should be number' );
3157
+ if (typeof to != 'number') throw new TypeError( '`to` should be number' );
3158
+
3159
+ var increase = to > from, stepIncrease = step > 0;
3160
+
3161
+ if (!step) {
3162
+ step = increase ? 1 : -1;
3163
+ } else if ( increase != stepIncrease ) {
3164
+ throw new RangeError( 'step direction is wrong' );
3165
+ }
3166
+
3167
+ var result = [];
3168
+ do {
3169
+ result.push(from);
3170
+ from += step;
3171
+ } while (increase ? from <= to : from >= to);
3172
+
3173
+ return result;
3174
+ },
3175
+ /**
3176
+ * @param {*} item
3177
+ * @returns {Array}
3178
+ */
3179
+ from: function (item) {
3180
+ if (item == null) return [];
3181
+ return (!coreIsArrayLike(item)) ? [item] :
3182
+ Array.isArray(item) ? item : slice.call(item);
3183
+ },
3184
+ /**
3185
+ * @private
3186
+ * @param {Array} args
3187
+ * @returns {Array}
3188
+ */
3189
+ pickFrom: function (args) {
3190
+ var fromZeroArgument = args && args.length == 1
3191
+ && coreIsArrayLike( args[0] );
3192
+
3193
+ return atom.array.from( fromZeroArgument ? args[0] : args );
3194
+ },
3195
+ /**
3196
+ * @param {number|Array} array
3197
+ * @param {*} fill
3198
+ * @returns {Array}
3199
+ */
3200
+ fill: function (array, fill) {
3201
+ array = Array.isArray(array) ? array : new Array(Number(array));
3202
+ for (var i = array.length; i--;) array[i] = fill;
3203
+ return array;
3204
+ },
3205
+ /**
3206
+ * @param {number} width
3207
+ * @param {number} height
3208
+ * @param {*} fill
3209
+ * @returns {Array[]}
3210
+ */
3211
+ fillMatrix: function (width, height, fill) {
3212
+ var array = new Array(height);
3213
+ while (height--) {
3214
+ array[height] = Array.fill(width, fill);
3215
+ }
3216
+ return array;
3217
+ },
3218
+ /**
3219
+ * It returns array, atom.object.collect returns hash
3220
+ * @param {Object} source
3221
+ * @param {Array} props
3222
+ * @param {*} [defaultValue=undefined]
3223
+ * @returns {Array}
3224
+ */
3225
+ collect: function (source, props, defaultValue) {
3226
+ var array = [], i = 0, l = props.length, prop;
3227
+ for (;i < l; i++) {
3228
+ prop = props[i];
3229
+ array.push(prop in source ? source[prop] : defaultValue);
3230
+ }
3231
+ return array;
3232
+ },
3233
+ /**
3234
+ * @param {Number} length
3235
+ * @param {function} callback
3236
+ * @param {Object} [context=undefined]
3237
+ * @returns {Array}
3238
+ */
3239
+ create: function (length, callback, context) {
3240
+ if (!coreIsFunction(callback)) {
3241
+ throw new TypeError('callback should be function');
3242
+ }
3243
+ var array = new Array(Number(length));
3244
+ for (var i = 0; i < length; i++) {
3245
+ array[i] = callback.call(context, i, array);
3246
+ }
3247
+ return array;
3248
+ },
3249
+ /**
3250
+ * @param {Array} array
3251
+ * @returns {Object}
3252
+ */
3253
+ toHash: function (array) {
3254
+ var hash = {}, i = 0, l = array.length;
3255
+ for (; i < l; i++) {
3256
+ hash[i] = array[i];
3257
+ }
3258
+ return hash;
3259
+ },
3260
+ /**
3261
+ * @param {Array} array
3262
+ * @returns {*}
3263
+ */
3264
+ last: function (array) {
3265
+ return array.length ? array[array.length - 1] : null;
3266
+ },
3267
+ /**
3268
+ * @param {Array} array
3269
+ * @returns number
3270
+ */
3271
+ randomIndex: function (array) {
3272
+ if (array.length == 0) return null;
3273
+
3274
+ return atom.number.random(0, array.length - 1);
3275
+ },
3276
+ /**
3277
+ * @param {Array} array
3278
+ * @param {boolean} erase - erase element after splice, or leave at place
3279
+ * @returns {*}
3280
+ */
3281
+ random: function (array, erase) {
3282
+ if (array.length == 0) return null;
3283
+
3284
+ var index = atom.array.randomIndex(array);
3285
+
3286
+ return erase ? array.splice(index, 1)[0] : array[index];
3287
+ },
3288
+ /**
3289
+ * Return array of property `name` values of objects
3290
+ * @param {Array} array
3291
+ * @param {string} name
3292
+ * @returns {Array}
3293
+ */
3294
+ property: function (array, name) {
3295
+ return array.map(function (elem) {
3296
+ return elem != null ? elem[ name ] : null;
3297
+ });
3298
+ },
3299
+ /** @deprecated - use `create` instead */
3300
+ fullMap: function (array, fn, bind) {
3301
+ var mapped = new Array(array.length);
3302
+ for (var i = 0, l = mapped.length; i < l; i++) {
3303
+ mapped[i] = fn.call(bind, array[i], i, array);
3304
+ }
3305
+ return mapped;
3306
+ },
3307
+ /**
3308
+ * Check, if array contains elem
3309
+ * @param {Array} array
3310
+ * @param {*} elem
3311
+ * @param {number} [fromIndex=0]
3312
+ * @returns {boolean}
3313
+ */
3314
+ contains: function (array, elem, fromIndex) {
3315
+ return array.indexOf(elem, fromIndex) != -1;
3316
+ },
3317
+ /**
3318
+ * Push element to array, if it doesn't contains such element
3319
+ * @param {Array} target
3320
+ * @param {*} item
3321
+ * @returns {Array} - target array
3322
+ */
3323
+ include: includeUnique,
3324
+ /**
3325
+ * Erase item from array
3326
+ * @param {Array} target
3327
+ * @param {*} item
3328
+ * @returns {Array} - target array
3329
+ */
3330
+ erase: coreEraseAll,
3331
+ /**
3332
+ * `push` source array values to the end of target array
3333
+ * @param {Array} target
3334
+ * @param {Array} source
3335
+ * @returns {Array} - target array
3336
+ */
3337
+ append: function (target, source) {
3338
+ for (var i = 1, l = arguments.length; i < l; i++) if (arguments[i]) {
3339
+ target.push.apply(target, arguments[i]);
3340
+ }
3341
+ return target;
3342
+ },
3343
+ /** @deprecated */
3344
+ toKeys: function (value) {
3345
+ var useValue = arguments.length == 1, obj = {};
3346
+ for (var i = 0, l = this.length; i < l; i++)
3347
+ obj[this[i]] = useValue ? value : i;
3348
+ return obj;
3349
+ },
3350
+ /**
3351
+ * `include` source array values to the end of target array
3352
+ * @param {Array} target
3353
+ * @param {Array} source
3354
+ * @returns {Array} - target array
3355
+ */
3356
+ combine: function(target, source){
3357
+ for (var i = 0, l = source.length; i < l; i++) {
3358
+ atom.array.include(target, source[i]);
3359
+ }
3360
+ return target;
3361
+ },
3362
+ /**
3363
+ * returns first not-null value, or returns null
3364
+ * @param {Array} source
3365
+ * @returns {*}
3366
+ */
3367
+ pick: function(source){
3368
+ for (var i = 0, l = source.length; i < l; i++) {
3369
+ if (source[i] != null) return source[i];
3370
+ }
3371
+ return null;
3372
+ },
3373
+ /**
3374
+ * You can invoke array of functions with context "context"
3375
+ * Or all methods of objects in array
3376
+ * all params except zero & first will be sed as argument
3377
+ * @param {Array} array
3378
+ * @param {Object|string} [context=null]
3379
+ * @returns {Array} - array of results
3380
+ */
3381
+ invoke: function(array, context){
3382
+ var args = slice.call(arguments, 2);
3383
+ if (typeof context == 'string') {
3384
+ var methodName = context;
3385
+ context = null;
3386
+ }
3387
+ return array.map(function(item){
3388
+ return item && (methodName ? item[methodName] : item).apply(methodName ? item : context, args);
3389
+ });
3390
+ },
3391
+ /**
3392
+ * shuffle array with smart algorithm
3393
+ * @param {Array} array
3394
+ * @returns {Array}
3395
+ */
3396
+ shuffle : function (array) {
3397
+ var tmp, moveTo, index = array.length;
3398
+ while (index--) {
3399
+ moveTo = atom.number.random( 0, index );
3400
+ tmp = array[index ];
3401
+ array[index] = array[moveTo];
3402
+ array[moveTo] = tmp;
3403
+ }
3404
+ return array;
3405
+ },
3406
+ /**
3407
+ * sort array by property value or method returns
3408
+ * @param {Array} array
3409
+ * @param {string} method
3410
+ * @param {boolean} [reverse=false] (if true) first - smallest, last - biggest
3411
+ * @returns {Array}
3412
+ */
3413
+ sortBy : function (array, method, reverse) {
3414
+ var get = function (elem) {
3415
+ return (coreIsFunction(elem[method]) ? elem[method]() : elem[method]) || 0;
3416
+ };
3417
+ var multi = reverse ? -1 : 1;
3418
+ return array.sort(function ($0, $1) {
3419
+ var diff = get($1) - get($0);
3420
+ return diff ? (diff < 0 ? -1 : 1) * multi : 0;
3421
+ });
3422
+ },
3423
+ /**
3424
+ * Returns min value in array
3425
+ * @param {Array} array
3426
+ * @returns {Array}
3427
+ */
3428
+ min: function(array){
3429
+ return Math.min.apply(null, array);
3430
+ },
3431
+ /**
3432
+ * Returns max value in array
3433
+ * @param {Array} array
3434
+ * @returns {Array}
3435
+ */
3436
+ max: function(array){
3437
+ return Math.max.apply(null, array);
3438
+ },
3439
+ /**
3440
+ * Multiply all values in array to factor & returns result array
3441
+ * @param {Array} array
3442
+ * @param {number} factor
3443
+ * @returns {Array}
3444
+ */
3445
+ mul: function (array, factor) {
3446
+ for (var i = array.length; i--;) array[i] *= factor;
3447
+ return array;
3448
+ },
3449
+ /**
3450
+ * Add to all values in array number & returns result array
3451
+ * @param {Array} array
3452
+ * @param {number} number
3453
+ * @returns {Array}
3454
+ */
3455
+ add: function (array, number) {
3456
+ for (var i = array.length; i--;) array[i] += number;
3457
+ return array;
3458
+ },
3459
+ /**
3460
+ * Returns sum of all elements in array
3461
+ * @param {Array} array
3462
+ * @returns {number}
3463
+ */
3464
+ sum: function (array) {
3465
+ for (var result = 0, i = array.length; i--;) result += array[i];
3466
+ return result;
3467
+ },
3468
+ /**
3469
+ * Returns product (result of multiplying) of all elements in array
3470
+ * @param {Array} array
3471
+ * @returns {number}
3472
+ */
3473
+ product: function (array) {
3474
+ for (var result = 1, i = array.length; i--;) result *= array[i];
3475
+ return result;
3476
+ },
3477
+ /**
3478
+ * Returns average value in array ( sum / length )
3479
+ * @param {Array} array
3480
+ * @returns {number}
3481
+ */
3482
+ average: function (array) {
3483
+ return array.length ? atom.array.sum(array) / array.length : 0;
3484
+ },
3485
+ /**
3486
+ * returns array with only unique values ( [1,2,2,3] => [1,2,3] )
3487
+ * @param {Array} array
3488
+ * @returns {Array}
3489
+ */
3490
+ unique: function(array){
3491
+ return atom.array.combine([], array);
3492
+ },
3493
+ /**
3494
+ * associate array values with keys
3495
+ * if `keys` is array it used as keys names, and array used as values
3496
+ * if `keys` if function it used as function, generated values & array used as keys
3497
+ * @param {Array} array
3498
+ * @param {Function|Array} keys
3499
+ * @returns {Object}
3500
+ */
3501
+ associate: function(array, keys){
3502
+ var
3503
+ i = 0,
3504
+ obj = {},
3505
+ length = array.length,
3506
+ isFn = coreIsFunction(keys),
3507
+ keysSource = isFn ? array : keys;
3508
+
3509
+ if (!isFn) length = Math.min(length, keys.length);
3510
+ for (;i < length; i++) {
3511
+ obj[ keysSource[i] ] = isFn ? keys(array[i], i) : array[i];
3512
+ }
3513
+ return obj;
3514
+ },
3515
+ /**
3516
+ * clean array from empty values & returns empty array
3517
+ * @param {Array} array
3518
+ * @returns {Array}
3519
+ */
3520
+ clean: function (array){
3521
+ return array.filter(function (item) { return item != null });
3522
+ },
3523
+ /**
3524
+ * quickly erase all values from array
3525
+ * @param {Array} array
3526
+ * @returns {Array}
3527
+ */
3528
+ empty: function (array) {
3529
+ array.length = 0;
3530
+ return array;
3531
+ },
3532
+ /** @deprecated */
3533
+ clone: function (array) { return atom.clone(array) },
3534
+ /**
3535
+ * @param array
3536
+ * @param {boolean} [asArray=false] - returns result as array, or as string
3537
+ * @returns {Array|string}
3538
+ */
3539
+ hexToRgb: function(array, asArray){
3540
+ if (array.length != 3) return null;
3541
+ var rgb = array.map(function(value){
3542
+ if (value.length == 1) value += value;
3543
+ return parseInt(value, 16);
3544
+ });
3545
+ return asArray ? rgb : 'rgb(' + rgb + ')';
3546
+ },
3547
+ /**
3548
+ * @param array
3549
+ * @param {boolean} [asArray=false] - returns result as array, or as string
3550
+ * @returns {Array|string}
3551
+ */
3552
+ rgbToHex: function(array, asArray) {
3553
+ if (array.length < 3) return null;
3554
+ if (array.length == 4 && array[3] == 0 && !asArray) return 'transparent';
3555
+ var hex = [], i = 0, bit;
3556
+ for (; i < 3; i++){
3557
+ bit = (array[i] - 0).toString(16);
3558
+ hex.push((bit.length == 1) ? '0' + bit : bit);
3559
+ }
3560
+ return asArray ? hex : '#' + hex.join('');
3561
+ },
3562
+
3563
+ /**
3564
+ * @param {Array} array
3565
+ * @param {Function} callback
3566
+ * @param {*} value
3567
+ * @returns {*}
3568
+ */
3569
+ reduce: function(array, callback, value){
3570
+ if (coreIsFunction(array.reduce)) return array.reduce(callback, value);
3571
+
3572
+ for (var i = 0, l = array.length; i < l; i++) if (i in array) {
3573
+ value = value === undefined ? array[i] : callback.call(null, value, array[i], i, array);
3574
+ }
3575
+ return value;
3576
+ },
3577
+
3578
+ /**
3579
+ * @param {Array} array
3580
+ * @param {Function} callback
3581
+ * @param {*} value
3582
+ * @returns {*}
3583
+ */
3584
+ reduceRight: function(array, callback, value){
3585
+ if (coreIsFunction(array.reduceRight)) return array.reduceRight(callback, value);
3586
+
3587
+ for (var i = array.length; i--;) if (i in array) {
3588
+ value = value === undefined ? array[i] : callback.call(null, value, array[i], i, array);
3589
+ }
3590
+ return value;
3591
+ }
3592
+ };
3593
+
3594
+ /*
3595
+ ---
3596
+
3597
+ name: "Color"
3598
+
3599
+ description: "Provides Color class"
3600
+
3601
+ license:
3602
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
3603
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
3604
+
3605
+ requires:
3606
+ - Core
3607
+ - declare
3608
+ - Types.Number
3609
+ - Types.Array
3610
+
3611
+ provides: Color
3612
+
3613
+ ...
3614
+ */
3615
+
3616
+ /** @class atom.Color */
3617
+ declare( 'atom.Color', {
3618
+ initialize: function (value) {
3619
+ var a = arguments, type;
3620
+ if (a.length == 4 || a.length == 3) {
3621
+ value = slice.call(a);
3622
+ } else if (value && value.length == 1) {
3623
+ value = value[0];
3624
+ }
3625
+
3626
+ type = typeof value;
3627
+ if (Array.isArray(value)) {
3628
+ this.fromArray(value);
3629
+ } else if (type == 'number') {
3630
+ this.fromNumber(value);
3631
+ } else if (type == 'string') {
3632
+ this.fromString(value);
3633
+ } else if (type == 'object') {
3634
+ this.fromObject(value);
3635
+ } else {
3636
+ throw new TypeError('Unknown type in atom.Color: ' + typeof value + ';\n' + value);
3637
+ }
3638
+ },
3639
+
3640
+ /** @private */
3641
+ r: 0,
3642
+ /** @private */
3643
+ g: 0,
3644
+ /** @private */
3645
+ b: 0,
3646
+ /** @private */
3647
+ a: 1,
3648
+
3649
+ /**
3650
+ * We are array-like object (looks at accessors at bottom of class)
3651
+ * @constant
3652
+ */
3653
+ length: 4,
3654
+
3655
+ noLimits: false,
3656
+
3657
+ get red () { return this.r; },
3658
+ get green () { return this.g; },
3659
+ get blue () { return this.b; },
3660
+ get alpha () { return this.a; },
3661
+
3662
+ set red (v) { this.setValue('r', v) },
3663
+ set green (v) { this.setValue('g', v) },
3664
+ set blue (v) { this.setValue('b', v) },
3665
+ set alpha (v) { this.setValue('a', v, true) },
3666
+
3667
+ /** @private */
3668
+ safeAlphaSet: function (v) {
3669
+ if (v != null) this.alpha = atom.number.round(v, 3);
3670
+ },
3671
+
3672
+ /** @private */
3673
+ setValue: function (prop, value, isFloat) {
3674
+ value = Number(value);
3675
+ if (value != value) { // isNaN
3676
+ throw new TypeError('Value is NaN (' + prop + '): ' + value);
3677
+ }
3678
+
3679
+ if (!isFloat) value = Math.round(value);
3680
+ // We don't want application down, if user script (e.g. animation)
3681
+ // generates such wrong array: [150, 125, -1]
3682
+ // `noLimits` switch off this check
3683
+ this[prop] = this.noLimits ? value :
3684
+ atom.number.limit( value, 0, isFloat ? 1 : 255 );
3685
+ },
3686
+
3687
+ // Parsing
3688
+
3689
+ /**
3690
+ * @param {int[]} array
3691
+ * @returns {atom.Color}
3692
+ */
3693
+ fromArray: function (array) {
3694
+ if (!array || array.length < 3 || array.length > 4) {
3695
+ throw new TypeError('Wrong array in atom.Color: ' + array);
3696
+ }
3697
+ this.red = array[0];
3698
+ this.green = array[1];
3699
+ this.blue = array[2];
3700
+ this.safeAlphaSet(array[3]);
3701
+ return this;
3702
+ },
3703
+ /**
3704
+ * @param {Object} object
3705
+ * @param {number} object.red
3706
+ * @param {number} object.green
3707
+ * @param {number} object.blue
3708
+ * @returns {atom.Color}
3709
+ */
3710
+ fromObject: function (object) {
3711
+ if (typeof object != 'object') {
3712
+ throw new TypeError( 'Not object in "fromObject": ' + typeof object );
3713
+ }
3714
+
3715
+ function fetch (p1, p2) {
3716
+ return object[p1] != null ? object[p1] : object[p2]
3717
+ }
3718
+
3719
+ this.red = fetch('r', 'red' );
3720
+ this.green = fetch('g', 'green');
3721
+ this.blue = fetch('b', 'blue' );
3722
+ this.safeAlphaSet(fetch('a', 'alpha'));
3723
+ return this;
3724
+ },
3725
+ /**
3726
+ * @param {string} string
3727
+ * @returns {atom.Color}
3728
+ */
3729
+ fromString: function (string) {
3730
+ if (!this.constructor.isColorString(string)) {
3731
+ throw new TypeError( 'Not color string in "fromString": ' + string );
3732
+ }
3733
+
3734
+ var hex, array;
3735
+
3736
+ string = string.toLowerCase();
3737
+ string = this.constructor.colorNames[string] || string;
3738
+
3739
+ if (hex = string.match(/^#(\w{1,2})(\w{1,2})(\w{1,2})(\w{1,2})?$/)) {
3740
+ array = hex.slice(1).clean();
3741
+ array = array.map(function (part) {
3742
+ if (part.length == 1) part += part;
3743
+ return parseInt(part, 16);
3744
+ });
3745
+ if (array.length == 4) array[3] /= 255;
3746
+ } else {
3747
+ array = string.match(/([\.\d]{1,})/g).map( Number );
3748
+ }
3749
+ return this.fromArray(array);
3750
+ },
3751
+ /**
3752
+ * @param {number} number
3753
+ * @returns {atom.Color}
3754
+ */
3755
+ fromNumber: function (number) {
3756
+ if (typeof number != 'number' || number < 0 || number > 0xffffffff) {
3757
+ throw new TypeError( 'Not color number in "fromNumber": ' + (number.toString(16)) );
3758
+ }
3759
+
3760
+ return this.fromArray([
3761
+ (number>>24) & 0xff,
3762
+ (number>>16) & 0xff,
3763
+ (number>> 8) & 0xff,
3764
+ (number & 0xff) / 255
3765
+ ]);
3766
+ },
3767
+
3768
+ // Casting
3769
+
3770
+ /** @returns {int[]} */
3771
+ toArray: function () {
3772
+ return [this.r, this.g, this.b, this.a];
3773
+ },
3774
+ /** @returns {string} */
3775
+ toString: function (type) {
3776
+ var arr = this.toArray();
3777
+ if (type == 'hex' || type == 'hexA') {
3778
+ return '#' + arr.map(function (color, i) {
3779
+ if (i == 3) { // alpha
3780
+ if (type == 'hex') return '';
3781
+ color = Math.round(color * 255);
3782
+ }
3783
+ var bit = color.toString(16);
3784
+ return bit.length == 1 ? '0' + bit : bit;
3785
+ }).join('');
3786
+ } else {
3787
+ return 'rgba(' + arr + ')';
3788
+ }
3789
+ },
3790
+ /** @returns {number} */
3791
+ toNumber: function () {
3792
+ // maybe needs optimizations
3793
+ return parseInt( this.toString('hexA').substr(1) , 16)
3794
+ },
3795
+ /** @returns {object} */
3796
+ toObject: function (abbreviationNames) {
3797
+ return atom.array.associate( this.toArray(),
3798
+ abbreviationNames ?
3799
+ ['r' , 'g' , 'b' ,'a' ] :
3800
+ ['red', 'green', 'blue','alpha']
3801
+ );
3802
+ },
3803
+
3804
+ // manipulations
3805
+
3806
+ /**
3807
+ * @param {atom.Color} color
3808
+ * @returns {atom.Color}
3809
+ */
3810
+ diff: function (color) {
3811
+ // we can't use this.constructor, because context exists in such way
3812
+ // && invoke is not called
3813
+ color = atom.Color( color );
3814
+ return new atom.Color.Shift([
3815
+ color.red - this.red ,
3816
+ color.green - this.green,
3817
+ color.blue - this.blue ,
3818
+ color.alpha - this.alpha
3819
+ ]);
3820
+ },
3821
+ /**
3822
+ * @param {atom.Color} color
3823
+ * @returns {atom.Color}
3824
+ */
3825
+ move: function (color) {
3826
+ color = atom.Color.Shift(color);
3827
+ this.red += color.red ;
3828
+ this.green += color.green;
3829
+ this.blue += color.blue ;
3830
+ this.alpha += color.alpha;
3831
+ return this;
3832
+ },
3833
+ /** @deprecated - use `clone`+`move` instead */
3834
+ shift: function (color) {
3835
+ return this.clone().move(color);
3836
+ },
3837
+ map: function (fn) {
3838
+ var color = this;
3839
+ ['red', 'green', 'blue', 'alpha'].forEach(function (component) {
3840
+ color[component] = fn.call( color, color[component], component, color );
3841
+ });
3842
+ return color;
3843
+ },
3844
+ add: function (factor) {
3845
+ return this.map(function (value) {
3846
+ return value + factor;
3847
+ });
3848
+ },
3849
+ mul: function (factor) {
3850
+ return this.map(function (value) {
3851
+ return value * factor;
3852
+ });
3853
+ },
3854
+ /**
3855
+ * @param {atom.Color} color
3856
+ * @returns {boolean}
3857
+ */
3858
+ equals: function (color) {
3859
+ return color &&
3860
+ color instanceof this.constructor &&
3861
+ color.red == this.red &&
3862
+ color.green == this.green &&
3863
+ color.blue == this.blue &&
3864
+ color.alpha == this.alpha;
3865
+ },
3866
+
3867
+ /** @private */
3868
+ dump: function () {
3869
+ return '[atom.Color(' + this.toString('hexA') + ')]';
3870
+ },
3871
+
3872
+ /**
3873
+ * @returns {atom.Color}
3874
+ */
3875
+ clone: function () {
3876
+ return new this.constructor(this);
3877
+ }
3878
+ }).own({
3879
+ invoke: declare.castArguments,
3880
+
3881
+ /**
3882
+ * Checks if string is color description
3883
+ * @param {string} string
3884
+ * @returns {boolean}
3885
+ */
3886
+ isColorString : function (string) {
3887
+ if (typeof string != 'string') return false;
3888
+ return Boolean(
3889
+ string in this.colorNames ||
3890
+ string.match(/^#\w{3,6}$/) ||
3891
+ string.match(/^rgba?\([\d\., ]+\)$/)
3892
+ );
3893
+ },
3894
+
3895
+ colorNames: {
3896
+ white: '#ffffff',
3897
+ silver: '#c0c0c0',
3898
+ gray: '#808080',
3899
+ black: '#000000',
3900
+ red: '#ff0000',
3901
+ maroon: '#800000',
3902
+ yellow: '#ffff00',
3903
+ olive: '#808000',
3904
+ lime: '#00ff00',
3905
+ green: '#008000',
3906
+ aqua: '#00ffff',
3907
+ teal: '#008080',
3908
+ blue: '#0000ff',
3909
+ navy: '#000080',
3910
+ fuchsia:'#ff00ff',
3911
+ purple: '#800080',
3912
+ orange: '#ffa500'
3913
+ },
3914
+
3915
+ /**
3916
+ * @param {boolean} [html=false] - only html color names
3917
+ * @returns {atom.Color}
3918
+ */
3919
+ random: function (html) {
3920
+ var random = atom.number.random;
3921
+ if (html) {
3922
+ return new this(atom.array.random(
3923
+ Object.keys(this.colorNames)
3924
+ ));
3925
+ } else {
3926
+ return new this([
3927
+ random(0, 255),
3928
+ random(0, 255),
3929
+ random(0, 255)
3930
+ ]);
3931
+ }
3932
+ }
3933
+ });
3934
+
3935
+ /** @class atom.Color.Shift */
3936
+ declare( 'atom.Color.Shift', atom.Color, { noLimits: true });
3937
+
3938
+ /** @class ImagePreloader */
3939
+ atom.declare( 'atom.ImagePreloader', {
3940
+ processed : 0,
3941
+ number : 0,
3942
+
3943
+ initialize: function (settings) {
3944
+ this.events = new Events(this);
3945
+ this.settings = new Settings(settings).addEvents(this.events);
3946
+
3947
+ this.count = {
3948
+ error: 0,
3949
+ abort: 0,
3950
+ load : 0
3951
+ };
3952
+
3953
+ this.suffix = this.settings.get('suffix') || '';
3954
+ this.usrImages = this.prefixImages(this.settings.get('images'));
3955
+ this.imageUrls = this.fetchUrls();
3956
+ this.domImages = {};
3957
+ //this.domImages = this.createDomImages();
3958
+ this.images = {};
3959
+ this.createNext();
3960
+ },
3961
+ get isReady () {
3962
+ return this.number == this.processed;
3963
+ },
3964
+ get info () {
3965
+ var stat = atom.string.substitute(
3966
+ "Images loaded: {load}; Errors: {error}; Aborts: {abort}",
3967
+ this.count
3968
+ );
3969
+ if (this.isReady) stat = "Image preloading has completed;\n" + stat;
3970
+ return stat;
3971
+ },
3972
+ get progress () {
3973
+ return this.isReady ? 1 : atom.number.round(this.processed / this.number, 4);
3974
+ },
3975
+ append: function (preloader) {
3976
+ for (var i in preloader.images) {
3977
+ this.images[i] = preloader.images[i];
3978
+ }
3979
+ return this;
3980
+ },
3981
+ exists: function (name) {
3982
+ return !!this.images[name];
3983
+ },
3984
+ get: function (name) {
3985
+ var image = this.images[name];
3986
+ if (image) {
3987
+ return image;
3988
+ } else {
3989
+ throw new Error('No image «' + name + '»');
3990
+ }
3991
+ },
3992
+
3993
+ /** @private */
3994
+ cropImage: function (img, c) {
3995
+ if (!c) return img;
3996
+
3997
+ var canvas = document.createElement('canvas');
3998
+ canvas.width = c[2];
3999
+ canvas.height = c[3];
4000
+ canvas.getContext('2d').drawImage( img,
4001
+ c[0], c[1], c[2], c[3], 0, 0, c[2], c[3]
4002
+ );
4003
+ return canvas;
4004
+ },
4005
+ /** @private */
4006
+ withoutPrefix: function (src) {
4007
+ return src.indexOf('http://') === 0 || src.indexOf('https://') === 0;
4008
+ },
4009
+ /** @private */
4010
+ prefixImages: function (images) {
4011
+ var prefix = this.settings.get('prefix');
4012
+ if (!prefix) return images;
4013
+
4014
+ return atom.object.map(images, function (src) {
4015
+ return this.withoutPrefix(src) ? src : prefix + src;
4016
+ }.bind(this));
4017
+ },
4018
+ /** @private */
4019
+ cutImages: function () {
4020
+ var i, parts, img;
4021
+ for (i in this.usrImages) if (this.usrImages.hasOwnProperty(i)) {
4022
+ parts = this.splitUrl( this.usrImages[i] );
4023
+ img = this.domImages[ parts.url ];
4024
+ this.images[i] = this.cropImage(img, parts.coords);
4025
+ }
4026
+ return this;
4027
+ },
4028
+ /** @private */
4029
+ splitUrl: function (str) {
4030
+ var url = str, size, cell, match, coords = null;
4031
+
4032
+ // searching for pattern 'url [x:y:w:y]'
4033
+ if (match = str.match(/ \[(\d+):(\d+):(\d+):(\d+)\]$/)) {
4034
+ coords = match.slice( 1 );
4035
+ // searching for pattern 'url [w:y]{x:y}'
4036
+ } else if (match = str.match(/ \[(\d+):(\d+)\]\{(\d+):(\d+)\}$/)) {
4037
+ coords = match.slice( 1 ).map( Number );
4038
+ size = coords.slice( 0, 2 );
4039
+ cell = coords.slice( 2, 4 );
4040
+ coords = [ cell[0] * size[0], cell[1] * size[1], size[0], size[1] ];
4041
+ }
4042
+ if (match) {
4043
+ url = str.substr(0, str.lastIndexOf(match[0]));
4044
+ coords = coords.map( Number );
4045
+ }
4046
+ if (this.suffix) {
4047
+ if (typeof this.suffix == 'function') {
4048
+ url = this.suffix( url );
4049
+ } else {
4050
+ url += this.suffix;
4051
+ }
4052
+ }
4053
+
4054
+ return { url: url, coords: coords };
4055
+ },
4056
+ /** @private */
4057
+ fetchUrls: function () {
4058
+ var i, result = [], hash = {}, url, images = this.usrImages;
4059
+ for (i in images) if (images.hasOwnProperty(i)) {
4060
+ url = this.splitUrl( images[i] ).url;
4061
+ if (!hash[url]) {
4062
+ result.push(url);
4063
+ hash[url] = true;
4064
+ this.number++;
4065
+ }
4066
+ }
4067
+ return result;
4068
+ },
4069
+ /** @private */
4070
+ createDomImage : function (src) {
4071
+ var img = new Image();
4072
+ img.src = src;
4073
+ if (window.opera && img.complete) {
4074
+ setTimeout(this.onProcessed.bind(this, 'load', img), 10);
4075
+ } else {
4076
+ ['load', 'error', 'abort'].forEach(function (event) {
4077
+ img.addEventListener( event, this.onProcessed.bind(this, event, img), false );
4078
+ }.bind(this));
4079
+ }
4080
+ return img;
4081
+ },
4082
+ createNext: function () {
4083
+ if (this.imageUrls.length) {
4084
+ var url = this.imageUrls.shift();
4085
+ this.domImages[url] = this.createDomImage(url);
4086
+ }
4087
+ },
4088
+ resetImage: function (img) {
4089
+ // opera fullscreen bug workaround
4090
+ img.width = img.width;
4091
+ img.height = img.height;
4092
+ img.naturalWidth = img.naturalWidth;
4093
+ img.naturalHeight = img.naturalHeight;
4094
+ },
4095
+ /** @private */
4096
+ onProcessed : function (type, img) {
4097
+ if (type == 'load' && window.opera) {
4098
+ this.resetImage(img);
4099
+ }
4100
+ this.count[type]++;
4101
+ this.processed++;
4102
+ this.events.fire('progress', [this, img]);
4103
+
4104
+ if (this.isReady) {
4105
+ this.cutImages();
4106
+ this.events.ensureReady('ready', [this]);
4107
+ } else {
4108
+ this.createNext();
4109
+ }
4110
+ return this;
4111
+ }
4112
+ }).own({
4113
+ run: function (images, callback, context) {
4114
+ var preloader = new this({ images: images });
4115
+
4116
+ preloader.events.add( 'ready', context ? callback.bind(context) : callback );
4117
+
4118
+ return preloader;
4119
+ }
4120
+ });
4121
+
4122
+ /*
4123
+ ---
4124
+
4125
+ name: "Keyboard"
4126
+
4127
+ description: ""
4128
+
4129
+ license:
4130
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
4131
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
4132
+
4133
+ requires:
4134
+ - declare
4135
+ - Events
4136
+
4137
+ provides: Keyboard
4138
+
4139
+ ...
4140
+ */
4141
+
4142
+ var Keyboard = function () {
4143
+
4144
+ var
4145
+ keyName,
4146
+ codeNames = {},
4147
+ keyCodes = {
4148
+ // Alphabet
4149
+ a:65, b:66, c:67, d:68, e:69,
4150
+ f:70, g:71, h:72, i:73, j:74,
4151
+ k:75, l:76, m:77, n:78, o:79,
4152
+ p:80, q:81, r:82, s:83, t:84,
4153
+ u:85, v:86, w:87, x:88, y:89, z:90,
4154
+ // Numbers
4155
+ n0:48, n1:49, n2:50, n3:51, n4:52,
4156
+ n5:53, n6:54, n7:55, n8:56, n9:57,
4157
+ // Controls
4158
+ tab: 9, enter:13, shift:16, backspace:8,
4159
+ ctrl:17, alt :18, esc :27, space :32,
4160
+ menu:93, pause:19, cmd :91,
4161
+ insert :45, home:36, pageup :33,
4162
+ 'delete':46, end :35, pagedown:34,
4163
+ // F*
4164
+ f1:112, f2:113, f3:114, f4 :115, f5 :116, f6 :117,
4165
+ f7:118, f8:119, f9:120, f10:121, f11:122, f12:123,
4166
+ // numpad
4167
+ np0: 96, np1: 97, np2: 98, np3: 99, np4:100,
4168
+ np5:101, np6:102, np7:103, np8:104, np9:105,
4169
+ npslash:11,npstar:106,nphyphen:109,npplus:107,npdot:110,
4170
+ // Lock
4171
+ capslock:20, numlock:144, scrolllock:145,
4172
+
4173
+ // Symbols
4174
+ equals: 61, hyphen :109, coma :188, dot:190,
4175
+ gravis:192, backslash:220, sbopen:219, sbclose:221,
4176
+ slash :191, semicolon: 59, apostrophe: 222,
4177
+
4178
+ // Arrows
4179
+ aleft:37, aup:38, aright:39, adown:40
4180
+ };
4181
+
4182
+ for (keyName in keyCodes) if (keyCodes.hasOwnProperty(keyName)) {
4183
+ codeNames[ keyCodes[keyName] ] = keyName;
4184
+ }
4185
+
4186
+ /** @class atom.Keyboard */
4187
+ return declare( 'atom.Keyboard', {
4188
+ initialize : function (element, preventDefault) {
4189
+ if (Array.isArray(element)) {
4190
+ preventDefault = element;
4191
+ element = null;
4192
+ }
4193
+ if (element == null) element = document;
4194
+
4195
+ if (element == document) {
4196
+ if (this.constructor.instance) {
4197
+ return this.constructor.instance;
4198
+ }
4199
+ this.constructor.instance = this;
4200
+ }
4201
+
4202
+ this.events = new Events(this);
4203
+ this.keyStates = {};
4204
+ this.preventDefault = preventDefault;
4205
+
4206
+ atom.dom(element).bind({
4207
+ keyup: this.keyEvent('up'),
4208
+ keydown: this.keyEvent('down'),
4209
+ keypress: this.keyEvent('press')
4210
+ });
4211
+ },
4212
+ /** @private */
4213
+ keyEvent: function (event) {
4214
+ return this.onKeyEvent.bind(this, event);
4215
+ },
4216
+ /** @private */
4217
+ onKeyEvent: function (event, e) {
4218
+ var key = this.constructor.keyName(e),
4219
+ prevent = this.prevent(key);
4220
+
4221
+ e.keyName = key;
4222
+
4223
+ if (prevent) e.preventDefault();
4224
+ this.events.fire( event, [e] );
4225
+
4226
+ if (event == 'down') {
4227
+ this.events.fire(key, [e]);
4228
+ this.keyStates[key] = true;
4229
+ } else if (event == 'up') {
4230
+ this.events.fire(key + ':up', [e]);
4231
+ delete this.keyStates[key];
4232
+ } else if (event == 'press') {
4233
+ this.events.fire(key + ':press', [e]);
4234
+ }
4235
+
4236
+ return !prevent;
4237
+ },
4238
+ /** @private */
4239
+ prevent : function (key) {
4240
+ var pD = this.preventDefault;
4241
+ return pD && (pD === true || pD.indexOf(key) >= 0);
4242
+ },
4243
+ key: function (keyName) {
4244
+ return !!this.keyStates[ this.constructor.keyName(keyName) ];
4245
+ }
4246
+ }).own({
4247
+ keyCodes : keyCodes,
4248
+ codeNames: codeNames,
4249
+ keyName: function (code) {
4250
+ if (code && code.keyCode != null) {
4251
+ code = code.keyCode;
4252
+ }
4253
+
4254
+ var type = typeof code;
4255
+
4256
+ if (type == 'number') {
4257
+ return this.codeNames[code];
4258
+ } else if (type == 'string' && code in this.keyCodes) {
4259
+ return code;
4260
+ }
4261
+
4262
+ return null;
4263
+ }
4264
+ });
4265
+
4266
+ }();
4267
+
4268
+
4269
+ /*
4270
+ ---
4271
+
4272
+ name: "Registry"
4273
+
4274
+ description: ""
4275
+
4276
+ license:
4277
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
4278
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
4279
+
4280
+ requires:
4281
+ - declare
4282
+
4283
+ provides: Registry
4284
+
4285
+ ...
4286
+ */
4287
+
4288
+ /** @class atom.Registry */
4289
+ declare( 'atom.Registry', {
4290
+ items: {},
4291
+ initialize: function (initial) {
4292
+ this.items = {};
4293
+ if (initial) this.set(initial);
4294
+ },
4295
+ set: atom.core.overloadSetter(function (name, value) {
4296
+ this.items[name] = value;
4297
+ }),
4298
+ get: atom.core.overloadGetter(function (name) {
4299
+ return this.items[name];
4300
+ })
4301
+ });
4302
+
4303
+ var Registry = atom.Registry;
4304
+
4305
+ /*
4306
+ ---
4307
+
4308
+ name: "trace"
4309
+
4310
+ description: ""
4311
+
4312
+ license:
4313
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
4314
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
4315
+
4316
+ requires:
4317
+ - declare
4318
+ - dom
4319
+ - CoreExtended
4320
+
4321
+ provides: trace
4322
+
4323
+ ...
4324
+ */
4325
+
4326
+ atom.trace = declare( 'atom.trace', {
4327
+ initialize : function (object) {
4328
+ this.value = object;
4329
+ this.stopped = false;
4330
+ },
4331
+ set value (value) {
4332
+ if (!this.stopped) {
4333
+ var html = atom.string.replaceAll( this.constructor.dump(value), {
4334
+ '\t': '&nbsp;'.repeat(3),
4335
+ '\n': '<br />'
4336
+ });
4337
+ this.createNode().html(html);
4338
+ }
4339
+ },
4340
+ destroy : function (force) {
4341
+ var trace = this;
4342
+ if (force) this.stop();
4343
+ if (trace.node) {
4344
+ trace.node.addClass('atom-trace-node-destroy');
4345
+ trace.timeout = setTimeout(function () {
4346
+ if (trace.node) {
4347
+ trace.node.destroy();
4348
+ trace.node = null;
4349
+ }
4350
+ }, 500);
4351
+ }
4352
+ return trace;
4353
+ },
4354
+ /** @private */
4355
+ stop : function () {
4356
+ this.stopped = true;
4357
+ return this;
4358
+ },
4359
+ /** @private */
4360
+ getContainer : function () {
4361
+ var cont = atom.dom('#atom-trace-container');
4362
+ return cont.length ? cont :
4363
+ atom.dom.create('div', { 'id' : 'atom-trace-container'})
4364
+ .appendTo('body');
4365
+ },
4366
+ /** @deprecated */
4367
+ trace : function (value) {
4368
+ this.value = value;
4369
+ return this;
4370
+ },
4371
+ /** @private */
4372
+ createNode : function () {
4373
+ var trace = this, node = trace.node;
4374
+
4375
+ if (node) {
4376
+ if (trace.timeout) {
4377
+ clearTimeout(trace.timeout);
4378
+ node.removeClass('atom-trace-node-destroy');
4379
+ }
4380
+ return node;
4381
+ }
4382
+
4383
+ return trace.node = atom.dom
4384
+ .create('div')
4385
+ .addClass('atom-trace-node')
4386
+ .appendTo(trace.getContainer())
4387
+ .bind({
4388
+ click : function () { trace.destroy(0) },
4389
+ dblclick : function () { trace.destroy(1) }
4390
+ });
4391
+ }
4392
+ }).own({
4393
+ dumpRec : function dumpRec (obj, level, plain) {
4394
+ var html = '', type, tabs;
4395
+
4396
+ level = parseInt(level) || 0;
4397
+
4398
+ if (level > 5) return '*TOO_DEEP*';
4399
+
4400
+ if (obj && typeof obj == 'object' && coreIsFunction(obj.dump)) return obj.dump();
4401
+
4402
+ function escape (v) {
4403
+ return plain ? v : atom.string.safeHtml(v);
4404
+ }
4405
+
4406
+ function subDump (elem, index) {
4407
+ return tabs + '\t' + index + ': ' + dumpRec(elem, level+1, plain) + '\n';
4408
+ }
4409
+
4410
+ type = atom.typeOf(obj);
4411
+ tabs = '\t'.repeat(level);
4412
+
4413
+ switch (type) {
4414
+ case 'object':
4415
+ for (var index in obj) if (obj.hasOwnProperty(index)) {
4416
+ html += subDump(obj[index], index);
4417
+ }
4418
+ return '{\n' + html + tabs + '}';
4419
+
4420
+ case 'element':
4421
+ var prop = (obj.width && obj.height) ? '('+obj.width+'×'+obj.height+')' : '';
4422
+ return '[DOM ' + obj.tagName.toLowerCase() + prop + ']';
4423
+
4424
+ case 'textnode':
4425
+ case 'whitespace':
4426
+ return '[DOM ' + type + ']';
4427
+
4428
+ case 'array' : return '[\n' + obj.map(subDump).join('') + tabs + ']';
4429
+ case 'null' : return 'null';
4430
+ case 'boolean': return obj ? 'true' : 'false';
4431
+ case 'string' : return escape('"' + obj + '"');
4432
+ default : return escape('' + obj);
4433
+ }
4434
+ },
4435
+ dumpPlain: function (object) {
4436
+ return (this.dumpRec(object, 0, true));
4437
+ },
4438
+ dump : function (object) {
4439
+ return (this.dumpRec(object, 0));
4440
+ }
4441
+ });
4442
+
4443
+ /*
4444
+ ---
4445
+
4446
+ name: "Prototypes.Abstract"
4447
+
4448
+ description: "Contains office methods for prototypes extension."
4449
+
4450
+ license:
4451
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
4452
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
4453
+
4454
+ requires:
4455
+ - Core
4456
+ - Types.Array
4457
+ - Types.Object
4458
+
4459
+ provides: Prototypes.Abstract
4460
+
4461
+ ...
4462
+ */
4463
+
4464
+ var prototypize = {
4465
+ fn: function (source) {
4466
+ return function (methodName) {
4467
+ return function () {
4468
+ var args = slice.call(arguments);
4469
+ args.unshift(this);
4470
+ return source[methodName].apply(source, args);
4471
+ };
4472
+ };
4473
+ },
4474
+ proto: function (object, proto, methodsString) {
4475
+ coreAppend(object.prototype, atom.array.associate(
4476
+ methodsString.split(' '), proto
4477
+ ));
4478
+ return prototypize;
4479
+ },
4480
+ own: function (object, source, methodsString) {
4481
+ coreAppend(object, atom.object.collect( source, methodsString.split(' ') ));
4482
+ return prototypize;
4483
+ }
4484
+ };
4485
+
4486
+ /*
4487
+ ---
4488
+
4489
+ name: "Prototypes.Array"
4490
+
4491
+ description: "Contains Array Prototypes like include, contains, and erase."
4492
+
4493
+ license:
4494
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
4495
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
4496
+
4497
+ requires:
4498
+ - Types.Array
4499
+ - Prototypes.Abstract
4500
+
4501
+ provides: Prototypes.Array
4502
+
4503
+ ...
4504
+ */
4505
+
4506
+ (function () {
4507
+
4508
+ var proto = prototypize.fn(atom.array);
4509
+
4510
+ prototypize
4511
+ .own(Array, atom.array, 'range from pickFrom fill fillMatrix collect create toHash')
4512
+ .proto(Array, proto, 'randomIndex property contains include append erase combine pick invoke shuffle sortBy min max mul add sum product average unique associate clean empty clone hexToRgb rgbToHex' );
4513
+
4514
+ atom.accessors.define(Array.prototype, {
4515
+ last : { get: function () {
4516
+ return atom.array.last(this);
4517
+ }},
4518
+ random: { get: function () {
4519
+ return atom.array.random(this, false);
4520
+ }}
4521
+ });
4522
+
4523
+ coreAppend(Array.prototype, {
4524
+ popRandom: function () {
4525
+ return atom.array.random(this, true);
4526
+ },
4527
+ /** @deprecated */
4528
+ toKeys: function () {
4529
+ console.log( '[].toKeys is deprecated. Use forEach instead' );
4530
+ return atom.array.toKeys(this);
4531
+ },
4532
+ /** @deprecated */
4533
+ fullMap: function (callback, context) {
4534
+ console.log( '[].fullMap is deprecated. Use atom.array.create instead' );
4535
+ return atom.array.create(this.length, callback, context);
4536
+ }
4537
+ });
4538
+
4539
+ if (!Array.prototype.reduce ) Array.prototype.reduce = proto('reduce');
4540
+ if (!Array.prototype.reduceRight) Array.prototype.reduceRight = proto('reduceRight');
4541
+
4542
+ })();
4543
+
4544
+ /*
4545
+ ---
4546
+
4547
+ name: "Types.Function"
4548
+
4549
+ description: "Contains function manipulation methods."
4550
+
4551
+ license:
4552
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
4553
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
4554
+
4555
+ requires:
4556
+ - Core
4557
+ - Types.Array
4558
+
4559
+ provides: Types.Function
4560
+
4561
+ ...
4562
+ */
4563
+
4564
+ atom.fn = {
4565
+ lambda: function (value) {
4566
+ var returnThis = (arguments.length == 0);
4567
+ return function () { return returnThis ? this : value; };
4568
+ },
4569
+
4570
+ after: function (onReady, fnName) {
4571
+ var after = {}, ready = {};
4572
+ function checkReady (){
4573
+ for (var i in after) if (!ready[i]) return;
4574
+ onReady(ready);
4575
+ }
4576
+ slice.call(arguments, 1).forEach(function (key) {
4577
+ after[key] = function () {
4578
+ ready[key] = slice.call(arguments);
4579
+ ready[key].context = this;
4580
+ checkReady();
4581
+ };
4582
+ });
4583
+ return after;
4584
+ }
4585
+ };
4586
+
4587
+
4588
+ /*
4589
+ ---
4590
+
4591
+ name: "Prototypes.Function"
4592
+
4593
+ description: "Contains Function Prototypes like after, periodical and delay."
4594
+
4595
+ license:
4596
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
4597
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
4598
+
4599
+ requires:
4600
+ - Core
4601
+ - Types.Function
4602
+ - Prototypes.Abstract
4603
+
4604
+ provides: Prototypes.Function
4605
+
4606
+ ...
4607
+ */
4608
+
4609
+ new function () {
4610
+
4611
+ Function.lambda = atom.fn.lambda;
4612
+
4613
+ function timer (periodical) {
4614
+ var set = periodical ? setInterval : setTimeout;
4615
+
4616
+ return function (time, bind, args) {
4617
+ var fn = this;
4618
+ return set(function () {
4619
+ fn.apply( bind, args || [] );
4620
+ }, time);
4621
+ };
4622
+ }
4623
+
4624
+ coreAppend(Function.prototype, {
4625
+ after: prototypize.fn(atom.fn)('after'),
4626
+ delay : timer(false),
4627
+ periodical: timer(true )
4628
+ });
4629
+
4630
+ }();
4631
+
4632
+
4633
+ /*
4634
+ ---
4635
+
4636
+ name: "Types.Math"
4637
+
4638
+ description: ""
4639
+
4640
+ license:
4641
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
4642
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
4643
+
4644
+ requires:
4645
+ - Core
4646
+
4647
+ provides: Types.Math
4648
+
4649
+ ...
4650
+ */
4651
+
4652
+ (function () {
4653
+
4654
+ var
4655
+ degree = Math.PI / 180,
4656
+ deg360 = Math.PI * 2;
4657
+
4658
+ atom.math = {
4659
+
4660
+ DEGREE360: deg360,
4661
+
4662
+ /**
4663
+ * Cast degrees to radians
4664
+ * atom.math.degree(90) == Math.PI/2
4665
+ */
4666
+ degree: function (degrees) {
4667
+ return degrees * degree;
4668
+ },
4669
+
4670
+ /**
4671
+ * Cast radians to degrees
4672
+ * atom.math.getDegree(Math.PI/2) == 90
4673
+ */
4674
+ getDegree: function (radians, round) {
4675
+ radians /= degree;
4676
+
4677
+ return round ? Math.round(radians) : radians;
4678
+ },
4679
+ normalizeAngle : function (radians) {
4680
+ radians %= deg360;
4681
+
4682
+ return radians + ( radians < 0 ? deg360 : 0 );
4683
+ },
4684
+
4685
+ hypotenuse: function (cathetus1, cathetus2) {
4686
+ return Math.sqrt(cathetus1*cathetus1 + cathetus2*cathetus2);
4687
+ },
4688
+ cathetus: function (hypotenuse, cathetus2) {
4689
+ return Math.sqrt(hypotenuse*hypotenuse - cathetus2*cathetus2);
4690
+ }
4691
+ };
4692
+
4693
+ })();
4694
+
4695
+
4696
+ /*
4697
+ ---
4698
+
4699
+ name: "Prototypes.Number"
4700
+
4701
+ description: "Contains Number Prototypes like limit, round, times, and ceil."
4702
+
4703
+ license:
4704
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
4705
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
4706
+
4707
+ requires:
4708
+ - Types.Number
4709
+ - Types.Math
4710
+ - Prototypes.Abstract
4711
+
4712
+ provides: Prototypes.Number
4713
+
4714
+ ...
4715
+ */
4716
+
4717
+ prototypize
4718
+ .own(Number, atom.number, 'random randomFloat')
4719
+ .proto(Number, prototypize.fn(atom.number), 'between equals limit round stop' )
4720
+ .proto(Number, prototypize.fn(atom.math ), 'degree getDegree normalizeAngle' );
4721
+
4722
+ coreAppend(Number.prototype, {
4723
+ toFloat: function(){
4724
+ return parseFloat(this);
4725
+ },
4726
+ toInt: function(base){
4727
+ return parseInt(this, base || 10);
4728
+ }
4729
+ });
4730
+
4731
+ 'abs acos asin atan atan2 ceil cos exp floor log max min pow sin sqrt tan'
4732
+ .split(' ')
4733
+ .forEach(function(method) {
4734
+ if (Number[method]) return;
4735
+
4736
+ Number.prototype[method] = function() {
4737
+ return Math[method].apply(null, [this].append(arguments));
4738
+ };
4739
+ });
4740
+
4741
+
4742
+ /*
4743
+ ---
4744
+
4745
+ name: "Prototypes.Object"
4746
+
4747
+ description: "Object generic methods"
4748
+
4749
+ license:
4750
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
4751
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
4752
+
4753
+ requires:
4754
+ - Types.Object
4755
+
4756
+ provides: Prototypes.Object
4757
+
4758
+ ...
4759
+ */
4760
+
4761
+ coreAppend(Object, atom.object);
4762
+
4763
+ /*
4764
+ ---
4765
+
4766
+ name: "Types.String"
4767
+
4768
+ description: "Contains string-manipulation methods like repeat, substitute, replaceAll and begins."
4769
+
4770
+ license:
4771
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
4772
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
4773
+
4774
+ requires:
4775
+ - Core
4776
+
4777
+ provides: Types.String
4778
+
4779
+ ...
4780
+ */
4781
+
4782
+ new function () {
4783
+
4784
+ var UID = Date.now();
4785
+
4786
+ atom.string = {
4787
+ /**
4788
+ * @returns {string} - unique for session value in 36-radix
4789
+ */
4790
+ uniqueID: function () {
4791
+ return (UID++).toString(36);
4792
+ },
4793
+ /**
4794
+ * escape all html unsafe characters - & ' " < >
4795
+ * @param {string} string
4796
+ * @returns {string}
4797
+ */
4798
+ safeHtml: function (string) {
4799
+ return string.replaceAll(/[<'&">]/g, {
4800
+ '&' : '&amp;',
4801
+ '\'' : '&#039;',
4802
+ '\"' : '&quot;',
4803
+ '<' : '&lt;',
4804
+ '>' : '&gt;'
4805
+ });
4806
+ },
4807
+ /**
4808
+ * repeat string `times` times
4809
+ * @param {string} string
4810
+ * @param {int} times
4811
+ * @returns {string}
4812
+ */
4813
+ repeat: function(string, times) {
4814
+ return new Array(times + 1).join(string);
4815
+ },
4816
+ /**
4817
+ * @param {string} string
4818
+ * @param {Object} object
4819
+ * @param {RegExp} [regexp=null]
4820
+ * @returns {string}
4821
+ */
4822
+ substitute: function(string, object, regexp){
4823
+ return string.replace(regexp || /\\?\{([^{}]+)\}/g, function(match, name){
4824
+ return (match[0] == '\\') ? match.slice(1) : (object[name] == null ? '' : object[name]);
4825
+ });
4826
+ },
4827
+ /**
4828
+ * @param {string} string
4829
+ * @param {Object|RegExp|string} find
4830
+ * @param {Object|string} [replace=null]
4831
+ * @returns {String}
4832
+ */
4833
+ replaceAll: function (string, find, replace) {
4834
+ if (toString.call(find) == '[object RegExp]') {
4835
+ return string.replace(find, function (symb) { return replace[symb]; });
4836
+ } else if (typeof find == 'object') {
4837
+ for (var i in find) string = string.replaceAll(i, find[i]);
4838
+ return string;
4839
+ }
4840
+ return string.split(find).join(replace);
4841
+ },
4842
+ /**
4843
+ * Checks if string contains such substring
4844
+ * @param {string} string
4845
+ * @param {string} substr
4846
+ */
4847
+ contains: function (string, substr) {
4848
+ return string ? string.indexOf( substr ) >= 0 : false;
4849
+ },
4850
+ /**
4851
+ * Checks if string begins with such substring
4852
+ * @param {string} string
4853
+ * @param {string} substring
4854
+ * @param {boolean} [caseInsensitive=false]
4855
+ * @returns {boolean}
4856
+ */
4857
+ begins: function (string, substring, caseInsensitive) {
4858
+ if (!string) return false;
4859
+ return (!caseInsensitive) ? substring == string.substr(0, substring.length) :
4860
+ substring.toLowerCase() == string.substr(0, substring.length).toLowerCase();
4861
+ },
4862
+ /**
4863
+ * Checks if string ends with such substring
4864
+ * @param {string} string
4865
+ * @param {string} substring
4866
+ * @param {boolean} [caseInsensitive=false]
4867
+ * @returns {boolean}
4868
+ */
4869
+ ends: function (string, substring, caseInsensitive) {
4870
+ if (!string) return false;
4871
+ return (!caseInsensitive) ? substring == string.substr(string.length - substring.length) :
4872
+ substring.toLowerCase() == string.substr(string.length - substring.length).toLowerCase();
4873
+ },
4874
+ /**
4875
+ * Uppercase first character
4876
+ * @param {string} string
4877
+ * @returns {string}
4878
+ */
4879
+ ucfirst : function (string) {
4880
+ return string ? string[0].toUpperCase() + string.substr(1) : '';
4881
+ },
4882
+ /**
4883
+ * Lowercase first character
4884
+ * @param {string} string
4885
+ * @returns {string}
4886
+ */
4887
+ lcfirst : function (string) {
4888
+ return string ? string[0].toLowerCase() + string.substr(1) : '';
4889
+ }
4890
+ };
4891
+
4892
+ }();
4893
+
4894
+ /*
4895
+ ---
4896
+
4897
+ name: "Prototypes.String"
4898
+
4899
+ description: "Contains String Prototypes like repeat, substitute, replaceAll and begins."
4900
+
4901
+ license:
4902
+ - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
4903
+ - "[MIT License](http://opensource.org/licenses/mit-license.php)"
4904
+
4905
+ requires:
4906
+ - Types.String
4907
+ - Prototypes.Abstract
4908
+
4909
+ provides: Prototypes.String
4910
+
4911
+ ...
4912
+ */
4913
+
4914
+ prototypize.proto(String, prototypize.fn(atom.string),
4915
+ 'safeHtml repeat substitute replaceAll contains begins ends ucfirst lcfirst'
4916
+ );
4917
+
4918
+ }.call(typeof exports == 'undefined' ? window : exports, Object, Array));