exojs 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ .DS_Store
2
+ *.gem
3
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/README.md ADDED
@@ -0,0 +1,22 @@
1
+ exo.js for Sprockets
2
+ ====================
3
+
4
+ This is a gem distribution of the [Exo.js](https://github.com/jpettersson/exo.js) JavaScript library. It is automatically kept up to date with the latest stable version from the [source repository](https://github.com/jpettersson/exo.js).
5
+
6
+ Documentation
7
+ -------------
8
+
9
+ Use with Rails
10
+ -----
11
+
12
+ Add to Gemfile & bundle:
13
+ ```
14
+ gem 'exojs'
15
+ ```
16
+
17
+ Require Exo.js with Spine.js extensions:
18
+
19
+ ```Ruby
20
+ #= require 'exo'
21
+ #= require 'exo.spine'
22
+ ```
data/Rakefile ADDED
File without changes
data/exojs.gemspec ADDED
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "exojs/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "exojs"
7
+ s.version = ExoJS::VERSION
8
+ s.authors = ["Jonathan Pettersson"]
9
+ s.email = ["jonathan@spacetofu.com"]
10
+ s.homepage = "https://github.com/jpettersson/exojs-gem"
11
+ s.summary = %q{Serves you the Exo.js library through Sprockets}
12
+ s.description = "Gives you easy access to the latest stable version of the Exo.js JavaScript library, for use in Middleman, Rails or other Sprockets capable applications."
13
+
14
+ s.rubyforge_project = "exojs"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+ end
@@ -0,0 +1,800 @@
1
+ // Generated by CoffeeScript 1.6.1
2
+ (function() {
3
+ var Exo, Node, StateMachine;
4
+
5
+ Exo = this.Exo = {};
6
+
7
+ Exo.VERSION = '0.1.0';
8
+
9
+ if (typeof module !== "undefined" && module !== null) {
10
+ module.exports = Exo;
11
+ }
12
+
13
+ StateMachine = (function() {
14
+
15
+ StateMachine.E_DUPLICATE_STATE = "E_DUPLICATE_STATE: States must be distinct";
16
+
17
+ StateMachine.E_DUPLICATE_TRANSITION = "E_DUPLICATE_TRANSITION: Transitions must be distinct";
18
+
19
+ StateMachine.E_UNDEFINED_STATE = "E_UNDEFINED_STATE: All states used in transitions must be defined in the states array";
20
+
21
+ function StateMachine(opts) {
22
+ var currentState, currentTransition, initialState, states, transitions, validate;
23
+ if (opts == null) {
24
+ opts = {};
25
+ }
26
+ states = opts.states || [];
27
+ transitions = opts.transitions || [];
28
+ (validate = function() {
29
+ var sCheck, tCheck, tStates, transition, unique;
30
+ unique = function(a) {
31
+ var key, output, value, _i, _ref, _results;
32
+ output = {};
33
+ for (key = _i = 0, _ref = a.length; 0 <= _ref ? _i < _ref : _i > _ref; key = 0 <= _ref ? ++_i : --_i) {
34
+ output[a[key]] = a[key];
35
+ }
36
+ _results = [];
37
+ for (key in output) {
38
+ value = output[key];
39
+ _results.push(value);
40
+ }
41
+ return _results;
42
+ };
43
+ if (states.length !== unique(states).length) {
44
+ throw StateMachine.E_DUPLICATE_STATE;
45
+ }
46
+ tCheck = [];
47
+ sCheck = [];
48
+ for (transition in transitions) {
49
+ tStates = transitions[transition];
50
+ tCheck.push("" + tStates.from + "->" + tStates.to);
51
+ sCheck.push(tStates.to);
52
+ sCheck.push(tStates.from);
53
+ }
54
+ if (unique(sCheck).length > states.length) {
55
+ throw StateMachine.E_UNDEFINED_STATE;
56
+ }
57
+ if (tCheck.length !== unique(tCheck).length) {
58
+ throw StateMachine.E_DUPLICATE_TRANSITION;
59
+ }
60
+ })();
61
+ currentState = initialState = opts.initialState || null;
62
+ currentTransition = null;
63
+ this.attemptTransition = function(transitionName) {
64
+ if (!this.isTransitioning() && this.transitionIsPossible(transitionName)) {
65
+ currentTransition = transitions[transitionName];
66
+ this.performTransition(transitionName);
67
+ return true;
68
+ } else {
69
+ return false;
70
+ }
71
+ };
72
+ this.isTransitioning = function() {
73
+ return currentTransition !== null;
74
+ };
75
+ this.transitionIsPossible = function(transitionName) {
76
+ var transition;
77
+ if (transition = transitions[transitionName]) {
78
+ return currentState !== transition.to && currentState === transition.from;
79
+ } else {
80
+ return false;
81
+ }
82
+ };
83
+ this.onTransitionComplete = function() {
84
+ if (currentTransition) {
85
+ currentState = currentTransition.to;
86
+ currentTransition = null;
87
+ return true;
88
+ } else {
89
+ return false;
90
+ }
91
+ };
92
+ this.states = function() {
93
+ return states;
94
+ };
95
+ this.transitions = function() {
96
+ return transitions;
97
+ };
98
+ this.currentState = function() {
99
+ return currentState;
100
+ };
101
+ this.initialState = function() {
102
+ return initialState;
103
+ };
104
+ }
105
+
106
+ StateMachine.prototype.performTransition = function(transitionName) {};
107
+
108
+ return StateMachine;
109
+
110
+ })();
111
+
112
+ Exo.StateMachine = StateMachine;
113
+
114
+ /*
115
+ Overview of a node
116
+
117
+ The Class Methods are used internally by the framework.
118
+ */
119
+
120
+
121
+ Node = (function() {
122
+
123
+ Node.__currentId = 0;
124
+
125
+ Node.Transitions = {
126
+ ACTIVATE: 'activate',
127
+ DEACTIVATE: 'deactivate'
128
+ };
129
+
130
+ Node.States = {
131
+ ACTIVATED: 'activated',
132
+ DEACTIVATED: 'deactivated'
133
+ };
134
+
135
+ Node.Modes = {
136
+ EXCLUSIVE: 'exclusive',
137
+ MULTI: 'multi'
138
+ };
139
+
140
+ /*
141
+ Generate the next unique node ID string.
142
+ */
143
+
144
+
145
+ Node.nextId = function() {
146
+ Node.__currentId = Node.__currentId + 1;
147
+ return Node.__currentId;
148
+ };
149
+
150
+ /*
151
+ Attempt to activate a node instance.
152
+ @param [Node] node
153
+ */
154
+
155
+
156
+ Node.activate = function(node) {
157
+ var parent, sibling;
158
+ if (this.lineageIsBusy(node) || node.isActivated()) {
159
+ return false;
160
+ }
161
+ if (parent = node.parent()) {
162
+ if (parent.isActivated()) {
163
+ if (parent.mode() === Node.Modes.EXCLUSIVE) {
164
+ if (sibling = parent.activatedChildren()[0]) {
165
+ sibling.setOnDeactivatedAction({
166
+ node: node,
167
+ transition: Node.Transitions.ACTIVATE
168
+ });
169
+ return Node.deactivate(sibling);
170
+ }
171
+ }
172
+ } else {
173
+ if (!parent.childrenCanActivate()) {
174
+ return false;
175
+ }
176
+ parent.setOnActivatedAction({
177
+ node: node,
178
+ transition: Node.Transitions.ACTIVATE
179
+ });
180
+ return Node.activate(parent);
181
+ }
182
+ }
183
+ return node.attemptTransition(Node.Transitions.ACTIVATE);
184
+ };
185
+
186
+ /*
187
+ Attempt to deactivate a node instance.
188
+ @param [Node] node
189
+ */
190
+
191
+
192
+ Node.deactivate = function(node) {
193
+ var child, _i, _len, _ref;
194
+ if (node.isActivated() && !this.lineageIsBusy(node)) {
195
+ if (node.mode() === Node.Modes.EXCLUSIVE) {
196
+ if (child = node.activatedChildren()[0]) {
197
+ child.setOnDeactivatedAction({
198
+ node: node,
199
+ transition: Node.Transitions.DEACTIVATE
200
+ });
201
+ return Node.deactivate(child);
202
+ }
203
+ } else if (node.mode === Node.Modes.MULTI) {
204
+ _ref = node.activatedChildren();
205
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
206
+ child = _ref[_i];
207
+ Node.deactivate(child);
208
+ }
209
+ }
210
+ node.attemptTransition(Node.Transitions.DEACTIVATE);
211
+ }
212
+ return false;
213
+ };
214
+
215
+ /*
216
+ Attempts to perform activation if the node is deactivated and vice versa.
217
+ @param [Node] node
218
+ */
219
+
220
+
221
+ Node.toggle = function(node) {
222
+ if (node.isActivated()) {
223
+ return this.deactivate(node);
224
+ } else {
225
+ return this.activate(node);
226
+ }
227
+ };
228
+
229
+ /*
230
+ Find out if the lineage of a node is busy. This will be true if a parent, sibling or child is currently transitioning.
231
+ @param [Node] node
232
+ */
233
+
234
+
235
+ Node.lineageIsBusy = function(node) {
236
+ var parent;
237
+ if (parent = node.parent()) {
238
+ if (parent.isBusy()) {
239
+ return true;
240
+ }
241
+ while (parent = parent.parent()) {
242
+ if (parent.isBusy()) {
243
+ return true;
244
+ }
245
+ }
246
+ }
247
+ return false;
248
+ };
249
+
250
+ /*
251
+ Node instances call this function when done activating. If there is a pending action it will be executed.
252
+ @param [Node] node
253
+ */
254
+
255
+
256
+ Node.onNodeActivated = function(node) {
257
+ var action;
258
+ if (node.parent()) {
259
+ node.parent().onChildActivated(node);
260
+ }
261
+ if (action = node.onActivatedAction()) {
262
+ return this.processAction(action);
263
+ }
264
+ };
265
+
266
+ /*
267
+ Node instances call this function when done deactivating. If there is a pending action it will be executed.
268
+ @param [Node] node
269
+ */
270
+
271
+
272
+ Node.onNodeDeactivated = function(node) {
273
+ var action, _ref;
274
+ if (node.parent()) {
275
+ node.parent().onChildDeactivated(node);
276
+ }
277
+ if (action = node.onDeactivatedAction()) {
278
+ return this.processAction(action);
279
+ } else if ((_ref = node.parent()) != null ? _ref.defaultChild() : void 0) {
280
+ return Node.activate(node.parent().defaultChild());
281
+ }
282
+ };
283
+
284
+ /*
285
+ Process an action of activating or deactivating a node reference.
286
+ @param [Object] action
287
+ */
288
+
289
+
290
+ Node.processAction = function(action) {
291
+ if (action.transition === Node.Transitions.ACTIVATE) {
292
+ return this.activate(action.node);
293
+ } else if (action.transition === Node.Transitions.DEACTIVATE) {
294
+ return this.deactivate(action.node);
295
+ }
296
+ };
297
+
298
+ /*
299
+ Constructor
300
+ @param [Object] options
301
+ @option options [Array] children add children at instantiation.
302
+ @option options [String] mode one of two possible operational modes: 'exclusive', 'multi'
303
+ @option options [String] initialState 'deactivated' or 'activated' default is 'deactivated'.
304
+ @option options [Boolean] childrenCanActivate If true, this node can be activated by it's children. Defaults to true.
305
+ */
306
+
307
+
308
+ function Node(opts) {
309
+ var child, node, _i, _j, _len, _len1, _ref, _ref1;
310
+ if (opts == null) {
311
+ opts = {};
312
+ }
313
+ this._parent = null;
314
+ this._childMap = {};
315
+ this._defaultChild = null;
316
+ this._nId = "exo#" + (Node.nextId());
317
+ if (opts.children) {
318
+ _ref = opts.children;
319
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
320
+ node = _ref[_i];
321
+ node.setParent(this);
322
+ _ref1 = opts.children;
323
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
324
+ child = _ref1[_j];
325
+ this.addChild(child);
326
+ }
327
+ }
328
+ }
329
+ this._mode = opts.mode || (opts.mode = Node.Modes.EXCLUSIVE);
330
+ this._initialState = opts.initialState || (opts.initialState = Node.States.DEACTIVATED);
331
+ if (opts.childrenCanActivate === false) {
332
+ this._childrenCanActivate = false;
333
+ } else {
334
+ this._childrenCanActivate = true;
335
+ }
336
+ this._onActivatedAction = null;
337
+ this._onDeactivatedAction = null;
338
+ }
339
+
340
+ /*
341
+ Returns the id of the node. By default this is a generated unique String value.
342
+ */
343
+
344
+
345
+ Node.prototype.nodeId = function() {
346
+ return this._nId;
347
+ };
348
+
349
+ /*
350
+ Manually set the node ID. Caution: If multiple children of a node are given the same ID only one instance will persist.
351
+ */
352
+
353
+
354
+ Node.prototype.setNodeId = function(nid) {
355
+ var _ref;
356
+ if ((_ref = this._parent) != null) {
357
+ _ref.onChildIdUpdated(this._nId, nid, this);
358
+ }
359
+ return this._nId = nid;
360
+ };
361
+
362
+ /*
363
+ Returns the internal state-machine instance.
364
+ */
365
+
366
+
367
+ Node.prototype.sm = function() {
368
+ var _this = this;
369
+ if (this._smRef) {
370
+ return this._smRef;
371
+ }
372
+ this._smRef = new Exo.StateMachine({
373
+ states: [Node.States.DEACTIVATED, Node.States.ACTIVATED],
374
+ initialState: this._initialState,
375
+ transitions: {
376
+ activate: {
377
+ from: Node.States.DEACTIVATED,
378
+ to: Node.States.ACTIVATED
379
+ },
380
+ deactivate: {
381
+ from: Node.States.ACTIVATED,
382
+ to: Node.States.DEACTIVATED
383
+ }
384
+ }
385
+ });
386
+ this._smRef.performTransition = function(t) {
387
+ if (t === Node.Transitions.ACTIVATE) {
388
+ _this.beforeActivate();
389
+ return _this.doActivate();
390
+ } else if (t === Node.Transitions.DEACTIVATE) {
391
+ _this.beforeDeactivate();
392
+ return _this.doDeactivate();
393
+ }
394
+ };
395
+ return this._smRef;
396
+ };
397
+
398
+ /*
399
+ Children call this function on their parent when their node ID has been manually changed.
400
+ */
401
+
402
+
403
+ Node.prototype.onChildIdUpdated = function(oldId, newId, child) {
404
+ delete this._childMap[oldId];
405
+ return this._childMap[newId] = child;
406
+ };
407
+
408
+ /*
409
+ Used by the framework to chain sequences of Node activation.
410
+ For instance, when activating a sibling of an already activated node this function will be called on the parent
411
+ with a reference to the sibling.
412
+ */
413
+
414
+
415
+ Node.prototype.setOnActivatedAction = function(action) {
416
+ return this._onActivatedAction = action;
417
+ };
418
+
419
+ /*
420
+ A getter to read the onActivatedAction value.
421
+ */
422
+
423
+
424
+ Node.prototype.onActivatedAction = function() {
425
+ return this._onActivatedAction;
426
+ };
427
+
428
+ /*
429
+ Used by the framework to chain sequences of Node deactivation.
430
+ */
431
+
432
+
433
+ Node.prototype.setOnDeactivatedAction = function(action) {
434
+ return this._onDeactivatedAction = action;
435
+ };
436
+
437
+ /*
438
+ Get the onDeactivatedAction value.
439
+ */
440
+
441
+
442
+ Node.prototype.onDeactivatedAction = function() {
443
+ return this._onDeactivatedAction;
444
+ };
445
+
446
+ /*
447
+ Get the childrenCanActivate setting.
448
+ */
449
+
450
+
451
+ Node.prototype.childrenCanActivate = function() {
452
+ return this._childrenCanActivate;
453
+ };
454
+
455
+ /*
456
+ Set the mode.
457
+ @param [String] mode
458
+ */
459
+
460
+
461
+ Node.prototype.setMode = function(m) {
462
+ return this._mode = m;
463
+ };
464
+
465
+ /*
466
+ Get the mode.
467
+ */
468
+
469
+
470
+ Node.prototype.mode = function() {
471
+ return this._mode;
472
+ };
473
+
474
+ /*
475
+ Set the parent Node. This is called automatically when using node.addChild
476
+ @param [Node] node
477
+ */
478
+
479
+
480
+ Node.prototype.setParent = function(node) {
481
+ return this._parent = node;
482
+ };
483
+
484
+ /*
485
+ Get the parent Node.
486
+ */
487
+
488
+
489
+ Node.prototype.parent = function() {
490
+ return this._parent;
491
+ };
492
+
493
+ /*
494
+ Add a Node instance as a child.
495
+ @param [Node] node
496
+ */
497
+
498
+
499
+ Node.prototype.addChild = function(node) {
500
+ if (node === null || typeof node === 'undefined') {
501
+ throw new Error("ExoReferenceError -> addChild: " + node + " is not a valid Exo.Node");
502
+ }
503
+ if (this.nodeId() === node.nodeId()) {
504
+ throw new Error("ExoReferenceError -> An Exo.Node instance can't pass itself to addChild");
505
+ }
506
+ node.setParent(this);
507
+ return this._childMap[node.nodeId()] = node;
508
+ };
509
+
510
+ /*
511
+ Remove a Node child from this instance.
512
+ @param [Node] node
513
+ */
514
+
515
+
516
+ Node.prototype.removeChild = function(node) {
517
+ return delete this._childMap[node.nodeId()];
518
+ };
519
+
520
+ /*
521
+ Set the default child node. This node will be automatically activated when this node has activated.
522
+ It will also be activated when a sibling has deactivated, unless there's an onDeactivatedAction set.
523
+ @param [Node] node
524
+ */
525
+
526
+
527
+ Node.prototype.setDefaultChild = function(node) {
528
+ return this._defaultChild = node;
529
+ };
530
+
531
+ /*
532
+ Get the default child Node.
533
+ */
534
+
535
+
536
+ Node.prototype.defaultChild = function() {
537
+ return this._defaultChild;
538
+ };
539
+
540
+ /*
541
+ An alias of childrenAsArray
542
+ */
543
+
544
+
545
+ Node.prototype.children = function() {
546
+ return this.childrenAsArray();
547
+ };
548
+
549
+ /*
550
+ Get the children of this node as an Array.
551
+ */
552
+
553
+
554
+ Node.prototype.childrenAsArray = function(obj) {
555
+ var arr, child, id, _ref;
556
+ arr = [];
557
+ _ref = this._childMap;
558
+ for (id in _ref) {
559
+ child = _ref[id];
560
+ arr.push(child);
561
+ }
562
+ return arr;
563
+ };
564
+
565
+ /*
566
+ Get an Array of activated child nodes.
567
+ */
568
+
569
+
570
+ Node.prototype.activatedChildren = function() {
571
+ return this.children().filter(function(n) {
572
+ return n.isActivated();
573
+ });
574
+ };
575
+
576
+ /*
577
+ Get a child by its String ID.
578
+ @param [String] id
579
+ */
580
+
581
+
582
+ Node.prototype.childById = function(id) {
583
+ return this._childMap[id];
584
+ };
585
+
586
+ /*
587
+ Get a descendant (child or deeper) by its String ID.
588
+ @param [String] id
589
+ */
590
+
591
+
592
+ Node.prototype.descendantById = function(id) {
593
+ var child, descendant, _i, _len, _ref;
594
+ child = this.childById(id);
595
+ if (child) {
596
+ return child;
597
+ }
598
+ _ref = this.children();
599
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
600
+ child = _ref[_i];
601
+ descendant = child.getDescendantById(id);
602
+ if (descendant) {
603
+ return descendant;
604
+ }
605
+ }
606
+ };
607
+
608
+ /*
609
+ Get an Array of Node instances that have the same parent as this instance.
610
+ */
611
+
612
+
613
+ Node.prototype.siblings = function() {
614
+ var ownId;
615
+ ownId = this.nodeId();
616
+ if (this.parent()) {
617
+ return this.parent().children().filter(function(n) {
618
+ return n.nodeId() !== ownId;
619
+ });
620
+ }
621
+ return [];
622
+ };
623
+
624
+ /*
625
+ Get a boolean stating if this Node instance is in the 'activated' state.
626
+ */
627
+
628
+
629
+ Node.prototype.isActivated = function() {
630
+ return this.sm().currentState() === Node.States.ACTIVATED;
631
+ };
632
+
633
+ /*
634
+ Get a boolean stating if this Node instance is currently transitioning.
635
+ */
636
+
637
+
638
+ Node.prototype.isTransitioning = function() {
639
+ return this.sm().isTransitioning();
640
+ };
641
+
642
+ /*
643
+ Get a boolean stating if this Node instance or any of its children are transitioning.
644
+ Note: Child transition status will only be included if mode == Node.Modes.Exclusive
645
+ */
646
+
647
+
648
+ Node.prototype.isBusy = function() {
649
+ if (this.isTransitioning()) {
650
+ return true;
651
+ }
652
+ if (this.mode() === Node.Modes.EXCLUSIVE) {
653
+ if (this.children().filter(function(n) {
654
+ return n.isBusy();
655
+ }).length > 0) {
656
+ return true;
657
+ }
658
+ }
659
+ return false;
660
+ };
661
+
662
+ /*
663
+ Get a boolean stating if any of the children of this node are transitioning.
664
+ */
665
+
666
+
667
+ Node.prototype.haveBusyChildren = function() {
668
+ return this.children().filter(function(n) {
669
+ return n.isBusy();
670
+ }).length > 0;
671
+ };
672
+
673
+ /*
674
+ Attempt to perform a transition to a new state.
675
+ @param [String] transition
676
+ */
677
+
678
+
679
+ Node.prototype.attemptTransition = function(t) {
680
+ return this.sm().attemptTransition(t);
681
+ };
682
+
683
+ /*
684
+ Attempt to activate this Node instance.
685
+ */
686
+
687
+
688
+ Node.prototype.activate = function() {
689
+ return Node.activate(this);
690
+ };
691
+
692
+ /*
693
+ Attempt to deactivate this Node instance.
694
+ */
695
+
696
+
697
+ Node.prototype.deactivate = function() {
698
+ return Node.deactivate(this);
699
+ };
700
+
701
+ /*
702
+ Attempt to toggle this Node instance.
703
+ */
704
+
705
+
706
+ Node.prototype.toggle = function() {
707
+ return Node.toggle(this);
708
+ };
709
+
710
+ /*
711
+ Attempt to deactivate all children of this Node instance.
712
+ */
713
+
714
+
715
+ Node.prototype.deactivateChildren = function() {
716
+ var child, _i, _len, _ref, _results;
717
+ _ref = this.children();
718
+ _results = [];
719
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
720
+ child = _ref[_i];
721
+ _results.push(child.deactivate());
722
+ }
723
+ return _results;
724
+ };
725
+
726
+ /*
727
+ Should be called when the activate transition is done. Can be overridden.
728
+ */
729
+
730
+
731
+ Node.prototype.onActivated = function() {
732
+ this.sm().onTransitionComplete();
733
+ Node.onNodeActivated(this);
734
+ return this.setOnActivatedAction(null);
735
+ };
736
+
737
+ /*
738
+ Should be called when the deactivate transition is done. Can be overridden.
739
+ */
740
+
741
+
742
+ Node.prototype.onDeactivated = function() {
743
+ this.sm().onTransitionComplete();
744
+ Node.onNodeDeactivated(this);
745
+ return this.setOnDeactivatedAction(null);
746
+ };
747
+
748
+ /*
749
+ Is called before doActivate. Can be overridden.
750
+ */
751
+
752
+
753
+ Node.prototype.beforeActivate = function() {};
754
+
755
+ /*
756
+ Called when the activate transition should begin. Can be overridden.
757
+ */
758
+
759
+
760
+ Node.prototype.doActivate = function() {
761
+ return this.onActivated();
762
+ };
763
+
764
+ /*
765
+ Is called before doDectivate. Can be overridden.
766
+ */
767
+
768
+
769
+ Node.prototype.beforeDeactivate = function() {};
770
+
771
+ /*
772
+ Called when the deactivate transition should begin. Can be overridden.
773
+ */
774
+
775
+
776
+ Node.prototype.doDeactivate = function() {
777
+ return this.onDeactivated();
778
+ };
779
+
780
+ /*
781
+ Called when a child Node of this instance has been activated.
782
+ */
783
+
784
+
785
+ Node.prototype.onChildActivated = function(child) {};
786
+
787
+ /*
788
+ Called when a child Node of this instance has been deactivated.
789
+ */
790
+
791
+
792
+ Node.prototype.onChildDeactivated = function(child) {};
793
+
794
+ return Node;
795
+
796
+ })();
797
+
798
+ Exo.Node = Node;
799
+
800
+ }).call(this);
@@ -0,0 +1,379 @@
1
+ // Generated by CoffeeScript 1.6.1
2
+ (function() {
3
+ var Controller, List, Model, Spine,
4
+ __hasProp = {}.hasOwnProperty,
5
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
6
+ __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
7
+ __slice = [].slice;
8
+
9
+ Spine = this.Spine || require('spine');
10
+
11
+ Controller = (function(_super) {
12
+
13
+ __extends(Controller, _super);
14
+
15
+ function Controller(opts) {
16
+ var _this = this;
17
+ if (opts == null) {
18
+ opts = {};
19
+ }
20
+ this._nodeOpts = opts;
21
+ this._node = null;
22
+ this.node().beforeActivate = function() {
23
+ var _ref;
24
+ _this.trigger('beforeActivate', _this);
25
+ return (_ref = _this.beforeActivate) != null ? _ref.call(_this) : void 0;
26
+ };
27
+ this.node().doActivate = function() {
28
+ return _this.doActivate();
29
+ };
30
+ this.node().beforeDeactivate = function() {
31
+ var _ref;
32
+ _this.trigger('beforeDeactivate', _this);
33
+ return (_ref = _this.beforeDeactivate) != null ? _ref.call(_this) : void 0;
34
+ };
35
+ this.node().doDeactivate = function() {
36
+ return _this.doDeactivate();
37
+ };
38
+ this.node().onChildActivated = function(node) {
39
+ _this.trigger('onChildActivated', node.controller);
40
+ return typeof _this.onChildActivated === "function" ? _this.onChildActivated(node.controller) : void 0;
41
+ };
42
+ this.node().onChildDeactivated = function(node) {
43
+ _this.trigger('onChildDeactivated', node.controller);
44
+ return typeof _this.onChildDeactivated === "function" ? _this.onChildDeactivated(node.controller) : void 0;
45
+ };
46
+ if (opts.initialState) {
47
+ delete opts.initialState;
48
+ }
49
+ if (opts.mode) {
50
+ delete opts.mode;
51
+ }
52
+ if (opts.children) {
53
+ delete opts.children;
54
+ }
55
+ Controller.__super__.constructor.call(this, opts);
56
+ this.prepare();
57
+ }
58
+
59
+ Controller.prototype.node = function() {
60
+ if (!this._node) {
61
+ this._node = new Exo.Node(this._nodeOpts);
62
+ this._node.controller = this;
63
+ }
64
+ return this._node;
65
+ };
66
+
67
+ Controller.prototype.nodeId = function() {
68
+ return this.node().nodeId();
69
+ };
70
+
71
+ Controller.prototype.setNodeId = function(id) {
72
+ return this.node().setNodeId(id);
73
+ };
74
+
75
+ Controller.prototype.setMode = function(mode) {
76
+ return this.node().setMode(mode);
77
+ };
78
+
79
+ Controller.prototype.activate = function() {
80
+ return this.node().activate();
81
+ };
82
+
83
+ Controller.prototype.deactivate = function() {
84
+ return this.node().deactivate();
85
+ };
86
+
87
+ Controller.prototype.toggle = function() {
88
+ return this.node().toggle();
89
+ };
90
+
91
+ Controller.prototype.deactivateChildren = function() {
92
+ return this.node().deactivateChildren();
93
+ };
94
+
95
+ Controller.prototype.addChild = function(controller) {
96
+ return this.node().addChild(controller != null ? controller.node() : void 0);
97
+ };
98
+
99
+ Controller.prototype.children = function() {
100
+ return this.node().children().map(function(node) {
101
+ return node.controller;
102
+ });
103
+ };
104
+
105
+ Controller.prototype.parent = function() {
106
+ var _ref;
107
+ return (_ref = this.node().parent()) != null ? _ref.controller : void 0;
108
+ };
109
+
110
+ Controller.prototype.childById = function(id) {
111
+ var _ref;
112
+ return (_ref = this.node().childById(id)) != null ? _ref.controller : void 0;
113
+ };
114
+
115
+ Controller.prototype.descendantById = function(id) {
116
+ var _ref;
117
+ return (_ref = this.node().descendantById(id)) != null ? _ref.controller : void 0;
118
+ };
119
+
120
+ Controller.prototype.siblings = function() {
121
+ return this.node().siblings().map(function(node) {
122
+ return node.controller;
123
+ });
124
+ };
125
+
126
+ Controller.prototype.activatedChildren = function() {
127
+ return this.node().activatedChildren();
128
+ };
129
+
130
+ Controller.prototype.removeChild = function(controller) {
131
+ return this.node().removeChild(controller.node());
132
+ };
133
+
134
+ Controller.prototype.setDefaultChild = function(controller) {
135
+ return this.node().setDefaultChild(controller.node());
136
+ };
137
+
138
+ Controller.prototype.defaultChild = function() {
139
+ return this.node().defaultChild();
140
+ };
141
+
142
+ Controller.prototype.isActivated = function() {
143
+ return this.node().isActivated();
144
+ };
145
+
146
+ Controller.prototype.isTransitioning = function() {
147
+ return this.node().isTransitioning();
148
+ };
149
+
150
+ Controller.prototype.isBusy = function() {
151
+ return this.node().isBusy();
152
+ };
153
+
154
+ Controller.prototype.haveBusyChildren = function() {
155
+ return this.node().haveBusyChildren();
156
+ };
157
+
158
+ Controller.prototype.prepare = function() {};
159
+
160
+ Controller.prototype.doActivate = function() {
161
+ return this.onActivated();
162
+ };
163
+
164
+ Controller.prototype.onActivated = function() {
165
+ this.node().onActivated();
166
+ return this.trigger('onActivated', this);
167
+ };
168
+
169
+ Controller.prototype.doDeactivate = function() {
170
+ return this.onDeactivated();
171
+ };
172
+
173
+ Controller.prototype.onDeactivated = function() {
174
+ this.node().onDeactivated();
175
+ return this.trigger('onDeactivated', this);
176
+ };
177
+
178
+ return Controller;
179
+
180
+ })(Spine.Controller);
181
+
182
+ Exo.Spine || (Exo.Spine = {});
183
+
184
+ Exo.Spine.Controller = Controller;
185
+
186
+ List = (function(_super) {
187
+
188
+ __extends(List, _super);
189
+
190
+ function List(opts) {
191
+ if (opts == null) {
192
+ opts = {};
193
+ }
194
+ opts.initialState || (opts.initialState = Exo.Node.States.ACTIVATED);
195
+ opts.mode || (opts.mode = Exo.Node.Modes.MULTI);
196
+ List.__super__.constructor.call(this, opts);
197
+ }
198
+
199
+ List.prototype.templateFor = function(templates, item) {
200
+ return templates[item.className];
201
+ };
202
+
203
+ List.prototype.controllerFor = function(controllers, item) {
204
+ return controllers[item.className];
205
+ };
206
+
207
+ List.prototype.render = function(collection, opts) {
208
+ if (opts == null) {
209
+ opts = {};
210
+ }
211
+ this.collection = collection;
212
+ if (this.template || this.templates) {
213
+ return this.renderTemplates(collection);
214
+ } else if (this.controller || this.controllers) {
215
+ return this.renderControllers(collection, opts);
216
+ }
217
+ };
218
+
219
+ List.prototype.renderTemplates = function(collection) {
220
+ var el, html, item, templates, _i, _len, _results;
221
+ templates = this.templates || {
222
+ "default": this.template
223
+ };
224
+ _results = [];
225
+ for (_i = 0, _len = collection.length; _i < _len; _i++) {
226
+ item = collection[_i];
227
+ html = (templates["default"] || templates[item.constructor.className]).call(this, item);
228
+ el = $(html).appendTo(this.el);
229
+ _results.push($(el).data('item', item));
230
+ }
231
+ return _results;
232
+ };
233
+
234
+ List.prototype.renderControllers = function(collection, opts) {
235
+ var child, controllers, i, item, _i, _len;
236
+ controllers = this.controllers || {
237
+ "default": this.controller
238
+ };
239
+ this.deactivateAndKillOrphans(this.children(), collection);
240
+ for (i = _i = 0, _len = collection.length; _i < _len; i = ++_i) {
241
+ item = collection[i];
242
+ child = this.getOrCreateChild(item, controllers[item.constructor.className] || controllers["default"], opts);
243
+ child.listIndex = i;
244
+ if (child.moveTo) {
245
+ child.moveTo(i);
246
+ }
247
+ child.activate();
248
+ }
249
+ return this.trigger('afterRender', this);
250
+ };
251
+
252
+ List.prototype.getOrCreateChild = function(item, controller, opts) {
253
+ var child;
254
+ child = this.childById(item.constructor.className + item.id);
255
+ if (!child) {
256
+ child = new controller(opts);
257
+ this.addChild(child);
258
+ child.setNodeId(item.constructor.className + item.id);
259
+ child.prepareWithModel(item);
260
+ this.append(child);
261
+ $(child.el).data('item', item);
262
+ }
263
+ return child;
264
+ };
265
+
266
+ List.prototype.deactivateAndKillOrphans = function(children, collection) {
267
+ var orphan, orphans, _i, _len, _results,
268
+ _this = this;
269
+ orphans = children.filter(function(child) {
270
+ var _ref;
271
+ return _ref = child.nodeId(), __indexOf.call(collection.map(function(item) {
272
+ return item.constructor.className + item.id;
273
+ }), _ref) < 0;
274
+ });
275
+ _results = [];
276
+ for (_i = 0, _len = orphans.length; _i < _len; _i++) {
277
+ orphan = orphans[_i];
278
+ if (orphan.isActivated() && !orphan.isBusy()) {
279
+ orphan.bind('onDeactivated', function(controller) {
280
+ _this.removeChild(controller);
281
+ return controller.release();
282
+ });
283
+ }
284
+ _results.push(orphan.deactivate());
285
+ }
286
+ return _results;
287
+ };
288
+
289
+ List.prototype.click = function(e) {
290
+ var item;
291
+ if ($(e.currentTarget).item) {
292
+ item = $(e.currentTarget).item();
293
+ } else {
294
+ item = $(e.currentTarget).data('item');
295
+ }
296
+ this.trigger('select', item, $(e.currentTarget));
297
+ return true;
298
+ };
299
+
300
+ return List;
301
+
302
+ })(Exo.Spine.Controller);
303
+
304
+ if (typeof Exo !== "undefined" && Exo !== null) {
305
+ Exo.Spine || (Exo.Spine = {});
306
+ }
307
+
308
+ if (typeof Exo !== "undefined" && Exo !== null) {
309
+ Exo.Spine.List = List;
310
+ }
311
+
312
+ if (typeof module !== "undefined" && module !== null) {
313
+ module.exports = List;
314
+ }
315
+
316
+ Spine = this.Spine || require('spine');
317
+
318
+ Model = (function(_super) {
319
+
320
+ __extends(Model, _super);
321
+
322
+ function Model() {
323
+ return Model.__super__.constructor.apply(this, arguments);
324
+ }
325
+
326
+ Model.defaults = function(atts) {
327
+ return this.defaultValues = atts;
328
+ };
329
+
330
+ Model.configure = function() {
331
+ var attributes, name;
332
+ name = arguments[0], attributes = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
333
+ attributes = attributes.concat(['created_at', 'updated_at']);
334
+ return Model.__super__.constructor.configure.apply(this, [name].concat(__slice.call(attributes)));
335
+ };
336
+
337
+ Model.create = function(atts, options) {
338
+ var attribute, _i, _len, _ref;
339
+ if (atts == null) {
340
+ atts = {};
341
+ }
342
+ if (options == null) {
343
+ options = {};
344
+ }
345
+ if (this.defaultValues) {
346
+ _ref = this.attributes;
347
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
348
+ attribute = _ref[_i];
349
+ if (!atts[attribute]) {
350
+ if (this.defaultValues[attribute.toString()] || this.defaultValues[attribute.toString()] === 0) {
351
+ atts[attribute.toString()] = this.defaultValues[attribute.toString()];
352
+ }
353
+ }
354
+ }
355
+ }
356
+ return Model.__super__.constructor.create.call(this, atts, options);
357
+ };
358
+
359
+ Model.prototype.getClassName = function() {
360
+ return this.constructor.className;
361
+ };
362
+
363
+ return Model;
364
+
365
+ })(Spine.Model);
366
+
367
+ if (typeof Exo !== "undefined" && Exo !== null) {
368
+ Exo.Spine || (Exo.Spine = {});
369
+ }
370
+
371
+ if (typeof Exo !== "undefined" && Exo !== null) {
372
+ Exo.Spine.Model = Model;
373
+ }
374
+
375
+ if (typeof module !== "undefined" && module !== null) {
376
+ module.exports = Model;
377
+ }
378
+
379
+ }).call(this);
@@ -0,0 +1,3 @@
1
+ module ExoJS
2
+ VERSION = '0.1.0'
3
+ end
data/lib/exojs.rb ADDED
@@ -0,0 +1,5 @@
1
+ module ExoJS
2
+
3
+ end
4
+
5
+ require_relative 'exojs/version'
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: exojs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jonathan Pettersson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-26 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Gives you easy access to the latest stable version of the Exo.js JavaScript
15
+ library, for use in Middleman, Rails or other Sprockets capable applications.
16
+ email:
17
+ - jonathan@spacetofu.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - Gemfile
24
+ - README.md
25
+ - Rakefile
26
+ - exojs.gemspec
27
+ - lib/assets/javascripts/exo.js
28
+ - lib/assets/javascripts/exo.spine.js
29
+ - lib/exojs.rb
30
+ - lib/exojs/version.rb
31
+ homepage: https://github.com/jpettersson/exojs-gem
32
+ licenses: []
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubyforge_project: exojs
51
+ rubygems_version: 1.8.24
52
+ signing_key:
53
+ specification_version: 3
54
+ summary: Serves you the Exo.js library through Sprockets
55
+ test_files: []