├── .gitignore ├── .gitmodules ├── Docs └── En │ ├── Accessors.md │ ├── Ajax.md │ ├── Class │ ├── Class.md │ ├── Events.md │ ├── Mutators │ │ └── Generators.md │ └── Options.md │ ├── Cookie.md │ ├── Core.md │ ├── CoreExtended.md │ ├── Declare │ ├── Animatable.md │ ├── Color.md │ ├── Declare.md │ ├── Events.md │ ├── ImagePreloader.md │ ├── Keyboard.md │ ├── Settings.md │ ├── Trace.md │ ├── Transition.md │ └── transition-graph.png │ ├── Dom.md │ ├── Frame.md │ ├── PointerLock.md │ ├── Prototypes │ ├── Array.md │ ├── Function.md │ ├── Number.md │ ├── Object.md │ └── String.md │ ├── Types │ ├── Array.md │ ├── Function.md │ ├── Math.md │ ├── Number.md │ ├── Object.md │ └── String.md │ └── Uri.md ├── README.md ├── Source ├── Accessors.js ├── Ajax.Dom.js ├── Ajax.js ├── Class │ ├── BindAll.js │ ├── Class.js │ ├── Events.js │ ├── Generators.js │ └── Options.js ├── Cookie.js ├── Core.js ├── CoreExtended.js ├── Declare │ ├── Animatable.js │ ├── ClassCompat.js │ ├── Color.js │ ├── Declare.js │ ├── Events.js │ ├── ImagePreloader.js │ ├── Keyboard.js │ ├── Registry.js │ ├── Settings.js │ ├── Trace.js │ └── Transition.js ├── Dom.js ├── Frame.js ├── Js185.js ├── PointerLock.js ├── Prototypes │ ├── Abstract.js │ ├── Array.js │ ├── Function.js │ ├── Number.js │ ├── Object.js │ └── String.js ├── Types │ ├── Array.js │ ├── Function.js │ ├── Math.js │ ├── Number.js │ ├── Object.js │ └── String.js ├── Uri.js ├── atom.css ├── overall.js └── package.yml ├── Tests ├── cells.png ├── index.html ├── lib │ ├── jquery.js │ ├── qunit.css │ └── qunit.js ├── tests │ ├── class.js │ ├── color.js │ ├── core.js │ ├── declare.js │ ├── dom.js │ ├── mootools.js │ ├── prototypes.js │ └── uri.js └── visual-tests.html ├── atom-full-compiled.js └── build /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.iml -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Packager"] 2 | path = Packager 3 | url = git@github.com:theshock/packager.git 4 | -------------------------------------------------------------------------------- /Docs/En/Accessors.md: -------------------------------------------------------------------------------- 1 | Atom Accessors 2 | ============== 3 | 4 | ## atom.accessors.has(object, prop) 5 | 6 | Checks if `object` has getter or setter for property `prop` as own property, or in prototype chain 7 | 8 | #### Example: 9 | var object = { 10 | set foo () {} 11 | }; 12 | 13 | atom.accessors.has(object, 'foo'); // true 14 | atom.accessors.has(object, 'bar'); // false 15 | 16 | ## atom.accessors.define(object, prop, value) 17 | 18 | Defines setter or getter of `object` with name `prop` 19 | 20 | #### Example: 21 | var object = {}; 22 | 23 | atom.accessors.define(object, 'foo', { 24 | set: function (value) { console.log('object.foo Setter'); ) 25 | get: function () { console.log('object.foo Getter'); ) 26 | }); 27 | 28 | object.foo = 123; // object.foo Setter 29 | object.foo + 123; // object.foo Getter 30 | 31 | ## atom.accessors.lookup(object, prop) 32 | 33 | Get accessors from `object` with name `prop` 34 | 35 | #### Examples: 36 | var object = { 37 | set foo(value) { console.log('object.foo Setter'); ), 38 | get foo() { console.log('object.foo Getter'); ), 39 | 40 | bar: 123 41 | }; 42 | 43 | console.log(atom.accessors.lookup(object, 'bar')); // null 44 | 45 | var accessors = atom.accessors.lookup(object, 'foo'); 46 | /* accessors equals to object: 47 | * { 48 | * set: function (value) { console.log('object.foo Setter'); ) 49 | * get: function () { console.log('object.foo Getter'); ) 50 | * } 51 | */ 52 | 53 | ## atom.accessors.inherit(from, to, prop) 54 | Inherit accessors from `from` to `to` with name `prop` and return `true`, or return `false` 55 | 56 | var Parent = { 57 | get foo() { return 'Parent.foo'; }, 58 | bar: 'Parent.bar' 59 | }; 60 | 61 | var Child = {}; 62 | 63 | atom.accessors.inherit(Parent, Child, 'foo'); // true 64 | atom.accessors.inherit(Parent, Child, 'bar'); // false 65 | 66 | /* accessors equals to: 67 | * { 68 | * get foo() { return 'Parent.foo'; } 69 | * } 70 | */ -------------------------------------------------------------------------------- /Docs/En/Ajax.md: -------------------------------------------------------------------------------- 1 | Atom AJAX 2 | ========= 3 | 4 | atom.ajax(config); 5 | 6 | #### Config parameters: 7 | 8 | * `interval`: 0. Repeat every `interval` seconds if it's greater than 0 9 | * `type`: `'plain'`. One of `'plain'` or `'json'` (response automatically parsed as JSON) 10 | * `method`: `'post'`. One of `'post'`, `'get'`, `'put'`, `'delete'` 11 | * `data`: `{}`. 12 | * `cache`: `false`. Disabling blowser cache: `cache:false` 13 | * `url`: `location.href`. Request url 14 | * `onLoad`: callback 15 | * `onError`: callback 16 | 17 | #### Example: 18 | 19 | atom.ajax({ 20 | type : 'json', 21 | method : 'get', 22 | url : 'test.php', 23 | data : { 'hello': 'world' }, 24 | cache : true, 25 | onLoad : function (json) { 26 | atom.log(json); 27 | }, 28 | onError: function () { 29 | atom.log('error'); 30 | } 31 | }); 32 | 33 | **Note:** if you're declare `onLoad()` function, then you function will be override default `onLoad()` and response text will not be added, like he did it default. 34 | 35 | # Atom.Plugins.Ajax + Atom.Plugins.Dom 36 | 37 | atom.dom('#newMsgs').ajax({ // update html of #newMsgs 38 | interval : 15, // every 15 seconds 39 | url : 'newMsgs.php' 40 | }); 41 | -------------------------------------------------------------------------------- /Docs/En/Class/Class.md: -------------------------------------------------------------------------------- 1 | # atom.Class 2 | 3 | Wrapper for native prototype-based OOP 4 | 5 | ### Base class creating 6 | var NameLogger = atom.Class({ 7 | log : function (msg) { 8 | atom.log(this.name, msg); 9 | return this; 10 | } 11 | }); 12 | 13 | ### Class creating with constuctor, static variable 14 | var Animal = atom.Class({ 15 | Extends: NameLogger, 16 | Static: { 17 | staticProperty: 'animal' 18 | }, 19 | initialize : function (name) { 20 | this.name = name; 21 | this.log('Animal.initialize'); 22 | }, 23 | walk : function () { 24 | this.log('Animal.walk'); 25 | } 26 | }); 27 | 28 | ### Extending classes 29 | var Dog = atom.Class({ 30 | Extends: Animal, 31 | initialize : function (name, breed) { 32 | this.parent(name); 33 | this.breed = breed; 34 | this.log('Dog.initialize'); 35 | }, 36 | bark : function () { 37 | return this.log('Dog.bark'); 38 | }, 39 | logStatic : function () { 40 | this.log(this.self.staticProperty); 41 | }, 42 | isSelf : function () { 43 | return this instanceof this.self; // always true 44 | } 45 | }); 46 | 47 | ### using 48 | var dog = new Dog('Box', 'shepherd'); 49 | dog.bark(); 50 | dog.walk(); 51 | atom.log(dog instanceof Animal); // true 52 | atom.log(dog instanceof Dog); // true 53 | 54 | ### Factory method: 55 | var cat = Animal.factory(['Tom']); 56 | var dog = Dog.factory(['Max', 'dalmatian']); 57 | 58 | ### Invoking Class 59 | You can invoke your Class without `new`. As default it just creates new instance: 60 | 61 | var MyClass = atom.Class({}); 62 | 63 | new MyClass(5, 42); 64 | // similar to 65 | MyClass(5, 42); 66 | 67 | But you can change this behaviour, changing Static method `invoke`: 68 | 69 | var MyClass = atom.Class({ 70 | Static: { 71 | invoke: function (first, second) { 72 | alert( first + second ); 73 | return this.factory( arguments ); 74 | } 75 | } 76 | }); 77 | 78 | // Just creates new instance: 79 | var mc = new MyClass(5, 42); 80 | 81 | // Alerts 47, than create instance 82 | var mc = MyClass(5, 42); 83 | 84 | You even can create width this way instances of another class: 85 | 86 | var Foo = atom.Class({}); 87 | 88 | var Bar = atom.Class({ 89 | Static: { 90 | invoke: function () { 91 | return Foo.factory( arguments ); 92 | } 93 | } 94 | }); 95 | 96 | var bar = new Bar(); 97 | var foo = Bar(); 98 | 99 | console.log( 100 | bar instanceof Bar, // true 101 | bar instanceof Foo, // false 102 | foo instanceof Bar, // false 103 | foo instanceof Foo // true 104 | ); 105 | 106 | ### Properties 107 | `self` You can use property "self" to get the link to the class as in methods `logStatic` and `isSelf` 108 | 109 | `parent` You can use method `parent` to call method with the same name of the parent 110 | 111 | `factory` You can use static factory property to create instance of object with array of arguments 112 | 113 | new Point(3, 8); 114 | // equals to 115 | Point.factory([3, 8]); 116 | 117 | *note*: `self`, `parent` & `factory` are reserved properties and you can't override them 118 | 119 | ### Methods 120 | Available some methods helpers: 121 | 122 | `abstractMethod`, which thrown mistake if is not overriden 123 | 124 | `protectedMethod`, which can be called only with parents 125 | 126 | `hiddenMethod`, which not implemented in children (not equals to private) 127 | 128 | var MyClass = atom.Class({ 129 | abstr: atom.Class.abstractMethod, 130 | 131 | initialize: atom.Class.hiddenMethod(function () { 132 | atom.log('initilize will not be implemented by children (hidden)'); 133 | }), 134 | 135 | prot: atom.Class.protectedMethod(function() { 136 | atom.log('this is protected method'); 137 | }) 138 | }); 139 | 140 | ### Accessors 141 | You can use accessors! 142 | 143 | var Foo = atom.Class({ 144 | _bar: 0, 145 | set bar (value) { 146 | this._bar = value * 2; 147 | }, 148 | get bar () { 149 | return 'Foo.bar: ' + this._bar; 150 | } 151 | }); 152 | 153 | var foo = new Foo; 154 | foo.bar = 21; 155 | log(foo.bar); // 'Foo.bar: 42' 156 | 157 | ### Expanding prototype, no reset 158 | Unlike the MooTools we dont reset each object. So the objects are links in prototype: 159 | 160 | var MyClass = atom.Class({ 161 | settings: {}, 162 | initialize: function (width, height) { 163 | this.settings.width = width; 164 | this.settings.height = height; 165 | } 166 | }); 167 | 168 | var small = new MyClass(100, 100); 169 | var big = new MyClass(555, 555); 170 | 171 | atom.log(small.settings. == big.settings); // true 172 | atom.log(small.settings.width, small.settings.height); // (555, 555) 173 | 174 | So, use constructor object creating instead: 175 | 176 | var MyClass = atom.Class({ 177 | initialize: function (width, height) { 178 | this.settings = {}; 179 | this.settings.width = width; 180 | this.settings.height = height; 181 | } 182 | }); 183 | 184 | var small = new MyClass(100, 100); 185 | var big = new MyClass(555, 555); 186 | 187 | atom.log(small.settings. == big.settings); // false 188 | atom.log(small.settings.width, small.settings.height); // (100, 100), as expected 189 | 190 | # Default Mutators 191 | 192 | ### Static 193 | Let you to add static properties: 194 | 195 | MyClass = atom.Class({ 196 | Static: { 197 | staticProperty: 15, 198 | staticMethod : function () { return 88; } 199 | } 200 | }); 201 | 202 | atom.log(MyClass.staticProperty); // 15 203 | atom.log(MyClass.staticMethod()); // 88 204 | 205 | ### Extends 206 | Let you to extends one class from another. You can call `parent` to access method with same name of parent class. 207 | Unlimited nesting is available. Accessors are implemented, but you can't call `parent` from them 208 | 209 | var Foo = atom.Class({ 210 | initialize: function () { 211 | log('Foo.initialize'); 212 | }, 213 | fooMethod: function () { 214 | log('Foo.fooMethod'); 215 | }, 216 | genMethod: function (arg) { 217 | log('genMethod: ' + arg); 218 | }, 219 | get accessor () { 220 | return 100; 221 | } 222 | }); 223 | 224 | var Bar = atom.Class({ 225 | Extends: Foo, 226 | initialize: function () { 227 | this.parent(); // 'Foo.initialize' 228 | log('Bar.initialize'); 229 | this.fooMethod(); // 'Foo.fooMethod' 230 | }, 231 | genMethod: function () { 232 | this.parent(42); // 'genMethod: 42' 233 | alert(this.accessor); // 100 234 | } 235 | }); 236 | 237 | var Qux = atom.Class({ 238 | Extends: Bar, 239 | initialize: function () { 240 | this.parent(); // 'Foo.initialize', 'Bar.initialize' 241 | log('Qux.initialize'); 242 | }, 243 | get accessor () { 244 | return this.parent() + 1; // Error 245 | } 246 | }); 247 | 248 | var foo = new Foo(); 249 | var qux = new Qux(); 250 | 251 | foo instanceof Foo; // true 252 | foo instanceof Qux; // false 253 | 254 | qux instanceof Foo; // true 255 | qux instanceof Qux; // true 256 | 257 | ### Implements 258 | Let you mixin properties from some classes. You can't access mixin properties using "parent" 259 | 260 | Bar = atom.Class({ 261 | barMethod: function () { 262 | log('Bar.barMethod'); 263 | } 264 | }); 265 | Qux = atom.Class({ 266 | quxMethod: function () { 267 | log('Qux.quxMethod'); 268 | } 269 | }); 270 | 271 | Foo = atom.Class({ 272 | Implements: [ Bar, Qux ], 273 | fooMethod: function () { 274 | log('Foo.fooMethod'); 275 | this.quxMethod(); // 'Qux.quxMethod' 276 | }, 277 | barMethod: function () { 278 | this.parent(); // Error('The method «barMethod» has no parent.'); 279 | } 280 | }); 281 | 282 | var foo = new Foo; 283 | foo instanceof Foo; // true 284 | foo instanceof Bar; // false 285 | foo instanceof Qux; // false 286 | 287 | -------------------------------------------------------------------------------- /Docs/En/Class/Events.md: -------------------------------------------------------------------------------- 1 | # atom.Class.Events 2 | 3 | Let you add and fire event, linked with current object 4 | 5 | #### method addEvent 6 | addEvent(string name, function fn) 7 | 8 | Using this method you can add events to eventable object 9 | 10 | #### method removeEvent 11 | removeEvent(string name, function fn) 12 | 13 | Using this method you can remove events from eventable object 14 | 15 | #### method fireEvent 16 | fireEvent(string name, array arguments) 17 | 18 | Using this method you can fire events in eventable object 19 | 20 | #### method readyEvent 21 | readyEvent(string name, array arguments) 22 | 23 | Using this method you can fire event in eventable object and automaticaly fire it on during all next "addEvent" (as image.onload) 24 | 25 | ### Base examples 26 | 27 | MyClass = atom.Class({ 28 | Implements: [ atom.Class.Events ] 29 | }); 30 | 31 | var my = new MyClass; 32 | 33 | 34 | // We listen 2 events: 35 | my.addEvent('foo', function ( firstArg ) { 36 | alert(firstArg); 37 | }); 38 | my.addEvent('bar', atom.log); 39 | 40 | // event `foo` fired 41 | my.fireEvent('foo'); 42 | // event `bar` fired 43 | my.fireEvent('bar'); 44 | 45 | // we don't listen `bar` event now 46 | me.removeEvent('bar', atom.log); 47 | 48 | ### readyEvent examples 49 | readyEvent used for once runable events. E.g. it can be application initialize or image loaded 50 | 51 | Application = atom.Class({ 52 | Implements: [ atom.Class.Events ], 53 | initialize: function (src) { 54 | this.image = new Image; 55 | this.image.onload = function () { 56 | this.readyEvent('ready'); 57 | }.bind(this); 58 | this.image.src = src; 59 | } 60 | }); 61 | 62 | var app = new Application('test'); 63 | app.addEvent('ready', function () { 64 | alert('image loaded and application is ready'); 65 | }); 66 | 67 | -------------------------------------------------------------------------------- /Docs/En/Class/Mutators/Generators.md: -------------------------------------------------------------------------------- 1 | # atom.Class.Mutators.Generators 2 | 3 | Used to DRY such pattern: 4 | 5 | MyClass = atom.Class({ 6 | _property: null, 7 | get property () { 8 | if (this._property == null) { 9 | this._property = countValue(); 10 | } 11 | return this._property; 12 | } 13 | }); 14 | 15 | You can use Generators mutators instead (it will be counted only once): 16 | 17 | MyClass = atom.Class({ 18 | Generators: { 19 | property: function () { 20 | return countValue(); 21 | } 22 | } 23 | }); -------------------------------------------------------------------------------- /Docs/En/Class/Options.md: -------------------------------------------------------------------------------- 1 | # atom.Class.Options 2 | 3 | Let you add options property to your class 4 | 5 | MyClass = atom.Class({ 6 | Implements: [ atom.Class.Options ], 7 | options : { // default options 8 | foo: 15, 9 | bar: 42 10 | } 11 | }); 12 | 13 | var my = new MyClass(); 14 | 15 | my.setOptions({ 16 | foo: 3, 17 | qux: 100 18 | }); 19 | 20 | atom.log(my.options); // {foo: 3, bar: 42, qux: 100} 21 | 22 | *note* never set options property, or one of the option directly. Always use `setOptions` for it. 23 | 24 | You can add several arguments to `setOptions`, which will be apply one-by-one 25 | 26 | MyClass = atom.Class({ 27 | Implements: [ atom.Class.Options ] 28 | }); 29 | 30 | var my = MyClass.factory(); 31 | my.setOptions({ a: 15 }, { b: 33 }); 32 | atom.log(my.options); // { a: 15, b: 33 }; 33 | 34 | ### With events 35 | 36 | When class also implement `atom.Class.Events` - you can set events using `on*` 37 | 38 | MyClass = atom.Class({ 39 | Implements: [ 40 | atom.Class.Options, 41 | atom.Class.Events 42 | ] 43 | }); 44 | 45 | var my = new MyClass; 46 | 47 | my.setOptions({ 48 | onClick: atom.log 49 | }); 50 | 51 | // equals to 52 | 53 | my.addEvent('click', atom.log); -------------------------------------------------------------------------------- /Docs/En/Cookie.md: -------------------------------------------------------------------------------- 1 | Atom Cookie 2 | =================== 3 | 4 | 5 | ### atom.cookie.get(name) 6 | Returns value of cookie `name` or `null` if not exists 7 | 8 | var testCookie = atom.cookie.get('test'); 9 | 10 | ### atom.cookie.set(name, value, options) 11 | 12 | Sets value of cookie, returns link to `atom.cookie` 13 | 14 | * `name` (*string*) cookie title 15 | 16 | * `value` (*string*) cookie value 17 | 18 | * `options` (*mixed*) additional options for cookie: 19 | 20 | * `expires` (*number|date*) Cookie expires, can be time in seconds, left to expire, or Date object 21 | * `path` (*string*) cookie path 22 | * `domain` (*string*) cookie domain 23 | * `secure` (*boolean*) secure connection 24 | 25 | #### example: 26 | 27 | atom.cookie 28 | .set('first' , 1) 29 | .set('second', 2); 30 | 31 | 32 | ### atom.cookie.del(name) 33 | Delete cookie with name `name` and returns `atom.cookie` 34 | 35 | atom.cookie 36 | .del('first') 37 | .del('second'); -------------------------------------------------------------------------------- /Docs/En/Core.md: -------------------------------------------------------------------------------- 1 | Atom Core 2 | ========= 3 | 4 | * title: ore 5 | * group: core 6 | 7 | 8 | ## atom.core.isFunction(fn) 9 | 10 | Checks if `fn` is function 11 | 12 | if (atom.core.isFunction(object.method)) { 13 | object.method(); 14 | } 15 | 16 | ## atom.core.objectize(key, value) 17 | 18 | If `key` is not object - returns object, where `key` is single key & `value` is value of this key. 19 | Else - returns `key` 20 | 21 | atom.core.objectize( 'test', 'foo' ); // { test: 'foo' ) 22 | atom.core.objectize({ test: 'foo' }); // { test: 'foo' ) 23 | 24 | Can be used, when you what to be sure, you works with object: 25 | 26 | method: function (callback, nameOrHash, value) { 27 | var hash = atom.core.objectize(nameOrHash, value); 28 | for (var i in hash) { 29 | // do 30 | } 31 | } 32 | 33 | ## atom.core.contains(array, value) 34 | 35 | Checks is array contains value. Is similar to `array.indexOf(value) != -1` 36 | 37 | if (atom.core.contains(['first', 'second'], value)) { 38 | // do smth 39 | } 40 | 41 | ## atom.core.includeUnique(array, value) 42 | 43 | Push `value` to `array` if it doesn't contains it; 44 | 45 | atom.core.includeUnique( [1,2,3], 1 ); // [1,2,3 ] 46 | atom.core.includeUnique( [1,2,3], 4 ); // [1,2,3,4] 47 | 48 | ## atom.core.eraseOne(array, value) 49 | 50 | Erase first `value` from `array` 51 | 52 | atom.core.eraseOne( [1,2,3,2,1], 2 ); // [1,3,2,1] 53 | 54 | ## atom.core.eraseAll(array, value) 55 | 56 | Erase all `value` from `array` 57 | 58 | atom.core.eraseAll( [1,2,3,2,1], 2 ); // [1,3,1] 59 | 60 | ## atom.core.toArray(arrayLikeObject) 61 | 62 | Cast `arrayLikeObject` (array, DomCollection, arguments) to `Array` 63 | 64 | var args = atom.core.toArray(arguments); 65 | 66 | ## atom.core.isArrayLike(object) 67 | 68 | Checks if `object` is arrayLike 69 | 70 | if (atom.core.isArrayLike(object)) { 71 | for (var i = 0; i < object.length; i++) { 72 | // do 73 | } 74 | } 75 | 76 | ## atom.core.append(target, source) 77 | 78 | Append all properties from sourceto target 79 | 80 | var target = { a: 1 }; 81 | var source = { b: 2 }; 82 | atom.core.append( target, source ); 83 | console.log(target); // { a: 1, b: 2 } 84 | 85 | 86 | 87 | 88 | JavaScript 1.8.5 Compatiblity 89 | ============================= 90 | 91 | Browsers, which do not have JavaScript 1.8.5 compatibility, will get those methods implemented: 92 | 93 | * [Function.prototype.bind](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind) 94 | * [Object.keys](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys) 95 | * [Array.isArray](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray) 96 | -------------------------------------------------------------------------------- /Docs/En/CoreExtended.md: -------------------------------------------------------------------------------- 1 | Atom Extended Core 2 | ================== 3 | 4 | ## atom.extend(object = atom, from) 5 | 6 | Extend `object` with `from` properties. 7 | 8 | #### Example: config 9 | config = atom.core.extend({ 10 | // default values for config 11 | a : 15, 12 | b : 20 13 | }, config); 14 | 15 | #### Example: extending atom 16 | atom.core.extend({ 17 | value: 123 18 | }); 19 | alert(atom.value); // 123 20 | 21 | 22 | ## atom.core.implement(object = atom, from) 23 | 24 | Extend `object.prototype` with `from` properties. 25 | 26 | #### Example: class extends 27 | atom.core.implement(child, parent); 28 | 29 | #### Example: expanding atom 30 | atom.core.implement({ 31 | test: function () { 32 | alert(123); 33 | } 34 | }); 35 | var a = atom(); 36 | a.test(); // 123 37 | 38 | ## atom.clone(object) 39 | Returns clone of object 40 | 41 | var cloneArray = atom.core.clone(oldArray); 42 | 43 | ## atom.typeOf(object) 44 | Returns type of object: 45 | 46 | atom.core.typeOf( document.body ) == 'element' 47 | atom.core.typeOf( function(){} ) == 'function' 48 | atom.core.typeOf( new Date() ) == 'date' 49 | atom.core.typeOf( null ) == 'null' 50 | atom.core.typeOf( arguments ) == 'arguments' 51 | atom.core.typeOf( /abc/i ) == 'regexp' 52 | atom.core.typeOf( [] ) == 'array' 53 | atom.core.typeOf( {} ) == 'object' 54 | atom.core.typeOf( 15 ) == 'number' 55 | atom.core.typeOf( true ) == 'boolean' 56 | 57 | var MyClass = atom.Class({}); 58 | atom.core.typeOf( new MyClass() ) == 'class' -------------------------------------------------------------------------------- /Docs/En/Declare/Animatable.md: -------------------------------------------------------------------------------- 1 | atom.Animatable 2 | =============== 3 | 4 | `atom.Animatable` provides you the way to change properies of objects during time. 5 | 6 | var animatable = new atom.Animatable( targetObject ); 7 | 8 | ### get current 9 | 10 | Contains current animation 11 | 12 | var currentAnimation = animatable.current; 13 | 14 | ### animate 15 | 16 | atom.Animatable.Animation animate( object config ) 17 | 18 | Push new animation to stack & starts it when all previous animations will finish 19 | 20 | `Config` properies: 21 | * `props` - properies on object, you want to animate 22 | * `time` - time in seconds animation should continue 23 | * `fn` - `atom.Transition` method (`linear` is default) 24 | * `onTick` - callback, should be runned each property change 25 | * `onComplete` - callback, should be runned, when animation successfully complete 26 | * `onDestroy` - callback, should be runned, when animation complete 27 | 28 | First argument in callback is always `animation` 29 | 30 | ### stop 31 | 32 | atom.Animatable stop( boolean all ) 33 | 34 | Stops current animation if `all=false` & all animations if `all=true` 35 | 36 | animatable.stop( true ); 37 | 38 | atom.Animatable.Animation 39 | ========================= 40 | 41 | Private class, which represents animation. It returns by `atom.Animatable#animate` & shouldn't be created manual 42 | 43 | var animation = animatable.animate(animateConfig); 44 | 45 | ### Properties: 46 | 47 | * `transition` - animation transition function 48 | * `initial` - values of properties, object contains on animation start 49 | * `target` - animation target values of properties 50 | * `delta` - difference between source & target values 51 | * `allTime` - time, which animation should continue 52 | * `timeLeft` - time, animation left to continue 53 | 54 | atom.dom.animate 55 | ================ 56 | 57 | ### atom.dom().animate() 58 | 59 | Provides the way to animate dom properties 60 | 61 | atom.dom('div').animate({ width: 150 }); 62 | 63 | ### atom.dom().stopAnimation(all) 64 | 65 | Stops current animation 66 | 67 | atom.dom('div').stopAnimation(true); 68 | 69 | atom.Color 70 | ========== 71 | 72 | You can animate colors if `atom.Color` class used. 73 | 74 | var object = { color: 'red' }; 75 | 76 | new atom.Animatable( object ).animate({ color: 'blue' }); 77 | 78 | 79 | -------------------------------------------------------------------------------- /Docs/En/Declare/Color.md: -------------------------------------------------------------------------------- 1 | atom.Color 2 | ========== 3 | 4 | `atom.Color` allows you to manipulate with colors. 5 | 6 | ## Own: 7 | 8 | ### colorNames 9 | Set of color names & hex values 10 | 11 | * `#ffffff` - white 12 | * `#c0c0c0` - silver 13 | * `#808080` - gray 14 | * `#000000` - black 15 | * `#ff0000` - red 16 | * `#800000` - maroon 17 | * `#ffff00` - yellow 18 | * `#808000` - olive 19 | * `#00ff00` - lime 20 | * `#008000` - green 21 | * `#00ffff` - aqua 22 | * `#008080` - teal 23 | * `#0000ff` - blue 24 | * `#000080` - navy 25 | * `#ff00ff` - fuchsia 26 | * `#800080` - purple 27 | * `#ffa500` - orange 28 | 29 | ### atom.Color.isColorString( string string ); 30 | Checks if `string` is hex/rgba or color name 31 | 32 | atom.Color.isColorString( [42,0,13] ) // false 33 | atom.Color.isColorString( 'foobar' ) // false 34 | atom.Color.isColorString( '#dec0de' ) // true 35 | atom.Color.isColorString( 'red' ) // true 36 | 37 | ### random( bool html ) 38 | 39 | Returns `atom.Color` instance with random color value. 40 | If `html` is `true` - gets value only from `colorNames` 41 | 42 | atom.Color.random().toString('hex'); // #61f405 43 | 44 | ## Prototype 45 | 46 | ### constructing 47 | 48 | var color = new atom.Color( value ); 49 | 50 | Value can be array, object, string or number according to `from*` methods. 51 | 52 | ### from* methods 53 | 54 | #### fromArray( Array color ) 55 | Sets values , parsing array as `[ red, green, blue, alpha=1 ]`, where `alpha` is optional 56 | 57 | color.fromArray([ 41, 55, 231, 0.5 ]); 58 | 59 | 60 | #### fromObject( Object color ) 61 | Sets values from object keys `red, green, blue, alpha` 62 | 63 | color.fromObject({ 64 | red : 14, 65 | green: 63, 66 | blue : 151, 67 | alpha: 0.5 68 | }); 69 | 70 | #### fromString( String color ) 71 | Parse valid (`true` in `atom.Color.isColorString`) string as color: 72 | 73 | color.fromString( '#dead13' ); 74 | color.fromString( 'cyan' ); 75 | 76 | #### fromNumber( Number number ) 77 | Parse number as color string. Format is `0xRRGGBBAA` 78 | 79 | color.fromNumber( 0xDECODEFF ); 80 | 81 | Note that color `0xFFFF00` is not yellow, because it equals to `0x00FFFF00` - cyan color with zero alpha. Correct yellow color is `0xFFFF00FF` 82 | 83 | ### to* methods 84 | 85 | #### toArray() 86 | Returns array `[red, green, blue, alpha]` of color. E.G.: 87 | 88 | console.log( new atom.Color('orange').toArray() ); // [255, 165, 0, 1] 89 | 90 | #### toObject(abbreviationNames) 91 | Returns object `{red, green, blue, alpha}` of color. E.G.: 92 | 93 | console.log( new atom.Color('orange').toObject() ); // {red:255, green:165, blue:0, alpha:1} 94 | console.log( new atom.Color('orange').toObject(true) ); // {r:255, g:165, b:0, a:1} 95 | 96 | #### toString(type) 97 | Returns string '#RRGGBB' is `type=='hex'` &t 'rgba(red, green, blue, alpha)' if hex otherwise 98 | 99 | console.log( new atom.Color('orange').toString() ); // 'rgba(255,165,0,1)' 100 | console.log( new atom.Color('orange').toString('hex') ); // '#ffa500' 101 | 102 | #### toNumber() 103 | Returns number 104 | 105 | console.log( new atom.Color('orange').toNumber() ); // 4289003775 106 | console.log( new atom.Color('orange').toNumber() == 0xffa500ff ); // true 107 | 108 | 109 | ### properties 110 | 111 | This properties can get or set values of color with checking limits 112 | 113 | * `red` 114 | * `green` 115 | * `blue` 116 | * `alpha` 117 | 118 | var color = new atom.Color('orange'); 119 | color.red = -1000; 120 | color.blue = 1000; 121 | color.toArray(); // [0, 165, 255, 1] 122 | 123 | ### manipulations 124 | 125 | #### equals() 126 | Checks, if colors are similar. 127 | 128 | var a = new atom.Color('red'); 129 | var b = new atom.Color('#ff0000'); 130 | 131 | console.log( a == b ); // false 132 | console.log( a.equals(b) ); // true 133 | 134 | #### clone() 135 | Clones color 136 | 137 | var a = new atom.Color('red'); 138 | var b = a.clone(); 139 | 140 | console.log( a == b ); // false 141 | console.log( a.equals(b) ); // true 142 | 143 | b.green = 150; 144 | 145 | console.log( a.equals(b) ); // false 146 | 147 | -------------------------------------------------------------------------------- /Docs/En/Declare/Declare.md: -------------------------------------------------------------------------------- 1 | atom.declare 2 | ============ 3 | 4 | Light and fast wrapper for native prototype-based OOP. 5 | 6 | Function atom.declare( String declareName = null, Function parent = null, Object params = null ) 7 | Function atom.declare( Object params ) 8 | 9 | Each argument is optional. Returns constructor that can be called with "new". 10 | 11 | #### Example: 12 | 13 | var Foo = atom.declare({ 14 | fooMethod: function () {} 15 | }); 16 | 17 | var Bar = atom.declare( Foo ); 18 | 19 | ### params 20 | 21 | `params` object without `prototype` property is recognized as `prototype`, otherwise it is parsed with the following rules: 22 | 23 | * `name` - name of the resulting constructor and instances. Can be used for debugging, and is returned by `toString` method 24 | 25 | var C = atom.declare({ 26 | name: 'FooQux', 27 | prototype: {} 28 | }); 29 | console.log( new C().toString() ); // '[object FooQux]' 30 | 31 | * `declareName` - property created by library. Can be used for easy namespace creation. It will automaticaly create all nessesary objects 32 | 33 | atom.declare({ 34 | declareName: 'Foo.Qux.Bar', 35 | name: 'FQB', 36 | prototype: {} 37 | }); 38 | console.log( new Foo.Qux.Bar().toString() ); // '[object FQB]' 39 | 40 | * `prototype` - with object will be mixed to constructor prototype 41 | 42 | var Foo = atom.declare({ 43 | prototype: { 44 | fooMethod: function () { 45 | return 'Foo#fooMethod'; 46 | } 47 | } 48 | }); 49 | 50 | console.log( new Foo().fooMethod() ); // 'Foo#fooMethod' 51 | 52 | * `parent` - this constructor will be parent of result constructor 53 | 54 | var Foo = atom.declare({ 55 | prototype: { 56 | fooMethod: function () { 57 | return 'Foo#fooMethod'; 58 | } 59 | } 60 | }); 61 | var Bar = atom.declare({ 62 | parent: Foo, 63 | 64 | prototype: { 65 | barMethod: function () { 66 | return 'Bar#barMethod'; 67 | } 68 | } 69 | }); 70 | 71 | var foo = new Foo(); 72 | var bar = new Bar(); 73 | 74 | console.log( foo instanceof Foo ); // true 75 | console.log( foo instanceof Bar ); // false 76 | console.log( bar instanceof Foo ); // true 77 | console.log( bar instanceof Bar ); // true 78 | 79 | console.log( foo.fooMethod() ); // 'Foo#fooMethod' 80 | console.log( bar.fooMethod() ); // 'Foo#fooMethod' 81 | console.log( bar.barMethod() ); // 'Bar#barMethod' 82 | 83 | * `own` - this properties will be mixed to constructor as static: 84 | 85 | var Foo = atom.declare({ 86 | 87 | own: { fooProp: 'foo-static-prop' }, 88 | prototype: {} 89 | }); 90 | 91 | var Bar = atom.declare({ 92 | parent: Foo, 93 | own: { barProp: 'bar-static-prop' }, 94 | prototype: { } 95 | }); 96 | 97 | console.log( Foo.fooProp ); // 'foo-static-prop' 98 | console.log( Bar.fooProp ); // 'foo-static-prop' 99 | console.log( Bar.barProp ); // 'bar-static-prop' 100 | 101 | ### alternate constructor params 102 | 103 | You can use alternate optional constructor params. 104 | 105 | Function atom.declare( String declareName = null, Function parent = null, Object params = null ) 106 | 107 | * `declareName` - will set `name` & `declareName` of original params, so: 108 | 109 | atom.declare( 'Foo.Bar', { 110 | prototype: { test: 1241 } 111 | }); 112 | 113 | // equals to: 114 | 115 | atom.declare({ 116 | declareName: 'Foo.Bar', 117 | name: 'Foo.Bar', 118 | prototype: { test: 1241 } 119 | }); 120 | 121 | * `parent` - will set `parent` of original params, so: 122 | 123 | atom.declare( Foo ); 124 | 125 | // equals to: 126 | 127 | atom.declare({ 128 | parent: Foo, 129 | prototype: {} 130 | }); 131 | 132 | Also, you can skip `prototype` property in `params` if you want `params` to be `prototype`: 133 | 134 | atom.declare({ 135 | prototype: { 136 | foo: 123, 137 | bar: function () { 138 | return this.foo; 139 | } 140 | } 141 | }); 142 | 143 | // equals to: 144 | 145 | atom.declare({ 146 | foo: 123, 147 | bar: function () { 148 | return this.foo; 149 | } 150 | }); 151 | 152 | That's why if you want empty `prototype` - you should set it manualy: 153 | 154 | // wrong way: 155 | atom.declare({ 156 | own: {/* static methods here */} 157 | }); 158 | // it equals to: 159 | atom.declare({ 160 | prototype: { 161 | own: {/* static methods here */} 162 | } 163 | }); 164 | // right way: 165 | atom.declare({ 166 | own: {/* static methods here */}, 167 | prototype: {} 168 | }); 169 | 170 | ### static methods of result constructor: 171 | 172 | * `own` - will mixin properties as static to constructor: 173 | 174 | var Foo = atom.declare({}); 175 | Foo.own({ a: 123 }); 176 | console.log( Foo.a ); // 123 177 | 178 | * `factory` - will produce object from array of params. It can be used, if you want to construct object from array (as `.apply` method of function): 179 | 180 | Foo.factory( [42, 'string', {test: null}] ) 181 | // equals to: 182 | new Foo(42, 'string', {test: null}); 183 | 184 | ### initialize 185 | 186 | `initialize` method in prototype will be called on instance construction: 187 | 188 | var Foo = atom.declare({ 189 | initialize: function (id) { 190 | console.log( 'Foo#initialize', id ); 191 | this.id = id; 192 | } 193 | }); 194 | 195 | var foo = new Foo(42); // Foo#initialize 42 196 | console.log( foo.id ); // 42 197 | 198 | ### extended methods 199 | 200 | Library mixin two properties to your methods - `path` & `previous` (if exists). You can access to them by named function: 201 | 202 | atom.declare( 'Foo', { 203 | method: function YOUR_NAME_HERE () { 204 | // use YOUR_NAME_HERE.%property% 205 | } 206 | }); 207 | 208 | Such way is fast & easy for debug. 209 | 210 | `path` property shows full path to method & can be used for logging: 211 | 212 | atom.declare( 'Foo.Bar', { 213 | testPathProperty: function method () { 214 | console.log( 'Invoke: ', method.path, arguments ); 215 | } 216 | }); 217 | 218 | new Foo.Bar().testPathProperty(); // Invoke: Foo.Bar#testPathProperty [13, 42] 219 | 220 | `previous` can be used for calling parent method. It contains link to method, that way previous with that name or null. You should call it with manual context set using `.call` or `.apply` 221 | 222 | atom.declare( 'Foo', { 223 | testPrevious: function method (arg) { 224 | console.log( method.path, arg ); 225 | } 226 | }); 227 | 228 | atom.declare( 'Bar', Foo, { 229 | testPrevious: function method (arg) { 230 | method.previous.call(this, arg); 231 | console.log( method.path, arg ); 232 | method.previous.call(this, 95612); 233 | } 234 | }); 235 | 236 | new Bar().testPrevious(42); 237 | /* Foo#testPrevious 42 238 | * Bar#testPrevious 42 239 | * Foo#testPrevious 95612 240 | */ 241 | 242 | Use `previous` property carefull - calling without `.call(this)` will provide wrong context & calling `null` property will throw an error: 243 | 244 | 245 | atom.declare( 'Fail', { 246 | testPrevious: function method () { 247 | method.previous.call(this); 248 | } 249 | }); 250 | 251 | new Fail().testPrevious(); // TypeError: Cannot call method 'call' of undefined 252 | 253 | 254 | 255 | 256 | 257 | -------------------------------------------------------------------------------- /Docs/En/Declare/Events.md: -------------------------------------------------------------------------------- 1 | atom.Events 2 | =========== 3 | 4 | `atom.Events` is class, which provides easy events manipulations 5 | 6 | var events = new atom.Events(); 7 | 8 | ### add 9 | 10 | `add` - add callback for event. 11 | 12 | atom.Events add( string name, function callback ); 13 | 14 | #### example: 15 | 16 | events.add( 'activate', function () { 17 | console.log( 'activate event fired' ); 18 | }); 19 | 20 | #### returns `this` 21 | 22 | ### remove 23 | 24 | `remove` - remove callback, binded for event. 25 | 26 | atom.Events remove( string name, function callback ); 27 | 28 | #### example: 29 | 30 | function listenActivate () { 31 | console.log( 'activate event fired' ); 32 | } 33 | 34 | events.add( 'activate', listenActivate ); 35 | 36 | // event now 37 | events.remove( 'activate', listenActivate ); 38 | 39 | #### returns `this` 40 | 41 | ### add/remove alternate: 42 | 43 | `add` & `remove` callbacks can be called with different arguments. `name` argument can be array, so we can bind or unbind for several events with one callback 44 | 45 | events.add( [ 'rotate', 'move' ], function () { 46 | console.log( 'position changed' ); 47 | }); 48 | 49 | instead of two arguments we can send object of arguments, where key will be name & value will be callback: 50 | 51 | events.add({ 52 | rotate: function () { console.log('rotated') }, 53 | move : function () { console.log('moved') }, 54 | }); 55 | 56 | ### exists 57 | 58 | `exists` checks if someone binded for event. 59 | 60 | events.add( 'complete', onComplete ); 61 | console.log( 62 | events.exists('comlete'), // true 63 | events.exists('error') // false 64 | ); 65 | 66 | ### fire 67 | 68 | atom.Events fire( string name, Array arguments ); 69 | 70 | `fire` invokes all callback, that was binded for that name. 71 | 72 | events.add( 'foo', function (arg) { console.log(13, arg) }); 73 | events.add( 'foo', function (arg) { console.log(42, arg) }); 74 | events.add( 'bar', function (arg) { console.log(99, arg) }); 75 | 76 | events.fire( 'foo', 5 ); 77 | // 13, 5 78 | // 42, 5 79 | 80 | ### ready 81 | 82 | atom.Events ready( string name, Array arguments ); 83 | 84 | `ready` fires events once & fire all callbacks immedeatly, when they are binded. Can be used for some kind of "ready" events such as `image.onload` and so on, which fires only once. 85 | 86 | events.add( 'complete', function () { console.log(13) }); // wait event 87 | 88 | events.ready('complete'); // log 13 89 | 90 | events.add( 'complete', function () { console.log(42) }); // immedeatly log 42 91 | 92 | ### changing context 93 | 94 | You can change context(value of `this`) in fired callbacks by setting in in constructor: 95 | 96 | atom.declare( 'Foo', { 97 | property: 42, 98 | 99 | initialize: function () { 100 | this.events = new atom.Events(this); 101 | }, 102 | 103 | run: function () { 104 | this.events.fire('run'); 105 | } 106 | }); 107 | 108 | var foo = new Foo(); 109 | 110 | foo.events.add( 'run', function () { 111 | console.log( this.property ); // 42 112 | }); 113 | 114 | foo.run(); -------------------------------------------------------------------------------- /Docs/En/Declare/ImagePreloader.md: -------------------------------------------------------------------------------- 1 | atom.ImagePreloader 2 | =================== 3 | 4 | Class, which provides the easy way to preload images. 5 | 6 | ## Properties 7 | 8 | * `events` - `atom.Events` object 9 | 10 | * `settings` - `atom.Settings` object 11 | 12 | * `count` - object, state of images preloading, subproperties: 13 | 14 | * * `load` - number of images, loaded successful 15 | * * `abort` - number of images, which loading was aborted 16 | * * `error` - number of images, loaded with errors 17 | 18 | * `isReady` - `bool`, true, if all images are loaded 19 | 20 | * `info` - returns debug info about images loading state 21 | 22 | * `progress` - float value between 0 and 1 - percent of images, loaded already 23 | 24 | ## Methods 25 | 26 | ### initialize 27 | 28 | void initialize( Settings settings ) 29 | 30 | ##### Settings: 31 | 32 | * `images` - hash of images should be preloaded 33 | * `prefix` - string, all images should be prefixed by. Can be used, if all images begins with similar path 34 | * `suffix` - string, all images should be suffixed by. Can be used to avoid images caching 35 | 36 | ##### Events: 37 | 38 | * `ready` - fires when all images are successfully loaded 39 | 40 | ##### Example: 41 | 42 | new atom.ImagePrealoader({ 43 | prefix: 'http://static.example.com/images/', 44 | suffix: '?_avoid_cache=' + Date.now(), 45 | images: { 46 | 'unit-tractor' : 'units/tractor.png', 47 | 'unit-tank' : 'units/tank.png', 48 | 'unit-fighter' : 'units/fighter.png', 49 | 'unit-destroyer': 'units/destroyer.png', 50 | 51 | 'building-factory' : 'building/factory.jpg', 52 | 'building-oilrig' : 'building/oilrig.jpg', 53 | 'building-warehouse': 'building/warehouse.jpg' 54 | }, 55 | onReady: function (imagePreloader) { 56 | new Game(imagePreloader); 57 | } 58 | }); 59 | 60 | ### exists 61 | 62 | bool exists( string name ) 63 | 64 | Checks, if image with name `name` was loaded. 65 | 66 | imagePreloader.exists( 'unit-traktor' ); // true 67 | imagePreloader.exists( 'unit-diablo' ); // false 68 | 69 | ### get 70 | 71 | Image get( string name ) 72 | 73 | Returns image with name `name`, if exists, or throws `Error` otherwise 74 | 75 | imagePreloader.exists( 'unit-traktor' ); // returns image 76 | imagePreloader.exists( 'unit-diablo' ); // throws Error 77 | 78 | ## atom.ImagePreloader.run 79 | 80 | imagePreloader ImagePreloader.run( Object images, Function onReady, mixed context = null ) 81 | 82 | Short way to create image preloader. 83 | 84 | ImagePrealoader.run({ unit: 'unit.png' }, function (preloader) { 85 | new Game(preloader); 86 | }); 87 | 88 | // equals to: 89 | 90 | new ImagePrealoader({ 91 | images: { unit: 'unit.png' }, 92 | onReady: function (preloader) { 93 | new Game(preloader); 94 | } 95 | }); 96 | 97 | ## images syntax 98 | 99 | Preloader can dynamically crop images (sprites). Just add `[x:y:w:h]` part in the end of image path: 100 | 101 | ImagePrealoader.run({ 102 | 'unit-tractor' : 'units.png [0:0:50:50]', 103 | 'unit-tank' : 'units.png [50:0:50:50]', 104 | 'unit-fighter' : 'units.png [100:0:50:50]', 105 | 'unit-destroyer': 'units.png [150:0:50:50]', 106 | 107 | 'building-factory' : 'building.jpg [0:0:200:100]', 108 | 'building-oilrig' : 'building.jpg [0:100:200:100]', 109 | 'building-warehouse': 'building.jpg [0:200:200:100]' 110 | }); 111 | 112 | Another way is `tile cropping`. Syntax is `[w:h]{x:y}` where `w` is width of tile, `h` is height of tile, `x` is horisontal index of tile at image and `y` is vertical index of tile in image. Next code is indetial to previous: 113 | 114 | ImagePrealoader.run({ 115 | 'unit-tractor' : 'units.png [50:50]{0:0}', 116 | 'unit-tank' : 'units.png [50:50]{1:0}', 117 | 'unit-fighter' : 'units.png [50:50]{2:0}', 118 | 'unit-destroyer': 'units.png [50:50]{3:0}', 119 | 120 | 'building-factory' : 'building.jpg [200:100]{0:0}', 121 | 'building-oilrig' : 'building.jpg [200:100]{0:1}', 122 | 'building-warehouse': 'building.jpg [200:100]{0:2}' 123 | }); 124 | 125 | You can begins image with `http://` or `https://` if you dont want to prefix them: 126 | 127 | new ImagePrealoader({ 128 | prefix: 'http://s1.example.com/images', 129 | images: { 130 | unit1: 'unit1.png', 131 | unit2: 'unit2.png', 132 | unit3: 'https://s2.example.com/images/secret-unit.png', 133 | }, 134 | }); 135 | 136 | 137 | -------------------------------------------------------------------------------- /Docs/En/Declare/Keyboard.md: -------------------------------------------------------------------------------- 1 | atom.Keyboard 2 | ============= 3 | 4 | Provides the way to easy manipulate the keyboard 5 | 6 | ### own 7 | 8 | * `keyCodes` - object, where key is key name & value is key code. 9 | * `codeNames` - object, where key is key code & value is key name. 10 | 11 | #### keyName 12 | 13 | Returns name of key. First argument can be event or number 14 | 15 | window.onclick = function (e) { 16 | atom.trace( atom.Keyboard.keyName(e) ); 17 | } 18 | 19 | ### prototype 20 | 21 | #### initialize 22 | 23 | new atom.Keyboard( DOMElement element ); 24 | 25 | First argument can be null - that used `document` as default. 26 | 27 | var keyboard = new atom.Keyboard(); 28 | 29 | #### key 30 | 31 | boolean key( string keyName ) 32 | 33 | Checks if current key is pressed now 34 | 35 | if (keyboard.key('aleft')) { 36 | turnLeft(); 37 | } else if (keyboard.key('aright')) { 38 | turnRight(); 39 | } 40 | 41 | #### events 42 | 43 | Contains `atom.Events` instance. You can bind keys here. `:up` & `:press` prefixes can be used to specialize events: 44 | 45 | keyboard.events.add( 'space', function () { 46 | unit.jump(); 47 | }); 48 | 49 | keyboard.events.add( 'tab:up', function () { 50 | console.log( 'tab up' ); 51 | }); 52 | 53 | 54 | Key Codes 55 | ========= 56 | 57 | ### Latin symbols 58 | 59 | Name | Code | Name | Code | Name | Code 60 | -------- | ---- | -------- | ---- | -------- | ---- 61 | a | 65 | b | 66 | c | 67 62 | d | 68 | e | 69 | f | 70 63 | g | 71 | h | 72 | i | 73 64 | j | 74 | k | 75 | l | 76 65 | m | 77 | n | 78 | o | 79 66 | p | 80 | q | 81 | r | 82 67 | s | 83 | t | 84 | u | 85 68 | v | 86 | w | 87 | x | 88 69 | y | 89 | z | 90 | | 70 | 71 | 72 | ### Numbers & F* 73 | 74 | Name | Code | Name | Code | Name | Code 75 | -------- | ---- | -------- | ---- | -------- | ---- 76 | n0 | 48 | n1 | 49 | n2 | 50 77 | n3 | 51 | n4 | 52 | n5 | 53 78 | n6 | 54 | n7 | 55 | n8 | 56 79 | n9 | 57 | | | | 80 | f1 | 112 | f2 | 113 | f3 | 114 81 | f4 | 115 | f5 | 116 | f6 | 117 82 | f7 | 118 | f8 | 119 | f9 | 120 83 | f10 | 121 | f11 | 122 | f12 | 123 84 | 85 | ### Controls 86 | 87 | Name | Code | Name | Code | Name | Code 88 | -------- | ---- | -------- | ---- | ---------- | ---- 89 | capslock | 20 | numlock | 144 | scrolllock | 145 90 | enter | 13 | shift | 16 | backspace | 6 91 | tab | 9 | ctrl | 17 | alt | 18 92 | menu | 93 | pause | 19 | esc | 27 93 | insert | 45 | home | 36 | pageup | 33 94 | delete | 46 | end | 35 | pagedown | 34 95 | | | aup | 38 | | 96 | aleft | 37 | adown | 40 | aright | 39 97 | 98 | ### Symbols 99 | 100 | Name | Code | Name | Code | Name | Code 101 | -------- | ---- | -------- | ---- | ---------- | ---- 102 | equals | 61 | hyphen | 109 | semicolon | 59 103 | dot | 190 | sbopen | 219 | sbclose | 221 104 | slash | 191 | gravis | 192 | backslash | 220 105 | | | coma | 188 | apostrophe | 222 106 | 107 | ### Numpad 108 | 109 | Name | Code | Name | Code | Name | Code 110 | -------- | ---- | -------- | ---- | ---------- | ---- 111 | np0 | 96 | np1 | 97 | npslash | 11 112 | np2 | 98 | np3 | 99 | npstar | 106 113 | np4 | 100 | np5 | 101 | nphyphen | 109 114 | np6 | 102 | np7 | 103 | npplus | 107 115 | np8 | 104 | np9 | 105 | npdot | 110 -------------------------------------------------------------------------------- /Docs/En/Declare/Settings.md: -------------------------------------------------------------------------------- 1 | atom.Settings 2 | ============= 3 | 4 | `atom.Settings` is class, which provides easy settings changing 5 | 6 | var settings = new atom.Settings(); 7 | 8 | ### set 9 | 10 | `set` - sets values 11 | 12 | atom.Settings set( string name, mixed value ); 13 | atom.Settings set( object values ); 14 | 15 | #### example: 16 | 17 | settings.set( 'test', 123 ); 18 | settings.set({ a: 1, b: 2 }); 19 | 20 | #### returns `this` 21 | 22 | ### get 23 | 24 | `get` - returns value of key, or all values 25 | 26 | mixed get( string key, mixed defaultValue = undefined ); 27 | 28 | #### example: 29 | 30 | settings.get( 'test' ); // 123 31 | settings.get( 'wrong', 'default' ); // 'default' 32 | 33 | ### properties 34 | 35 | `properties` - such properties will be set automatically to target object. 36 | If no names set - all properties will be set. 37 | 38 | atom.Settings properties( string target, string[] names = null ); 39 | 40 | #### example: 41 | 42 | var object = {}; 43 | 44 | settings.properties( object, [ 'foo' ] ); 45 | settings.set({ foo: 1, bar: 2 }); 46 | 47 | console.log( object.foo ); // 1 48 | console.log( object.bar ); // undefined 49 | 50 | ### initial values 51 | 52 | You can set initial values of Settings using first argument while constructing: 53 | 54 | var settings = new atom.Settings({ initial: 42 }); 55 | settings.get('initial'); // 42 56 | 57 | ### addEvents 58 | 59 | atom.Settings addEvents( atom.Events events ); 60 | 61 | When events are added all settings, which begins with 'on' are recognized as events 62 | 63 | var events = new atom.Events(); 64 | var settings = new atom.Settings(); 65 | settings.addEvents( events ); 66 | 67 | settings.set({ onClick: onClickCallback }); 68 | //equals to: 69 | events.add( 'click', onClickCallback ); 70 | 71 | This can be used for easy events+settings class construction: 72 | 73 | atom.declare( 'Button', { 74 | initialize: function (settings) { 75 | this.events = new atom.Events(this); 76 | this.settings = new atom.Settings(settings); 77 | 78 | this.settings.addEvents( this.events ); 79 | } 80 | }); 81 | 82 | new Button({ 83 | title: 'My Test Button', 84 | onClick: function () { 85 | // button onClick event 86 | } 87 | }); 88 | -------------------------------------------------------------------------------- /Docs/En/Declare/Trace.md: -------------------------------------------------------------------------------- 1 | atom.trace 2 | ========== 3 | 4 | This class used in browsers for easy online debug without using browser console. Please, use `atom.css` from repo core. 5 | 6 | It recurcively dumps (map depth is 5) object according inner rules & object 'dump' method & show result at screen. 7 | 8 | ### atom.trace.dumpPlain( object ) 9 | 10 | Returns plain dump (string) of object, that can be logged e.g. in console or another place. 11 | 12 | #### example: 13 | 14 | atom.trace.dumpPlain({ 15 | foo: 123, 16 | bar: null, 17 | arr: [ 1, 2, 3 ], 18 | sub: { test: 'string' }, 19 | dumpable: { 20 | dump: function () { return '[My Dumpable Object]' } 21 | } 22 | }); 23 | 24 | #### result: 25 | 26 | { 27 | foo: 123 28 | bar: null 29 | arr: [ 30 | 0: 1 31 | 1: 2 32 | 2: 3 33 | ] 34 | sub: { 35 | test: "string" 36 | } 37 | dumpable: [My Dumpable Object] 38 | } 39 | 40 | ### Instance 41 | 42 | var trace = new atom.Trace( value ); 43 | 44 | Shows result of dump on page. Can be dynamicaly changed. It can be used for showing current fps number, mouse coord or another debug info, which can be change so fast, that we can't just log it into console. 45 | 46 | You can use `destroy` method to remove it from screen, or just click on it. 47 | 48 | You can change current its content by setting value property: 49 | 50 | var trace = atom.trace(); 51 | var value = 0; 52 | 53 | setInterval(function () { 54 | trace.value = value++; 55 | }, 100); 56 | 57 | You can set as value any object, you can see. 58 | 59 | // Some class: 60 | atom.declare( 'Changer', { 61 | value: 0, 62 | max : 0, 63 | 64 | initialize: function (initial, max) { 65 | this.value = initial; 66 | this.max = max; 67 | this.events = new atom.Events(this); 68 | this.runNext(); 69 | }, 70 | 71 | change: function () { 72 | this.value += Number.random(-5, 10); 73 | 74 | if (this.value > this.max) { 75 | this.events.fire('stop'); 76 | } else { 77 | this.events.fire('change'); 78 | this.runNext(); 79 | } 80 | }, 81 | 82 | runNext: function () { 83 | this.change.delay(100, this); 84 | }, 85 | 86 | dump: function () { 87 | return '[Changer ' + this.value + ']'; 88 | } 89 | }); 90 | 91 | // listen code: 92 | var myChanger = new Changer(1000, 1200); 93 | 94 | var changerTrace = atom.trace(myChanger); 95 | myChanger.events.add({ 96 | change: function () { 97 | changerTrace.value = myChanger; 98 | }, 99 | stop: function (){ 100 | changerTrace.destroy(); 101 | } 102 | }); 103 | 104 | 105 | -------------------------------------------------------------------------------- /Docs/En/Declare/Transition.md: -------------------------------------------------------------------------------- 1 | atom.Transition 2 | =============== 3 | 4 | `atom.Transition` specifies the speed curves of the transition effects. 5 | 6 | ### atom.Transition.set 7 | 8 | atom.Transition.set( id, fn ); 9 | 10 | Sets new transition function: 11 | 12 | atom.Transition.set( 'Special', function(p){ 13 | return Math.sqrt( Math.atan(p*Math.PI/2) ); 14 | }); 15 | 16 | ### atom.Transition.get 17 | 18 | atom.Transition.get( id ); 19 | 20 | Returns transition function. Returns 'ease-in-out' as default, 'ease-in' if `-in` prefix contains & 'ease-out' if `out` prefix contains; 21 | 22 | var transitionInOut = atom.Transition.get( 'special' ); 23 | var transitionIn = atom.Transition.get( 'special-in' ); 24 | var transitionOut = atom.Transition.get( 'special-out' ); 25 | 26 | console.log( transitionInOut(0.5) ); // 0.5 27 | 28 | ### Build-in timing functions 29 | 30 | * linear 31 | * sine 32 | * asine 33 | * back 34 | * bounce 35 | * elastic 36 | * expo 37 | * circ 38 | * quad 39 | * cubic 40 | * quart 41 | * quint 42 | 43 | ![Transition Graph](https://github.com/theshock/atomjs/raw/master/Docs/En/Declare/transition-graph.png) -------------------------------------------------------------------------------- /Docs/En/Declare/transition-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theshock/atomjs/8fcc3209e9b49727fd30c1b15194f895054ad6dc/Docs/En/Declare/transition-graph.png -------------------------------------------------------------------------------- /Docs/En/Dom.md: -------------------------------------------------------------------------------- 1 | Atom DOM 2 | ======== 3 | 4 | #### Constructor: 5 | 6 | atom.dom(); 7 | atom.dom('tag .class'); 8 | atom.dom(document.getElementsByTagName('tag')); 9 | atom.dom(selector, context); 10 | 11 | #### onready 12 | 13 | atom.dom(function () { 14 | // DOMContentLoaded 15 | }); 16 | 17 | #### atom.dom.create(tagName, attrs = null) 18 | 19 | Creates and returns (*atom.dom*) tag with name `tagName` 20 | 21 | Example: 22 | 23 | // creating Canvas with properties 24 | var atomCanvas = atom.dom.create('canvas', { 25 | width : 400, 26 | height : 100 27 | }); 28 | 29 | #### atom.dom().body 30 | 31 | var body = atom.dom().body; 32 | 33 | #### atom.dom().get(index = 0) 34 | 35 | Returns html-element from current collection 36 | 37 | atom.dom('img').first; // first image on a page 38 | atom.dom('img').get(); // first image on a page 39 | atom.dom('img').get(5); // fifth image on a page 40 | 41 | #### atom.dom().create(tagName, index = 0, attrs = null) 42 | 43 | Creates element, adds it to node and returns node 44 | 45 | Optional arguments: 46 | 47 | * `index` - index of node in current collection 48 | * `attrs` - properties to set on new element 49 | 50 | Example: 51 | 52 | // creating Canvas in fifth div: 53 | atom.dom('div').create('canvas', 5); 54 | 55 | // creating Canvas with properties 56 | atom.dom('div').create('canvas', { 57 | width : 400, 58 | height : 100 59 | }); 60 | 61 | // creating few elements in div 62 | var divNode = atom.dom('div') 63 | .create('canvas') 64 | .create('canvas') 65 | .create('footer') 66 | 67 | console.log(divNode) //
...
68 | 69 | and now div looks like: 70 | 71 |
72 | 73 | 74 | 75 |
76 | 77 | #### atom.dom().each(fn) 78 | 79 | Apply function on each element of collection (analogue of `Array.forEach`): 80 | 81 | atom.dom('div').each(function (div, index) { 82 | div.className = 'active'; 83 | // this == atom.dom('div') 84 | }); 85 | 86 | #### atom.dom().parent(step = 1) 87 | 88 | Returns parent element for choosed step. 89 | 90 | Example: 91 | 92 | 93 |
94 |
95 |
96 |
97 |
98 | 99 | 100 | atom.dom('#id3').parent().id; //id2 101 | atom.dom('#id3').parent(2).id; //id1 102 | 103 | #### atom.dom().css(properties) 104 | 105 | Apply CSS to every element: 106 | 107 | // let's paint every div in red 108 | atom.dom('div').css('background', 'red'); 109 | atom.dom('div').css({background: 'red'}); 110 | 111 | #### atom.dom().addEvent(events) 112 | 113 | Attach event handler to every element in current collection 114 | 115 | atom.dom('div').addEvent({click: function () { 116 | alert('div clicked') 117 | }}); 118 | 119 | Prevent default actions for events 120 | 121 | atom.dom("a").addEvent("click", false); 122 | 123 | #### atom.dom().bind(events) 124 | 125 | Deprecated, use *addEvent* 126 | 127 | #### atom.dom().removeEvent(events) 128 | 129 | Detach event handler from evety element in current collection 130 | 131 | atom.dom("div").addEvent("click", function listener (event) { 132 | alert('div clicked') 133 | this.removeEvent("click", listener); 134 | }); 135 | 136 | #### atom.dom().unbind(events) 137 | 138 | Deprecated, use *removeEvent* 139 | 140 | #### atom.dom().delegate(selector, event, fn) 141 | 142 | Attach event handler to every matching element in current collection now and in 143 | future. 144 | 145 | atom.dom('div').delegate('img', 'click', function () { 146 | alert('img in div clicked') 147 | }}); 148 | 149 | #### atom.dom().find(selector) 150 | 151 | Find element inside current collection. Equivalent to atom(selector, context); 152 | 153 | atom.dom('div').find('p') == atom.dom('div p'); 154 | 155 | #### atom.dom().appendTo(elem) 156 | 157 | Append collection to another element 158 | 159 | atom.dom('img').appendTo('div'); // append every image to div 160 | 161 | #### atom.dom().attr(values) 162 | 163 | Set attribute for every element in current collection 164 | 165 | atom.dom('canvas').attr({ 166 | width : 50, 167 | height : 50 168 | }); 169 | 170 | #### atom.dom().destroy() 171 | 172 | Destroy current collection 173 | 174 | atom.dom('div').destroy(); 175 | 176 | #### atom.dom().filter(selector) 177 | 178 | Filter elements according to selector 179 | 180 | // returns only divs with class "className" 181 | atom.dom('div').filter('.className'); 182 | 183 | 184 | #### atom.dom().is(selector) 185 | 186 | Checks if elems is matched to selector 187 | 188 | // returns true is there are divs with class "className" 189 | atom.dom('div').is('.className'); 190 | 191 | #### atom.dom().html(value = undefined) 192 | 193 | get or set html of first element in set 194 | 195 | atom.dom('div').html('abc'); 196 | atom.dom('div').html(); // 'abc' 197 | 198 | #### atom.dom().text(value = undefined) 199 | 200 | get or set text of first element in set 201 | 202 | atom.dom('div').text('abc'); 203 | atom.dom('div').text(); // 'abc'; 204 | 205 | atom.dom('div').html('abc'); 206 | atom.dom('div').text(); // 'abc'; 207 | 208 | #### atom.dom().wrap(wrapper) 209 | 210 | Wrap first element of set with wrapper 211 | 212 | atom.dom('span').wrap( atom.dom.create('div') ); 213 | 214 | #### atom.dom().replaceWith(newElement) 215 | 216 | Replace first element of the set with newElement 217 | 218 | atom.dom('span').replaceWith( atom.dom.create('div') ); 219 | 220 | #### atom.dom().addClass(className) 221 | 222 | Adds new class "className" to all elements of set 223 | 224 | atom.dom('span').addClass('foo'); 225 | 226 | 227 | #### atom.dom().removeClass(className) 228 | 229 | Removes class "className" from all elements of set 230 | 231 | atom.dom('span').removeClass('foo'); 232 | 233 | 234 | #### atom.dom().toggleClass(className) 235 | 236 | Toggles class "className" for all elements of set 237 | 238 | atom.dom('span').toggleClass('foo'); 239 | 240 | 241 | #### atom.dom().hasClass(className) 242 | 243 | Returns true if set contains one or more elements 244 | having class "className" 245 | 246 | atom.dom('span').hasClass('foo'); 247 | -------------------------------------------------------------------------------- /Docs/En/Frame.md: -------------------------------------------------------------------------------- 1 | Atom Frame 2 | ========== 3 | 4 | Provides interface to perform animation. It calls you function up to 60 times per second. 5 | Alternative (and wrapper in future) for `requestAnimationFrame` 6 | 7 | 8 | ### atom.frame.add(function callback) 9 | Adds callback for animation 10 | 11 | ### atom.frame.remove(function callback) 12 | Remove callback from animation 13 | 14 | #### Example 15 | atom.frame.add(function animate() { 16 | element.left += 5; 17 | if (element.left > 100) { 18 | atom.frame.remove(animate); 19 | } 20 | }); -------------------------------------------------------------------------------- /Docs/En/PointerLock.md: -------------------------------------------------------------------------------- 1 | Pointer Lock 2 | ============ 3 | 4 | Provides interface for cross browser pointer locking 5 | 6 | 7 | ### atom.pointerLock.supports 8 | Equals `true` if `PointerLock` supports: 9 | 10 | ```js 11 | if (atom.pointerLock.supports) { 12 | console.log('PointerLock supports'); 13 | } 14 | ``` 15 | 16 | ### atom.pointerLock.locked(DOMElement element) 17 | Returns `true` if element is locked now: 18 | 19 | ```js 20 | if (atom.pointerLock.locked(myCanvas)) { 21 | console.log('myCanvas locked'); 22 | } 23 | ``` 24 | 25 | ### atom.pointerLock.request(DOMElement element, function callback) 26 | Try to pointer lock `element` & then calls `callback` on mouse move: 27 | 28 | ```js 29 | atom.pointerLock.request( myCanvas, function (e) { 30 | console.log( 'Locked mouse move: ', e.movementX, e.movementY ); 31 | }); 32 | ``` 33 | 34 | ### atom.pointerLock.exit() 35 | Unlock pointer if locked 36 | 37 | ```js 38 | atom.pointerLock.exit() 39 | ``` -------------------------------------------------------------------------------- /Docs/En/Prototypes/Array.md: -------------------------------------------------------------------------------- 1 | Array extending 2 | =============== 3 | 4 | Generally build-in type extending use `atom.%type%.*` methods, so here you will only see links to manual and examples 5 | 6 | ### See: [atom.array](https://github.com/theshock/atomjs/blob/master/Docs/En/Types/Math.md) 7 | 8 | ### Own properties 9 | 10 | Next list of properties mixin to Array: 11 | 12 | * range 13 | * from 14 | * pickFrom 15 | * fill 16 | * fillMatrix 17 | * collect 18 | * create 19 | * toHash 20 | 21 | ##### example 22 | 23 | Array.range( from, to ); 24 | // equals to: 25 | atom.array.range( from, to ); 26 | 27 | ### prototype extending 28 | 29 | Next properties mixed in to prototype, where first property is `this` array: 30 | 31 | * randomIndex 32 | * property 33 | * contains 34 | * include 35 | * append 36 | * erase 37 | * combine 38 | * pick 39 | * invoke 40 | * shuffle 41 | * sortBy 42 | * min 43 | * max 44 | * mul 45 | * add 46 | * sum 47 | * product 48 | * average 49 | * unique 50 | * associate 51 | * clean 52 | * empty 53 | * clone 54 | * hexToRgb 55 | * rgbToHex 56 | 57 | ##### example 58 | var myArray = [1,2,3]; 59 | 60 | myArray.include( 4 ); 61 | // equals to: 62 | atom.array.include( myArray, 4 ); 63 | 64 | // and 65 | 66 | myArray.sum() 67 | // equals to: 68 | atom.array.sum( myArray ); 69 | 70 | ### Own properties 71 | 72 | * `last` - returns last element in array 73 | 74 | var myArray = ['foo','bar','qux']; 75 | console.log( myArray.last ); // 'qux' 76 | 77 | * `random` - returns random property of array: 78 | 79 | var myArray = ['foo','bar','qux']; 80 | console.log( myArray.random ); // 'foo' or 'bar' or 'qux' 81 | 82 | 83 | -------------------------------------------------------------------------------- /Docs/En/Prototypes/Function.md: -------------------------------------------------------------------------------- 1 | Function extending 2 | ================== 3 | 4 | Generally build-in type extending use `atom.%type%.*` methods, so here you will only see links to manual and examples 5 | 6 | ### See: [atom.fn](https://github.com/theshock/atomjs/blob/master/Docs/En/Types/Function.md) 7 | 8 | ### Own properties 9 | 10 | * `after` - Equals to `atom.fn.after` 11 | * `lambda` - Equals to `atom.fn.lambda` 12 | 13 | ### Prototype extending 14 | 15 | #### delay 16 | 17 | Function delay( Number time, mixed context = null, Array arguments = [] ); 18 | 19 | equivalent to `setTimeout`, easy wat to launch function `time` later. 20 | 21 | object.method.delay( 500, object, [ 1, 'foo' ] ); 22 | // equals to: 23 | setTimeout( object.method.bind( object, 1, 'foo' ), 500 ); 24 | 25 | #### periodical 26 | 27 | Function periodical( Number time, mixed context = null, Array arguments = [] ); 28 | 29 | equivalent to `setInterval`, easy wat to launch function `time` later. 30 | 31 | object.method.periodical( 500, object, [ 1, 'foo' ] ); 32 | // equals to: 33 | setInterval( object.method.bind( object, 1, 'foo' ), 500 ); 34 | -------------------------------------------------------------------------------- /Docs/En/Prototypes/Number.md: -------------------------------------------------------------------------------- 1 | Number extending 2 | ================ 3 | 4 | Generally build-in type extending use `atom.%type%.*` methods, so here you will only see links to manual and examples 5 | 6 | ### See: [atom.number](https://github.com/theshock/atomjs/blob/master/Docs/En/Types/Number.md), [atom.math](https://github.com/theshock/atomjs/blob/master/Docs/En/Types/Math.md) 7 | 8 | ### Own properties 9 | 10 | * Number.random 11 | 12 | Equivalent to `atom.number.random`: 13 | 14 | Number.random(5, 100); 15 | // equals to 16 | atom.number.random(5, 100); 17 | 18 | * Number.randomFloat 19 | 20 | Equivalent to `atom.number.randomFloat`: 21 | 22 | Number.randomFloat(5, 100); 23 | // equals to 24 | atom.number.randomFloat(5, 100); 25 | 26 | ### prototype extending 27 | 28 | Next properties mixed into prototype from `atom.number`, where first property is `this` array: 29 | 30 | * between 31 | * equals 32 | * limit 33 | * round 34 | * stop 35 | 36 | 37 | Next properties mixed into prototype from `atom.math`, where first property is `this` array: 38 | 39 | * degree 40 | * getDegree 41 | * normalizeAngle 42 | 43 | 44 | ##### example 45 | var myNumber = 10; 46 | 47 | myNumber.between( 5, 15 ); 48 | // equals to: 49 | atom.number.between( myNumber, 5, 15 ); 50 | 51 | // and 52 | 53 | myNumber.degree() 54 | // equals to: 55 | atom.math.degree( myNumber ); 56 | 57 | 58 | Next properties mixed into prototype from javascript build-in `Math`, where first property is `this` array: 59 | 60 | * abs 61 | * acos 62 | * asin 63 | * atan 64 | * atan2 65 | * ceil 66 | * cos 67 | * exp 68 | * floor 69 | * log 70 | * max 71 | * min 72 | * pow 73 | * sin 74 | * sqrt 75 | * tan 76 | 77 | 78 | ##### example 79 | 80 | var myNumber = -5.123; 81 | 82 | myNumber.abs(); 83 | // equals to 84 | Math.abs( myNumber ); 85 | 86 | // and 87 | 88 | myNumber.pow(3); 89 | // equals to: 90 | Math.pow( myNumber, 3 ); 91 | 92 | -------------------------------------------------------------------------------- /Docs/En/Prototypes/Object.md: -------------------------------------------------------------------------------- 1 | Object extending 2 | ================ 3 | 4 | Generally build-in type extending use `atom.%type%.*` methods, so here you will only see links to manual and examples 5 | 6 | ### See: [atom.object](https://github.com/theshock/atomjs/blob/master/Docs/En/Types/Object.md) 7 | 8 | ### Own properties 9 | 10 | All properties of `atom.object` mixed to `Object`: 11 | 12 | * invert 13 | * collect 14 | * values 15 | * map 16 | * max 17 | * min 18 | * isEmpty 19 | * path 20 | 21 | ##### example 22 | 23 | Object.invert( myObject ); 24 | // equals to: 25 | atom.object.invert( myObject ); 26 | 27 | // and 28 | 29 | Object.map( myObject, callback ); 30 | // equals to: 31 | atom.object.map( myObject, callback ); -------------------------------------------------------------------------------- /Docs/En/Prototypes/String.md: -------------------------------------------------------------------------------- 1 | String extending 2 | ================ 3 | 4 | Generally build-in type extending use `atom.%type%.*` methods, so here you will only see links to manual and examples 5 | 6 | ### See: [atom.string](https://github.com/theshock/atomjs/blob/master/Docs/En/Types/String.md) 7 | 8 | ### prototype extending 9 | 10 | Next properties mixed in to prototype, where first property is `this` array: 11 | 12 | * safeHtml 13 | * repeat 14 | * substitute 15 | * replaceAll 16 | * contains 17 | * begins 18 | * ends 19 | * ucfirst 20 | * lcfirst 21 | 22 | ##### example 23 | 24 | var myString = 'test {string} is here'; 25 | 26 | myString.begins( 'test' ); 27 | // equals to: 28 | atom.string.begins( myString, 'test' ); 29 | 30 | // and 31 | 32 | myString.substitute({ 'string': 'substring' }); 33 | // equals to: 34 | atom.string.substitute( myString, { 'string': 'substring' }); 35 | -------------------------------------------------------------------------------- /Docs/En/Types/Function.md: -------------------------------------------------------------------------------- 1 | atom.fn 2 | ======= 3 | 4 | Provides method to operate with functions: 5 | 6 | ### atom.fn.lambda(value) 7 | 8 | Returns function, which returns value. 9 | 10 | window.onclick = atom.fn.lambda(false); 11 | 12 | ### atom.fn.after(onReady, fnName) 13 | 14 | Returns hash of functions, which should be invoked before onReady will be invoked. Can be used for parallel invoking of several async callbacks. 15 | 16 | var callbacks = atom.fn.after(function (args) { 17 | console.log( 18 | args.fileReaded, // data from file 19 | args.dbQuery, // data from database 20 | args.userInput // data from user 21 | ); 22 | }, 'fileReaded', 'dbQuery', 'userInput' ); 23 | 24 | // here we subscribe to async events: 25 | 26 | new My.File.Read.Async( 'filename.txt', callbacks.fileReaded ); 27 | new My.Db.Query.Async( 'SELECT * from `db`', callbacks.dbQuery ); 28 | document.onclick = callbacks.userInput; -------------------------------------------------------------------------------- /Docs/En/Types/Math.md: -------------------------------------------------------------------------------- 1 | atom.math 2 | ========= 3 | 4 | ### atom.math.degree( degrees ) 5 | 6 | Cast degrees to radians 7 | 8 | atom.math.degree(90) == Math.PI/2 9 | 10 | ### atom.math.getDegree( radians ) 11 | 12 | Cast radians to degrees. If second argument is `true` - result will be rounded 13 | 14 | atom.math.getDegree(Math.PI/2) == 90 15 | 16 | ### atom.math.normalizeAngle( radians ) 17 | 18 | Ensure, angle is between 0 & 360 degrees: 19 | 20 | var angle = atom.math.degree( 1000 ); 21 | var normal = atom.math.normalizeAngle( angle ); 22 | console.log( atom.math.getDegree( normal, true ) ); // 280 23 | 24 | ### atom.math.hypotenuse( cathetus1, cathetus2 ) 25 | 26 | Returns hypotenuse of right triangle from two cathetus 27 | 28 | atom.math.hypotenuse( 5, 12 ); // 13 29 | 30 | ### atom.math.cathetus( hypotenuse, cathetus2 ) 31 | 32 | Returns cathetus of right triangle from hypotenuse & cathetus 33 | 34 | atom.math.cathetus( 13, 12 ); // 5 -------------------------------------------------------------------------------- /Docs/En/Types/Number.md: -------------------------------------------------------------------------------- 1 | atom.number 2 | =========== 3 | 4 | Provides methods to operate with numbers 5 | 6 | ### random(min, max) { 7 | Returns random number between `min` & `max` inclusive 8 | 9 | atom.number.random(1, 3); // returns 1 or 2 or 3 10 | 11 | ### randomFloat(min, max) { 12 | Returns random float number between `min` & `max` 13 | 14 | atom.number.randomFloat(1, 3.5); // returns 1.4152 or 3.672, or smth else 15 | 16 | ### between(number, left, right, equals) { 17 | 18 | Checks if `number` is greater than `left` & less than `right`. 19 | `Equals` can be used if `number` can be equals to one or both of sides 20 | 21 | `Equals` can be: 22 | * false or '' - not equals to anyone `number => (left, right)` 23 | * 'L' - can be equals to left side, but not equals right `number => [left, right)` 24 | * 'R' - can be equals to right side, but not equals left `number => (left, right]` 25 | * true or 'LR' - can be equals to both side `number => [left, right]` 26 | 27 | ##### Examples 28 | 29 | atom.number.between( 5, 3, 7 ); // true 30 | atom.number.between( 5, 3, 7, 'L' ); // true 31 | atom.number.between( 5, 3, 7, 'R' ); // true 32 | atom.number.between( 5, 3, 7, true ); // true 33 | 34 | atom.number.between( 7, 3, 7 ); // false 35 | atom.number.between( 7, 3, 7, 'L' ); // false 36 | atom.number.between( 7, 3, 7, 'R' ); // true 37 | atom.number.between( 7, 3, 7, true ); // true 38 | 39 | atom.number.between( 3, 3, 7 ); // false 40 | atom.number.between( 3, 3, 7, 'L' ); // true 41 | atom.number.between( 3, 3, 7, 'R' ); // false 42 | atom.number.between( 3, 3, 7, true ); // true 43 | 44 | atom.number.between( 0, 3, 7 ); // false 45 | atom.number.between( 0, 3, 7, 'L' ); // false 46 | atom.number.between( 0, 3, 7, 'R' ); // false 47 | atom.number.between( 0, 3, 7, true ); // false 48 | 49 | ### equals(left, right, accuracy = 8) 50 | 51 | Allows to compare two float numbers (which can't be done with ==) with `accuracy` digits after dot 52 | 53 | 54 | (0.7 + 0.1) * 10 == 8; // false 55 | atom.number.equals((0.7 + 0.1) * 10, 8); // true 56 | 57 | atom.number.equals(1.15177354, 1.1517, 2); // true (1.152 == 1.152) 58 | 59 | ### limit(number, min, max) 60 | 61 | Returns `number` limited by `min` & `max` values. `max` can be null & only `min` will be used 62 | 63 | atom.number.limit( 42, 0, 100 ); // 42 64 | atom.number.limit( 666, 0, 100 ); // 100 65 | atom.number.limit( -13, 0, 100 ); // 0 66 | 67 | atom.number.limit( -13, 0 ); // 0 68 | atom.number.limit( 183, 0 ); // 183 69 | 70 | 71 | ### round(number, precision = 0) 72 | 73 | Rounds number to `precision` digits after dots if `precision > 0` 74 | Rounds number to `precision` digits before dots if `precision < 0` 75 | 76 | 77 | atom.number.round( 84139.234567 ); // 84139 78 | 79 | atom.number.round( 84139.234567, 1 ); // 84139.2 80 | atom.number.round( 84139.234567, 3 ); // 84139.235 81 | atom.number.round( 84139.234567, 9 ); // 84139.234567 82 | 83 | atom.number.round( 84139.234567, -1 ); // 84140 84 | atom.number.round( 84139.234567, -3 ); // 84000 85 | atom.number.round( 84139.234567, -9 ); // 0 86 | -------------------------------------------------------------------------------- /Docs/En/Types/Object.md: -------------------------------------------------------------------------------- 1 | atom.object 2 | =========== 3 | 4 | Provides methods to operate with object 5 | 6 | #### append(target, source1, source2, ... ) 7 | 8 | Appends source objects content to target 9 | 10 | var source = { a: 1, b: 2, c: 3 }; 11 | 12 | atom.object.append( source, {d:4}, {e:5} ); 13 | 14 | console.log( source ); // { a: 1, b: 2, c: 3, d: 4, e: 5 }; 15 | 16 | #### invert(object) 17 | 18 | Returns inverted object - where keys is values & values is keys. 19 | 20 | var source = { a: 1, b: 2, c: 3 }; 21 | var result = atom.object.invert( source ); 22 | 23 | console.log( result ); // { 1: 'a', 2: 'b', 3: 'c' }; 24 | 25 | 26 | #### collect(object, Array properties, mixed default = undefined) 27 | 28 | Returns subset with only `properties` as keys 29 | 30 | var source = { a: 1, b: 2, c: 3 }; 31 | var result = atom.object.collect( source, [ 'a', 'b', 'e', 'x' ], 42 ); 32 | 33 | console.log( result ); // { a: 1, b: 2, e: 42, x: 42 }; 34 | 35 | #### values(object) 36 | 37 | Returns array of object values 38 | 39 | var source = { a: 1, b: 2, c: 3 }; 40 | var result = atom.object.values( source ); 41 | console.log( result ); // [1,2,3] 42 | 43 | #### map(object, callback) 44 | 45 | Returns new object, which has mapped with `callback` values: 46 | 47 | 48 | var source = { a: 1, b: 2, c: 3 }; 49 | var result = atom.object.map( source, function (value, key) { 50 | return value * value; 51 | }); 52 | 53 | console.log( result ); // { a: 1, b: 4, c: 9}; 54 | 55 | #### max(object) 56 | 57 | Returns key, where max value contains 58 | 59 | var source = { x: 42, a: 1, b: 2, c: 3 }; 60 | console.log( atom.object.max(source) ); // 'x' 61 | 62 | #### min(object) 63 | 64 | Returns key, where min value contains 65 | 66 | var source = { x: 42, a: 1, b: 2, c: 3 }; 67 | console.log( atom.object.max(source) ); // 'a' 68 | 69 | #### isEmpty(object) 70 | 71 | Checks if object is empty 72 | 73 | console.log( atom.object.isEmpty({ }) ); // true 74 | console.log( atom.object.isEmpty({a:1}) ); // false 75 | 76 | #### path.get(object, path) 77 | 78 | Returns value by the path. 79 | 80 | var source = { 81 | foo: { 82 | bar: { 83 | qux: 123 84 | } 85 | } 86 | }; 87 | 88 | console.log( atom.object.path.get(source, 'foo.bar.qux') ); // 123 89 | console.log( atom.object.path.get(source, 'nil.bar.qux') ); // undefined 90 | 91 | #### path.set(object, path) 92 | 93 | Sets value by the path. 94 | 95 | var source = { 96 | foo: { 97 | bar: { 98 | qux: 123 99 | } 100 | } 101 | }; 102 | 103 | atom.object.path.set(source, 'foo.bar.qux', 42 ); 104 | atom.object.path.set(source, 'nil.bar.qux', 13 ); 105 | atom.object.path.set(source, 'foo.bar.qwe', 99 ); 106 | atom.object.path.set(source, 'foo.sub' , 9126 ); 107 | 108 | console.log( source ); /* { 109 | foo: { 110 | bar: { 111 | qux: 42, 112 | qwe: 99 113 | }, 114 | sub: 9126 115 | }, 116 | nil: { 117 | bar: { qux: 13 } 118 | } 119 | } */ 120 | 121 | Can be used to safely create namespaces: 122 | 123 | atom.object.path.set( window, 'My.Namespace.Foo', function () { 124 | // My.Namespace.Foo function 125 | }); 126 | 127 | atom.object.path.set( window, 'My.Namespace.Bar', function () { 128 | // My.Namespace.Bar function 129 | }); -------------------------------------------------------------------------------- /Docs/En/Types/String.md: -------------------------------------------------------------------------------- 1 | atom.string 2 | =========== 3 | 4 | #### uniqueID 5 | Returns unique for sessiong string id 6 | 7 | atom.string.uniqueID() // "h3biq3tz" 8 | atom.string.uniqueID() // "h3biq3u0" 9 | 10 | #### safeHtml 11 | Returns escaped string, safe to insert as html 12 | 13 | atom.string.safeHtml( 'Hello "World"' ); 14 | // "<b>Hello "World"</b>" 15 | 16 | #### repeat 17 | Repeat string `times` times 18 | 19 | atom.string.repeat( 'bar*', 3 ); // bar*bar*bar* 20 | 21 | #### substitute 22 | Append values to string from object 23 | 24 | 25 | atom.string.substitute( 26 | 'Hello, {name}! How are you? Are you {type}? "{name}" is your real name?', 27 | { 28 | name: 't800', type: 'destroyer' 29 | }); 30 | // "Hello, t800! How are you? Are you destroyer? "t800" is your real name?" 31 | 32 | 33 | #### replaceAll 34 | Replace all source substrings with target 35 | 36 | atom.string.replaceAll('Hi--my--dear--friend!', { '--': '+', '!': '?' }) 37 | // "Hi+my+dear+friend?" 38 | 39 | #### contains 40 | Checks if string contains substring 41 | 42 | atom.string.contains( 'Hello, World!', 'World' ); // true 43 | atom.string.contains( 'Hello, World!', 'Heaven' ); // false 44 | 45 | #### begins 46 | Checks if string begins with substring 47 | 48 | atom.string.begins( 'Hello, World!', 'Hello' ); // true 49 | atom.string.begins( 'Hello, World!', 'World' ); // false 50 | 51 | #### begins 52 | Checks if string begins with substring 53 | 54 | atom.string.begins( 'Hello, World!', 'Hello' ); // true 55 | atom.string.begins( 'Hello, World!', 'World' ); // false 56 | 57 | #### ends 58 | Checks if string ends with substring 59 | 60 | atom.string.ends( 'Hello, World!', 'Hello' ); // false 61 | atom.string.ends( 'Hello, World!', 'World!' ); // true 62 | 63 | #### ucfirst 64 | Uppercase first character 65 | 66 | atom.string.ucfirst( 'hello, world!' ); // 'Hello, world!' 67 | 68 | #### lcfirst 69 | Lowercase first character 70 | 71 | atom.string.lcfirst( 'Hello, world!' ); // 'hello, world!' 72 | -------------------------------------------------------------------------------- /Docs/En/Uri.md: -------------------------------------------------------------------------------- 1 | Atom Uri 2 | ======== 3 | 4 | ## atom.accessors.uri(str = location.href) 5 | 6 | Parse and returns object - parts of uri `str` 7 | 8 | Available such properties: 9 | 10 | * anchor 11 | * query 12 | * file 13 | * directory 14 | * path 15 | * relative 16 | * port 17 | * host 18 | * password 19 | * user 20 | * userInfo 21 | * authority 22 | * protocol 23 | * source 24 | * queryKey 25 | 26 | #### Result, absolute path `http://usr:pwd@www.example.com:81/dir/dir.2/index.htm?q1=0&&test1&test2=value#top`: 27 | 28 | anchor: 'top', 29 | query: 'q1=0&&test1&test2=value', 30 | file: 'index.htm', 31 | directory: '/dir/dir.2/', 32 | path: '/dir/dir.2/index.htm', 33 | relative: '/dir/dir.2/index.htm?q1=0&&test1&test2=value#top', 34 | port: '81', 35 | host: 'www.example.com', 36 | password: 'pwd', 37 | user: 'usr', 38 | userInfo: 'usr:pwd', 39 | authority: 'usr:pwd@www.example.com:81', 40 | protocol: 'http', 41 | source: uri, 42 | queryKey: { 43 | q1: '0', 44 | test1: '', 45 | test2: 'value' 46 | } 47 | 48 | #### Result, relative path `/dir/dir.2/index.htm?q1=0&&test1&test2=value#top`: 49 | 50 | anchor: 'top', 51 | query: 'q1=0&&test1&test2=value', 52 | file: 'index.htm', 53 | directory: '/dir/dir.2/', 54 | path: '/dir/dir.2/index.htm', 55 | relative: '/dir/dir.2/index.htm?q1=0&&test1&test2=value#top', 56 | port: '', 57 | host: '', 58 | password: '', 59 | user: '', 60 | userInfo: '', 61 | authority: '', 62 | protocol: '', 63 | source: uri, 64 | queryKey: { 65 | q1: '0', 66 | test1: '', 67 | test2: 'value' 68 | } 69 | 70 | #### Example: 71 | 72 | var uri = atom.uri('http://example.com?debug=1'); 73 | 74 | if (uri.queryKey.debug) initDebug(); 75 | 76 | #### Default parameter: 77 | 78 | var uri = atom.uri(); 79 | // equals to: 80 | var url = atom.uri(location.href); 81 | 82 | alert(uri.anchor); 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Atom 2 | ==== 3 | 4 | Atom is compact JavaScript framework oriented on modern browsers, which allows 5 | to support quite broad list of features without keeping a lot of cruft necessary 6 | to implement them in old browsers. 7 | 8 | Supported browsers: 9 | 10 | * Firefox 3.5+ 11 | * Google Chrome 12 | * Safari 4+ 13 | * Opera 10+ 14 | * Internet Explorer 9+ 15 | * Mobile Safari 16 | * Android Browser 17 | * Opera Mobile 18 | 19 | Distributed under terms of MIT or LGPL. 20 | 21 | Documentation: see [Docs folder](/master/Docs/En) for description of Atom core and bundled plugins. 22 | 23 | 24 | ## Integration 25 | 26 | * [Ruby on Rails gem](https://github.com/tanraya/atomjs-rails) 27 | 28 | -------------------------------------------------------------------------------- /Source/Accessors.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Accessors" 5 | 6 | description: "Implementing accessors" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | 15 | provides: accessors 16 | 17 | ... 18 | */ 19 | 20 | (function (Object) { 21 | var standard = !!Object.getOwnPropertyDescriptor, nonStandard = !!{}.__defineGetter__; 22 | 23 | if (!standard && !nonStandard) throw new Error('Accessors are not supported'); 24 | 25 | var lookup = nonStandard ? 26 | function (from, key, bool) { 27 | var g = from.__lookupGetter__(key), s = from.__lookupSetter__(key), has = !!(g || s); 28 | 29 | if (bool) return has; 30 | 31 | return has ? { get: g, set: s } : null; 32 | } : 33 | function (from, key, bool) { 34 | var descriptor = Object.getOwnPropertyDescriptor(from, key); 35 | if (!descriptor) { 36 | // try to find accessors according to chain of prototypes 37 | var proto = Object.getPrototypeOf(from); 38 | if (proto) return atom.accessors.lookup(proto, key, bool); 39 | } else if ( descriptor.set || descriptor.get ) { 40 | if (bool) return true; 41 | 42 | return { 43 | set: descriptor.set, 44 | get: descriptor.get 45 | }; 46 | } 47 | return bool ? false : null; 48 | }; /* lookup */ 49 | 50 | var define = nonStandard ? 51 | function (object, prop, descriptor) { 52 | if (descriptor) { 53 | if (descriptor.get) object.__defineGetter__(prop, descriptor.get); 54 | if (descriptor.set) object.__defineSetter__(prop, descriptor.set); 55 | } 56 | return object; 57 | } : 58 | function (object, prop, descriptor) { 59 | if (descriptor) { 60 | var desc = { 61 | get: descriptor.get, 62 | set: descriptor.set, 63 | configurable: true, 64 | enumerable: true 65 | }; 66 | Object.defineProperty(object, prop, desc); 67 | } 68 | return object; 69 | }; 70 | 71 | atom.accessors = { 72 | lookup: lookup, 73 | define: function (object, prop, descriptor) { 74 | if (typeof prop == 'object') { 75 | for (var i in prop) define(object, i, prop[i]); 76 | } else { 77 | define(object, prop, descriptor); 78 | } 79 | return object; 80 | }, 81 | has: function (object, key) { 82 | return atom.accessors.lookup(object, key, true); 83 | }, 84 | inherit: function (from, to, key) { 85 | var a = atom.accessors.lookup(from, key); 86 | 87 | if ( a ) { 88 | atom.accessors.define(to, key, a); 89 | return true; 90 | } 91 | return false; 92 | } 93 | }; 94 | })(Object); -------------------------------------------------------------------------------- /Source/Ajax.Dom.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Ajax.Dom" 5 | 6 | description: todo 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | - dom 15 | - ajax 16 | 17 | provides: ajax.dom 18 | 19 | ... 20 | */ 21 | 22 | atom.dom.prototype.ajax = function (config) { 23 | config = coreAppend({}, config); 24 | 25 | var $dom = this; 26 | 27 | if (config.onLoad ) { 28 | config.onLoad = config.onLoad.bind($dom); 29 | } else { 30 | config.onLoad = function (r) { $dom.first.innerHTML = r }; 31 | } 32 | if (config.onError) config.onError = config.onError.bind($dom); 33 | 34 | atom.ajax(config); 35 | return $dom; 36 | }; 37 | -------------------------------------------------------------------------------- /Source/Ajax.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Ajax" 5 | 6 | description: "todo" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | - CoreExtended 15 | 16 | provides: ajax 17 | 18 | ... 19 | */ 20 | 21 | (function () { 22 | var extend = atom.core.extend, emptyFn = function () {}; 23 | 24 | var ajax = function (userConfig) { 25 | var data, config, method, req, url; 26 | config = {}; 27 | extend(config, ajax.defaultProps); 28 | extend(config, userConfig); 29 | config.headers = {}; 30 | extend(config.headers, ajax.defaultHeaders); 31 | extend(config.headers, userConfig.headers); 32 | 33 | data = ajax.stringify( config.data ); 34 | req = new XMLHttpRequest(); 35 | url = config.url; 36 | method = config.method.toUpperCase(); 37 | if (method == 'GET' && data) { 38 | url += (url.indexOf( '?' ) == -1 ? '?' : '&') + data; 39 | } 40 | if (!config.cache) { 41 | url += (url.indexOf( '?' ) == -1 ? '?' : '&') + '_no_cache=' + Date.now(); 42 | } 43 | req.onreadystatechange = ajax.onready(req, config); 44 | req.open(method, url, true); 45 | for (var i in config.headers) { 46 | req.setRequestHeader(i, config.headers[i]); 47 | } 48 | req.send( method == 'POST' && data ? data : null ); 49 | }; 50 | 51 | ajax.stringify = function (object) { 52 | if (!object) return ''; 53 | if (typeof object == 'string' || typeof object == 'number') return String( object ); 54 | 55 | var array = [], e = encodeURIComponent; 56 | for (var i in object) if (object.hasOwnProperty(i)) { 57 | array.push( e(i) + '=' + e(object[i]) ); 58 | } 59 | return array.join('&'); 60 | }; 61 | 62 | ajax.defaultProps = { 63 | interval: 0, 64 | type : 'plain', 65 | method : 'post', 66 | data : {}, 67 | headers : {}, 68 | cache : false, 69 | url : location.href, 70 | onLoad : emptyFn, 71 | onError : emptyFn 72 | }; 73 | 74 | ajax.defaultHeaders = { 75 | 'X-Requested-With': 'XMLHttpRequest', 76 | 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' 77 | }; 78 | /** @type {function} */ 79 | ajax.onready = function (req, config) { 80 | return function (e) { 81 | if (req.readyState == 4) { 82 | if (req.status != 200) return config.onError(e); 83 | 84 | var result = req.responseText; 85 | if (config.type.toLowerCase() == 'json') { 86 | result = JSON.parse(result); 87 | } 88 | if (config.interval > 0) setTimeout(function () { 89 | atom.ajax(config); 90 | }, config.interval * 1000); 91 | config.onLoad(result); 92 | } 93 | }; 94 | }; 95 | 96 | atom.ajax = ajax; 97 | })(); 98 | -------------------------------------------------------------------------------- /Source/Class/BindAll.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Class.BindAll" 5 | 6 | description: "" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | - Class 15 | 16 | inspiration: 17 | - "[MooTools](http://mootools.net)" 18 | 19 | provides: Class.BindAll 20 | 21 | ... 22 | */ 23 | 24 | atom.Class.bindAll = function (object, methods) { 25 | if (typeof methods == 'string') { 26 | if ( 27 | methods != '$caller' && 28 | !atom.accessors.has(object, methods) && 29 | coreIsFunction(object[methods]) 30 | ) { 31 | object[methods] = object[methods].bind( object ); 32 | } 33 | } else if (methods) { 34 | for (var i = methods.length; i--;) atom.Class.bindAll( object, methods[i] ); 35 | } else { 36 | for (var i in object) atom.Class.bindAll( object, i ); 37 | } 38 | return object; 39 | }; 40 | -------------------------------------------------------------------------------- /Source/Class/Class.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Class" 5 | 6 | description: "Contains the Class Function for easily creating, extending, and implementing reusable Classes." 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | - CoreExtended 15 | - accessors 16 | - Array 17 | 18 | inspiration: 19 | - "[MooTools](http://mootools.net)" 20 | 21 | provides: Class 22 | 23 | deprecated: "Use declare instead" 24 | 25 | ... 26 | */ 27 | 28 | 29 | (function(atom){ 30 | 31 | var typeOf = atom.core.typeOf, 32 | extend = atom.core.extend, 33 | accessors = atom.accessors.inherit, 34 | prototype = 'prototype', 35 | lambda = function (value) { return function () { return value; }}, 36 | prototyping = false; 37 | 38 | var Class = function (params) { 39 | if (prototyping) return this; 40 | 41 | if (typeof params == 'function' && typeOf(params) == 'function') params = { initialize: params }; 42 | 43 | var Constructor = function(){ 44 | if (this instanceof Constructor) { 45 | if (prototyping) return this; 46 | return this.initialize ? this.initialize.apply(this, arguments) : this; 47 | } else { 48 | return Constructor.invoke.apply(Constructor, arguments); 49 | } 50 | }; 51 | extend(Constructor, Class); 52 | Constructor.prototype = getInstance(Class); 53 | 54 | Constructor 55 | .implement(params, false) 56 | .reserved(true, { 57 | parent: parent, 58 | self : Constructor 59 | }) 60 | .reserved({ 61 | factory : function() { 62 | function Factory(args) { return Constructor.apply(this, args); } 63 | Factory.prototype = Constructor.prototype; 64 | return function(args) { return new Factory(args || []); } 65 | }() 66 | }); 67 | 68 | Constructor.prototype.constructor = Constructor; 69 | 70 | return Constructor; 71 | }; 72 | 73 | var parent = function(){ 74 | if (!this.$caller) throw new Error('The method «parent» cannot be called.'); 75 | var name = this.$caller.$name, 76 | parent = this.$caller.$owner.parent, 77 | previous = parent && parent.prototype[name]; 78 | if (!previous) throw new Error('The method «' + name + '» has no parent.'); 79 | return previous.apply(this, arguments); 80 | }; 81 | 82 | var wrap = function(self, key, method){ 83 | // if method is already wrapped 84 | if (method.$origin) method = method.$origin; 85 | 86 | var wrapper = function() { 87 | if (!this || this == atom.global) throw new TypeError('Context lost'); 88 | if (method.$protected && !this.$caller) throw new Error('The method «' + key + '» is protected.'); 89 | var current = this.$caller; 90 | this.$caller = wrapper; 91 | var result = method.apply(this, arguments); 92 | this.$caller = current; 93 | return result; 94 | }; 95 | wrapper.$owner = self; 96 | wrapper.$origin = method; 97 | wrapper.$name = key; 98 | 99 | return wrapper; 100 | }; 101 | 102 | var getInstance = function(Class){ 103 | if (atom.declare && Class instanceof atom.declare) { 104 | return atom.declare.config.methods.proto(Class); 105 | } 106 | 107 | prototyping = true; 108 | var proto = new Class; 109 | prototyping = false; 110 | return proto; 111 | }; 112 | 113 | Class.extend = function (name, fn) { 114 | if (typeof name == 'string') { 115 | var object = {}; 116 | object[name] = fn; 117 | } else { 118 | object = name; 119 | } 120 | 121 | for (var i in object) if (!accessors(object, this, i)) { 122 | this[i] = object[i]; 123 | } 124 | return this; 125 | }; 126 | 127 | Class.extend({ 128 | implement: function(name, fn, retain){ 129 | if (typeof name == 'string') { 130 | var params = {}; 131 | params[name] = fn; 132 | } else { 133 | params = name; 134 | retain = fn; 135 | } 136 | 137 | for (var key in params) { 138 | if (!accessors(params, this.prototype, key)) { 139 | var value = params[key]; 140 | 141 | if (Class.Mutators.hasOwnProperty(key)){ 142 | value = Class.Mutators[key].call(this, value); 143 | if (value == null) continue; 144 | } 145 | 146 | if (typeof value == 'function' && typeOf(value) == 'function'){ 147 | if (value.$origin) value = value.$origin; 148 | if (value.$hidden == 'next') { 149 | value.$hidden = true 150 | } else if (value.$hidden) { 151 | continue; 152 | } 153 | this.prototype[key] = (retain) ? value : wrap(this, key, value); 154 | } else { 155 | this.prototype[key] = atom.clone(value); 156 | } 157 | } 158 | } 159 | return this; 160 | }, 161 | mixin: function () { 162 | Array.from(arguments).forEach(function (item) { 163 | this.implement(getInstance(item)); 164 | }.bind(this)); 165 | return this; 166 | }, 167 | reserved: function (toProto, props) { // use careful !! 168 | if (arguments.length == 1) { 169 | props = toProto; 170 | toProto = false; 171 | } 172 | var target = toProto ? this.prototype : this; 173 | for (var name in props) { 174 | atom.accessors.define(target, name, { get: lambda(props[name]) }); 175 | } 176 | return this; 177 | }, 178 | isInstance: function (object) { 179 | return object instanceof this; 180 | }, 181 | invoke: function () { 182 | return this.factory( arguments ); 183 | }, 184 | Mutators: { 185 | Extends: function(parent){ 186 | if (parent == null) throw new TypeError('Cant extends from null'); 187 | this.extend(parent).reserved({ parent: parent }); 188 | this.prototype = getInstance(parent); 189 | }, 190 | 191 | Implements: function(items){ 192 | this.mixin.apply(this, Array.from(items)); 193 | }, 194 | 195 | Static: function(properties) { 196 | this.extend(properties); 197 | } 198 | }, 199 | abstractMethod: function () { 200 | throw new Error('Abstract Method «' + this.$caller.$name + '» called'); 201 | }, 202 | protectedMethod: function (fn) { 203 | return extend(fn, { $protected: true }); 204 | }, 205 | hiddenMethod: function (fn) { 206 | return extend(fn, { $hidden: 'next' }); 207 | } 208 | }); 209 | 210 | Class.abstractMethod.$abstract = true; 211 | atom.Class = Class; 212 | 213 | })(atom); -------------------------------------------------------------------------------- /Source/Class/Events.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Class.Events" 5 | 6 | description: "" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | - Class 15 | 16 | inspiration: 17 | - "[MooTools](http://mootools.net)" 18 | 19 | provides: Class.Events 20 | 21 | ... 22 | */ 23 | 24 | new function () { 25 | 26 | var Class = atom.Class; 27 | 28 | var fire = function (name, fn, args) { 29 | var result = fn.apply(this, Array.from(args || [])); 30 | if (typeof result == 'string' && result.toLowerCase() == 'removeevent') { 31 | this.removeEvent(name, fn); 32 | } 33 | }; 34 | 35 | var removeOn = function(string){ 36 | return (string || '').replace(/^on([A-Z])/, function(full, first){ 37 | return first.toLowerCase(); 38 | }); 39 | }; 40 | 41 | var initEvents = function (object, reset) { 42 | if (reset || !object._events) object._events = { $ready: {} }; 43 | }; 44 | 45 | var nextTick = function (fn) { 46 | nextTick.fn.push(fn); 47 | if (!nextTick.id) { 48 | nextTick.id = function () { 49 | nextTick.reset().invoke(); 50 | }.delay(1); 51 | } 52 | }; 53 | nextTick.reset = function () { 54 | var fn = nextTick.fn; 55 | nextTick.fn = []; 56 | nextTick.id = 0; 57 | return fn; 58 | }; 59 | nextTick.reset(); 60 | 61 | coreAppend(Class, { 62 | Events: Class({ 63 | addEvent: function(name, fn) { 64 | initEvents(this); 65 | 66 | var i, l, onfinish = []; 67 | if (arguments.length == 1 && typeof name != 'string') { 68 | for (i in name) { 69 | this.addEvent(i, name[i]); 70 | } 71 | } else if (Array.isArray(name)) { 72 | for (i = 0, l = name.length; i < l; i++) { 73 | this.addEvent(name[i], fn); 74 | } 75 | } else { 76 | name = removeOn(name); 77 | if (name == '$ready') { 78 | throw new TypeError('Event name «$ready» is reserved'); 79 | } else if (!fn) { 80 | throw new TypeError('Function is empty'); 81 | } else { 82 | Object.ifEmpty(this._events, name, []); 83 | 84 | this._events[name].include(fn); 85 | 86 | var ready = this._events.$ready[name]; 87 | if (ready) fire.apply(this, [name, fn, ready, onfinish]); 88 | onfinish.invoke(); 89 | } 90 | } 91 | return this; 92 | }, 93 | removeEvent: function (name, fn) { 94 | if (!arguments.length) { 95 | initEvents( this, true ); 96 | return this; 97 | } 98 | 99 | initEvents(this); 100 | 101 | if (Array.isArray(name)) { 102 | for (var i = name.length; i--;) { 103 | this.removeEvent(name[i], fn); 104 | } 105 | } else if (arguments.length == 1 && typeof name != 'string') { 106 | for (i in name) { 107 | this.removeEvent(i, name[i]); 108 | } 109 | } else { 110 | name = removeOn(name); 111 | if (name == '$ready') { 112 | throw new TypeError('Event name «$ready» is reserved'); 113 | } else if (arguments.length == 1) { 114 | this._events[name] = []; 115 | } else if (name in this._events) { 116 | this._events[name].erase(fn); 117 | } 118 | } 119 | return this; 120 | }, 121 | isEventAdded: function (name) { 122 | initEvents(this); 123 | 124 | var e = this._events[name]; 125 | return !!(e && e.length); 126 | }, 127 | fireEvent: function (name, args) { 128 | initEvents(this); 129 | 130 | name = removeOn(name); 131 | // we should prevent skipping next event on removing this in different fireEvents 132 | var funcs = atom.clone(this._events[name]); 133 | if (funcs) { 134 | var l = funcs.length, 135 | i = 0; 136 | for (;i < l; i++) fire.call(this, name, funcs[i], args || []); 137 | } 138 | return this; 139 | }, 140 | readyEvent: function (name, args) { 141 | initEvents(this); 142 | 143 | nextTick(function () { 144 | name = removeOn(name); 145 | this._events.$ready[name] = args || []; 146 | this.fireEvent(name, args || []); 147 | }.bind(this)); 148 | return this; 149 | } 150 | }) 151 | }); 152 | 153 | }; -------------------------------------------------------------------------------- /Source/Class/Generators.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Class.Mutators.Generators" 5 | 6 | description: "Provides Generators mutator" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | authors: 13 | - "Shock " 14 | 15 | requires: 16 | - Core 17 | - accessors 18 | - Class 19 | 20 | provides: Class.Mutators.Generators 21 | 22 | ... 23 | */ 24 | 25 | new function () { 26 | 27 | var getter = function (key, fn) { 28 | return function() { 29 | var pr = '_' + key, obj = this; 30 | return pr in obj ? obj[pr] : (obj[pr] = fn.call(obj)); 31 | }; 32 | }; 33 | 34 | atom.Class.Mutators.Generators = function(properties) { 35 | atom.Class.Mutators.Generators.init(this, properties); 36 | }; 37 | 38 | atom.Class.Mutators.Generators.init = function (Class, properties) { 39 | for (var i in properties) atom.accessors.define(Class.prototype, i, { get: getter(i, properties[i]) }); 40 | }; 41 | 42 | }; -------------------------------------------------------------------------------- /Source/Class/Options.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Class.Options" 5 | 6 | description: "" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | - Class 15 | 16 | inspiration: 17 | - "[MooTools](http://mootools.net)" 18 | 19 | provides: Class.Options 20 | 21 | ... 22 | */ 23 | 24 | atom.Class.Options = atom.Class({ 25 | options: {}, 26 | fastSetOptions: false, 27 | setOptions: function(){ 28 | if (!this.options) { 29 | this.options = {}; 30 | } else if (this.options == this.self.prototype.options) { 31 | // it shouldn't be link to static options 32 | if (this.fastSetOptions) { 33 | this.options = coreAppend({}, this.options); 34 | } else { 35 | this.options = atom.clone(this.options); 36 | } 37 | } 38 | var options = this.options; 39 | 40 | for (var a = arguments, i = 0, l = a.length; i < l; i++) { 41 | if (typeof a[i] == 'object') { 42 | if (this.fastSetOptions) { 43 | coreAppend(options, a[i]); 44 | } else { 45 | atom.extend(options, a[i]); 46 | } 47 | } 48 | } 49 | 50 | if (this.addEvent) for (var option in options){ 51 | if (atom.typeOf(options[option]) == 'function' && (/^on[A-Z]/).test(option)) { 52 | this.addEvent(option, options[option]); 53 | delete options[option]; 54 | } 55 | } 56 | return this; 57 | } 58 | }); -------------------------------------------------------------------------------- /Source/Cookie.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Cookie" 5 | 6 | description: "todo" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | 15 | provides: cookie 16 | 17 | ... 18 | */ 19 | 20 | atom.cookie = { 21 | get: function (name) { 22 | var matches = document.cookie.match(new RegExp( 23 | "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)" 24 | )); 25 | return matches ? decodeURIComponent(matches[1]) : null; 26 | }, 27 | set: function (name, value, options) { 28 | options = options || {}; 29 | var exp = options.expires; 30 | if (exp) { 31 | if (typeof exp == 'number') { 32 | exp = new Date(exp * 1000 + Date.now()); 33 | } 34 | if (exp.toUTCString) { 35 | exp = exp.toUTCString(); 36 | } 37 | options.expires = exp; 38 | } 39 | 40 | var cookie = [name + "=" + encodeURIComponent(value)]; 41 | for (var o in options) cookie.push( 42 | options[o] === true ? o : o + "=" + options[o] 43 | ); 44 | document.cookie = cookie.join('; '); 45 | 46 | return atom.cookie; 47 | }, 48 | del: function (name) { 49 | return atom.cookie.set(name, '', { expires: -1 }); 50 | } 51 | }; -------------------------------------------------------------------------------- /Source/Core.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Core" 5 | 6 | description: "The core of AtomJS." 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | inspiration: 13 | - "[JQuery](http://jquery.com)" 14 | - "[MooTools](http://mootools.net)" 15 | 16 | provides: Core 17 | 18 | requires: 19 | - js185 20 | 21 | ... 22 | */ 23 | 24 | function coreIsFunction (item) { 25 | return item && toString.call(item) == '[object Function]'; 26 | } 27 | 28 | function coreObjectize (properties, value) { 29 | if (typeof properties != 'object') { 30 | var key = properties; 31 | properties = {}; 32 | if (key != null) { 33 | properties[key] = value; 34 | } 35 | } 36 | return properties; 37 | } 38 | 39 | function coreContains (array, element) { 40 | return array.indexOf(element) >= 0; 41 | } 42 | 43 | function includeUnique(array, element) { 44 | if (!coreContains(array, element)) { 45 | array.push(element); 46 | } 47 | return array; 48 | } 49 | 50 | function coreEraseOne(array, element) { 51 | element = array.indexOf(element); 52 | if (element != -1) { 53 | array.splice( element, 1 ); 54 | } 55 | return array; 56 | } 57 | 58 | function coreEraseAll(array, element) { 59 | for (var i = array.length; i--;) { 60 | if (array[i] == element) { 61 | array.splice( i, 1 ); 62 | } 63 | } 64 | return array; 65 | } 66 | function coreToArray (elem) { return slice.call(elem) } 67 | function coreIsArrayLike (item) { 68 | return item && (Array.isArray(item) || ( 69 | typeof item != 'string' && 70 | !coreIsFunction(item) && 71 | typeof item.nodeName != 'string' && 72 | typeof item.length == 'number' 73 | )); 74 | } 75 | function coreAppend(target, source) { 76 | if (source) for (var key in source) if (hasOwn.call(source, key)) { 77 | target[key] = source[key]; 78 | } 79 | return target; 80 | } 81 | 82 | new function () { 83 | 84 | function ensureObjectSetter (fn) { 85 | return function (properties, value) { 86 | return fn.call(this, coreObjectize(properties, value)) 87 | } 88 | } 89 | function overloadSetter (fn) { 90 | return function (properties, value) { 91 | properties = coreObjectize(properties, value); 92 | for (var i in properties) fn.call( this, i, properties[i] ); 93 | return this; 94 | }; 95 | } 96 | function overloadGetter (fn, ignoreEmpty) { 97 | return function (properties) { 98 | if (Array.isArray(properties)) { 99 | var result = {}, name, value; 100 | for (var i = properties.length; i--;) { 101 | name = properties[i]; 102 | value = fn.call(this, name); 103 | if (!ignoreEmpty || typeof value !== 'undefined') { 104 | result[name] = value; 105 | } 106 | } 107 | return result; 108 | } 109 | return fn.call(this, properties); 110 | }; 111 | } 112 | /** 113 | * Returns function that calls callbacks.get 114 | * if first parameter is primitive & second parameter is undefined 115 | * object.attr('name') - get 116 | * object.attr('name', 'value') - set 117 | * object.attr({name: 'value'}) - set 118 | * @param {Object} callbacks 119 | * @param {Function} callbacks.get 120 | * @param {Function} callbacks.set 121 | */ 122 | function slickAccessor (callbacks) { 123 | var setter = atom.core.overloadSetter(callbacks.set); 124 | 125 | return function (properties, value) { 126 | if (typeof value === 'undefined' && typeof properties !== 'object') { 127 | return callbacks.get.call(this, properties); 128 | } else { 129 | return setter.call(this, properties, value); 130 | } 131 | }; 132 | } 133 | 134 | atom.core = { 135 | isFunction: coreIsFunction, 136 | objectize : coreObjectize, 137 | contains : coreContains, 138 | eraseOne : coreEraseOne, 139 | eraseAll : coreEraseAll, 140 | toArray : coreToArray, 141 | append : coreAppend, 142 | isArrayLike : coreIsArrayLike, 143 | includeUnique : includeUnique, 144 | slickAccessor : slickAccessor, 145 | overloadSetter: overloadSetter, 146 | overloadGetter: overloadGetter, 147 | ensureObjectSetter: ensureObjectSetter 148 | }; 149 | 150 | /** @deprecated - use atom.core.toArray instead */ 151 | atom.toArray = coreToArray; 152 | /** @deprecated - use console-cap instead: https://github.com/theshock/console-cap/ */ 153 | atom.log = function () { throw new Error('deprecated') }; 154 | /** @deprecated - use atom.core.isArrayLike instead */ 155 | atom.isArrayLike = coreIsArrayLike; 156 | /** @deprecated - use atom.core.append instead */ 157 | atom.append = coreAppend; 158 | 159 | }; -------------------------------------------------------------------------------- /Source/CoreExtended.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "CoreExtended" 5 | 6 | description: "Extended core of AtomJS - extend, implements, clone, typeOf" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | inspiration: 13 | - "[JQuery](http://jquery.com)" 14 | - "[MooTools](http://mootools.net)" 15 | 16 | provides: CoreExtended 17 | 18 | requires: 19 | - js185 20 | - Core 21 | 22 | ... 23 | */ 24 | 25 | new function () { 26 | 27 | function innerExtend (proto) { 28 | return function (elem, from) { 29 | if (from == null) { 30 | from = elem; 31 | elem = atom; 32 | } 33 | 34 | var ext = proto ? elem.prototype : elem, 35 | accessors = atom.accessors && atom.accessors.inherit; 36 | 37 | for (var i in from) if (i != 'constructor') { 38 | if ( accessors && accessors(from, ext, i) ) continue; 39 | 40 | ext[i] = clone(from[i]); 41 | } 42 | return elem; 43 | }; 44 | } 45 | 46 | function typeOf (item) { 47 | if (item == null) return 'null'; 48 | 49 | var string = toString.call(item); 50 | for (var i in typeOf.types) if (i == string) return typeOf.types[i]; 51 | 52 | if (item.nodeName){ 53 | if (item.nodeType == 1) return 'element'; 54 | if (item.nodeType == 3) return /\S/.test(item.nodeValue) ? 'textnode' : 'whitespace'; 55 | } 56 | 57 | var type = typeof item; 58 | 59 | if (item && type == 'object') { 60 | if (atom.Class && item instanceof atom.Class) return 'class'; 61 | if (coreIsArrayLike(item)) return 'arguments'; 62 | } 63 | 64 | return type; 65 | } 66 | 67 | typeOf.types = {}; 68 | ['Boolean', 'Number', 'String', 'Function', 'Array', 'Date', 'RegExp', 'Class'].forEach(function(name) { 69 | typeOf.types['[object ' + name + ']'] = name.toLowerCase(); 70 | }); 71 | 72 | 73 | function clone (object) { 74 | var type = typeOf(object); 75 | return type in clone.types ? clone.types[type](object) : object; 76 | } 77 | clone.types = { 78 | 'array': function (array) { 79 | var i = array.length, c = new Array(i); 80 | while (i--) c[i] = clone(array[i]); 81 | return c; 82 | }, 83 | 'class':function (object) { 84 | return typeof object.clone == 'function' ? 85 | object.clone() : object; 86 | }, 87 | 'object': function (object) { 88 | if (typeof object.clone == 'function') return object.clone(); 89 | 90 | var c = {}, accessors = atom.accessors && atom.accessors.inherit; 91 | for (var key in object) { 92 | if (accessors && accessors(object, c, key)) continue; 93 | c[key] = clone(object[key]); 94 | } 95 | return c; 96 | } 97 | }; 98 | 99 | atom.core.extend = innerExtend(false); 100 | atom.core.implement = innerExtend(true); 101 | atom.core.typeOf = typeOf; 102 | atom.core.clone = clone; 103 | 104 | atom.extend = atom.core.extend; 105 | atom.implement = atom.core.implement; 106 | atom.typeOf = atom.core.typeOf; 107 | atom.clone = atom.core.clone; 108 | 109 | }; -------------------------------------------------------------------------------- /Source/Declare/Animatable.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Animatable" 5 | 6 | description: "Provides Color class" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | - declare 15 | - frame 16 | - Transition 17 | - Events 18 | - Settings 19 | - Types.Object 20 | 21 | provides: Animatable 22 | 23 | ... 24 | */ 25 | 26 | /** @class atom.Animatable */ 27 | declare( 'atom.Animatable', { 28 | 29 | element: null, 30 | 31 | initialize: function (callbacks, context) { 32 | this.bindMethods('animate'); 33 | this.context = context || null; 34 | 35 | if (!callbacks) throw new TypeError( 'callbacks cant be null' ); 36 | 37 | this.animations = []; 38 | if (this.isValidCallbacks(callbacks)) { 39 | this.callbacks = callbacks; 40 | } else { 41 | this.callbacks = this.getDefaultCallbacks(callbacks); 42 | } 43 | }, 44 | 45 | get current () { 46 | return this.animations[0]; 47 | }, 48 | 49 | /** 50 | * Binded to `Animatable` 51 | * @returns {atom.Animatable.Animation} 52 | */ 53 | animate: atom.core.ensureObjectSetter(function (properties) { 54 | return this.next(new atom.Animatable.Animation(this, properties)); 55 | }), 56 | 57 | stop: function (all) { 58 | var current = this.current; 59 | if (current) { 60 | if (all) this.animations.length = 0; 61 | current.destroy('stop'); 62 | } 63 | return this; 64 | }, 65 | 66 | /** @private */ 67 | getDefaultCallbacks: function (element) { 68 | return { 69 | get: function (property) { 70 | return atom.object.path.get(element, property); 71 | }, 72 | set: atom.core.overloadSetter(function (property, value) { 73 | return atom.object.path.set(element, property, value); 74 | }) 75 | }; 76 | }, 77 | /** @private */ 78 | isValidCallbacks: function (callbacks) { 79 | return typeof callbacks == 'object' && 80 | Object.keys(callbacks).length == 2 && 81 | coreIsFunction(callbacks.set) && 82 | coreIsFunction(callbacks.get); 83 | }, 84 | 85 | /** @private */ 86 | animations: null, 87 | 88 | /** @private */ 89 | next: function (animation) { 90 | var queue = this.animations; 91 | if (animation) { 92 | queue.push(animation); 93 | if (queue.length == 1) { 94 | this.launch(animation); 95 | } 96 | } else if (queue.length) { 97 | this.launch(this.current); 98 | } 99 | return animation; 100 | }, 101 | /** @private */ 102 | launch: function (animation) { 103 | var queue = this.animations, animatable = this; 104 | animation.events.add('destroy', function remove () { 105 | queue.splice(queue.indexOf(animation), 1); 106 | animation.events.remove('destroy', remove); 107 | animatable.next(); 108 | }); 109 | animation.start(); 110 | }, 111 | /** @private */ 112 | get: function (name) { 113 | return this.callbacks.get.apply(this.context, arguments); 114 | }, 115 | /** @private */ 116 | set: function (name, value) { 117 | return this.callbacks.set.apply(this.context, arguments); 118 | } 119 | }); 120 | 121 | /** @class atom.Animatable.Animation */ 122 | declare( 'atom.Animatable.Animation', { 123 | /** @property {atom.Animatable} */ 124 | animatable: null, 125 | 126 | /** 127 | * initial values of properties 128 | * @property {Object} 129 | */ 130 | initial: null, 131 | 132 | /** 133 | * target values of properties 134 | * @property {Object} 135 | */ 136 | target: null, 137 | 138 | initialize: function (animatable, settings) { 139 | this.bindMethods([ 'tick', 'start' ]); 140 | 141 | if (!settings.props) settings = {props: settings}; 142 | this.events = new atom.Events(animatable); 143 | this.settings = new atom.Settings({ 144 | fn : 'linear', 145 | time: 500 146 | }) 147 | .set(settings) 148 | .addEvents(this.events); 149 | this.animatable = animatable; 150 | this.transition = atom.Transition.get(this.settings.get('fn')); 151 | this.allTime = this.settings.get('time'); 152 | this.target = this.settings.get('props'); 153 | }, 154 | 155 | start: function () { 156 | this.initial = this.fetchInitialValues(); 157 | this.delta = this.countValuesDelta(); 158 | this.timeLeft = this.allTime; 159 | this.events.fire( 'start', [ this ]); 160 | atom.frame.add(this.tick); 161 | return this; 162 | }, 163 | 164 | /** @private */ 165 | countValuesDelta: function () { 166 | var initial = this.initial; 167 | return atom.object.map(this.target, function (value, key) { 168 | var start = initial[key]; 169 | if (atom.Color && start instanceof atom.Color) { 170 | return start.diff( new atom.Color(value) ); 171 | } else { 172 | return value - start; 173 | } 174 | }); 175 | }, 176 | 177 | /** @private */ 178 | fetchInitialValues: function () { 179 | var animatable = this.animatable; 180 | return atom.object.map(this.target, function (value, key) { 181 | var v = animatable.get(key); 182 | if (atom.Color && atom.Color.isColorString(value) || value instanceof atom.Color) { 183 | if (!v) { 184 | v = new atom.Color(value); 185 | v.alpha = 0; 186 | return v; 187 | } 188 | return new atom.Color(v); 189 | } else if (isNaN(v)) { 190 | throw new Error('value is not animatable: ' + v); 191 | } else { 192 | return v; 193 | } 194 | }); 195 | }, 196 | 197 | /** @private */ 198 | changeValues: function (progress) { 199 | var delta = this.delta, animatable = this.animatable, initial, target; 200 | for (var i in delta) if (delta.hasOwnProperty(i)) { 201 | if (progress == null) { 202 | target = this.target[i]; 203 | animatable.set( i, 204 | atom.Color && target instanceof atom.Color 205 | ? target.toString() : target 206 | ); 207 | } else { 208 | initial = this.initial[i]; 209 | animatable.set( i, 210 | atom.Color && initial instanceof atom.Color ? 211 | initial.clone().move(delta[i].clone().mul(progress)).toString() : 212 | initial + delta[i] * progress 213 | ); 214 | } 215 | } 216 | }, 217 | 218 | /** @private */ 219 | tick: function (time) { 220 | var lastTick = time >= this.timeLeft; 221 | this.timeLeft = lastTick ? 0 : this.timeLeft - time; 222 | 223 | this.changeValues(this.transition( 224 | lastTick ? 1 : (this.allTime - this.timeLeft) / this.allTime 225 | )); 226 | this.events.fire( 'tick', [ this ]); 227 | 228 | if (lastTick) this.destroy('complete'); 229 | }, 230 | 231 | destroy: function (type) { 232 | if (!type) type = 'error'; 233 | this.events.fire( type, [ this ]); 234 | this.events.fire( 'destroy', [ this ]); 235 | atom.frame.remove(this.tick); 236 | return this; 237 | } 238 | }); 239 | 240 | if (atom.dom) (function (animatable) { 241 | var accessors = { 242 | get: function (name) { 243 | var value = this.css(name); 244 | return atom.Color && atom.Color.isColorString(value) ? value : parseFloat(value); 245 | }, 246 | set: function (name, value) { 247 | this.css(name, value); 248 | } 249 | }; 250 | 251 | atom.dom.prototype.animate = atom.core.ensureObjectSetter(function (params) { 252 | this.each(function (elem) { 253 | if (!elem[animatable]) { 254 | elem[animatable] = new atom.Animatable(accessors, atom.dom(elem)); 255 | } 256 | elem[animatable].animate(params); 257 | }); 258 | return this 259 | }); 260 | 261 | atom.dom.prototype.stopAnimation = function (force) { 262 | this.each(function (elem) { 263 | if (elem[animatable]) { 264 | elem[animatable].stop(force); 265 | } 266 | }); 267 | return this; 268 | }; 269 | })('atom.animatable'); -------------------------------------------------------------------------------- /Source/Declare/ClassCompat.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "ClassCompat" 5 | 6 | description: "Contains the Class Function for easily creating, extending, and implementing reusable Classes." 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | - CoreExtended 15 | - declare 16 | 17 | provides: ClassCompat 18 | ... 19 | */ 20 | 21 | declare( 'atom.Settings.Mixin', 22 | /** @deprecated */ 23 | { 24 | /** 25 | * @private 26 | * @property atom.Settings 27 | */ 28 | settings: null, 29 | options : {}, 30 | 31 | setOptions: function (options) { 32 | if (!this.settings) { 33 | this.settings = new atom.Settings( 34 | atom.clone(this.options || {}) 35 | ); 36 | this.options = this.settings.values; 37 | } 38 | 39 | for (var i = 0; i < arguments.length; i++) { 40 | this.settings.set(arguments[i]); 41 | } 42 | 43 | return this; 44 | } 45 | }); 46 | 47 | declare( 'atom.Events.Mixin', new function () { 48 | var init = function () { 49 | var events = this.__events; 50 | if (!events) events = this.__events = new atom.Events(this); 51 | if (this._events) { 52 | for (var name in this._events) if (name != '$ready') { 53 | this._events[name].forEach(function (fn) { 54 | events.add(name, fn); 55 | }); 56 | } 57 | } 58 | return events; 59 | }; 60 | 61 | var method = function (method, useReturn) { 62 | return function () { 63 | var result, events = init.call(this); 64 | 65 | result = events[method].apply( events, arguments ); 66 | return useReturn ? result : this; 67 | } 68 | }; 69 | 70 | return { 71 | get events ( ) { return init.call(this); }, 72 | set events (e) { this.__events = e; }, 73 | isEventAdded: method( 'exists', true ), 74 | addEvent : method( 'add' , false ), 75 | removeEvent : method( 'remove', false ), 76 | fireEvent : method( 'fire' , false ), 77 | readyEvent : method( 'ready' , false ) 78 | }; 79 | }); -------------------------------------------------------------------------------- /Source/Declare/Color.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Color" 5 | 6 | description: "Provides Color class" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | - declare 15 | 16 | provides: Color 17 | 18 | ... 19 | */ 20 | /** @class atom.Color */ 21 | declare( 'atom.Color', { 22 | initialize: function (value) { 23 | var a = arguments, type; 24 | if (a.length == 4 || a.length == 3) { 25 | value = slice.call(a); 26 | } else if (value && value.length == 1) { 27 | value = value[0]; 28 | } 29 | 30 | type = typeof value; 31 | if (Array.isArray(value)) { 32 | this.fromArray(value); 33 | } else if (type == 'number') { 34 | this.fromNumber(value); 35 | } else if (type == 'string') { 36 | this.fromString(value); 37 | } else if (type == 'object') { 38 | this.fromObject(value); 39 | } else { 40 | throw new TypeError('Unknown type in atom.Color: ' + typeof value + ';\n' + value); 41 | } 42 | }, 43 | 44 | /** @private */ 45 | r: 0, 46 | /** @private */ 47 | g: 0, 48 | /** @private */ 49 | b: 0, 50 | /** @private */ 51 | a: 1, 52 | 53 | /** 54 | * We are array-like object (looks at accessors at bottom of class) 55 | * @constant 56 | */ 57 | length: 4, 58 | 59 | noLimits: false, 60 | 61 | get red () { return this.r; }, 62 | get green () { return this.g; }, 63 | get blue () { return this.b; }, 64 | get alpha () { return this.a; }, 65 | 66 | set red (v) { this.setValue('r', v) }, 67 | set green (v) { this.setValue('g', v) }, 68 | set blue (v) { this.setValue('b', v) }, 69 | set alpha (v) { this.setValue('a', v, true) }, 70 | 71 | /** @private */ 72 | safeAlphaSet: function (v) { 73 | if (v != null) { 74 | this.alpha = Math.round(v*1000)/1000; 75 | } 76 | }, 77 | 78 | /** @private */ 79 | setValue: function (prop, value, isFloat) { 80 | value = Number(value); 81 | if (value != value) { // isNaN 82 | throw new TypeError('Value is NaN (' + prop + '): ' + value); 83 | } 84 | 85 | if (!isFloat) value = Math.round(value); 86 | // We don't want application down, if user script (e.g. animation) 87 | // generates such wrong array: [150, 125, -1] 88 | // `noLimits` switch off this check 89 | this[prop] = this.noLimits ? value : 90 | atom.number.limit( value, 0, isFloat ? 1 : 255 ); 91 | }, 92 | 93 | // Parsing 94 | 95 | /** 96 | * @param {int[]} array 97 | * @returns {atom.Color} 98 | */ 99 | fromArray: function (array) { 100 | if (!array || array.length < 3 || array.length > 4) { 101 | throw new TypeError('Wrong array in atom.Color: ' + array); 102 | } 103 | this.red = array[0]; 104 | this.green = array[1]; 105 | this.blue = array[2]; 106 | this.safeAlphaSet(array[3]); 107 | return this; 108 | }, 109 | /** 110 | * @param {Object} object 111 | * @param {number} object.red 112 | * @param {number} object.green 113 | * @param {number} object.blue 114 | * @returns {atom.Color} 115 | */ 116 | fromObject: function (object) { 117 | if (typeof object != 'object') { 118 | throw new TypeError( 'Not object in "fromObject": ' + typeof object ); 119 | } 120 | 121 | function fetch (p1, p2) { 122 | return object[p1] != null ? object[p1] : object[p2] 123 | } 124 | 125 | this.red = fetch('r', 'red' ); 126 | this.green = fetch('g', 'green'); 127 | this.blue = fetch('b', 'blue' ); 128 | this.safeAlphaSet(fetch('a', 'alpha')); 129 | return this; 130 | }, 131 | /** 132 | * @param {string} string 133 | * @returns {atom.Color} 134 | */ 135 | fromString: function (string) { 136 | if (!this.constructor.isColorString(string)) { 137 | throw new TypeError( 'Not color string in "fromString": ' + string ); 138 | } 139 | 140 | var hex, array; 141 | 142 | string = string.toLowerCase(); 143 | string = this.constructor.colorNames[string] || string; 144 | 145 | if (hex = string.match(/^#(\w{1,2})(\w{1,2})(\w{1,2})(\w{1,2})?$/)) { 146 | array = atom.array.clean(hex.slice(1)); 147 | array = array.map(function (part) { 148 | if (part.length == 1) part += part; 149 | return parseInt(part, 16); 150 | }); 151 | if (array.length == 4) array[3] /= 255; 152 | } else { 153 | array = string.match(/([\.\d]{1,})/g).map( Number ); 154 | } 155 | return this.fromArray(array); 156 | }, 157 | /** 158 | * @param {number} number 159 | * @returns {atom.Color} 160 | */ 161 | fromNumber: function (number) { 162 | if (typeof number != 'number' || number < 0 || number > 0xffffffff) { 163 | throw new TypeError( 'Not color number in "fromNumber": ' + (number.toString(16)) ); 164 | } 165 | 166 | return this.fromArray([ 167 | (number>>24) & 0xff, 168 | (number>>16) & 0xff, 169 | (number>> 8) & 0xff, 170 | (number & 0xff) / 255 171 | ]); 172 | }, 173 | 174 | // Casting 175 | 176 | /** @returns {int[]} */ 177 | toArray: function () { 178 | return [this.r, this.g, this.b, this.a]; 179 | }, 180 | /** @returns {string} */ 181 | toString: function (type) { 182 | var arr = this.toArray(); 183 | if (type == 'hex' || type == 'hexA') { 184 | return '#' + arr.map(function (color, i) { 185 | if (i == 3) { // alpha 186 | if (type == 'hex') return ''; 187 | color = Math.round(color * 255); 188 | } 189 | var bit = color.toString(16); 190 | return bit.length == 1 ? '0' + bit : bit; 191 | }).join(''); 192 | } else { 193 | return 'rgba(' + arr + ')'; 194 | } 195 | }, 196 | /** @returns {number} */ 197 | toNumber: function () { 198 | // maybe needs optimizations 199 | return parseInt( this.toString('hexA').substr(1) , 16) 200 | }, 201 | /** @returns {object} */ 202 | toObject: function (abbreviationNames) { 203 | return abbreviationNames ? 204 | { r : this.r, g : this.g, b : this.b, a : this.a } : 205 | { red: this.r, green: this.g, blue: this.b, alpha: this.a }; 206 | }, 207 | 208 | // manipulations 209 | 210 | /** 211 | * @param {atom.Color} color 212 | * @returns {atom.Color} 213 | */ 214 | diff: function (color) { 215 | // we can't use this.constructor, because context exists in such way 216 | // && invoke is not called 217 | color = atom.Color( color ); 218 | return new atom.Color.Shift([ 219 | color.red - this.red , 220 | color.green - this.green, 221 | color.blue - this.blue , 222 | color.alpha - this.alpha 223 | ]); 224 | }, 225 | /** 226 | * @param {atom.Color} color 227 | * @returns {atom.Color} 228 | */ 229 | move: function (color) { 230 | color = atom.Color.Shift(color); 231 | this.red += color.red ; 232 | this.green += color.green; 233 | this.blue += color.blue ; 234 | this.alpha += color.alpha; 235 | return this; 236 | }, 237 | /** @deprecated - use `clone`+`move` instead */ 238 | shift: function (color) { 239 | return this.clone().move(color); 240 | }, 241 | map: function (fn) { 242 | var color = this; 243 | ['red', 'green', 'blue', 'alpha'].forEach(function (component) { 244 | color[component] = fn.call( color, color[component], component, color ); 245 | }); 246 | return color; 247 | }, 248 | add: function (factor) { 249 | return this.map(function (value) { 250 | return value + factor; 251 | }); 252 | }, 253 | mul: function (factor) { 254 | return this.map(function (value) { 255 | return value * factor; 256 | }); 257 | }, 258 | /** 259 | * @param {atom.Color} color 260 | * @returns {boolean} 261 | */ 262 | equals: function (color) { 263 | return color && 264 | color instanceof this.constructor && 265 | color.red == this.red && 266 | color.green == this.green && 267 | color.blue == this.blue && 268 | color.alpha == this.alpha; 269 | }, 270 | 271 | /** @private */ 272 | dump: function () { 273 | return '[atom.Color(' + this.toString('hexA') + ')]'; 274 | }, 275 | 276 | /** 277 | * @returns {atom.Color} 278 | */ 279 | clone: function () { 280 | return new this.constructor(this); 281 | } 282 | }).own({ 283 | invoke: declare.castArguments, 284 | 285 | /** 286 | * Checks if string is color description 287 | * @param {string} string 288 | * @returns {boolean} 289 | */ 290 | isColorString : function (string) { 291 | if (typeof string != 'string') return false; 292 | return Boolean( 293 | string in this.colorNames || 294 | string.match(/^#\w{3,6}$/) || 295 | string.match(/^rgba?\([\d\., ]+\)$/) 296 | ); 297 | }, 298 | 299 | colorNames: { 300 | white: '#ffffff', 301 | silver: '#c0c0c0', 302 | gray: '#808080', 303 | black: '#000000', 304 | red: '#ff0000', 305 | maroon: '#800000', 306 | yellow: '#ffff00', 307 | olive: '#808000', 308 | lime: '#00ff00', 309 | green: '#008000', 310 | aqua: '#00ffff', 311 | teal: '#008080', 312 | blue: '#0000ff', 313 | navy: '#000080', 314 | fuchsia:'#ff00ff', 315 | purple: '#800080', 316 | orange: '#ffa500' 317 | }, 318 | 319 | /** 320 | * @param {boolean} [html=false] - only html color names 321 | * @returns {atom.Color} 322 | */ 323 | random: function (html) { 324 | var source, random = atom.number.random; 325 | 326 | if (html) { 327 | source = atom.array.random( this.colorNamesList ); 328 | } else { 329 | source = [ random(0, 255), random(0, 255), random(0, 255) ]; 330 | } 331 | 332 | return new this(source); 333 | } 334 | }); 335 | 336 | atom.Color.colorNamesList = Object.keys(atom.Color.colorNames); 337 | 338 | /** @class atom.Color.Shift */ 339 | declare( 'atom.Color.Shift', atom.Color, { noLimits: true }); -------------------------------------------------------------------------------- /Source/Declare/Declare.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Declare" 5 | 6 | description: "Contains the Class Function for easily creating, extending, and implementing reusable Classes." 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | - accessors 15 | 16 | provides: declare 17 | 18 | ... 19 | */ 20 | 21 | var declare = (function(atom){ 22 | 23 | var 24 | declare, methods, 25 | accessors = atom.accessors.inherit, 26 | factory = false, 27 | prototyping = false, 28 | mutators = []; 29 | 30 | declare = function (declareName, Parent, params) { 31 | if (prototyping) return this; 32 | 33 | params = methods.prepareParams(declareName, Parent, params); 34 | 35 | // line break for more user-friendly debug string 36 | var Constructor = function () 37 | { return methods.construct.call(this, Constructor, arguments) }; 38 | 39 | // - should be removed on production 40 | if (params.name) { 41 | Constructor = new Function('con', 'return {"' + params.name + '": ' + 42 | function(){ return con.apply(this, arguments) } 43 | + '}["' + params.name + '"];')(Constructor); 44 | } 45 | // 46 | 47 | for (var i = 0, l = mutators.length; i < l; i++) { 48 | mutators[i].fn( Constructor, params[mutators[i].name] ); 49 | } 50 | 51 | Constructor.prototype.constructor = Constructor; 52 | 53 | if (params.declareName) methods.define( params.declareName, Constructor ); 54 | 55 | return Constructor; 56 | }; 57 | 58 | declare.prototype.bindMethods = function (methods) { 59 | var i; 60 | 61 | if (typeof methods == 'string') { 62 | if (typeof this[methods] == 'function') { 63 | this[methods] = this[methods].bind(this); 64 | } 65 | return this; 66 | } 67 | 68 | if (!methods) { 69 | for (i in this) this.bindMethods(i); 70 | return this; 71 | } 72 | 73 | for (i = methods.length; i--;) this.bindMethods( methods[i] ); 74 | return this; 75 | }; 76 | 77 | declare.prototype.toString = function () { 78 | return '[object ' + (this.constructor.NAME || 'Declare') + ']'; 79 | }; 80 | 81 | declare.NAME = 'atom.declare'; 82 | 83 | declare.invoke = function () { 84 | return this.factory( arguments ); 85 | }; 86 | 87 | declare.own = function (properties) { 88 | methods.addTo(this, properties, this.NAME + '.'); 89 | return this; 90 | }; 91 | 92 | declare.factory = function (args) { 93 | factory = true; 94 | return new this(args); 95 | }; 96 | 97 | declare.castArguments = function (args) { 98 | if (args == null) return null; 99 | 100 | var constructor = this; 101 | 102 | return (args != null && args[0] && args[0] instanceof constructor) ? 103 | args[0] : args instanceof constructor ? args : new constructor( args ); 104 | }; 105 | 106 | methods = { 107 | define: function (path, value) { 108 | var key, part, target = atom.global; 109 | 110 | path = path.split('.'); 111 | key = path.pop(); 112 | 113 | while (path.length) { 114 | part = path.shift(); 115 | if (!target[part]) { 116 | target = target[part] = {}; 117 | } else { 118 | target = target[part]; 119 | } 120 | } 121 | 122 | target[key] = value; 123 | }, 124 | mixin: function (target, items) { 125 | if (!Array.isArray(items)) items = [ items ]; 126 | for (var i = 0, l = items.length; i < l; i++) { 127 | methods.addTo( target.prototype, methods.proto(items[i]) ); 128 | } 129 | return this; 130 | }, 131 | addTo: function (target, source, name) { 132 | var i, property; 133 | if (source) for (i in source) if (source.hasOwnProperty(i)) { 134 | if (!accessors(source, target, i) && source[i] != declare.config) { 135 | property = source[i]; 136 | if (coreIsFunction(property)) { 137 | if (name) property.path = name + i; 138 | if (!property.previous && coreIsFunction(target[i])) { 139 | property.previous = target[i]; 140 | } 141 | } 142 | target[i] = property; 143 | } 144 | } 145 | return target; 146 | }, 147 | prepareParams: function (declareName, Parent, params) { 148 | if (typeof declareName != 'string') { 149 | params = Parent; 150 | Parent = declareName; 151 | declareName = null; 152 | } 153 | 154 | if (params == null && typeof Parent != 'function') { 155 | params = Parent; 156 | Parent = null; 157 | } 158 | 159 | if (!params ) params = {}; 160 | if (!params.prototype ) params = { prototype: params }; 161 | if (!params.name ) params.name = declareName; 162 | if (!params.declareName ) params.declareName = declareName; 163 | if (!params.parent && Parent) params.parent = Parent; 164 | 165 | if (!params.prototype.initialize) { 166 | params.prototype.initialize = function () { 167 | if (!params.parent) return; 168 | return params.parent.prototype.initialize.apply(this, arguments); 169 | }; 170 | } 171 | return params; 172 | }, 173 | proto: function (Fn) { 174 | prototyping = true; 175 | var result = new Fn; 176 | prototyping = false; 177 | return result; 178 | }, 179 | construct: function (Constructor, args) { 180 | if (factory) { 181 | args = args[0]; 182 | factory = false; 183 | } 184 | 185 | if (prototyping) return this; 186 | 187 | if (this instanceof Constructor) { 188 | if (Constructor.NAME) this.Constructor = Constructor.NAME; 189 | return this.initialize.apply(this, args); 190 | } else { 191 | return Constructor.invoke.apply(Constructor, args); 192 | } 193 | } 194 | }; 195 | 196 | declare.config = { 197 | methods: methods, 198 | mutator: atom.core.overloadSetter(function (name, fn) { 199 | mutators.push({ name: name, fn: fn }); 200 | return this; 201 | }) 202 | }; 203 | 204 | declare.config 205 | .mutator( 'parent', function (Constructor, parent) { 206 | parent = parent || declare; 207 | methods.addTo( Constructor, parent ); 208 | Constructor.prototype = methods.proto( parent ); 209 | Constructor.Parent = parent; 210 | }) 211 | .mutator( 'mixin', function (Constructor, mixins) { 212 | if (mixins) methods.mixin( Constructor, mixins ); 213 | }) 214 | .mutator( 'name', function (Constructor, name) { 215 | if (!name) return; 216 | Constructor.NAME = name; 217 | }) 218 | .mutator( 'own', function (Constructor, properties) { 219 | Constructor.own(properties); 220 | }) 221 | .mutator( 'prototype', function (Constructor, properties) { 222 | methods.addTo(Constructor.prototype, properties, Constructor.NAME + '#'); 223 | }); 224 | 225 | return atom.declare = declare; 226 | 227 | })(atom); -------------------------------------------------------------------------------- /Source/Declare/Events.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Events" 5 | 6 | description: "" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | - declare 15 | 16 | inspiration: 17 | - "[MooTools](http://mootools.net)" 18 | 19 | provides: Events 20 | 21 | ... 22 | */ 23 | 24 | /** @class atom.Events */ 25 | declare( 'atom.Events', { 26 | 27 | /** @constructs */ 28 | initialize: function (context) { 29 | this.context = context || this; 30 | this.locked = []; 31 | this.events = {}; 32 | this.actions = {}; 33 | this.readyList = {}; 34 | }, 35 | 36 | /** 37 | * @param {String} name 38 | * @return Boolean 39 | */ 40 | exists: function (name) { 41 | var array = this.events[this.removeOn( name )]; 42 | return !!(array && array.length); 43 | }, 44 | 45 | /** 46 | * @param {String} name 47 | * @param {Function} callback 48 | * @return Boolean 49 | */ 50 | add: function (name, callback) { 51 | this.run( 'addOne', name, callback ); 52 | return this; 53 | }, 54 | 55 | /** 56 | * @param {String} name 57 | * @param {Function} [callback] 58 | * @return Boolean 59 | */ 60 | remove: function (name, callback) { 61 | if (typeof name == 'string' && !callback) { 62 | this.removeAll( name ); 63 | } else { 64 | this.run( 'removeOne', name, callback ); 65 | } 66 | return this; 67 | }, 68 | 69 | /** 70 | * @param {String} name 71 | * @param {Array} args 72 | * @return atom.Events 73 | */ 74 | fire: function (name, args) { 75 | args = args ? slice.call( args ) : []; 76 | name = this.removeOn( name ); 77 | 78 | this.locked.push(name); 79 | var i = 0, l, events = this.events[name]; 80 | if (events) for (l = events.length; i < l; i++) { 81 | events[i].apply( this.context, args ); 82 | } 83 | this.unlock( name ); 84 | return this; 85 | }, 86 | 87 | /** 88 | * @param {String} name 89 | * @param {Array} [args=null] 90 | * @return atom.Events 91 | */ 92 | ready: function (name, args) { 93 | name = this.removeOn( name ); 94 | this.locked.push(name); 95 | if (name in this.readyList) { 96 | throw new Error( 'Event «'+name+'» is ready' ); 97 | } 98 | this.readyList[name] = args; 99 | this.fire(name, args); 100 | this.removeAll(name); 101 | this.unlock( name ); 102 | return this; 103 | }, 104 | 105 | /** 106 | * @param {String} name 107 | * @param {Array} [args=null] 108 | * @return atom.Events 109 | */ 110 | ensureReady: function (name, args) { 111 | if (!(name in this.readyList)) { 112 | this.ready(name, args); 113 | } 114 | return this; 115 | }, 116 | 117 | 118 | // only private are below 119 | 120 | /** @private */ 121 | context: null, 122 | /** @private */ 123 | events: {}, 124 | /** @private */ 125 | readyList: {}, 126 | /** @private */ 127 | locked: [], 128 | /** @private */ 129 | actions: {}, 130 | 131 | /** @private */ 132 | removeOn: function (name) { 133 | return (name || '').replace(/^on([A-Z])/, function(full, first){ 134 | return first.toLowerCase(); 135 | }); 136 | }, 137 | /** @private */ 138 | removeAll: function (name) { 139 | var events = this.events[name]; 140 | if (events) for (var i = events.length; i--;) { 141 | this.removeOne( name, events[i] ); 142 | } 143 | }, 144 | /** @private */ 145 | unlock: function (name) { 146 | var action, 147 | all = this.actions[name], 148 | index = this.locked.indexOf( name ); 149 | 150 | this.locked.splice(index, 1); 151 | 152 | if (all) for (index = 0; index < all.length; index++) { 153 | action = all[index]; 154 | 155 | this[action.method]( name, action.callback ); 156 | } 157 | }, 158 | /** @private */ 159 | run: function (method, name, callback) { 160 | var i = 0, l = 0; 161 | 162 | if (Array.isArray(name)) { 163 | for (i = 0, l = name.length; i < l; i++) { 164 | this[method](name[i], callback); 165 | } 166 | } else if (typeof name == 'object') { 167 | for (i in name) { 168 | this[method](i, name[i]); 169 | } 170 | } else if (typeof name == 'string') { 171 | this[method](name, callback); 172 | } else { 173 | throw new TypeError( 'Wrong arguments in Events.' + method ); 174 | } 175 | }, 176 | /** @private */ 177 | register: function (name, method, callback) { 178 | var actions = this.actions; 179 | if (!actions[name]) { 180 | actions[name] = []; 181 | } 182 | actions[name].push({ method: method, callback: callback }) 183 | }, 184 | /** @private */ 185 | addOne: function (name, callback) { 186 | var events, ready, context; 187 | 188 | name = this.removeOn( name ); 189 | 190 | if (this.locked.indexOf(name) == -1) { 191 | ready = this.readyList[name]; 192 | if (ready) { 193 | context = this.context; 194 | setTimeout(function () { 195 | callback.apply(context, ready); 196 | }, 0); 197 | return this; 198 | } else { 199 | events = this.events; 200 | if (!events[name]) { 201 | events[name] = [callback]; 202 | } else { 203 | events[name].push(callback); 204 | } 205 | } 206 | } else { 207 | this.register(name, 'addOne', callback); 208 | } 209 | }, 210 | /** @private */ 211 | removeOne: function (name, callback) { 212 | name = this.removeOn( name ); 213 | 214 | if (this.locked.indexOf(name) == -1) { 215 | var events = this.events[name], i = events.length; 216 | while (i--) if (events[i] == callback) { 217 | events.splice(i, 1); 218 | } 219 | } else { 220 | this.register(name, 'removeOne', callback); 221 | } 222 | } 223 | }); 224 | 225 | // local alias 226 | var Events = atom.Events; -------------------------------------------------------------------------------- /Source/Declare/ImagePreloader.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "ImagePreloader" 5 | 6 | description: "" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - declare 14 | - Events 15 | - Settings 16 | 17 | provides: ImagePreloader 18 | 19 | ... 20 | */ 21 | 22 | atom.declare( 'atom.ImagePreloader', { 23 | processed : 0, 24 | number : 0, 25 | 26 | initialize: function (settings) { 27 | this.events = new Events(this); 28 | this.settings = new Settings(settings).addEvents(this.events); 29 | 30 | this.count = { 31 | error: 0, 32 | abort: 0, 33 | load : 0 34 | }; 35 | 36 | this.suffix = this.settings.get('suffix') || ''; 37 | this.usrImages = this.prefixImages(this.settings.get('images')); 38 | this.imageUrls = this.fetchUrls(); 39 | this.domImages = {}; 40 | //this.domImages = this.createDomImages(); 41 | this.images = {}; 42 | this.createNext(); 43 | }, 44 | get isReady () { 45 | return this.number == this.processed; 46 | }, 47 | get info () { 48 | var stat = atom.string.substitute( 49 | "Images loaded: {load}; Errors: {error}; Aborts: {abort}", 50 | this.count 51 | ); 52 | if (this.isReady) stat = "Image preloading has completed;\n" + stat; 53 | return stat; 54 | }, 55 | get progress () { 56 | return this.isReady ? 1 : atom.number.round(this.processed / this.number, 4); 57 | }, 58 | append: function (preloader) { 59 | for (var i in preloader.images) { 60 | this.images[i] = preloader.images[i]; 61 | } 62 | return this; 63 | }, 64 | exists: function (name) { 65 | return !!this.images[name]; 66 | }, 67 | get: function (name) { 68 | var image = this.images[name]; 69 | if (image) { 70 | return image; 71 | } else { 72 | throw new Error('No image «' + name + '»'); 73 | } 74 | }, 75 | 76 | /** @private */ 77 | cropImage: function (img, c) { 78 | if (!c) return img; 79 | 80 | var canvas = document.createElement('canvas'); 81 | canvas.width = c[2]; 82 | canvas.height = c[3]; 83 | canvas.getContext('2d').drawImage( img, 84 | c[0], c[1], c[2], c[3], 0, 0, c[2], c[3] 85 | ); 86 | return canvas; 87 | }, 88 | /** @private */ 89 | withoutPrefix: function (src) { 90 | return src.indexOf('http://') === 0 || src.indexOf('https://') === 0; 91 | }, 92 | /** @private */ 93 | prefixImages: function (images) { 94 | var prefix = this.settings.get('prefix'); 95 | if (!prefix) return images; 96 | 97 | return atom.object.map(images, function (src) { 98 | return this.withoutPrefix(src) ? src : prefix + src; 99 | }.bind(this)); 100 | }, 101 | /** @private */ 102 | cutImages: function () { 103 | var i, parts, img; 104 | for (i in this.usrImages) if (this.usrImages.hasOwnProperty(i)) { 105 | parts = this.splitUrl( this.usrImages[i] ); 106 | img = this.domImages[ parts.url ]; 107 | this.images[i] = this.cropImage(img, parts.coords); 108 | } 109 | return this; 110 | }, 111 | /** @private */ 112 | splitUrl: function (str) { 113 | var url = str, size, cell, match, coords = null; 114 | 115 | // searching for pattern 'url [x:y:w:y]' 116 | if (match = str.match(/ \[(\d+):(\d+):(\d+):(\d+)\]$/)) { 117 | coords = match.slice( 1 ); 118 | // searching for pattern 'url [w:y]{x:y}' 119 | } else if (match = str.match(/ \[(\d+):(\d+)\]\{(\d+):(\d+)\}$/)) { 120 | coords = match.slice( 1 ).map( Number ); 121 | size = coords.slice( 0, 2 ); 122 | cell = coords.slice( 2, 4 ); 123 | coords = [ cell[0] * size[0], cell[1] * size[1], size[0], size[1] ]; 124 | } 125 | if (match) { 126 | url = str.substr(0, str.lastIndexOf(match[0])); 127 | coords = coords.map( Number ); 128 | } 129 | if (this.suffix) { 130 | if (typeof this.suffix == 'function') { 131 | url = this.suffix( url ); 132 | } else { 133 | url += this.suffix; 134 | } 135 | } 136 | 137 | return { url: url, coords: coords }; 138 | }, 139 | /** @private */ 140 | fetchUrls: function () { 141 | var i, result = [], hash = {}, url, images = this.usrImages; 142 | for (i in images) if (images.hasOwnProperty(i)) { 143 | url = this.splitUrl( images[i] ).url; 144 | if (!hash[url]) { 145 | result.push(url); 146 | hash[url] = true; 147 | this.number++; 148 | } 149 | } 150 | return result; 151 | }, 152 | /** @private */ 153 | createDomImage : function (src) { 154 | var img = new Image(); 155 | img.src = src; 156 | if (window.opera && img.complete) { 157 | setTimeout(this.onProcessed.bind(this, 'load', img), 10); 158 | } else { 159 | ['load', 'error', 'abort'].forEach(function (event) { 160 | img.addEventListener( event, this.onProcessed.bind(this, event, img), false ); 161 | }.bind(this)); 162 | } 163 | return img; 164 | }, 165 | createNext: function () { 166 | if (this.imageUrls.length) { 167 | var url = this.imageUrls.shift(); 168 | this.domImages[url] = this.createDomImage(url); 169 | } 170 | }, 171 | resetImage: function (img) { 172 | // opera fullscreen bug workaround 173 | img.width = img.width; 174 | img.height = img.height; 175 | img.naturalWidth = img.naturalWidth; 176 | img.naturalHeight = img.naturalHeight; 177 | }, 178 | /** @private */ 179 | onProcessed : function (type, img) { 180 | if (type == 'load' && window.opera) { 181 | this.resetImage(img); 182 | } 183 | this.count[type]++; 184 | this.processed++; 185 | this.events.fire('progress', [this, img]); 186 | 187 | if (this.isReady) { 188 | this.cutImages(); 189 | this.events.ensureReady('ready', [this]); 190 | } else { 191 | this.createNext(); 192 | } 193 | return this; 194 | } 195 | }).own({ 196 | run: function (images, callback, context) { 197 | var preloader = new this({ images: images }); 198 | 199 | preloader.events.add( 'ready', context ? callback.bind(context) : callback ); 200 | 201 | return preloader; 202 | } 203 | }); -------------------------------------------------------------------------------- /Source/Declare/Keyboard.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Keyboard" 5 | 6 | description: "" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - declare 14 | - Events 15 | 16 | provides: Keyboard 17 | 18 | ... 19 | */ 20 | 21 | var Keyboard = function () { 22 | 23 | var 24 | keyName, 25 | codeNames = {}, 26 | keyCodes = { 27 | // Alphabet 28 | a:65, b:66, c:67, d:68, e:69, 29 | f:70, g:71, h:72, i:73, j:74, 30 | k:75, l:76, m:77, n:78, o:79, 31 | p:80, q:81, r:82, s:83, t:84, 32 | u:85, v:86, w:87, x:88, y:89, z:90, 33 | // Numbers 34 | n0:48, n1:49, n2:50, n3:51, n4:52, 35 | n5:53, n6:54, n7:55, n8:56, n9:57, 36 | // Controls 37 | tab: 9, enter:13, shift:16, backspace:8, 38 | ctrl:17, alt :18, esc :27, space :32, 39 | menu:93, pause:19, cmd :91, 40 | insert :45, home:36, pageup :33, 41 | 'delete':46, end :35, pagedown:34, 42 | // F* 43 | f1:112, f2:113, f3:114, f4 :115, f5 :116, f6 :117, 44 | f7:118, f8:119, f9:120, f10:121, f11:122, f12:123, 45 | // numpad 46 | np0: 96, np1: 97, np2: 98, np3: 99, np4:100, 47 | np5:101, np6:102, np7:103, np8:104, np9:105, 48 | npslash:11,npstar:106,nphyphen:109,npplus:107,npdot:110, 49 | // Lock 50 | capslock:20, numlock:144, scrolllock:145, 51 | 52 | // Symbols 53 | equals: 61, hyphen :109, coma :188, dot:190, 54 | gravis:192, backslash:220, sbopen:219, sbclose:221, 55 | slash :191, semicolon: 59, apostrophe: 222, 56 | 57 | // Arrows 58 | aleft:37, aup:38, aright:39, adown:40 59 | }; 60 | 61 | for (keyName in keyCodes) if (keyCodes.hasOwnProperty(keyName)) { 62 | codeNames[ keyCodes[keyName] ] = keyName; 63 | } 64 | 65 | /** @class atom.Keyboard */ 66 | return declare( 'atom.Keyboard', { 67 | initialize : function (element, preventDefault) { 68 | if (Array.isArray(element)) { 69 | preventDefault = element; 70 | element = null; 71 | } 72 | if (element == null) element = document; 73 | 74 | if (element == document) { 75 | if (this.constructor.instance) { 76 | return this.constructor.instance; 77 | } 78 | this.constructor.instance = this; 79 | } 80 | 81 | this.events = new Events(this); 82 | this.keyStates = {}; 83 | this.preventDefault = preventDefault; 84 | 85 | atom.dom(element).bind({ 86 | keyup: this.keyEvent('up'), 87 | keydown: this.keyEvent('down'), 88 | keypress: this.keyEvent('press') 89 | }); 90 | }, 91 | /** @private */ 92 | keyEvent: function (event) { 93 | return this.onKeyEvent.bind(this, event); 94 | }, 95 | /** @private */ 96 | onKeyEvent: function (event, e) { 97 | var key = this.constructor.keyName(e), 98 | prevent = this.prevent(key); 99 | 100 | e.keyName = key; 101 | 102 | if (prevent) e.preventDefault(); 103 | this.events.fire( event, [e] ); 104 | 105 | if (event == 'down') { 106 | this.events.fire(key, [e]); 107 | this.keyStates[key] = true; 108 | } else if (event == 'up') { 109 | this.events.fire(key + ':up', [e]); 110 | delete this.keyStates[key]; 111 | } else if (event == 'press') { 112 | this.events.fire(key + ':press', [e]); 113 | } 114 | 115 | return !prevent; 116 | }, 117 | /** @private */ 118 | prevent : function (key) { 119 | var pD = this.preventDefault; 120 | return pD && (pD === true || pD.indexOf(key) >= 0); 121 | }, 122 | key: function (keyName) { 123 | return !!this.keyStates[ this.constructor.keyName(keyName) ]; 124 | } 125 | }).own({ 126 | keyCodes : keyCodes, 127 | codeNames: codeNames, 128 | keyName: function (code) { 129 | if (code && code.keyCode != null) { 130 | code = code.keyCode; 131 | } 132 | 133 | var type = typeof code; 134 | 135 | if (type == 'number') { 136 | return this.codeNames[code]; 137 | } else if (type == 'string' && code in this.keyCodes) { 138 | return code; 139 | } 140 | 141 | return null; 142 | } 143 | }); 144 | 145 | }(); 146 | -------------------------------------------------------------------------------- /Source/Declare/Registry.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Registry" 5 | 6 | description: "" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - declare 14 | 15 | provides: Registry 16 | 17 | ... 18 | */ 19 | 20 | /** @class atom.Registry */ 21 | declare( 'atom.Registry', { 22 | items: {}, 23 | initialize: function (initial) { 24 | this.items = {}; 25 | if (initial) this.set(initial); 26 | }, 27 | set: atom.core.overloadSetter(function (name, value) { 28 | this.items[name] = value; 29 | }), 30 | get: atom.core.overloadGetter(function (name) { 31 | return this.items[name]; 32 | }) 33 | }); 34 | 35 | var Registry = atom.Registry; -------------------------------------------------------------------------------- /Source/Declare/Settings.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Settings" 5 | 6 | description: "" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - declare 14 | 15 | provides: Settings 16 | 17 | ... 18 | */ 19 | 20 | /** @class atom.Settings */ 21 | declare( 'atom.Settings', { 22 | /** @private */ 23 | recursive: false, 24 | 25 | /** @private */ 26 | values: {}, 27 | 28 | /** 29 | * @constructs 30 | * @param {Object} [initialValues] 31 | */ 32 | initialize: function (initialValues) { 33 | this.values = {}; 34 | 35 | if (initialValues) this.set(initialValues); 36 | }, 37 | 38 | /** 39 | * @param {atom.Events} events 40 | * @return atom.Options 41 | */ 42 | addEvents: function (events) { 43 | this.events = events; 44 | return this.invokeEvents(); 45 | }, 46 | 47 | /** 48 | * @param {string|Array} name 49 | */ 50 | get: function (name, defaultValue) { 51 | if (Array.isArray(name)) return this.subset(name, defaultValue); 52 | 53 | return name in this.values ? this.values[name] : defaultValue; 54 | }, 55 | 56 | /** 57 | * @param {object} target 58 | * @param {string[]} [names=undefined] 59 | * @return {atom.Settings} 60 | */ 61 | properties: function (target, names) { 62 | var originalNames = this.propertiesNames; 63 | 64 | if (typeof names == 'string') { 65 | names = names.split(' '); 66 | } 67 | 68 | if (names == null || names === true) { 69 | this.propertiesNames = true; 70 | } else if (originalNames == null) { 71 | this.propertiesNames = names; 72 | } else if (originalNames !== true) { 73 | atom.array.append(originalNames, names); 74 | } 75 | 76 | this.propertiesTarget = target; 77 | 78 | for (var i in this.values) { 79 | this.exportProperty(i, this.values); 80 | } 81 | 82 | return this; 83 | }, 84 | 85 | subset: function (names, defaultValue) { 86 | var i, values = {}; 87 | 88 | for (i = names.length; i--;) { 89 | values[names[i]] = this.get( names[i], defaultValue ); 90 | } 91 | 92 | return values; 93 | }, 94 | 95 | /** @private */ 96 | propertiesNames : null, 97 | /** @private */ 98 | propertiesTarget: null, 99 | 100 | /** 101 | * @param {Object} options 102 | * @return atom.Options 103 | */ 104 | set: function (options, value) { 105 | var i, values = this.values; 106 | 107 | options = this.prepareOptions(options, value); 108 | 109 | for (i in options) { 110 | value = options[i]; 111 | if (values[i] != value) { 112 | values[i] = value; 113 | this.exportProperty(i, values); 114 | } 115 | } 116 | 117 | this.invokeEvents(); 118 | 119 | return this; 120 | }, 121 | 122 | /** @private */ 123 | exportProperty: function (i, values) { 124 | var 125 | target = this.propertiesTarget, 126 | names = this.propertiesNames; 127 | 128 | if (target && (names === true || names.indexOf(i) >= 0)) { 129 | target[i] = values[i]; 130 | } 131 | }, 132 | 133 | /** @private */ 134 | prepareOptions: function (options, value) { 135 | if (typeof options == 'string') { 136 | var i = options; 137 | options = {}; 138 | options[i] = value; 139 | } else if (options instanceof this.constructor) { 140 | options = options.values; 141 | } 142 | return options; 143 | }, 144 | 145 | /** 146 | * @param {String} name 147 | * @return atom.Options 148 | */ 149 | unset: function (name) { 150 | delete this.values[name]; 151 | return this; 152 | }, 153 | 154 | /** @private */ 155 | invokeEvents: function () { 156 | if (!this.events) return this; 157 | 158 | var values = this.values, name, option; 159 | for (name in values) if (values.hasOwnProperty(name)) { 160 | option = values[name]; 161 | if (this.isInvokable(name, option)) { 162 | this.events.add(name, option); 163 | this.unset(name); 164 | } 165 | } 166 | return this; 167 | }, 168 | 169 | /** @private */ 170 | isInvokable: function (name, option) { 171 | return name && 172 | option && 173 | coreIsFunction(option) && 174 | (/^on[A-Z]/).test(name); 175 | } 176 | }); 177 | 178 | var Settings = atom.Settings; -------------------------------------------------------------------------------- /Source/Declare/Trace.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "trace" 5 | 6 | description: "" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - declare 14 | - dom 15 | - CoreExtended 16 | 17 | provides: trace 18 | 19 | ... 20 | */ 21 | 22 | atom.trace = declare( 'atom.trace', { 23 | initialize : function (object) { 24 | this.value = object; 25 | this.stopped = false; 26 | }, 27 | set value (value) { 28 | if (!this.stopped) { 29 | var html = atom.string.replaceAll( this.constructor.dump(value), { 30 | '\t': ' '.repeat(3), 31 | '\n': '
' 32 | }); 33 | this.createNode().html(html); 34 | } 35 | }, 36 | destroy : function (force) { 37 | var trace = this; 38 | if (force) this.stop(); 39 | if (trace.node) { 40 | trace.node.addClass('atom-trace-node-destroy'); 41 | trace.timeout = setTimeout(function () { 42 | if (trace.node) { 43 | trace.node.destroy(); 44 | trace.node = null; 45 | } 46 | }, 500); 47 | } 48 | return trace; 49 | }, 50 | /** @private */ 51 | stop : function () { 52 | this.stopped = true; 53 | return this; 54 | }, 55 | /** @private */ 56 | getContainer : function () { 57 | var cont = atom.dom('#atom-trace-container'); 58 | return cont.length ? cont : 59 | atom.dom.create('div', { 'id' : 'atom-trace-container'}) 60 | .appendTo('body'); 61 | }, 62 | /** @deprecated */ 63 | trace : function (value) { 64 | this.value = value; 65 | return this; 66 | }, 67 | /** @private */ 68 | createNode : function () { 69 | var trace = this, node = trace.node; 70 | 71 | if (node) { 72 | if (trace.timeout) { 73 | clearTimeout(trace.timeout); 74 | node.removeClass('atom-trace-node-destroy'); 75 | } 76 | return node; 77 | } 78 | 79 | return trace.node = atom.dom 80 | .create('div') 81 | .addClass('atom-trace-node') 82 | .appendTo(trace.getContainer()) 83 | .bind({ 84 | click : function () { trace.destroy(0) }, 85 | dblclick : function () { trace.destroy(1) } 86 | }); 87 | } 88 | }).own({ 89 | dumpRec : function dumpRec (obj, level, plain) { 90 | var html = '', type, tabs; 91 | 92 | level = parseInt(level) || 0; 93 | 94 | if (level > 5) return '*TOO_DEEP*'; 95 | 96 | if (obj && typeof obj == 'object' && coreIsFunction(obj.dump)) return obj.dump(); 97 | 98 | function escape (v) { 99 | return plain ? v : atom.string.safeHtml(v); 100 | } 101 | 102 | function subDump (elem, index) { 103 | return tabs + '\t' + index + ': ' + dumpRec(elem, level+1, plain) + '\n'; 104 | } 105 | 106 | type = atom.typeOf(obj); 107 | tabs = '\t'.repeat(level); 108 | 109 | switch (type) { 110 | case 'object': 111 | for (var index in obj) if (obj.hasOwnProperty(index)) { 112 | html += subDump(obj[index], index); 113 | } 114 | return '{\n' + html + tabs + '}'; 115 | 116 | case 'element': 117 | var prop = (obj.width && obj.height) ? '('+obj.width+'×'+obj.height+')' : ''; 118 | return '[DOM ' + obj.tagName.toLowerCase() + prop + ']'; 119 | 120 | case 'textnode': 121 | case 'whitespace': 122 | return '[DOM ' + type + ']'; 123 | 124 | case 'array' : return '[\n' + obj.map(subDump).join('') + tabs + ']'; 125 | case 'null' : return 'null'; 126 | case 'boolean': return obj ? 'true' : 'false'; 127 | case 'string' : return escape('"' + obj + '"'); 128 | default : return escape('' + obj); 129 | } 130 | }, 131 | dumpPlain: function (object) { 132 | return (this.dumpRec(object, 0, true)); 133 | }, 134 | dump : function (object) { 135 | return (this.dumpRec(object, 0)); 136 | } 137 | }); -------------------------------------------------------------------------------- /Source/Declare/Transition.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Transition" 5 | 6 | description: "" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | - declare 15 | 16 | inspiration: 17 | - "[MooTools](http://mootools.net)" 18 | 19 | provides: Transition 20 | 21 | ... 22 | */ 23 | 24 | atom.Transition = function (method, noEase) { 25 | var easeIn = function (progress) { 26 | return method(progress); 27 | }; 28 | 29 | if (noEase) { 30 | return coreAppend( easeIn, { 31 | easeIn : easeIn, 32 | easeOut : easeIn, 33 | easeInOut: easeIn 34 | }); 35 | } 36 | 37 | return coreAppend( easeIn, { 38 | easeIn: easeIn, 39 | easeOut: function(progress){ 40 | return 1 - method(1 - progress); 41 | }, 42 | easeInOut: function(progress){ 43 | if (progress > 0.5) { 44 | return ( 2 - method(2 * (1 - progress)) ) /2 45 | } else { 46 | return method(2 * progress)/2; 47 | } 48 | } 49 | }); 50 | }; 51 | 52 | atom.Transition.set = atom.core.overloadSetter(function (id, fn) { 53 | atom.Transition[id] = atom.Transition(fn); 54 | }); 55 | 56 | atom.Transition.get = function (fn) { 57 | if (typeof fn != 'string') return fn; 58 | var method = fn.split('-')[0], ease = 'easeInOut', In, Out; 59 | if (method != fn) { 60 | In = fn.indexOf('-in' ) > 0; 61 | Out = fn.indexOf('-out') > 0; 62 | if (In ^ Out) { 63 | if (In ) ease = 'easeIn'; 64 | if (Out) ease = 'easeOut'; 65 | } 66 | } 67 | method = method[0].toUpperCase() + method.substr(1); 68 | if (!atom.Transition[method]) { 69 | throw new Error('No Transition method: ' + method); 70 | } 71 | return atom.Transition[method][ease]; 72 | }; 73 | 74 | atom.Transition.Linear = atom.Transition(function(p) { return p }, true); 75 | 76 | atom.Transition.set({ 77 | Expo: function(p){ 78 | return Math.pow(2, 8 * (p - 1)); 79 | }, 80 | 81 | Circ: function(p){ 82 | return 1 - Math.sin(Math.acos(p)); 83 | }, 84 | 85 | Sine: function(p){ 86 | return 1 - Math.cos(p * Math.PI / 2); 87 | }, 88 | 89 | Back: function(p){ 90 | var x = 1.618; 91 | return Math.pow(p, 2) * ((x + 1) * p - x); 92 | }, 93 | 94 | Bounce: function(p){ 95 | var value, a = 0, b = 1; 96 | for (;;){ 97 | if (p >= (7 - 4 * a) / 11){ 98 | value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2); 99 | break; 100 | } 101 | a += b, b /= 2 102 | } 103 | return value; 104 | }, 105 | 106 | Elastic: function(p){ 107 | return Math.pow(2, 10 * --p) * Math.cos(12 * p); 108 | } 109 | 110 | }); 111 | 112 | ['Quad', 'Cubic', 'Quart', 'Quint'].forEach(function(transition, i){ 113 | atom.Transition.set(transition, function(p){ 114 | return Math.pow(p, i + 2); 115 | }); 116 | }); -------------------------------------------------------------------------------- /Source/Frame.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Frame" 5 | 6 | description: "Provides cross-browser interface for requestAnimationFrame" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | 15 | provides: frame 16 | 17 | ... 18 | */ 19 | (function () { 20 | 21 | var previous, 22 | started = false, 23 | callbacks = [], 24 | remove = [], 25 | frameTime = 16, // 62 fps 26 | // we'll switch to real `requestAnimationFrame` here 27 | // when all browsers will be ready 28 | requestAnimationFrame = function (callback) { 29 | window.setTimeout(callback, frameTime); 30 | }; 31 | 32 | function startAnimation () { 33 | if (!started) { 34 | previous = Date.now(); 35 | requestAnimationFrame(frame); 36 | started = true; 37 | } 38 | } 39 | 40 | function invokeFrame () { 41 | var fn, i, l, 42 | now = Date.now(), 43 | // 1 sec is max time for frame to avoid some bugs with too large time 44 | delta = Math.min(now - previous, 1000); 45 | 46 | for (i = 0, l = remove.length; i < l; i++) { 47 | coreEraseOne(callbacks, remove[i]); 48 | } 49 | remove.length = 0; 50 | 51 | for (i = 0, l = callbacks.length; i < l; i++) { 52 | fn = callbacks[i]; 53 | // one of previous calls can remove our fn 54 | if (remove.indexOf(fn) == -1) { 55 | fn.call(null, delta); 56 | } 57 | } 58 | 59 | previous = now; 60 | } 61 | 62 | function frame() { 63 | requestAnimationFrame(frame); 64 | 65 | if (callbacks.length == 0) { 66 | remove.length = 0; 67 | previous = Date.now(); 68 | } else invokeFrame(); 69 | } 70 | 71 | atom.frame = { 72 | add: function (fn) { 73 | startAnimation(); 74 | includeUnique(callbacks, fn); 75 | }, 76 | // we dont want to fragmentate callbacks, so remove only before frame started 77 | remove: function (fn) { 78 | if (started) includeUnique(remove, fn); 79 | } 80 | }; 81 | 82 | }()); -------------------------------------------------------------------------------- /Source/Js185.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "JavaScript 1.8.5" 5 | 6 | description: "JavaScript 1.8.5 Compatiblity." 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | inspiration: 13 | - "[JQuery](http://jquery.com)" 14 | - "[MooTools](http://mootools.net)" 15 | 16 | provides: js185 17 | 18 | ... 19 | */ 20 | 21 | // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind 22 | if (!Function.prototype.bind) { 23 | Function.prototype.bind = function(context /*, arg1, arg2... */) { 24 | if (typeof this !== "function") throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); 25 | 26 | var args = slice.call(arguments, 1), 27 | toBind = this, 28 | Nop = function () {}, 29 | Bound = function () { 30 | var isInstance; 31 | // Opera & Safari bug fixed. I must fix it in right way 32 | // TypeError: Second argument to 'instanceof' does not implement [[HasInstance]] 33 | try { 34 | isInstance = this instanceof Nop; 35 | } catch (ignored) { 36 | // console.log( 'bind error', Nop.prototype ); 37 | isInstance = false; 38 | } 39 | return toBind.apply( 40 | isInstance ? this : ( context || {} ), 41 | args.concat( slice.call(arguments) ) 42 | ); 43 | }; 44 | Nop.prototype = toBind.prototype; 45 | Bound.prototype = new Nop(); 46 | return Bound; 47 | }; 48 | } 49 | 50 | // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys 51 | if (!Object.keys) (function (has) { 52 | 53 | Object.keys = function(obj) { 54 | if (obj !== Object(obj)) throw new TypeError('Object.keys called on non-object'); 55 | 56 | var keys = [], i; 57 | for (i in obj) if (has.call(obj, i)) keys.push(i); 58 | return keys; 59 | }; 60 | })({}.hasOwnProperty); 61 | 62 | // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray 63 | if (!Array.isArray) { 64 | Array.isArray = function(o) { 65 | return o && toString.call(o) === '[object Array]'; 66 | }; 67 | } 68 | 69 | // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/create 70 | if (!Object.create) { 71 | Object.create = function (o) { 72 | if (arguments.length > 1) { 73 | throw new Error('Object.create implementation only accepts the first parameter.'); 74 | } 75 | function F() {} 76 | F.prototype = o; 77 | return new F(); 78 | }; 79 | } 80 | 81 | if (!String.prototype.trim) { 82 | String.prototype.trim = function () { 83 | return this.replace(/^\s+|\s+$/g, ''); 84 | } 85 | } 86 | 87 | if (!String.prototype.trimLeft) { 88 | String.prototype.trimLeft = function () { 89 | return this.replace(/^\s+/, ''); 90 | } 91 | } 92 | 93 | if (!String.prototype.trimRight) { 94 | String.prototype.trimRight = function () { 95 | return this.replace(/\s+$/g, ''); 96 | } 97 | } -------------------------------------------------------------------------------- /Source/PointerLock.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "PointerLock" 5 | 6 | description: "Provides cross-browser interface for locking pointer" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | 15 | provides: PointerLock 16 | 17 | ... 18 | */ 19 | (function (document) { 20 | var prefix = 21 | 'pointerLockElement' in document ? '': 22 | 'mozPointerLockElement' in document ? 'moz': 23 | 'webkitPointerLockElement' in document ? 'webkit': null; 24 | 25 | function PointerLock (supports) { 26 | this.supports = supports; 27 | } 28 | 29 | function p (string) { 30 | return prefix ? prefix + string : 31 | string[0].toLowerCase() + string.substr(1); 32 | } 33 | 34 | function isLocked (element) { 35 | return document[p('PointerLockElement')] === element; 36 | } 37 | 38 | if (prefix == null) { 39 | PointerLock.prototype = { 40 | locked : function () { return false }, 41 | request : function () {}, 42 | exit : function () {} 43 | }; 44 | } else { 45 | 46 | document.addEventListener("mousemove", function onMove (e) { 47 | if (lockedElement && isLocked(lockedElement)) { 48 | e.movementX = e[p('MovementX')] || 0; 49 | e.movementY = e[p('MovementY')] || 0; 50 | 51 | callback && callback(e); 52 | } 53 | }, false); 54 | 55 | 56 | var lockedElement = false, callback = null; 57 | 58 | PointerLock.prototype = { 59 | locked: function (element) { 60 | return isLocked(element || lockedElement); 61 | }, 62 | request: function (element, fn) { 63 | lockedElement = element; 64 | callback = fn; 65 | element[p('RequestPointerLock')](); 66 | }, 67 | exit: function () { 68 | lockedElement = null; 69 | callback = null; 70 | document[p('ExitPointerLock')](); 71 | } 72 | }; 73 | } 74 | 75 | atom.pointerLock = new PointerLock(prefix != null); 76 | 77 | }(document)); -------------------------------------------------------------------------------- /Source/Prototypes/Abstract.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Prototypes.Abstract" 5 | 6 | description: "Contains office methods for prototypes extension." 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | - Types.Array 15 | - Types.Object 16 | 17 | provides: Prototypes.Abstract 18 | 19 | ... 20 | */ 21 | 22 | var prototypize = { 23 | callbacks: [], 24 | fn: function (source) { 25 | return function (methodName) { 26 | return function () { 27 | var args = slice.call(arguments); 28 | args.unshift(this); 29 | return source[methodName].apply(source, args); 30 | }; 31 | }; 32 | }, 33 | proto: function (object, proto, methodsString) { 34 | coreAppend(object.prototype, atom.array.associate( 35 | methodsString.split(' '), proto 36 | )); 37 | return prototypize; 38 | }, 39 | own: function (object, source, methodsString) { 40 | coreAppend(object, atom.object.collect( source, methodsString.split(' ') )); 41 | return prototypize; 42 | }, 43 | add: function (callback) { 44 | this.callbacks.push(callback); 45 | } 46 | }; 47 | 48 | atom.patching = function (globalObject) { 49 | prototypize.callbacks.forEach(function (callback) { 50 | callback(globalObject); 51 | }); 52 | }; -------------------------------------------------------------------------------- /Source/Prototypes/Array.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Prototypes.Array" 5 | 6 | description: "Contains Array Prototypes like include, contains, and erase." 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Types.Array 14 | - Prototypes.Abstract 15 | 16 | provides: Prototypes.Array 17 | 18 | ... 19 | */ 20 | 21 | prototypize.add(function (globalObject) { 22 | 23 | var Array = globalObject.Array; 24 | 25 | var proto = prototypize.fn(atom.array); 26 | 27 | prototypize 28 | .own(Array, atom.array, 'range from pickFrom fill fillMatrix collect create toHash') 29 | .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' ); 30 | 31 | atom.accessors.define(Array.prototype, { 32 | last : { get: function () { 33 | return atom.array.last(this); 34 | }}, 35 | random: { get: function () { 36 | return atom.array.random(this, false); 37 | }} 38 | }); 39 | 40 | coreAppend(Array.prototype, { 41 | popRandom: function () { 42 | return atom.array.random(this, true); 43 | }, 44 | /** @deprecated */ 45 | toKeys: function () { 46 | console.log( '[].toKeys is deprecated. Use forEach instead' ); 47 | return atom.array.toKeys(this); 48 | }, 49 | /** @deprecated */ 50 | fullMap: function (callback, context) { 51 | console.log( '[].fullMap is deprecated. Use atom.array.create instead' ); 52 | return atom.array.create(this.length, callback, context); 53 | } 54 | }); 55 | 56 | if (!Array.prototype.reduce ) Array.prototype.reduce = proto('reduce'); 57 | if (!Array.prototype.reduceRight) Array.prototype.reduceRight = proto('reduceRight'); 58 | 59 | }); -------------------------------------------------------------------------------- /Source/Prototypes/Function.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Prototypes.Function" 5 | 6 | description: "Contains Function Prototypes like after, periodical and delay." 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | - Types.Function 15 | - Prototypes.Abstract 16 | 17 | provides: Prototypes.Function 18 | 19 | ... 20 | */ 21 | 22 | prototypize.add(function (globalObject) { 23 | 24 | var Function = globalObject.Function; 25 | 26 | Function.lambda = atom.fn.lambda; 27 | 28 | function timer (periodical) { 29 | var set = periodical ? setInterval : setTimeout; 30 | 31 | return function (time, bind, args) { 32 | var fn = this; 33 | return set(function () { 34 | fn.apply( bind, args || [] ); 35 | }, time); 36 | }; 37 | } 38 | 39 | coreAppend(Function.prototype, { 40 | after: prototypize.fn(atom.fn)('after'), 41 | delay : timer(false), 42 | periodical: timer(true ) 43 | }); 44 | 45 | }); 46 | -------------------------------------------------------------------------------- /Source/Prototypes/Number.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Prototypes.Number" 5 | 6 | description: "Contains Number Prototypes like limit, round, times, and ceil." 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Types.Number 14 | - Types.Math 15 | - Prototypes.Abstract 16 | 17 | provides: Prototypes.Number 18 | 19 | ... 20 | */ 21 | 22 | prototypize.add(function (globalObject) { 23 | 24 | var Number = globalObject.Number; 25 | 26 | prototypize 27 | .own(Number, atom.number, 'random randomFloat') 28 | .proto(Number, prototypize.fn(atom.number), 'between equals limit round stop' ) 29 | .proto(Number, prototypize.fn(atom.math ), 'degree getDegree normalizeAngle' ); 30 | 31 | coreAppend(Number.prototype, { 32 | toFloat: function(){ 33 | return parseFloat(this); 34 | }, 35 | toInt: function(base){ 36 | return parseInt(this, base || 10); 37 | } 38 | }); 39 | 40 | 'abs acos asin atan atan2 ceil cos exp floor log max min pow sin sqrt tan' 41 | .split(' ') 42 | .forEach(function(method) { 43 | if (Number[method]) return; 44 | 45 | Number.prototype[method] = function() { 46 | return Math[method].apply(null, [this].append(arguments)); 47 | }; 48 | }); 49 | }); -------------------------------------------------------------------------------- /Source/Prototypes/Object.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Prototypes.Object" 5 | 6 | description: "Object generic methods" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Types.Object 14 | 15 | provides: Prototypes.Object 16 | 17 | ... 18 | */ 19 | 20 | prototypize.add(function (globalObject) { 21 | coreAppend(globalObject.Object, atom.object); 22 | }); -------------------------------------------------------------------------------- /Source/Prototypes/String.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Prototypes.String" 5 | 6 | description: "Contains String Prototypes like repeat, substitute, replaceAll and begins." 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Types.String 14 | - Prototypes.Abstract 15 | 16 | provides: Prototypes.String 17 | 18 | ... 19 | */ 20 | 21 | prototypize.add(function (globalObject) { 22 | prototypize.proto(globalObject.String, prototypize.fn(atom.string), 23 | 'safeHtml repeat substitute replaceAll contains begins ends ucfirst lcfirst' 24 | ); 25 | }); -------------------------------------------------------------------------------- /Source/Types/Function.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Types.Function" 5 | 6 | description: "Contains function manipulation methods." 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | - Types.Array 15 | 16 | provides: Types.Function 17 | 18 | ... 19 | */ 20 | 21 | atom.fn = { 22 | lambda: function (value) { 23 | var returnThis = (arguments.length == 0); 24 | return function () { return returnThis ? this : value; }; 25 | }, 26 | 27 | after: function (onReady, fnName) { 28 | var after = {}, ready = {}; 29 | function checkReady (){ 30 | for (var i in after) if (!ready[i]) return; 31 | onReady(ready); 32 | } 33 | slice.call(arguments, 1).forEach(function (key) { 34 | after[key] = function () { 35 | ready[key] = slice.call(arguments); 36 | ready[key].context = this; 37 | checkReady(); 38 | }; 39 | }); 40 | return after; 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /Source/Types/Math.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Types.Math" 5 | 6 | description: "" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | 15 | provides: Types.Math 16 | 17 | ... 18 | */ 19 | 20 | (function () { 21 | 22 | var 23 | degree = Math.PI / 180, 24 | deg360 = Math.PI * 2; 25 | 26 | atom.math = { 27 | 28 | DEGREE360: deg360, 29 | 30 | /** 31 | * Cast degrees to radians 32 | * atom.math.degree(90) == Math.PI/2 33 | */ 34 | degree: function (degrees) { 35 | return degrees * degree; 36 | }, 37 | 38 | /** 39 | * Cast radians to degrees 40 | * atom.math.getDegree(Math.PI/2) == 90 41 | */ 42 | getDegree: function (radians, round) { 43 | radians /= degree; 44 | 45 | return round ? Math.round(radians) : radians; 46 | }, 47 | normalizeAngle : function (radians) { 48 | radians %= deg360; 49 | 50 | return radians + ( radians < 0 ? deg360 : 0 ); 51 | }, 52 | 53 | hypotenuse: function (cathetus1, cathetus2) { 54 | return Math.sqrt(cathetus1*cathetus1 + cathetus2*cathetus2); 55 | }, 56 | cathetus: function (hypotenuse, cathetus2) { 57 | return Math.sqrt(hypotenuse*hypotenuse - cathetus2*cathetus2); 58 | } 59 | }; 60 | 61 | })(); 62 | -------------------------------------------------------------------------------- /Source/Types/Number.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Types.Number" 5 | 6 | description: "Contains number-manipulation methods like limit, round, times, and ceil." 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | 15 | provides: Types.Number 16 | 17 | ... 18 | */ 19 | 20 | atom.number = { 21 | randomFloat: function (max, min) { 22 | return Math.random() * (max - min) + min; 23 | }, 24 | random : function (min, max) { 25 | return Math.floor(Math.random() * (max - min + 1) + min); 26 | }, 27 | between: function (number, n1, n2, equals) { 28 | number = Number(number); 29 | n1 = Number(n1); 30 | n2 = Number(n2); 31 | return (n1 <= n2) && ( 32 | (equals == 'L' && number == n1) || 33 | (equals == 'R' && number == n2) || 34 | (number > n1 && number < n2) || 35 | ([true,'LR','RL'].indexOf(equals) != -1 && (n1 == number || n2 == number)) 36 | ); 37 | }, 38 | equals : function (number, to, accuracy) { 39 | if (accuracy == null) accuracy = 8; 40 | return number.toFixed(accuracy) == to.toFixed(accuracy); 41 | }, 42 | limit: function(number, min, max){ 43 | var bottom = Math.max(min, Number(number)); 44 | return max != null ? Math.min(max, bottom) : bottom; 45 | }, 46 | round: function(number, precision){ 47 | if (!precision) return Math.round(number); 48 | 49 | if (precision < 0) { 50 | precision = Number( Math.pow(10, precision).toFixed( -precision ) ); 51 | } else { 52 | precision = Math.pow(10, precision); 53 | } 54 | return Math.round(number * precision) / precision; 55 | }, 56 | stop: function(num) { 57 | num = Number(num); 58 | if (num) { 59 | clearInterval(num); 60 | clearTimeout (num); 61 | } 62 | return this; 63 | } 64 | }; -------------------------------------------------------------------------------- /Source/Types/Object.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Types.Object" 5 | 6 | description: "Object generic methods" 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | 15 | provides: Types.Object 16 | 17 | ... 18 | */ 19 | 20 | atom.object = { 21 | append: function (target, source1, source2) { 22 | for (var i = 1, l = arguments.length; i < l; i++) { 23 | atom.core.append(target, arguments[i]); 24 | } 25 | return target; 26 | }, 27 | invert: function (object) { 28 | var newObj = {}; 29 | for (var i in object) newObj[object[i]] = i; 30 | return newObj; 31 | }, 32 | collect: function (obj, props, Default) { 33 | var newObj = {}; 34 | props.forEach(function (i){ 35 | newObj[i] = i in obj ? obj[i] : Default; 36 | }); 37 | return newObj; 38 | }, 39 | values: function (obj) { 40 | var values = []; 41 | for (var i in obj) values.push(obj[i]); 42 | return values; 43 | }, 44 | /** @deprecated */ 45 | isDefined: function (obj) { 46 | return typeof obj !== 'undefined'; 47 | }, 48 | /** @deprecated */ 49 | isReal: function (obj) { 50 | return obj != null; 51 | }, 52 | map: function (obj, fn) { 53 | var mapped = {}; 54 | for (var i in obj) if (obj.hasOwnProperty(i)) { 55 | mapped[i] = fn( obj[i], i, obj ); 56 | } 57 | return mapped; 58 | }, 59 | max: function (obj) { 60 | var max = null, key = null; 61 | for (var i in obj) if (max == null || obj[i] > max) { 62 | key = i; 63 | max = obj[i]; 64 | } 65 | return key; 66 | }, 67 | min: function (obj) { 68 | var min = null, key = null; 69 | for (var i in obj) if (min == null || obj[i] < min) { 70 | key = i; 71 | min = obj[i]; 72 | } 73 | return key; 74 | }, 75 | deepEquals: function (first, second) { 76 | if (!first || (typeof first) !== (typeof second)) return false; 77 | 78 | for (var i in first) { 79 | var f = first[i], s = second[i]; 80 | if (typeof f === 'object') { 81 | if (!s || !Object.deepEquals(f, s)) return false; 82 | } else if (f !== s) { 83 | return false; 84 | } 85 | } 86 | 87 | for (i in second) if (!(i in first)) return false; 88 | 89 | return true; 90 | }, 91 | isEmpty: function (object) { 92 | for (var i in object) if (object.hasOwnProperty(i)) { 93 | return false; 94 | } 95 | return true; 96 | }, 97 | ifEmpty: function (object, key, defaultValue) { 98 | if (!(key in object)) { 99 | object[key] = defaultValue; 100 | } 101 | return object; 102 | }, 103 | path: { 104 | parts: function (path, delimiter) { 105 | return Array.isArray(path) ? path : String(path).split( delimiter || '.' ); 106 | }, 107 | get: function (object, path, delimiter) { 108 | if (!path) return object; 109 | 110 | path = atom.object.path.parts( path, delimiter ); 111 | 112 | for (var i = 0; i < path.length; i++) { 113 | if (object != null && path[i] in object) { 114 | object = object[path[i]]; 115 | } else { 116 | return; 117 | } 118 | } 119 | 120 | return object; 121 | }, 122 | set: function (object, path, value, delimiter) { 123 | path = atom.object.path.parts( path, delimiter ); 124 | 125 | var key = path.pop(); 126 | 127 | while (path.length) { 128 | var current = path.shift(); 129 | if (object[current]) { 130 | object = object[current]; 131 | } else { 132 | object = object[current] = {}; 133 | } 134 | } 135 | 136 | object[key] = value; 137 | } 138 | } 139 | }; -------------------------------------------------------------------------------- /Source/Types/String.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Types.String" 5 | 6 | description: "Contains string-manipulation methods like repeat, substitute, replaceAll and begins." 7 | 8 | license: 9 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 10 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 11 | 12 | requires: 13 | - Core 14 | 15 | provides: Types.String 16 | 17 | ... 18 | */ 19 | 20 | new function () { 21 | 22 | var UID = Date.now(); 23 | 24 | atom.string = { 25 | /** 26 | * @returns {string} - unique for session value in 36-radix 27 | */ 28 | uniqueID: function () { 29 | return (UID++).toString(36); 30 | }, 31 | /** 32 | * escape all html unsafe characters - & ' " < > 33 | * @param {string} string 34 | * @returns {string} 35 | */ 36 | safeHtml: function (string) { 37 | return this.replaceAll(string, /[<'&">]/g, { 38 | '&' : '&', 39 | '\'' : ''', 40 | '\"' : '"', 41 | '<' : '<', 42 | '>' : '>' 43 | }); 44 | }, 45 | /** 46 | * repeat string `times` times 47 | * @param {string} string 48 | * @param {int} times 49 | * @returns {string} 50 | */ 51 | repeat: function(string, times) { 52 | return new Array(times + 1).join(string); 53 | }, 54 | /** 55 | * @param {string} string 56 | * @param {Object} object 57 | * @param {RegExp} [regexp=null] 58 | * @returns {string} 59 | */ 60 | substitute: function(string, object, regexp){ 61 | return string.replace(regexp || /\\?\{([^{}]+)\}/g, function(match, name){ 62 | return (match[0] == '\\') ? match.slice(1) : (object[name] == null ? '' : object[name]); 63 | }); 64 | }, 65 | /** 66 | * @param {string} string 67 | * @param {Object|RegExp|string} find 68 | * @param {Object|string} [replace=null] 69 | * @returns {String} 70 | */ 71 | replaceAll: function (string, find, replace) { 72 | if (toString.call(find) == '[object RegExp]') { 73 | return string.replace(find, function (symb) { return replace[symb]; }); 74 | } else if (typeof find == 'object') { 75 | for (var i in find) string = this.replaceAll(string, i, find[i]); 76 | return string; 77 | } 78 | return string.split(find).join(replace); 79 | }, 80 | /** 81 | * Checks if string contains such substring 82 | * @param {string} string 83 | * @param {string} substr 84 | */ 85 | contains: function (string, substr) { 86 | return string ? string.indexOf( substr ) >= 0 : false; 87 | }, 88 | /** 89 | * Checks if string begins with such substring 90 | * @param {string} string 91 | * @param {string} substring 92 | * @param {boolean} [caseInsensitive=false] 93 | * @returns {boolean} 94 | */ 95 | begins: function (string, substring, caseInsensitive) { 96 | if (!string) return false; 97 | return (!caseInsensitive) ? substring == string.substr(0, substring.length) : 98 | substring.toLowerCase() == string.substr(0, substring.length).toLowerCase(); 99 | }, 100 | /** 101 | * Checks if string ends with such substring 102 | * @param {string} string 103 | * @param {string} substring 104 | * @param {boolean} [caseInsensitive=false] 105 | * @returns {boolean} 106 | */ 107 | ends: function (string, substring, caseInsensitive) { 108 | if (!string) return false; 109 | return (!caseInsensitive) ? substring == string.substr(string.length - substring.length) : 110 | substring.toLowerCase() == string.substr(string.length - substring.length).toLowerCase(); 111 | }, 112 | /** 113 | * Uppercase first character 114 | * @param {string} string 115 | * @returns {string} 116 | */ 117 | ucfirst : function (string) { 118 | return string ? string[0].toUpperCase() + string.substr(1) : ''; 119 | }, 120 | /** 121 | * Lowercase first character 122 | * @param {string} string 123 | * @returns {string} 124 | */ 125 | lcfirst : function (string) { 126 | return string ? string[0].toLowerCase() + string.substr(1) : ''; 127 | } 128 | }; 129 | 130 | }(); -------------------------------------------------------------------------------- /Source/Uri.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "Uri" 5 | 6 | description: "Port of parseUri function" 7 | 8 | license: "MIT License" 9 | 10 | author: "Steven Levithan " 11 | 12 | requires: 13 | - Core 14 | 15 | provides: uri 16 | 17 | ... 18 | */ 19 | new function () { 20 | 21 | var uri = function (str) { 22 | var o = atom.uri.options, 23 | m = o.parser.exec(str || window.location.href), 24 | uri = {}, 25 | i = 14; 26 | 27 | while (i--) uri[o.key[i]] = m[i] || ""; 28 | 29 | uri[o.q.name] = {}; 30 | uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { 31 | if ($1) uri[o.q.name][$1] = $2; 32 | }); 33 | 34 | return uri; 35 | }; 36 | uri.options = { 37 | key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], 38 | q: { 39 | name: "queryKey", 40 | parser: /(?:^|&)([^&=]*)=?([^&]*)/g 41 | }, 42 | parser: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ 43 | }; 44 | 45 | atom.uri = uri; 46 | 47 | }; -------------------------------------------------------------------------------- /Source/atom.css: -------------------------------------------------------------------------------- 1 | #atom-trace-container { 2 | z-index : 87223; 3 | position : fixed; 4 | top : 3px; 5 | right : 6px; 6 | max-width : 70%; 7 | max-height: 100%; 8 | overflow-y: auto; 9 | background: rgba(0,192,0,0.2); 10 | } 11 | 12 | .atom-trace-node { 13 | background : #000; 14 | border : 1px dashed #0c0; 15 | color : #0c0; 16 | cursor : pointer; 17 | font-family: monospace; 18 | margin : 1px; 19 | min-width : 200px; 20 | overflow : auto; 21 | padding : 3px 12px; 22 | white-space: pre; 23 | } 24 | 25 | .atom-trace-node-destroy { 26 | background : #300; 27 | } -------------------------------------------------------------------------------- /Source/overall.js: -------------------------------------------------------------------------------- 1 | /* 2 | --- 3 | 4 | name: "AtomJS" 5 | 6 | license: 7 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 8 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 9 | 10 | authors: 11 | - Pavel Ponomarenko aka Shock 12 | 13 | inspiration: 14 | - "[JQuery](http://jquery.com)" 15 | - "[MooTools](http://mootools.net)" 16 | 17 | ... 18 | */ 19 | 20 | (function (Object, Array, undefined) { // AtomJS 21 | // Safari 5 bug: 22 | // 'use strict'; 23 | 24 | var 25 | toString = Object.prototype.toString, 26 | hasOwn = Object.prototype.hasOwnProperty, 27 | slice = Array .prototype.slice, 28 | atom = this.atom = function () { 29 | if (atom.initialize) return atom.initialize.apply(this, arguments); 30 | }; 31 | 32 | atom.global = this; 33 | 34 | /*** [Code] ***/ 35 | 36 | }.call(typeof exports == 'undefined' ? window : exports, Object, Array)); -------------------------------------------------------------------------------- /Source/package.yml: -------------------------------------------------------------------------------- 1 | name: "AtomJS" 2 | 3 | exports: "atom.js" 4 | 5 | web: "[atomjs.com](http://atomjs.com/)" 6 | 7 | description: "Atom, The JavaScript framework" 8 | 9 | license: 10 | - "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)" 11 | - "[MIT License](http://opensource.org/licenses/mit-license.php)" 12 | 13 | copyright: "© [AtomJS](http://atomjs.com)" 14 | 15 | authors: "[AtomJS Development Team](http://atomjs.com)" 16 | 17 | sources: "*.js" 18 | 19 | overall: "overall.js" -------------------------------------------------------------------------------- /Tests/cells.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theshock/atomjs/8fcc3209e9b49727fd30c1b15194f895054ad6dc/Tests/cells.png -------------------------------------------------------------------------------- /Tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

Atom Javascript framework tests

14 |

15 |
16 |

17 |
    18 |
    19 | ccc 20 |

    The standard Lorem Ipsum passage, used since the 1500s

    21 |

    "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."

    22 |

    Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC

    23 |

    "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"

    24 |

    1914 translation by H. Rackham

    25 |

    "But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"

    26 |

    Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC

    27 |

    "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."

    28 |

    1914 translation by H. Rackham

    29 |

    "On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."

    30 |
    31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Tests/lib/qunit.css: -------------------------------------------------------------------------------- 1 | /** Font Family and Sizes */ 2 | 3 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { 4 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 5 | } 6 | 7 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 8 | #qunit-tests { font-size: smaller; } 9 | 10 | 11 | /** Resets */ 12 | 13 | #qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult { 14 | margin: 0; 15 | padding: 0; 16 | } 17 | 18 | 19 | /** Header */ 20 | 21 | #qunit-header { 22 | padding: 0.5em 0 0.5em 1em; 23 | 24 | color: #8699a4; 25 | background-color: #0d3349; 26 | 27 | font-size: 1.5em; 28 | line-height: 1em; 29 | font-weight: normal; 30 | 31 | border-radius: 15px 15px 0 0; 32 | -moz-border-radius: 15px 15px 0 0; 33 | -webkit-border-top-right-radius: 15px; 34 | -webkit-border-top-left-radius: 15px; 35 | } 36 | 37 | #qunit-header a { 38 | text-decoration: none; 39 | color: #c2ccd1; 40 | } 41 | 42 | #qunit-header a:hover, 43 | #qunit-header a:focus { 44 | color: #fff; 45 | } 46 | 47 | #qunit-banner { 48 | height: 5px; 49 | } 50 | 51 | #qunit-testrunner-toolbar { 52 | padding: 0em 0 0.5em 2em; 53 | } 54 | 55 | #qunit-userAgent { 56 | padding: 0.5em 0 0.5em 2.5em; 57 | background-color: #2b81af; 58 | color: #fff; 59 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 60 | } 61 | 62 | 63 | /** Tests: Pass/Fail */ 64 | 65 | #qunit-tests { 66 | list-style-position: inside; 67 | } 68 | 69 | #qunit-tests li { 70 | padding: 0.4em 0.5em 0.4em 2.5em; 71 | border-bottom: 1px solid #fff; 72 | list-style-position: inside; 73 | } 74 | 75 | #qunit-tests li strong { 76 | cursor: pointer; 77 | } 78 | 79 | #qunit-tests ol { 80 | margin-top: 0.5em; 81 | padding: 0.5em; 82 | 83 | background-color: #fff; 84 | 85 | border-radius: 15px; 86 | -moz-border-radius: 15px; 87 | -webkit-border-radius: 15px; 88 | 89 | box-shadow: inset 0px 2px 13px #999; 90 | -moz-box-shadow: inset 0px 2px 13px #999; 91 | -webkit-box-shadow: inset 0px 2px 13px #999; 92 | } 93 | 94 | #qunit-tests table { 95 | border-collapse: collapse; 96 | margin-top: .2em; 97 | } 98 | 99 | #qunit-tests th { 100 | text-align: right; 101 | vertical-align: top; 102 | padding: 0 .5em 0 0; 103 | } 104 | 105 | #qunit-tests td { 106 | vertical-align: top; 107 | } 108 | 109 | #qunit-tests pre { 110 | margin: 0; 111 | white-space: pre-wrap; 112 | word-wrap: break-word; 113 | } 114 | 115 | #qunit-tests del { 116 | background-color: #e0f2be; 117 | color: #374e0c; 118 | text-decoration: none; 119 | } 120 | 121 | #qunit-tests ins { 122 | background-color: #ffcaca; 123 | color: #500; 124 | text-decoration: none; 125 | } 126 | 127 | /*** Test Counts */ 128 | 129 | #qunit-tests b.counts { color: black; } 130 | #qunit-tests b.passed { color: #5E740B; } 131 | #qunit-tests b.failed { color: #710909; } 132 | 133 | #qunit-tests li li { 134 | margin: 0.5em; 135 | padding: 0.4em 0.5em 0.4em 0.5em; 136 | background-color: #fff; 137 | border-bottom: none; 138 | list-style-position: inside; 139 | } 140 | 141 | /*** Passing Styles */ 142 | 143 | #qunit-tests li li.pass { 144 | color: #5E740B; 145 | background-color: #fff; 146 | border-left: 26px solid #C6E746; 147 | } 148 | 149 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 150 | #qunit-tests .pass .test-name { color: #366097; } 151 | 152 | #qunit-tests .pass .test-actual, 153 | #qunit-tests .pass .test-expected { color: #999999; } 154 | 155 | #qunit-banner.qunit-pass { background-color: #C6E746; } 156 | 157 | /*** Failing Styles */ 158 | 159 | #qunit-tests li li.fail { 160 | color: #710909; 161 | background-color: #fff; 162 | border-left: 26px solid #EE5757; 163 | } 164 | 165 | #qunit-tests .fail { color: #000000; background-color: #EE5757; } 166 | #qunit-tests .fail .test-name, 167 | #qunit-tests .fail .module-name { color: #000000; } 168 | 169 | #qunit-tests .fail .test-actual { color: #EE5757; } 170 | #qunit-tests .fail .test-expected { color: green; } 171 | 172 | #qunit-banner.qunit-fail, 173 | #qunit-testrunner-toolbar { background-color: #EE5757; } 174 | 175 | 176 | /** Footer */ 177 | 178 | #qunit-testresult { 179 | padding: 0.5em 0.5em 0.5em 2.5em; 180 | 181 | color: #2b81af; 182 | background-color: #D2E0E6; 183 | 184 | border-radius: 0 0 15px 15px; 185 | -moz-border-radius: 0 0 15px 15px; 186 | -webkit-border-bottom-right-radius: 15px; 187 | -webkit-border-bottom-left-radius: 15px; 188 | } 189 | 190 | /** Fixture */ 191 | 192 | #qunit-fixture { 193 | position: absolute; 194 | top: -10000px; 195 | left: -10000px; 196 | } -------------------------------------------------------------------------------- /Tests/tests/color.js: -------------------------------------------------------------------------------- 1 | 2 | module('[Atom Plugins] Color'); 3 | 4 | test('Color Constructing', function(){ 5 | var color; 6 | 7 | color = new atom.Color('#ac45de'); 8 | 9 | equal(color.r, 172, 'Hex: red is correct'); 10 | equal(color.g, 69, 'Hex: green is correct'); 11 | equal(color.b, 222, 'Hex: blue is correct'); 12 | equal(color.a, 1, 'Hex: alpha is default'); 13 | 14 | color = new atom.Color(24, 56, 12, 0.7); 15 | 16 | equal(color.r, 24, 'Arguments: red is correct'); 17 | equal(color.g, 56, 'Arguments: green is correct'); 18 | equal(color.b, 12, 'Arguments: blue is correct'); 19 | equal(color.a, 0.7, 'Arguments: alpha is correct'); 20 | 21 | color = new atom.Color.Shift(-24, 56, -12, 0.7); 22 | 23 | equal(color.r, -24, 'No limits: red is correct'); 24 | equal(color.g, 56, 'No limits: green is correct'); 25 | equal(color.b, -12, 'No limits: blue is correct'); 26 | equal(color.a, 0.7, 'No limits: alpha is correct'); 27 | 28 | color = new atom.Color([174, 41, 62, 0.4]); 29 | 30 | equal(color.r, 174, 'Array: red is correct'); 31 | equal(color.g, 41, 'Array: green is correct'); 32 | equal(color.b, 62, 'Array: blue is correct'); 33 | equal(color.a, 0.4, 'Array: alpha is correct'); 34 | 35 | color = new atom.Color({ r: 46, g: 72, b: 0, a: 0.6 }); 36 | 37 | equal(color.r, 46, 'Object short: red is correct'); 38 | equal(color.g, 72, 'Object short: green is correct'); 39 | equal(color.b, 0, 'Object short: blue is correct'); 40 | equal(color.a, 0.6, 'Object short: alpha is correct'); 41 | 42 | color = new atom.Color({ red: 12, green: 34, blue: 50 }); 43 | 44 | equal(color.r, 12, 'Object long: red is correct'); 45 | equal(color.g, 34, 'Object long: green is correct'); 46 | equal(color.b, 50, 'Object long: blue is correct'); 47 | equal(color.a, 1, 'Object long: alpha is default'); 48 | 49 | color = new atom.Color(0x2246dd66); 50 | 51 | equal(color.r, 34, 'Number: red is correct'); 52 | equal(color.g, 70, 'Number: green is correct'); 53 | equal(color.b, 221, 'Number: blue is correct'); 54 | equal(color.a, 0.4, 'Number: alpha is correct'); 55 | 56 | color = new atom.Color(0xff000000); 57 | 58 | equal(color.r, 255, 'Big Int: red is correct'); 59 | }); 60 | 61 | test('Color Casting', function(){ 62 | var color = new atom.Color(0x2246dd66); 63 | 64 | deepEqual( color.toArray(), [34, 70, 221, 0.4], 'color.toArray()'); 65 | deepEqual( color.toString(), 'rgba(34,70,221,0.4)', 'color.toString()'); 66 | deepEqual( color.toString('hex'), '#2246dd', 'color.toString("hex")'); 67 | deepEqual( color.toString('hexA'), '#2246dd66', 'color.toString("hexA")'); 68 | deepEqual( color.toObject(), {red:34, green:70, blue:221, alpha:0.4}, 'color.toObject()'); 69 | deepEqual( color.toObject(true), {r:34, g:70, b:221, a:0.4}, 'color.toObject(true)'); 70 | deepEqual( color.toNumber(), 0x2246dd66, 'color.toNumber()'); 71 | }); 72 | 73 | test('Color Equals', function(){ 74 | var foo = new atom.Color(0x2246dd66); 75 | var bar = new atom.Color(0x2246dd66); 76 | var red = new atom.Color(0xff0000ff); 77 | 78 | notEqual(foo, bar, 'foo & bar are different objects'); 79 | ok( foo.equals(bar), 'foo equals bar'); 80 | ok(!foo.equals(red), 'foo not equals red'); 81 | ok(!foo.equals(null),'foo not equals null'); 82 | }); 83 | 84 | test('Color maniplations', function () { 85 | var foo, bar; 86 | 87 | foo = 0x12345678, bar = new atom.Color(foo); 88 | 89 | ok( atom.Color(foo).equals(bar), 'Color.invoke' ); 90 | 91 | foo = new atom.Color(foo); 92 | 93 | ok( atom.Color(foo).equals(bar), 'Color.invoke empty' ); 94 | 95 | foo = new atom.Color([ 255, 240, 225, 0.8 ]); 96 | bar = new atom.Color([ 220, 240, 250, 0.4 ]); 97 | var diff = new atom.Color.Shift([ -35, 0, 25, -0.4 ]); 98 | 99 | ok( foo.diff(bar).equals(diff), 'foo.diff(bar) is correct' ); 100 | ok( foo.move(diff).equals(bar), 'foo.move(bar) is correct' ); 101 | }); -------------------------------------------------------------------------------- /Tests/tests/core.js: -------------------------------------------------------------------------------- 1 | 2 | new function(undefined) { 3 | 4 | module('[Atom Core]'); 5 | 6 | test('Initialize', function(){ 7 | ok( atom, 'atom' ); 8 | }); 9 | test('JavaScript 1.8.5 Compatiblity', function(){ 10 | equal( typeof (function(){}.bind) , 'function', 'typeof function(){}.bind' ); 11 | equal( typeof Object.keys , 'function', 'typeof Object.keys' ); 12 | equal( typeof Array.isArray, 'function', 'typeof Array.isArray' ); 13 | 14 | ok( Array.isArray([]), ' Array.isArray([])' ); 15 | ok( !Array.isArray({}), '!Array.isArray({})' ); 16 | 17 | deepEqual( Object.keys({3:3,a:1,b:2}), ['3','a','b'], 'Object.keys({a:1,b:2,3:3})' ); 18 | }); 19 | test('atom.typeOf', function(){ 20 | equal( atom.typeOf(document.body), 'element' , 'atom.typeOf(document.body)'); 21 | equal( atom.typeOf(function(){}) , 'function' , 'atom.typeOf(function(){})'); 22 | equal( atom.typeOf(new Date()) , 'date' , 'atom.typeOf(new Date())'); 23 | equal( atom.typeOf(null) , 'null' , 'atom.typeOf(null)'); 24 | equal( atom.typeOf(arguments), 'arguments', 'atom.typeOf(arguments)'); 25 | equal( atom.typeOf(/abc/i) , 'regexp' , 'atom.typeOf(/abc/i)'); 26 | equal( atom.typeOf([]) , 'array' , 'atom.typeOf([])'); 27 | equal( atom.typeOf({}) , 'object' , 'atom.typeOf({})'); 28 | equal( atom.typeOf(15) , 'number' , 'atom.typeOf(15)'); 29 | equal( atom.typeOf(true) , 'boolean' , 'atom.typeOf(true)'); 30 | }); 31 | test('atom.clone', function(){ 32 | // array cloning 33 | var mixed, object, array, clone; 34 | array = [1,2,3,[4,5]]; 35 | clone = atom.clone(array); 36 | notStrictEqual(clone, array, 'array !== clone'); 37 | deepEqual(clone, array, 'clone is same to array'); 38 | clone[4] = 'changed'; 39 | notDeepEqual(clone, array, 'clone is changed'); 40 | 41 | // hash cloning 42 | object = {a:'2', b:'3', array: [1,2,3], object: {foo:'bar'}}; 43 | clone = atom.clone(object); 44 | notStrictEqual(clone, object, 'object !== clone'); 45 | deepEqual(clone, object, 'clone is same to object'); 46 | clone['prop'] = 'changed'; 47 | notDeepEqual(clone, object, 'clone is changed'); 48 | 49 | // object cloning 50 | var Foo = function (name) { this.name = name; }; 51 | var Bar = function (name) { 52 | this.name = name; 53 | this.clone = function () { 54 | return new Bar('clone of ' + this.name); 55 | }; 56 | }; 57 | 58 | object = {foo: new Foo('fooName'), bar: new Bar('barName')}; 59 | clone = atom.clone(object); 60 | notStrictEqual(object.bar, clone.bar, 'Objects with "clone" - cloning'); 61 | equal(clone.bar.name, 'clone of barName', 'Objects with "clone" - cloning'); 62 | 63 | // todo: [qtest] accessors 64 | }); 65 | 66 | 67 | // todo: [qtest] atom.merge 68 | test('atom.extend', function(){ 69 | atom.extend({ 70 | get testProp() { return 'testPropValue:static'; }, 71 | testMethod: function () { return 'testMethodValue:static'; } 72 | }); 73 | equal(atom.testProp, 'testPropValue:static' , 'atom.extend getter'); 74 | equal(atom.testMethod(), 'testMethodValue:static', 'atom.extend method'); 75 | 76 | var testObject = {}; 77 | atom.extend(testObject, { prop : 'Yes' }); 78 | equal(testObject.prop, 'Yes', 'atom object extend'); 79 | }); 80 | 81 | 82 | }; -------------------------------------------------------------------------------- /Tests/tests/mootools.js: -------------------------------------------------------------------------------- 1 | 2 | module('[MooTools]'); 3 | 4 | test('Prototypes.Array', function () { 5 | ok([1,2,3,0,0,0].contains(0), 'contains: element found'); 6 | ok(![0,1,2].contains('not found'), 'contains: element not found'); 7 | deepEqual([1,2,3,4].include(1).include(5), [1,2,3,4,5], 'include'); 8 | 9 | new function () { 10 | var a = [1,2,4]; 11 | var b = [2,3,4,5]; 12 | a.append(b); 13 | deepEqual(a, [1,2,4,2,3,4,5], 'append'); 14 | deepEqual(b, [2,3,4,5], 'append (original element left the same)'); 15 | }; 16 | 17 | deepEqual([1,2,3,0,0,0].erase(0), [1,2,3], 'erase'); 18 | deepEqual([1,2,3,4].combine([3,1,4,5,6,7]), [1,2,3,4,5,6,7], 'combine'); 19 | 20 | strictEqual([null, undefined, true, 1].pick(), true, 'pick: true'); 21 | strictEqual([].pick(), null, 'pick: null'); 22 | 23 | deepEqual([1,2,3,0,0,0].associate(['a', 'b', 'c', 'd']), {a:1, b:2, c:3, d:0}, 'associate'); 24 | deepEqual([null, 1, 0, true, false, "foo", undefined].clean(), [1, 0, true, false, "foo"], 'clean'); 25 | deepEqual([1,2,3,4].empty(), [], 'empty'); 26 | 27 | new function () { // Array.hexToRgb 28 | strictEqual([].hexToRgb(), null, 'hexToRgb: null'); 29 | strictEqual(['0','0','0'].hexToRgb(), 'rgb(0,0,0)', 'hexToRgb: string, digits'); 30 | strictEqual(['c','c','c'].hexToRgb(), 'rgb(204,204,204)', 'hexToRgb: string, alpha'); 31 | deepEqual(['ff','ff','ff'].hexToRgb(true), [255,255,255], 'hexToRgb: array'); 32 | }; 33 | 34 | new function () { 35 | strictEqual([0,1].rgbToHex(), null, 'rgbToHex: null'); 36 | strictEqual(['255', '0', '0'].rgbToHex(), '#ff0000', 'rgbToHex: strings'); 37 | strictEqual([0,0,255].rgbToHex(), '#0000ff', 'rgbToHex: numbers'); 38 | deepEqual([0,255,0].rgbToHex(true), ['00', 'ff', '00'], 'rgbToHex: array'); 39 | }; 40 | }); -------------------------------------------------------------------------------- /Tests/tests/prototypes.js: -------------------------------------------------------------------------------- 1 | 2 | new function () { 3 | 4 | /****************************************** 5 | * [Atom Plugins] Prototypes 6 | ******************************************/ 7 | 8 | module('[Atom Plugins] Prototypes'); 9 | 10 | test('Function', function() { 11 | 12 | equal(Function.lambda('Foo')(), 'Foo', 'Function.lambda'); 13 | 14 | // todo: [qtest] function.delay 15 | // todo: [qtest] function.periodical 16 | }); 17 | 18 | test('Number', function(){ 19 | ok(Number.random(150, 200).between(150, 200, true), 'Number.random in right range'); 20 | 21 | // between 22 | ok( (50).between(20, 80), ' (50).between(20, 80)'); 23 | ok(!(20).between(20, 80), '!(20).between(20, 80)'); 24 | ok(!( 0).between(20, 80), '!( 0).between(20, 80)'); 25 | ok( (20).between(20, 80, true), ' (20).between(20, 80, true)'); 26 | ok(!(20).between(20, 80, 'R'), '!(20).between(20, 80, "R")'); 27 | ok( (20).between(20, 80, 'L'), ' (20).between(20, 80, "L")'); 28 | ok( (20).between(20, 80, 'LR'), ' (20).between(20, 80, "LR")'); 29 | ok( (80).between(20, 80, true), ' (80).between(20, 80, true)'); 30 | ok( (80).between(20, 80, 'R'), ' (80).between(20, 80, "R")'); 31 | ok(!(80).between(20, 80, 'L'), '!(80).between(20, 80, "L")'); 32 | ok( (80).between(20, 80, 'LR'), ' (80).between(20, 80, "LR")'); 33 | 34 | // equals 35 | ok( (5).equals(5), '(5).equals(5)' ); 36 | ok(!(7).equals(5), '(7).equals(5)' ); 37 | notEqual( (0.7+0.1)*10, 8, '(0.7+0.1)*10 != 8' ); 38 | ok( ((0.7+0.1)*10).equals(8), '(0.7+0.1)*10.equals(8)' ); 39 | ok( (0.123456).equals(0.123456), ' (0.123456).equals(0.123456)' ); 40 | ok(!(0.123456).equals(0.123457), '!(0.123456).equals(0.123457)' ); 41 | ok( (0.123456).equals(0.123457, 4), ' (0.123456).equals(0.123457, 4)' ); 42 | 43 | // limit 44 | equal((50).limit(20, 80), 50, '(50).limit(20, 80) == 50'); 45 | equal((10).limit(20, 80), 20, '(10).limit(20, 80) == 20'); 46 | equal((90).limit(20, 80), 80, '(90).limit(20, 80) == 80'); 47 | 48 | // todo: [qtest] number.round(value) 49 | equal((15.234).round(), 15, '(15.234).round() == 15'); 50 | 51 | // todo: [qtest] number.toFloat 52 | // todo: [qtest] number.toInt 53 | // todo: [qtest] number.stop 54 | 55 | // todo: [qtest] number.Math 56 | }); 57 | 58 | test('String', function(){ 59 | // todo: [qtest] string.safehtml 60 | 61 | ok( 'abc def ghi'.contains('abc'), 'Search with index=0' ); 62 | ok( 'abc def ghi'.contains('def'), 'Search with index=average' ); 63 | ok( 'abc def ghi'.contains('ghi'), 'Search with index=max' ); 64 | ok( !'abc def ghi'.contains('xyz'), 'Fail search' ); 65 | 66 | // repeat 67 | equal('ab-'.repeat(3), 'ab-ab-ab-', 'String.repeat'); 68 | 69 | // repeat 70 | equal('result is {here}!'.substitute({ here: 123 }), 'result is 123!', 'String.substitute'); 71 | 72 | // replaceAll 73 | equal('Repl/ace /all "/a"'.replaceAll('/a', '0'), 'Repl0ce 0ll "0"', 'String.replaceAll(from, to)'); 74 | equal('Repl/ace /all "/a"'.replaceAll({ '/a': '0' }), 'Repl0ce 0ll "0"', 'String.replaceAll(object)'); 75 | 76 | // begins 77 | ok( 'String'.begins('Str'), 'String.begins("Str")'); 78 | ok(!'String'.begins('ing'), 'String.begins("ing")'); 79 | 80 | 81 | ok(!'String'.ends('Str'), 'String.ends("Str")'); 82 | ok( 'String'.ends('ing'), 'String.ends("ing")'); 83 | 84 | // [ul]cfirst 85 | equal( 'string'.ucfirst(), 'String', 'String.ucfirst'); 86 | equal( 'STRING'.lcfirst(), 'sTRING', 'String.lcfirst'); 87 | }); 88 | 89 | test('Array', function(){ 90 | /** Static **/ 91 | 92 | // todo: [qtest] Array.pickFrom 93 | deepEqual(Array.range(5, 9), [5,6,7,8,9], 'Array.range(5, 9)'); 94 | deepEqual(Array.range(5, 9, 2), [5, 7, 9], 'Array.range(5, 9, 2)'); 95 | deepEqual(Array.fill(5, 8), [8,8,8,8,8], 'Array.fill(5,8)'); 96 | deepEqual(Array.collect({a:1, b:2, c:3}, ['a','b','z'], 9), [1,2,9], 'Array.collect'); 97 | 98 | /** Dynamic **/ 99 | // Contains 100 | ok( [1,2,3,4].contains(3), ' [1,2,3,4].contains(3)' ); 101 | ok(![1,2,3,4].contains(0), '![1,2,3,4].contains(0)' ); 102 | 103 | // include 104 | deepEqual([1,2,3].include(4), [1,2,3,4], '[1,2,3].include(4)'); 105 | deepEqual([1,2,3].include(3), [1,2,3 ], '[1,2,3].include(3)'); 106 | 107 | deepEqual([1,2,3].append([2,3,4]), [1,2,3,2,3,4], '[1,2,3].append([2,3,4])'); 108 | deepEqual([1,2,3].append([2,3,4], [5,6,7]), [1,2,3,2,3,4,5,6,7], '[1,2,3].append([2,3,4],[5,6,7])'); 109 | 110 | // erase 111 | deepEqual([1,2,3,1,2,3].erase(2), [1,3,1,3], 'array.erase'); 112 | 113 | // combine 114 | deepEqual([1,2,3].combine([2,3,4]), [1,2,3,4], 'array.combine'); 115 | 116 | // last 117 | equal([6,7,8,9].last, 9, 'array.last'); 118 | 119 | // random 120 | ok([6,7,8,9].random.between(6, 9, true), 'array.random'); 121 | 122 | strictEqual([undefined, null, 1, undefined].pick(), 1, 'array.pick, 1'); 123 | strictEqual([undefined, null, 0, undefined].pick(), 0, 'array.pick, 0'); 124 | strictEqual([undefined, null, '', undefined].pick(), '', 'array.pick, ""'); 125 | strictEqual([undefined, null, undefined].pick(), null, 'array.pick, null'); 126 | 127 | deepEqual([ 128 | function (x) { return x * this.i * 0; }, 129 | function (x) { return x * this.i * 1; }, 130 | function (x) { return x * this.i * 2; }, 131 | function (x) { return x * this.i * 3; } 132 | ].invoke({i : 2}, 5), [0, 10, 20, 30], 'array.invoke'); 133 | // todo: [qtest] array.shuffle 134 | // todo: [qtest] array.sortBy 135 | equal([4, 1, 8, 13, 8].min(), 1, 'array.min'); 136 | equal([4, 1, 8, 13, 8].max(), 13, 'array.max'); 137 | equal([1, 2, 3, 4, 5].sum(), 15, 'array.sum'); 138 | equal([1, 2, 3, 4, 5].average(), 3, 'array.average'); 139 | deepEqual([1, 2, 1, 2, 1, 2].unique(), [1,2], 'array.unique'); 140 | // todo: [qtest] array.associate 141 | deepEqual([1,2,0,null,'string'].clean(), [1,2,0,'string'], 'array.clean'); 142 | deepEqual([1,2,3].empty(), [], 'array.empty'); 143 | deepEqual([1,2,3].clone(), [1,2,3], 'array.clone() result is similar to array'); 144 | notStrictEqual([1,2,3].clone(), [1,2,3], 'array.clone() result not equals to array'); 145 | 146 | // todo: [qtest] array.hexToRgb 147 | // todo: [qtest] array.rgbToHex 148 | }); 149 | 150 | test('Object', function(){ 151 | 152 | deepEqual(Object.invert({ a:'x', b:'y', c:'z' }), { x:'a', y: 'b', z: 'c'}, 'Object.invert'); 153 | deepEqual(Object.collect({ a:'x', b:'y', c:'z' }, ['a','b','k'], 5), { a:'x', b:'y', k:5}, 'Object.collect'); 154 | 155 | deepEqual( Object.map({a: 5, b: 6}, function (x) { return x * x }), { a: 25, b: 36 }, 'Object.map'); 156 | // todo: [qtest] Object.deepEquals 157 | 158 | var undefined, test = { foo: 2, bar: { qux: 3, zog: { asd: 4 } } }; 159 | 160 | equal( Object.path.get(test, 'foo'), 2, 'Object.path.get: First level'); 161 | equal( Object.path.get(test, 'bar.zog.asd'), 4, 'Object.path.get: Third level'); 162 | strictEqual( Object.path.get(test, 'no.value'), undefined, 'Object.path.get: no such value'); 163 | 164 | Object.path.set(test, 'rex', 15); 165 | Object.path.set(test, 'bar.zog.max', 42); 166 | 167 | equal( test.rex, 15, 'First level Object.path.set'); 168 | equal( test.bar.zog.max, 42, 'Third level Object.path.set'); 169 | 170 | deepEqual(test, { foo: 2, rex: 15, bar: { qux: 3, zog: { max: 42, asd: 4 } } }); 171 | }); 172 | 173 | }; -------------------------------------------------------------------------------- /Tests/tests/uri.js: -------------------------------------------------------------------------------- 1 | 2 | new function () { 3 | 4 | module('[Atom Plugins] Uri'); 5 | 6 | var testUri = function (uri, tests) { 7 | // based on http://stevenlevithan.com/demo/parseuri/js/ 8 | 9 | var parse = atom.uri(uri); 10 | 11 | for (prop in tests) if (prop != 'queryKey') { 12 | equal(parse[prop], tests[prop], prop); 13 | } 14 | 15 | 16 | if ('queryKey' in tests) deepEqual(parse.queryKey, tests.queryKey, 'queryKey'); 17 | }; 18 | 19 | test('Full path', function(){ 20 | var uri = 'http://usr:pwd@www.example.com:81/dir/dir.2/index.htm?q1=0&&test1&test2=value#top'; 21 | testUri( uri, { 22 | anchor: 'top', 23 | query: 'q1=0&&test1&test2=value', 24 | file: 'index.htm', 25 | directory: '/dir/dir.2/', 26 | path: '/dir/dir.2/index.htm', 27 | relative: '/dir/dir.2/index.htm?q1=0&&test1&test2=value#top', 28 | port: '81', 29 | host: 'www.example.com', 30 | password: 'pwd', 31 | user: 'usr', 32 | userInfo: 'usr:pwd', 33 | authority: 'usr:pwd@www.example.com:81', 34 | protocol: 'http', 35 | source: uri, 36 | queryKey: { 37 | q1: '0', 38 | test1: '', 39 | test2: 'value' 40 | } 41 | }); 42 | }); 43 | 44 | test('Relative path', function(){ 45 | var uri = '/dir/dir.2/index.htm?q1=0&&test1&test2=value#top'; 46 | testUri( uri, { 47 | anchor: 'top', 48 | query: 'q1=0&&test1&test2=value', 49 | file: 'index.htm', 50 | directory: '/dir/dir.2/', 51 | path: '/dir/dir.2/index.htm', 52 | relative: '/dir/dir.2/index.htm?q1=0&&test1&test2=value#top', 53 | port: '', 54 | host: '', 55 | password: '', 56 | user: '', 57 | userInfo: '', 58 | authority: '', 59 | protocol: '', 60 | source: uri, 61 | queryKey: { 62 | q1: '0', 63 | test1: '', 64 | test2: 'value' 65 | } 66 | }); 67 | }); 68 | 69 | }; -------------------------------------------------------------------------------- /Tests/visual-tests.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 16 | 17 | 18 | 19 | 20 | 94 | -------------------------------------------------------------------------------- /build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | 3 | get_all_files() : $pkg->components_to_files($argv); 16 | 17 | $files = $pkg->complete_files($files); 18 | 19 | fwrite($stderr, "/**\n"); 20 | fwrite($stderr, " * AtomJS\n * \n"); 21 | fwrite($stderr, " * Included Components:\n"); 22 | foreach ($files as $file){ 23 | fwrite($stderr, " * - $file\n"); 24 | } 25 | fwrite($stderr, " */\n\n"); 26 | 27 | $output = $pkg->build($files, array(), array(), array()); 28 | 29 | echo $output; 30 | 31 | fclose($stderr); 32 | 33 | ?> 34 | --------------------------------------------------------------------------------