flipper-ui 0.2.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +17 -0
  5. data/Guardfile +26 -0
  6. data/LICENSE +22 -0
  7. data/README.md +101 -0
  8. data/Rakefile +7 -0
  9. data/examples/basic.ru +44 -0
  10. data/examples/flipper.html +14 -0
  11. data/examples/flipper.png +0 -0
  12. data/flipper-ui.gemspec +21 -0
  13. data/lib/flipper-ui.rb +1 -0
  14. data/lib/flipper/ui.rb +23 -0
  15. data/lib/flipper/ui/action.rb +172 -0
  16. data/lib/flipper/ui/action_collection.rb +20 -0
  17. data/lib/flipper/ui/actions/features.rb +21 -0
  18. data/lib/flipper/ui/actions/file.rb +17 -0
  19. data/lib/flipper/ui/actions/gate.rb +143 -0
  20. data/lib/flipper/ui/actions/index.rb +17 -0
  21. data/lib/flipper/ui/assets/javascripts/application.coffee +305 -0
  22. data/lib/flipper/ui/assets/javascripts/spine/ajax.coffee +223 -0
  23. data/lib/flipper/ui/assets/javascripts/spine/list.coffee +43 -0
  24. data/lib/flipper/ui/assets/javascripts/spine/local.coffee +16 -0
  25. data/lib/flipper/ui/assets/javascripts/spine/manager.coffee +83 -0
  26. data/lib/flipper/ui/assets/javascripts/spine/relation.coffee +148 -0
  27. data/lib/flipper/ui/assets/javascripts/spine/route.coffee +146 -0
  28. data/lib/flipper/ui/assets/javascripts/spine/spine.coffee +542 -0
  29. data/lib/flipper/ui/assets/javascripts/spine/version +1 -0
  30. data/lib/flipper/ui/assets/stylesheets/application.scss +237 -0
  31. data/lib/flipper/ui/decorators/feature.rb +37 -0
  32. data/lib/flipper/ui/decorators/gate.rb +36 -0
  33. data/lib/flipper/ui/error.rb +10 -0
  34. data/lib/flipper/ui/eruby.rb +11 -0
  35. data/lib/flipper/ui/middleware.rb +66 -0
  36. data/lib/flipper/ui/public/css/application.css +183 -0
  37. data/lib/flipper/ui/public/css/images/animated-overlay.gif +0 -0
  38. data/lib/flipper/ui/public/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  39. data/lib/flipper/ui/public/css/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  40. data/lib/flipper/ui/public/css/images/ui-bg_flat_10_000000_40x100.png +0 -0
  41. data/lib/flipper/ui/public/css/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  42. data/lib/flipper/ui/public/css/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  43. data/lib/flipper/ui/public/css/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  44. data/lib/flipper/ui/public/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  45. data/lib/flipper/ui/public/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  46. data/lib/flipper/ui/public/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  47. data/lib/flipper/ui/public/css/images/ui-icons_222222_256x240.png +0 -0
  48. data/lib/flipper/ui/public/css/images/ui-icons_228ef1_256x240.png +0 -0
  49. data/lib/flipper/ui/public/css/images/ui-icons_ef8c08_256x240.png +0 -0
  50. data/lib/flipper/ui/public/css/images/ui-icons_ffd27a_256x240.png +0 -0
  51. data/lib/flipper/ui/public/css/images/ui-icons_ffffff_256x240.png +0 -0
  52. data/lib/flipper/ui/public/css/jquery-ui-1.10.3.slider.min.css +5 -0
  53. data/lib/flipper/ui/public/images/logo.png +0 -0
  54. data/lib/flipper/ui/public/images/remove.png +0 -0
  55. data/lib/flipper/ui/public/js/application.js +544 -0
  56. data/lib/flipper/ui/public/js/handlebars.js +1992 -0
  57. data/lib/flipper/ui/public/js/jquery-ui-1.10.3.slider.min.js +6 -0
  58. data/lib/flipper/ui/public/js/jquery.js +9555 -0
  59. data/lib/flipper/ui/public/js/jquery.min.js +4 -0
  60. data/lib/flipper/ui/public/js/jquery.min.map +1 -0
  61. data/lib/flipper/ui/public/js/spine/ajax.js +320 -0
  62. data/lib/flipper/ui/public/js/spine/list.js +72 -0
  63. data/lib/flipper/ui/public/js/spine/local.js +29 -0
  64. data/lib/flipper/ui/public/js/spine/manager.js +157 -0
  65. data/lib/flipper/ui/public/js/spine/relation.js +260 -0
  66. data/lib/flipper/ui/public/js/spine/route.js +223 -0
  67. data/lib/flipper/ui/public/js/spine/spine.js +927 -0
  68. data/lib/flipper/ui/util.rb +12 -0
  69. data/lib/flipper/ui/version.rb +5 -0
  70. data/lib/flipper/ui/views/index.erb +9 -0
  71. data/lib/flipper/ui/views/layout.erb +161 -0
  72. data/script/bootstrap +21 -0
  73. data/script/server +19 -0
  74. data/script/test +30 -0
  75. data/spec/flipper/ui/decorators/feature_spec.rb +59 -0
  76. data/spec/flipper/ui/decorators/gate_spec.rb +47 -0
  77. data/spec/flipper/ui/util_spec.rb +18 -0
  78. data/spec/flipper/ui_spec.rb +470 -0
  79. data/spec/helper.rb +35 -0
  80. metadata +168 -0
@@ -0,0 +1,927 @@
1
+ (function() {
2
+ var $, Controller, Events, Log, Model, Module, Spine, createObject, isArray, isBlank, makeArray, moduleKeywords,
3
+ __slice = [].slice,
4
+ __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; },
5
+ __hasProp = {}.hasOwnProperty,
6
+ __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; },
7
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
8
+
9
+ Events = {
10
+ bind: function(ev, callback) {
11
+ var calls, evs, name, _i, _len;
12
+ evs = ev.split(' ');
13
+ calls = this.hasOwnProperty('_callbacks') && this._callbacks || (this._callbacks = {});
14
+ for (_i = 0, _len = evs.length; _i < _len; _i++) {
15
+ name = evs[_i];
16
+ calls[name] || (calls[name] = []);
17
+ calls[name].push(callback);
18
+ }
19
+ return this;
20
+ },
21
+ one: function(ev, callback) {
22
+ return this.bind(ev, function() {
23
+ this.unbind(ev, arguments.callee);
24
+ return callback.apply(this, arguments);
25
+ });
26
+ },
27
+ trigger: function() {
28
+ var args, callback, ev, list, _i, _len, _ref;
29
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
30
+ ev = args.shift();
31
+ list = this.hasOwnProperty('_callbacks') && ((_ref = this._callbacks) != null ? _ref[ev] : void 0);
32
+ if (!list) {
33
+ return;
34
+ }
35
+ for (_i = 0, _len = list.length; _i < _len; _i++) {
36
+ callback = list[_i];
37
+ if (callback.apply(this, args) === false) {
38
+ break;
39
+ }
40
+ }
41
+ return true;
42
+ },
43
+ unbind: function(ev, callback) {
44
+ var cb, i, list, _i, _len, _ref;
45
+ if (!ev) {
46
+ this._callbacks = {};
47
+ return this;
48
+ }
49
+ list = (_ref = this._callbacks) != null ? _ref[ev] : void 0;
50
+ if (!list) {
51
+ return this;
52
+ }
53
+ if (!callback) {
54
+ delete this._callbacks[ev];
55
+ return this;
56
+ }
57
+ for (i = _i = 0, _len = list.length; _i < _len; i = ++_i) {
58
+ cb = list[i];
59
+ if (!(cb === callback)) {
60
+ continue;
61
+ }
62
+ list = list.slice();
63
+ list.splice(i, 1);
64
+ this._callbacks[ev] = list;
65
+ break;
66
+ }
67
+ return this;
68
+ }
69
+ };
70
+
71
+ Log = {
72
+ trace: true,
73
+ logPrefix: '(App)',
74
+ log: function() {
75
+ var args;
76
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
77
+ if (!this.trace) {
78
+ return;
79
+ }
80
+ if (this.logPrefix) {
81
+ args.unshift(this.logPrefix);
82
+ }
83
+ if (typeof console !== "undefined" && console !== null) {
84
+ if (typeof console.log === "function") {
85
+ console.log.apply(console, args);
86
+ }
87
+ }
88
+ return this;
89
+ }
90
+ };
91
+
92
+ moduleKeywords = ['included', 'extended'];
93
+
94
+ Module = (function() {
95
+
96
+ Module.include = function(obj) {
97
+ var key, value, _ref;
98
+ if (!obj) {
99
+ throw new Error('include(obj) requires obj');
100
+ }
101
+ for (key in obj) {
102
+ value = obj[key];
103
+ if (__indexOf.call(moduleKeywords, key) < 0) {
104
+ this.prototype[key] = value;
105
+ }
106
+ }
107
+ if ((_ref = obj.included) != null) {
108
+ _ref.apply(this);
109
+ }
110
+ return this;
111
+ };
112
+
113
+ Module.extend = function(obj) {
114
+ var key, value, _ref;
115
+ if (!obj) {
116
+ throw new Error('extend(obj) requires obj');
117
+ }
118
+ for (key in obj) {
119
+ value = obj[key];
120
+ if (__indexOf.call(moduleKeywords, key) < 0) {
121
+ this[key] = value;
122
+ }
123
+ }
124
+ if ((_ref = obj.extended) != null) {
125
+ _ref.apply(this);
126
+ }
127
+ return this;
128
+ };
129
+
130
+ Module.proxy = function(func) {
131
+ var _this = this;
132
+ return function() {
133
+ return func.apply(_this, arguments);
134
+ };
135
+ };
136
+
137
+ Module.prototype.proxy = function(func) {
138
+ var _this = this;
139
+ return function() {
140
+ return func.apply(_this, arguments);
141
+ };
142
+ };
143
+
144
+ function Module() {
145
+ if (typeof this.init === "function") {
146
+ this.init.apply(this, arguments);
147
+ }
148
+ }
149
+
150
+ return Module;
151
+
152
+ })();
153
+
154
+ Model = (function(_super) {
155
+
156
+ __extends(Model, _super);
157
+
158
+ Model.extend(Events);
159
+
160
+ Model.records = {};
161
+
162
+ Model.crecords = {};
163
+
164
+ Model.attributes = [];
165
+
166
+ Model.configure = function() {
167
+ var attributes, name;
168
+ name = arguments[0], attributes = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
169
+ this.className = name;
170
+ this.records = {};
171
+ this.crecords = {};
172
+ if (attributes.length) {
173
+ this.attributes = attributes;
174
+ }
175
+ this.attributes && (this.attributes = makeArray(this.attributes));
176
+ this.attributes || (this.attributes = []);
177
+ this.unbind();
178
+ return this;
179
+ };
180
+
181
+ Model.toString = function() {
182
+ return "" + this.className + "(" + (this.attributes.join(", ")) + ")";
183
+ };
184
+
185
+ Model.find = function(id) {
186
+ var record;
187
+ record = this.records[id];
188
+ if (!record && ("" + id).match(/c-\d+/)) {
189
+ return this.findCID(id);
190
+ }
191
+ if (!record) {
192
+ throw new Error("\"" + this.className + "\" model could not find a record for the ID \"" + id + "\"");
193
+ }
194
+ return record.clone();
195
+ };
196
+
197
+ Model.findCID = function(cid) {
198
+ var record;
199
+ record = this.crecords[cid];
200
+ if (!record) {
201
+ throw new Error("\"" + this.className + "\" model could not find a record for the ID \"" + id + "\"");
202
+ }
203
+ return record.clone();
204
+ };
205
+
206
+ Model.exists = function(id) {
207
+ try {
208
+ return this.find(id);
209
+ } catch (e) {
210
+ return false;
211
+ }
212
+ };
213
+
214
+ Model.refresh = function(values, options) {
215
+ var record, records, _i, _len;
216
+ if (options == null) {
217
+ options = {};
218
+ }
219
+ if (options.clear) {
220
+ this.records = {};
221
+ this.crecords = {};
222
+ }
223
+ records = this.fromJSON(values);
224
+ if (!isArray(records)) {
225
+ records = [records];
226
+ }
227
+ for (_i = 0, _len = records.length; _i < _len; _i++) {
228
+ record = records[_i];
229
+ record.id || (record.id = record.cid);
230
+ this.records[record.id] = record;
231
+ this.crecords[record.cid] = record;
232
+ }
233
+ this.trigger('refresh', this.cloneArray(records));
234
+ return this;
235
+ };
236
+
237
+ Model.select = function(callback) {
238
+ var id, record, result;
239
+ result = (function() {
240
+ var _ref, _results;
241
+ _ref = this.records;
242
+ _results = [];
243
+ for (id in _ref) {
244
+ record = _ref[id];
245
+ if (callback(record)) {
246
+ _results.push(record);
247
+ }
248
+ }
249
+ return _results;
250
+ }).call(this);
251
+ return this.cloneArray(result);
252
+ };
253
+
254
+ Model.findByAttribute = function(name, value) {
255
+ var id, record, _ref;
256
+ _ref = this.records;
257
+ for (id in _ref) {
258
+ record = _ref[id];
259
+ if (record[name] === value) {
260
+ return record.clone();
261
+ }
262
+ }
263
+ return null;
264
+ };
265
+
266
+ Model.findAllByAttribute = function(name, value) {
267
+ return this.select(function(item) {
268
+ return item[name] === value;
269
+ });
270
+ };
271
+
272
+ Model.each = function(callback) {
273
+ var key, value, _ref, _results;
274
+ _ref = this.records;
275
+ _results = [];
276
+ for (key in _ref) {
277
+ value = _ref[key];
278
+ _results.push(callback(value.clone()));
279
+ }
280
+ return _results;
281
+ };
282
+
283
+ Model.all = function() {
284
+ return this.cloneArray(this.recordsValues());
285
+ };
286
+
287
+ Model.first = function() {
288
+ var record;
289
+ record = this.recordsValues()[0];
290
+ return record != null ? record.clone() : void 0;
291
+ };
292
+
293
+ Model.last = function() {
294
+ var record, values;
295
+ values = this.recordsValues();
296
+ record = values[values.length - 1];
297
+ return record != null ? record.clone() : void 0;
298
+ };
299
+
300
+ Model.count = function() {
301
+ return this.recordsValues().length;
302
+ };
303
+
304
+ Model.deleteAll = function() {
305
+ var key, value, _ref, _results;
306
+ _ref = this.records;
307
+ _results = [];
308
+ for (key in _ref) {
309
+ value = _ref[key];
310
+ _results.push(delete this.records[key]);
311
+ }
312
+ return _results;
313
+ };
314
+
315
+ Model.destroyAll = function() {
316
+ var key, value, _ref, _results;
317
+ _ref = this.records;
318
+ _results = [];
319
+ for (key in _ref) {
320
+ value = _ref[key];
321
+ _results.push(this.records[key].destroy());
322
+ }
323
+ return _results;
324
+ };
325
+
326
+ Model.update = function(id, atts, options) {
327
+ return this.find(id).updateAttributes(atts, options);
328
+ };
329
+
330
+ Model.create = function(atts, options) {
331
+ var record;
332
+ record = new this(atts);
333
+ return record.save(options);
334
+ };
335
+
336
+ Model.destroy = function(id, options) {
337
+ return this.find(id).destroy(options);
338
+ };
339
+
340
+ Model.change = function(callbackOrParams) {
341
+ if (typeof callbackOrParams === 'function') {
342
+ return this.bind('change', callbackOrParams);
343
+ } else {
344
+ return this.trigger('change', callbackOrParams);
345
+ }
346
+ };
347
+
348
+ Model.fetch = function(callbackOrParams) {
349
+ if (typeof callbackOrParams === 'function') {
350
+ return this.bind('fetch', callbackOrParams);
351
+ } else {
352
+ return this.trigger('fetch', callbackOrParams);
353
+ }
354
+ };
355
+
356
+ Model.toJSON = function() {
357
+ return this.recordsValues();
358
+ };
359
+
360
+ Model.fromJSON = function(objects) {
361
+ var value, _i, _len, _results;
362
+ if (!objects) {
363
+ return;
364
+ }
365
+ if (typeof objects === 'string') {
366
+ objects = JSON.parse(objects);
367
+ }
368
+ if (isArray(objects)) {
369
+ _results = [];
370
+ for (_i = 0, _len = objects.length; _i < _len; _i++) {
371
+ value = objects[_i];
372
+ _results.push(new this(value));
373
+ }
374
+ return _results;
375
+ } else {
376
+ return new this(objects);
377
+ }
378
+ };
379
+
380
+ Model.fromForm = function() {
381
+ var _ref;
382
+ return (_ref = new this).fromForm.apply(_ref, arguments);
383
+ };
384
+
385
+ Model.recordsValues = function() {
386
+ var key, result, value, _ref;
387
+ result = [];
388
+ _ref = this.records;
389
+ for (key in _ref) {
390
+ value = _ref[key];
391
+ result.push(value);
392
+ }
393
+ return result;
394
+ };
395
+
396
+ Model.cloneArray = function(array) {
397
+ var value, _i, _len, _results;
398
+ _results = [];
399
+ for (_i = 0, _len = array.length; _i < _len; _i++) {
400
+ value = array[_i];
401
+ _results.push(value.clone());
402
+ }
403
+ return _results;
404
+ };
405
+
406
+ Model.idCounter = 0;
407
+
408
+ Model.uid = function(prefix) {
409
+ var uid;
410
+ if (prefix == null) {
411
+ prefix = '';
412
+ }
413
+ uid = prefix + this.idCounter++;
414
+ if (this.exists(uid)) {
415
+ uid = this.uid(prefix);
416
+ }
417
+ return uid;
418
+ };
419
+
420
+ function Model(atts) {
421
+ Model.__super__.constructor.apply(this, arguments);
422
+ if (atts) {
423
+ this.load(atts);
424
+ }
425
+ this.cid = this.constructor.uid('c-');
426
+ }
427
+
428
+ Model.prototype.isNew = function() {
429
+ return !this.exists();
430
+ };
431
+
432
+ Model.prototype.isValid = function() {
433
+ return !this.validate();
434
+ };
435
+
436
+ Model.prototype.validate = function() {};
437
+
438
+ Model.prototype.load = function(atts) {
439
+ var key, value;
440
+ for (key in atts) {
441
+ value = atts[key];
442
+ if (typeof this[key] === 'function') {
443
+ this[key](value);
444
+ } else {
445
+ this[key] = value;
446
+ }
447
+ }
448
+ return this;
449
+ };
450
+
451
+ Model.prototype.attributes = function() {
452
+ var key, result, _i, _len, _ref;
453
+ result = {};
454
+ _ref = this.constructor.attributes;
455
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
456
+ key = _ref[_i];
457
+ if (key in this) {
458
+ if (typeof this[key] === 'function') {
459
+ result[key] = this[key]();
460
+ } else {
461
+ result[key] = this[key];
462
+ }
463
+ }
464
+ }
465
+ if (this.id) {
466
+ result.id = this.id;
467
+ }
468
+ return result;
469
+ };
470
+
471
+ Model.prototype.eql = function(rec) {
472
+ return !!(rec && rec.constructor === this.constructor && (rec.cid === this.cid) || (rec.id && rec.id === this.id));
473
+ };
474
+
475
+ Model.prototype.save = function(options) {
476
+ var error, record;
477
+ if (options == null) {
478
+ options = {};
479
+ }
480
+ if (options.validate !== false) {
481
+ error = this.validate();
482
+ if (error) {
483
+ this.trigger('error', error);
484
+ return false;
485
+ }
486
+ }
487
+ this.trigger('beforeSave', options);
488
+ record = this.isNew() ? this.create(options) : this.update(options);
489
+ this.stripCloneAttrs();
490
+ this.trigger('save', options);
491
+ return record;
492
+ };
493
+
494
+ Model.prototype.stripCloneAttrs = function() {
495
+ var key, value;
496
+ if (this.hasOwnProperty('cid')) {
497
+ return;
498
+ }
499
+ for (key in this) {
500
+ if (!__hasProp.call(this, key)) continue;
501
+ value = this[key];
502
+ if (this.constructor.attributes.indexOf(key) > -1) {
503
+ delete this[key];
504
+ }
505
+ }
506
+ return this;
507
+ };
508
+
509
+ Model.prototype.updateAttribute = function(name, value, options) {
510
+ this[name] = value;
511
+ return this.save(options);
512
+ };
513
+
514
+ Model.prototype.updateAttributes = function(atts, options) {
515
+ this.load(atts);
516
+ return this.save(options);
517
+ };
518
+
519
+ Model.prototype.changeID = function(id) {
520
+ var records;
521
+ records = this.constructor.records;
522
+ records[id] = records[this.id];
523
+ delete records[this.id];
524
+ this.id = id;
525
+ return this.save();
526
+ };
527
+
528
+ Model.prototype.destroy = function(options) {
529
+ if (options == null) {
530
+ options = {};
531
+ }
532
+ this.trigger('beforeDestroy', options);
533
+ delete this.constructor.records[this.id];
534
+ delete this.constructor.crecords[this.cid];
535
+ this.destroyed = true;
536
+ this.trigger('destroy', options);
537
+ this.trigger('change', 'destroy', options);
538
+ this.unbind();
539
+ return this;
540
+ };
541
+
542
+ Model.prototype.dup = function(newRecord) {
543
+ var result;
544
+ result = new this.constructor(this.attributes());
545
+ if (newRecord === false) {
546
+ result.cid = this.cid;
547
+ } else {
548
+ delete result.id;
549
+ }
550
+ return result;
551
+ };
552
+
553
+ Model.prototype.clone = function() {
554
+ return createObject(this);
555
+ };
556
+
557
+ Model.prototype.reload = function() {
558
+ var original;
559
+ if (this.isNew()) {
560
+ return this;
561
+ }
562
+ original = this.constructor.find(this.id);
563
+ this.load(original.attributes());
564
+ return original;
565
+ };
566
+
567
+ Model.prototype.toJSON = function() {
568
+ return this.attributes();
569
+ };
570
+
571
+ Model.prototype.toString = function() {
572
+ return "<" + this.constructor.className + " (" + (JSON.stringify(this)) + ")>";
573
+ };
574
+
575
+ Model.prototype.fromForm = function(form) {
576
+ var key, result, _i, _len, _ref;
577
+ result = {};
578
+ _ref = $(form).serializeArray();
579
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
580
+ key = _ref[_i];
581
+ result[key.name] = key.value;
582
+ }
583
+ return this.load(result);
584
+ };
585
+
586
+ Model.prototype.exists = function() {
587
+ return this.id && this.id in this.constructor.records;
588
+ };
589
+
590
+ Model.prototype.update = function(options) {
591
+ var clone, records;
592
+ this.trigger('beforeUpdate', options);
593
+ records = this.constructor.records;
594
+ records[this.id].load(this.attributes());
595
+ clone = records[this.id].clone();
596
+ clone.trigger('update', options);
597
+ clone.trigger('change', 'update', options);
598
+ return clone;
599
+ };
600
+
601
+ Model.prototype.create = function(options) {
602
+ var clone, record;
603
+ this.trigger('beforeCreate', options);
604
+ if (!this.id) {
605
+ this.id = this.cid;
606
+ }
607
+ record = this.dup(false);
608
+ this.constructor.records[this.id] = record;
609
+ this.constructor.crecords[this.cid] = record;
610
+ clone = record.clone();
611
+ clone.trigger('create', options);
612
+ clone.trigger('change', 'create', options);
613
+ return clone;
614
+ };
615
+
616
+ Model.prototype.bind = function(events, callback) {
617
+ var binder, unbinder,
618
+ _this = this;
619
+ this.constructor.bind(events, binder = function(record) {
620
+ if (record && _this.eql(record)) {
621
+ return callback.apply(_this, arguments);
622
+ }
623
+ });
624
+ this.constructor.bind('unbind', unbinder = function(record) {
625
+ if (record && _this.eql(record)) {
626
+ _this.constructor.unbind(events, binder);
627
+ return _this.constructor.unbind('unbind', unbinder);
628
+ }
629
+ });
630
+ return binder;
631
+ };
632
+
633
+ Model.prototype.one = function(events, callback) {
634
+ var binder,
635
+ _this = this;
636
+ return binder = this.bind(events, function() {
637
+ _this.constructor.unbind(events, binder);
638
+ return callback.apply(_this, arguments);
639
+ });
640
+ };
641
+
642
+ Model.prototype.trigger = function() {
643
+ var args, _ref;
644
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
645
+ args.splice(1, 0, this);
646
+ return (_ref = this.constructor).trigger.apply(_ref, args);
647
+ };
648
+
649
+ Model.prototype.unbind = function() {
650
+ return this.trigger('unbind');
651
+ };
652
+
653
+ return Model;
654
+
655
+ })(Module);
656
+
657
+ Controller = (function(_super) {
658
+
659
+ __extends(Controller, _super);
660
+
661
+ Controller.include(Events);
662
+
663
+ Controller.include(Log);
664
+
665
+ Controller.prototype.eventSplitter = /^(\S+)\s*(.*)$/;
666
+
667
+ Controller.prototype.tag = 'div';
668
+
669
+ function Controller(options) {
670
+ this.release = __bind(this.release, this);
671
+ var key, value, _ref;
672
+ this.options = options;
673
+ _ref = this.options;
674
+ for (key in _ref) {
675
+ value = _ref[key];
676
+ this[key] = value;
677
+ }
678
+ if (!this.el) {
679
+ this.el = document.createElement(this.tag);
680
+ }
681
+ this.el = $(this.el);
682
+ this.$el = this.el;
683
+ if (this.className) {
684
+ this.el.addClass(this.className);
685
+ }
686
+ if (this.attributes) {
687
+ this.el.attr(this.attributes);
688
+ }
689
+ if (!this.events) {
690
+ this.events = this.constructor.events;
691
+ }
692
+ if (!this.elements) {
693
+ this.elements = this.constructor.elements;
694
+ }
695
+ if (this.events) {
696
+ this.delegateEvents(this.events);
697
+ }
698
+ if (this.elements) {
699
+ this.refreshElements();
700
+ }
701
+ Controller.__super__.constructor.apply(this, arguments);
702
+ }
703
+
704
+ Controller.prototype.release = function() {
705
+ this.trigger('release');
706
+ this.el.remove();
707
+ return this.unbind();
708
+ };
709
+
710
+ Controller.prototype.$ = function(selector) {
711
+ return $(selector, this.el);
712
+ };
713
+
714
+ Controller.prototype.delegateEvents = function(events) {
715
+ var eventName, key, match, method, selector, _results,
716
+ _this = this;
717
+ _results = [];
718
+ for (key in events) {
719
+ method = events[key];
720
+ if (typeof method === 'function') {
721
+ method = (function(method) {
722
+ return function() {
723
+ method.apply(_this, arguments);
724
+ return true;
725
+ };
726
+ })(method);
727
+ } else {
728
+ if (!this[method]) {
729
+ throw new Error("" + method + " doesn't exist");
730
+ }
731
+ method = (function(method) {
732
+ return function() {
733
+ _this[method].apply(_this, arguments);
734
+ return true;
735
+ };
736
+ })(method);
737
+ }
738
+ match = key.match(this.eventSplitter);
739
+ eventName = match[1];
740
+ selector = match[2];
741
+ if (selector === '') {
742
+ _results.push(this.el.bind(eventName, method));
743
+ } else {
744
+ _results.push(this.el.delegate(selector, eventName, method));
745
+ }
746
+ }
747
+ return _results;
748
+ };
749
+
750
+ Controller.prototype.refreshElements = function() {
751
+ var key, value, _ref, _results;
752
+ _ref = this.elements;
753
+ _results = [];
754
+ for (key in _ref) {
755
+ value = _ref[key];
756
+ _results.push(this[value] = this.$(key));
757
+ }
758
+ return _results;
759
+ };
760
+
761
+ Controller.prototype.delay = function(func, timeout) {
762
+ return setTimeout(this.proxy(func), timeout || 0);
763
+ };
764
+
765
+ Controller.prototype.html = function(element) {
766
+ this.el.html(element.el || element);
767
+ this.refreshElements();
768
+ return this.el;
769
+ };
770
+
771
+ Controller.prototype.append = function() {
772
+ var e, elements, _ref;
773
+ elements = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
774
+ elements = (function() {
775
+ var _i, _len, _results;
776
+ _results = [];
777
+ for (_i = 0, _len = elements.length; _i < _len; _i++) {
778
+ e = elements[_i];
779
+ _results.push(e.el || e);
780
+ }
781
+ return _results;
782
+ })();
783
+ (_ref = this.el).append.apply(_ref, elements);
784
+ this.refreshElements();
785
+ return this.el;
786
+ };
787
+
788
+ Controller.prototype.appendTo = function(element) {
789
+ this.el.appendTo(element.el || element);
790
+ this.refreshElements();
791
+ return this.el;
792
+ };
793
+
794
+ Controller.prototype.prepend = function() {
795
+ var e, elements, _ref;
796
+ elements = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
797
+ elements = (function() {
798
+ var _i, _len, _results;
799
+ _results = [];
800
+ for (_i = 0, _len = elements.length; _i < _len; _i++) {
801
+ e = elements[_i];
802
+ _results.push(e.el || e);
803
+ }
804
+ return _results;
805
+ })();
806
+ (_ref = this.el).prepend.apply(_ref, elements);
807
+ this.refreshElements();
808
+ return this.el;
809
+ };
810
+
811
+ Controller.prototype.replace = function(element) {
812
+ var previous, _ref;
813
+ _ref = [this.el, $(element.el || element)], previous = _ref[0], this.el = _ref[1];
814
+ previous.replaceWith(this.el);
815
+ this.delegateEvents(this.events);
816
+ this.refreshElements();
817
+ return this.el;
818
+ };
819
+
820
+ return Controller;
821
+
822
+ })(Module);
823
+
824
+ $ = (typeof window !== "undefined" && window !== null ? window.jQuery : void 0) || (typeof window !== "undefined" && window !== null ? window.Zepto : void 0) || function(element) {
825
+ return element;
826
+ };
827
+
828
+ createObject = Object.create || function(o) {
829
+ var Func;
830
+ Func = function() {};
831
+ Func.prototype = o;
832
+ return new Func();
833
+ };
834
+
835
+ isArray = function(value) {
836
+ return Object.prototype.toString.call(value) === '[object Array]';
837
+ };
838
+
839
+ isBlank = function(value) {
840
+ var key;
841
+ if (!value) {
842
+ return true;
843
+ }
844
+ for (key in value) {
845
+ return false;
846
+ }
847
+ return true;
848
+ };
849
+
850
+ makeArray = function(args) {
851
+ return Array.prototype.slice.call(args, 0);
852
+ };
853
+
854
+ Spine = this.Spine = {};
855
+
856
+ if (typeof module !== "undefined" && module !== null) {
857
+ module.exports = Spine;
858
+ }
859
+
860
+ Spine.version = '1.0.8';
861
+
862
+ Spine.isArray = isArray;
863
+
864
+ Spine.isBlank = isBlank;
865
+
866
+ Spine.$ = $;
867
+
868
+ Spine.Events = Events;
869
+
870
+ Spine.Log = Log;
871
+
872
+ Spine.Module = Module;
873
+
874
+ Spine.Controller = Controller;
875
+
876
+ Spine.Model = Model;
877
+
878
+ Module.extend.call(Spine, Events);
879
+
880
+ Module.create = Module.sub = Controller.create = Controller.sub = Model.sub = function(instances, statics) {
881
+ var Result;
882
+ Result = (function(_super) {
883
+
884
+ __extends(Result, _super);
885
+
886
+ function Result() {
887
+ Result.__super__.constructor.apply(this, arguments);
888
+ }
889
+
890
+ return Result;
891
+
892
+ })(this);
893
+ if (instances) {
894
+ Result.include(instances);
895
+ }
896
+ if (statics) {
897
+ Result.extend(statics);
898
+ }
899
+ if (typeof Result.unbind === "function") {
900
+ Result.unbind();
901
+ }
902
+ return Result;
903
+ };
904
+
905
+ Model.setup = function(name, attributes) {
906
+ var Instance;
907
+ if (attributes == null) {
908
+ attributes = [];
909
+ }
910
+ Instance = (function(_super) {
911
+
912
+ __extends(Instance, _super);
913
+
914
+ function Instance() {
915
+ Instance.__super__.constructor.apply(this, arguments);
916
+ }
917
+
918
+ return Instance;
919
+
920
+ })(this);
921
+ Instance.configure.apply(Instance, [name].concat(__slice.call(attributes)));
922
+ return Instance;
923
+ };
924
+
925
+ Spine.Class = Module;
926
+
927
+ }).call(this);