atomjs-rails 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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));