exojs 0.1.0

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