spine-rails 0.0.1 → 0.0.2
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 +5 -3
- data/Gemfile +6 -1
- data/Gemfile.lock +26 -0
- data/Rakefile +8 -0
- data/{vendor → app}/assets/javascripts/json2.js +43 -38
- data/app/assets/javascripts/spine.js +717 -0
- data/app/assets/javascripts/spine/ajax.js +194 -0
- data/app/assets/javascripts/spine/list.js +61 -0
- data/app/assets/javascripts/spine/local.js +26 -0
- data/app/assets/javascripts/spine/manager.js +86 -0
- data/app/assets/javascripts/spine/relation.js +145 -0
- data/app/assets/javascripts/spine/route.js +184 -0
- data/app/assets/javascripts/spine/tabs.js +58 -0
- data/app/assets/javascripts/spine/tmpl.js +17 -0
- data/lib/generators/spine/install/install_generator.rb +18 -0
- data/lib/spine-rails.rb +1 -12
- data/lib/spine/rails.rb +6 -0
- data/lib/spine/rails/engine.rb +6 -0
- data/lib/spine/rails/version.rb +6 -0
- data/spine-rails.gemspec +15 -18
- metadata +60 -87
- data/lib/generators/spinejs/install/install_generator.rb +0 -84
- data/lib/spine-rails/railtie.rb +0 -18
- data/lib/spine-rails/version.rb +0 -5
- data/lib/tasks/get_js.rake +0 -52
- data/tasks/get_js.rake +0 -52
- data/vendor/assets/javascripts/icanhaz.js +0 -401
- data/vendor/assets/javascripts/icanhaz.min.js +0 -9
- data/vendor/assets/javascripts/spine.js +0 -534
- data/vendor/assets/javascripts/spine.min.js +0 -1
data/.gitignore
CHANGED
data/Gemfile
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
source
|
1
|
+
source 'http://rubygems.org'
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in spine-rails.gemspec
|
4
4
|
gemspec
|
5
|
+
# Rails is already being pulled in through gemspec
|
6
|
+
# gem "rails", :git => "git://github.com/rails/rails.git"
|
7
|
+
gem "rack", :git => "git://github.com/rack/rack.git"
|
8
|
+
gem "sprockets", :git => "git://github.com/sstephenson/sprockets.git"
|
9
|
+
gem "i18n", "0.6.0beta1"
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
daemons (1.1.3)
|
5
|
+
eventmachine (0.12.10)
|
6
|
+
json (1.5.2)
|
7
|
+
rack (1.3.0)
|
8
|
+
shotgun (0.9)
|
9
|
+
rack (>= 1.0)
|
10
|
+
sinatra (1.2.6)
|
11
|
+
rack (~> 1.1)
|
12
|
+
tilt (< 2.0, >= 1.2.2)
|
13
|
+
thin (1.2.11)
|
14
|
+
daemons (>= 1.0.9)
|
15
|
+
eventmachine (>= 0.12.6)
|
16
|
+
rack (>= 1.0.0)
|
17
|
+
tilt (1.3.2)
|
18
|
+
|
19
|
+
PLATFORMS
|
20
|
+
ruby
|
21
|
+
|
22
|
+
DEPENDENCIES
|
23
|
+
json
|
24
|
+
shotgun
|
25
|
+
sinatra (~> 1.0)
|
26
|
+
thin
|
data/Rakefile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
http://www.JSON.org/json2.js
|
3
|
-
|
3
|
+
2009-09-29
|
4
4
|
|
5
5
|
Public Domain.
|
6
6
|
|
@@ -146,7 +146,7 @@
|
|
146
146
|
redistribute.
|
147
147
|
*/
|
148
148
|
|
149
|
-
/*jslint evil: true, strict: false
|
149
|
+
/*jslint evil: true, strict: false */
|
150
150
|
|
151
151
|
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
152
152
|
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
@@ -159,13 +159,15 @@
|
|
159
159
|
// Create a JSON object only if one does not already exist. We create the
|
160
160
|
// methods in a closure to avoid creating global variables.
|
161
161
|
|
162
|
-
|
163
|
-
|
164
|
-
JSON = {};
|
162
|
+
if (!this.JSON) {
|
163
|
+
this.JSON = {};
|
165
164
|
}
|
166
165
|
|
166
|
+
if (this.module)
|
167
|
+
module.exports = JSON;
|
168
|
+
|
167
169
|
(function () {
|
168
|
-
|
170
|
+
|
169
171
|
|
170
172
|
function f(n) {
|
171
173
|
// Format integers to have at least two digits.
|
@@ -177,19 +179,19 @@ if (!JSON) {
|
|
177
179
|
Date.prototype.toJSON = function (key) {
|
178
180
|
|
179
181
|
return isFinite(this.valueOf()) ?
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
182
|
+
this.getUTCFullYear() + '-' +
|
183
|
+
f(this.getUTCMonth() + 1) + '-' +
|
184
|
+
f(this.getUTCDate()) + 'T' +
|
185
|
+
f(this.getUTCHours()) + ':' +
|
186
|
+
f(this.getUTCMinutes()) + ':' +
|
187
|
+
f(this.getUTCSeconds()) + 'Z' : null;
|
186
188
|
};
|
187
189
|
|
188
|
-
String.prototype.toJSON
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
190
|
+
String.prototype.toJSON =
|
191
|
+
Number.prototype.toJSON =
|
192
|
+
Boolean.prototype.toJSON = function (key) {
|
193
|
+
return this.valueOf();
|
194
|
+
};
|
193
195
|
}
|
194
196
|
|
195
197
|
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
@@ -216,11 +218,13 @@ if (!JSON) {
|
|
216
218
|
// sequences.
|
217
219
|
|
218
220
|
escapable.lastIndex = 0;
|
219
|
-
return escapable.test(string) ?
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
221
|
+
return escapable.test(string) ?
|
222
|
+
'"' + string.replace(escapable, function (a) {
|
223
|
+
var c = meta[a];
|
224
|
+
return typeof c === 'string' ? c :
|
225
|
+
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
226
|
+
}) + '"' :
|
227
|
+
'"' + string + '"';
|
224
228
|
}
|
225
229
|
|
226
230
|
|
@@ -303,9 +307,11 @@ if (!JSON) {
|
|
303
307
|
// Join all of the elements together, separated with commas, and wrap them in
|
304
308
|
// brackets.
|
305
309
|
|
306
|
-
v = partial.length === 0 ? '[]' :
|
307
|
-
|
308
|
-
|
310
|
+
v = partial.length === 0 ? '[]' :
|
311
|
+
gap ? '[\n' + gap +
|
312
|
+
partial.join(',\n' + gap) + '\n' +
|
313
|
+
mind + ']' :
|
314
|
+
'[' + partial.join(',') + ']';
|
309
315
|
gap = mind;
|
310
316
|
return v;
|
311
317
|
}
|
@@ -315,8 +321,8 @@ if (!JSON) {
|
|
315
321
|
if (rep && typeof rep === 'object') {
|
316
322
|
length = rep.length;
|
317
323
|
for (i = 0; i < length; i += 1) {
|
318
|
-
|
319
|
-
|
324
|
+
k = rep[i];
|
325
|
+
if (typeof k === 'string') {
|
320
326
|
v = str(k, value);
|
321
327
|
if (v) {
|
322
328
|
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
@@ -328,7 +334,7 @@ if (!JSON) {
|
|
328
334
|
// Otherwise, iterate through all of the keys in the object.
|
329
335
|
|
330
336
|
for (k in value) {
|
331
|
-
if (Object.
|
337
|
+
if (Object.hasOwnProperty.call(value, k)) {
|
332
338
|
v = str(k, value);
|
333
339
|
if (v) {
|
334
340
|
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
@@ -340,9 +346,9 @@ if (!JSON) {
|
|
340
346
|
// Join all of the member texts together, separated with commas,
|
341
347
|
// and wrap them in braces.
|
342
348
|
|
343
|
-
v = partial.length === 0 ? '{}' :
|
344
|
-
'{\n' + gap + partial.join(',\n' + gap) + '\n' +
|
345
|
-
|
349
|
+
v = partial.length === 0 ? '{}' :
|
350
|
+
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
|
351
|
+
mind + '}' : '{' + partial.join(',') + '}';
|
346
352
|
gap = mind;
|
347
353
|
return v;
|
348
354
|
}
|
@@ -383,7 +389,7 @@ if (!JSON) {
|
|
383
389
|
rep = replacer;
|
384
390
|
if (replacer && typeof replacer !== 'function' &&
|
385
391
|
(typeof replacer !== 'object' ||
|
386
|
-
|
392
|
+
typeof replacer.length !== 'number')) {
|
387
393
|
throw new Error('JSON.stringify');
|
388
394
|
}
|
389
395
|
|
@@ -413,7 +419,7 @@ if (!JSON) {
|
|
413
419
|
var k, v, value = holder[key];
|
414
420
|
if (value && typeof value === 'object') {
|
415
421
|
for (k in value) {
|
416
|
-
if (Object.
|
422
|
+
if (Object.hasOwnProperty.call(value, k)) {
|
417
423
|
v = walk(value, k);
|
418
424
|
if (v !== undefined) {
|
419
425
|
value[k] = v;
|
@@ -431,7 +437,6 @@ if (!JSON) {
|
|
431
437
|
// Unicode characters with escape sequences. JavaScript handles many characters
|
432
438
|
// incorrectly, either silently deleting them, or treating them as line endings.
|
433
439
|
|
434
|
-
text = String(text);
|
435
440
|
cx.lastIndex = 0;
|
436
441
|
if (cx.test(text)) {
|
437
442
|
text = text.replace(cx, function (a) {
|
@@ -453,10 +458,10 @@ if (!JSON) {
|
|
453
458
|
// we look to see that the remaining characters are only whitespace or ']' or
|
454
459
|
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
455
460
|
|
456
|
-
if (/^[\],:{}\s]
|
457
|
-
|
458
|
-
|
459
|
-
|
461
|
+
if (/^[\],:{}\s]*$/.
|
462
|
+
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
|
463
|
+
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
|
464
|
+
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
460
465
|
|
461
466
|
// In the third stage we use the eval function to compile the text into a
|
462
467
|
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
@@ -0,0 +1,717 @@
|
|
1
|
+
(function() {
|
2
|
+
var $, Controller, Events, Log, Model, Module, Spine, guid, isArray, isBlank, makeArray, moduleKeywords;
|
3
|
+
var __slice = Array.prototype.slice, __indexOf = Array.prototype.indexOf || function(item) {
|
4
|
+
for (var i = 0, l = this.length; i < l; i++) {
|
5
|
+
if (this[i] === item) return i;
|
6
|
+
}
|
7
|
+
return -1;
|
8
|
+
}, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
|
9
|
+
for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
|
10
|
+
function ctor() { this.constructor = child; }
|
11
|
+
ctor.prototype = parent.prototype;
|
12
|
+
child.prototype = new ctor;
|
13
|
+
child.__super__ = parent.prototype;
|
14
|
+
return child;
|
15
|
+
};
|
16
|
+
Events = {
|
17
|
+
bind: function(ev, callback) {
|
18
|
+
var calls, evs, name, _i, _len;
|
19
|
+
evs = ev.split(' ');
|
20
|
+
calls = this.hasOwnProperty('_callbacks') && this._callbacks || (this._callbacks = {});
|
21
|
+
for (_i = 0, _len = evs.length; _i < _len; _i++) {
|
22
|
+
name = evs[_i];
|
23
|
+
calls[name] || (calls[name] = []);
|
24
|
+
calls[name].push(callback);
|
25
|
+
}
|
26
|
+
return this;
|
27
|
+
},
|
28
|
+
trigger: function() {
|
29
|
+
var args, callback, ev, list, _i, _len, _ref;
|
30
|
+
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
31
|
+
ev = args.shift();
|
32
|
+
list = this.hasOwnProperty('_callbacks') && ((_ref = this._callbacks) != null ? _ref[ev] : void 0);
|
33
|
+
if (!list) {
|
34
|
+
return false;
|
35
|
+
}
|
36
|
+
for (_i = 0, _len = list.length; _i < _len; _i++) {
|
37
|
+
callback = list[_i];
|
38
|
+
if (callback.apply(this, args) === false) {
|
39
|
+
break;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
return true;
|
43
|
+
},
|
44
|
+
unbind: function(ev, callback) {
|
45
|
+
var cb, i, list, _len, _ref;
|
46
|
+
if (!ev) {
|
47
|
+
this._callbacks = {};
|
48
|
+
return this;
|
49
|
+
}
|
50
|
+
list = (_ref = this._callbacks) != null ? _ref[ev] : void 0;
|
51
|
+
if (!list) {
|
52
|
+
return this;
|
53
|
+
}
|
54
|
+
if (!callback) {
|
55
|
+
delete this._callbacks[ev];
|
56
|
+
return this;
|
57
|
+
}
|
58
|
+
for (i = 0, _len = list.length; i < _len; i++) {
|
59
|
+
cb = list[i];
|
60
|
+
if (cb === callback) {
|
61
|
+
list = list.slice();
|
62
|
+
list.splice(i, 1);
|
63
|
+
this._callbacks[ev] = list;
|
64
|
+
break;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
return this;
|
68
|
+
}
|
69
|
+
};
|
70
|
+
Log = {
|
71
|
+
trace: true,
|
72
|
+
logPrefix: '(App)',
|
73
|
+
log: function() {
|
74
|
+
var args;
|
75
|
+
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
76
|
+
if (!this.trace) {
|
77
|
+
return;
|
78
|
+
}
|
79
|
+
if (typeof console === 'undefined') {
|
80
|
+
return;
|
81
|
+
}
|
82
|
+
if (this.logPrefix) {
|
83
|
+
args.unshift(this.logPrefix);
|
84
|
+
}
|
85
|
+
console.log.apply(console, args);
|
86
|
+
return this;
|
87
|
+
}
|
88
|
+
};
|
89
|
+
moduleKeywords = ['included', 'extended'];
|
90
|
+
Module = (function() {
|
91
|
+
Module.include = function(obj) {
|
92
|
+
var included, key, value;
|
93
|
+
if (!obj) {
|
94
|
+
throw 'include(obj) requires obj';
|
95
|
+
}
|
96
|
+
for (key in obj) {
|
97
|
+
value = obj[key];
|
98
|
+
if (__indexOf.call(moduleKeywords, key) < 0) {
|
99
|
+
this.prototype[key] = value;
|
100
|
+
}
|
101
|
+
}
|
102
|
+
included = obj.included;
|
103
|
+
if (included) {
|
104
|
+
included.apply(this);
|
105
|
+
}
|
106
|
+
return this;
|
107
|
+
};
|
108
|
+
Module.extend = function(obj) {
|
109
|
+
var extended, key, value;
|
110
|
+
if (!obj) {
|
111
|
+
throw 'extend(obj) requires obj';
|
112
|
+
}
|
113
|
+
for (key in obj) {
|
114
|
+
value = obj[key];
|
115
|
+
if (__indexOf.call(moduleKeywords, key) < 0) {
|
116
|
+
this[key] = value;
|
117
|
+
}
|
118
|
+
}
|
119
|
+
extended = obj.extended;
|
120
|
+
if (extended) {
|
121
|
+
extended.apply(this);
|
122
|
+
}
|
123
|
+
return this;
|
124
|
+
};
|
125
|
+
Module.proxy = function(func) {
|
126
|
+
return __bind(function() {
|
127
|
+
return func.apply(this, arguments);
|
128
|
+
}, this);
|
129
|
+
};
|
130
|
+
Module.prototype.proxy = function(func) {
|
131
|
+
return __bind(function() {
|
132
|
+
return func.apply(this, arguments);
|
133
|
+
}, this);
|
134
|
+
};
|
135
|
+
function Module() {
|
136
|
+
if (typeof this.init === "function") {
|
137
|
+
this.init.apply(this, arguments);
|
138
|
+
}
|
139
|
+
}
|
140
|
+
return Module;
|
141
|
+
})();
|
142
|
+
Model = (function() {
|
143
|
+
__extends(Model, Module);
|
144
|
+
Model.extend(Events);
|
145
|
+
Model.records = {};
|
146
|
+
Model.attributes = [];
|
147
|
+
Model.configure = function() {
|
148
|
+
var attributes, name;
|
149
|
+
name = arguments[0], attributes = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
150
|
+
this.className = name;
|
151
|
+
this.records = {};
|
152
|
+
if (attributes.length) {
|
153
|
+
this.attributes = attributes;
|
154
|
+
}
|
155
|
+
this.attributes && (this.attributes = makeArray(this.attributes));
|
156
|
+
this.attributes || (this.attributes = []);
|
157
|
+
this.unbind();
|
158
|
+
return this;
|
159
|
+
};
|
160
|
+
Model.toString = function() {
|
161
|
+
return "" + this.className + "(" + (this.attributes.join(", ")) + ")";
|
162
|
+
};
|
163
|
+
Model.find = function(id) {
|
164
|
+
var record;
|
165
|
+
record = this.records[id];
|
166
|
+
if (!record) {
|
167
|
+
throw 'Unknown record';
|
168
|
+
}
|
169
|
+
return record.clone();
|
170
|
+
};
|
171
|
+
Model.exists = function(id) {
|
172
|
+
try {
|
173
|
+
return this.find(id);
|
174
|
+
} catch (e) {
|
175
|
+
return false;
|
176
|
+
}
|
177
|
+
};
|
178
|
+
Model.refresh = function(values, options) {
|
179
|
+
var record, _i, _len, _ref;
|
180
|
+
if (options == null) {
|
181
|
+
options = {};
|
182
|
+
}
|
183
|
+
if (options.clear) {
|
184
|
+
this.records = {};
|
185
|
+
}
|
186
|
+
_ref = this.fromJSON(values);
|
187
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
188
|
+
record = _ref[_i];
|
189
|
+
record.newRecord = false;
|
190
|
+
record.id || (record.id = guid());
|
191
|
+
this.records[record.id] = record;
|
192
|
+
}
|
193
|
+
this.trigger('refresh');
|
194
|
+
return this;
|
195
|
+
};
|
196
|
+
Model.select = function(callback) {
|
197
|
+
var id, record, result;
|
198
|
+
result = (function() {
|
199
|
+
var _ref, _results;
|
200
|
+
_ref = this.records;
|
201
|
+
_results = [];
|
202
|
+
for (id in _ref) {
|
203
|
+
record = _ref[id];
|
204
|
+
if (callback(record)) {
|
205
|
+
_results.push(record);
|
206
|
+
}
|
207
|
+
}
|
208
|
+
return _results;
|
209
|
+
}).call(this);
|
210
|
+
return this.cloneArray(result);
|
211
|
+
};
|
212
|
+
Model.findByAttribute = function(name, value) {
|
213
|
+
var id, record, _ref;
|
214
|
+
_ref = this.records;
|
215
|
+
for (id in _ref) {
|
216
|
+
record = _ref[id];
|
217
|
+
if (record[name] === value) {
|
218
|
+
return record.clone();
|
219
|
+
}
|
220
|
+
}
|
221
|
+
return null;
|
222
|
+
};
|
223
|
+
Model.findAllByAttribute = function(name, value) {
|
224
|
+
return this.select(function(item) {
|
225
|
+
return item[name] === value;
|
226
|
+
});
|
227
|
+
};
|
228
|
+
Model.each = function(callback) {
|
229
|
+
var key, value, _ref, _results;
|
230
|
+
_ref = this.records;
|
231
|
+
_results = [];
|
232
|
+
for (key in _ref) {
|
233
|
+
value = _ref[key];
|
234
|
+
_results.push(callback(value.clone()));
|
235
|
+
}
|
236
|
+
return _results;
|
237
|
+
};
|
238
|
+
Model.all = function() {
|
239
|
+
return this.cloneArray(this.recordsValues());
|
240
|
+
};
|
241
|
+
Model.first = function() {
|
242
|
+
var record;
|
243
|
+
record = this.recordsValues()[0];
|
244
|
+
return record != null ? record.clone() : void 0;
|
245
|
+
};
|
246
|
+
Model.last = function() {
|
247
|
+
var record, values;
|
248
|
+
values = this.recordsValues();
|
249
|
+
record = values[values.length - 1];
|
250
|
+
return record != null ? record.clone() : void 0;
|
251
|
+
};
|
252
|
+
Model.count = function() {
|
253
|
+
return this.recordsValues().length;
|
254
|
+
};
|
255
|
+
Model.deleteAll = function() {
|
256
|
+
var key, value, _ref, _results;
|
257
|
+
_ref = this.records;
|
258
|
+
_results = [];
|
259
|
+
for (key in _ref) {
|
260
|
+
value = _ref[key];
|
261
|
+
_results.push(delete this.records[key]);
|
262
|
+
}
|
263
|
+
return _results;
|
264
|
+
};
|
265
|
+
Model.destroyAll = function() {
|
266
|
+
var key, value, _ref, _results;
|
267
|
+
_ref = this.records;
|
268
|
+
_results = [];
|
269
|
+
for (key in _ref) {
|
270
|
+
value = _ref[key];
|
271
|
+
_results.push(this.records[key].destroy());
|
272
|
+
}
|
273
|
+
return _results;
|
274
|
+
};
|
275
|
+
Model.update = function(id, atts) {
|
276
|
+
return this.find(id).updateAttributes(atts);
|
277
|
+
};
|
278
|
+
Model.create = function(atts) {
|
279
|
+
var record;
|
280
|
+
record = new this(atts);
|
281
|
+
return record.save();
|
282
|
+
};
|
283
|
+
Model.destroy = function(id) {
|
284
|
+
return this.find(id).destroy();
|
285
|
+
};
|
286
|
+
Model.change = function(callbackOrParams) {
|
287
|
+
if (typeof callbackOrParams === 'function') {
|
288
|
+
return this.bind('change', callbackOrParams);
|
289
|
+
} else {
|
290
|
+
return this.trigger('change', callbackOrParams);
|
291
|
+
}
|
292
|
+
};
|
293
|
+
Model.fetch = function(callbackOrParams) {
|
294
|
+
if (typeof callbackOrParams === 'function') {
|
295
|
+
return this.bind('fetch', callbackOrParams);
|
296
|
+
} else {
|
297
|
+
return this.trigger('fetch', callbackOrParams);
|
298
|
+
}
|
299
|
+
};
|
300
|
+
Model.toJSON = function() {
|
301
|
+
return this.recordsValues();
|
302
|
+
};
|
303
|
+
Model.fromJSON = function(objects) {
|
304
|
+
var value, _i, _len, _results;
|
305
|
+
if (!objects) {
|
306
|
+
return;
|
307
|
+
}
|
308
|
+
if (typeof objects === 'string') {
|
309
|
+
objects = JSON.parse(objects);
|
310
|
+
}
|
311
|
+
if (isArray(objects)) {
|
312
|
+
_results = [];
|
313
|
+
for (_i = 0, _len = objects.length; _i < _len; _i++) {
|
314
|
+
value = objects[_i];
|
315
|
+
_results.push(new this(value));
|
316
|
+
}
|
317
|
+
return _results;
|
318
|
+
} else {
|
319
|
+
return new this(objects);
|
320
|
+
}
|
321
|
+
};
|
322
|
+
Model.recordsValues = function() {
|
323
|
+
var key, result, value, _ref;
|
324
|
+
result = [];
|
325
|
+
_ref = this.records;
|
326
|
+
for (key in _ref) {
|
327
|
+
value = _ref[key];
|
328
|
+
result.push(value);
|
329
|
+
}
|
330
|
+
return result;
|
331
|
+
};
|
332
|
+
Model.cloneArray = function(array) {
|
333
|
+
var value, _i, _len, _results;
|
334
|
+
_results = [];
|
335
|
+
for (_i = 0, _len = array.length; _i < _len; _i++) {
|
336
|
+
value = array[_i];
|
337
|
+
_results.push(value.clone());
|
338
|
+
}
|
339
|
+
return _results;
|
340
|
+
};
|
341
|
+
Model.prototype.newRecord = true;
|
342
|
+
function Model(atts) {
|
343
|
+
Model.__super__.constructor.apply(this, arguments);
|
344
|
+
this.ids = [];
|
345
|
+
if (atts) {
|
346
|
+
this.load(atts);
|
347
|
+
}
|
348
|
+
}
|
349
|
+
Model.prototype.isNew = function() {
|
350
|
+
return this.newRecord;
|
351
|
+
};
|
352
|
+
Model.prototype.isValid = function() {
|
353
|
+
return !this.validate();
|
354
|
+
};
|
355
|
+
Model.prototype.validate = function() {};
|
356
|
+
Model.prototype.load = function(atts) {
|
357
|
+
var key, value, _results;
|
358
|
+
_results = [];
|
359
|
+
for (key in atts) {
|
360
|
+
value = atts[key];
|
361
|
+
_results.push(this[key] = value);
|
362
|
+
}
|
363
|
+
return _results;
|
364
|
+
};
|
365
|
+
Model.prototype.attributes = function() {
|
366
|
+
var key, result, _i, _len, _ref;
|
367
|
+
result = {};
|
368
|
+
_ref = this.constructor.attributes;
|
369
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
370
|
+
key = _ref[_i];
|
371
|
+
result[key] = this[key];
|
372
|
+
}
|
373
|
+
result.id = this.id;
|
374
|
+
return result;
|
375
|
+
};
|
376
|
+
Model.prototype.eql = function(rec) {
|
377
|
+
var _ref, _ref2;
|
378
|
+
return rec && rec.constructor === this.constructor && (rec.id === this.id || (_ref = this.id, __indexOf.call(rec.ids, _ref) >= 0) || (_ref2 = rec.id, __indexOf.call(this.ids, _ref2) >= 0));
|
379
|
+
};
|
380
|
+
Model.prototype.save = function() {
|
381
|
+
var error;
|
382
|
+
error = this.validate();
|
383
|
+
if (error) {
|
384
|
+
this.trigger('error', this, error);
|
385
|
+
return false;
|
386
|
+
}
|
387
|
+
this.trigger('beforeSave', this);
|
388
|
+
if (this.newRecord) {
|
389
|
+
this.create();
|
390
|
+
} else {
|
391
|
+
this.update();
|
392
|
+
}
|
393
|
+
this.trigger('save', this);
|
394
|
+
return this;
|
395
|
+
};
|
396
|
+
Model.prototype.updateAttribute = function(name, value) {
|
397
|
+
this[name] = value;
|
398
|
+
return this.save();
|
399
|
+
};
|
400
|
+
Model.prototype.updateAttributes = function(atts) {
|
401
|
+
this.load(atts);
|
402
|
+
return this.save();
|
403
|
+
};
|
404
|
+
Model.prototype.changeID = function(id) {
|
405
|
+
var records;
|
406
|
+
this.ids.push(this.id);
|
407
|
+
records = this.constructor.records;
|
408
|
+
records[id] = records[this.id];
|
409
|
+
delete records[this.id];
|
410
|
+
this.id = id;
|
411
|
+
return this.save();
|
412
|
+
};
|
413
|
+
Model.prototype.destroy = function() {
|
414
|
+
this.trigger('beforeDestroy', this);
|
415
|
+
delete this.constructor.records[this.id];
|
416
|
+
this.destroyed = true;
|
417
|
+
this.trigger('destroy', this);
|
418
|
+
this.trigger('change', this, 'destroy');
|
419
|
+
this.unbind();
|
420
|
+
return this;
|
421
|
+
};
|
422
|
+
Model.prototype.dup = function(newRecord) {
|
423
|
+
var result;
|
424
|
+
result = new this.constructor(this.attributes());
|
425
|
+
if (newRecord === false) {
|
426
|
+
result.newRecord = this.newRecord;
|
427
|
+
} else {
|
428
|
+
delete result.id;
|
429
|
+
}
|
430
|
+
return result;
|
431
|
+
};
|
432
|
+
Model.prototype.clone = function() {
|
433
|
+
return Object.create(this);
|
434
|
+
};
|
435
|
+
Model.prototype.reload = function() {
|
436
|
+
var original;
|
437
|
+
if (this.newRecord) {
|
438
|
+
return this;
|
439
|
+
}
|
440
|
+
original = this.constructor.find(this.id);
|
441
|
+
this.load(original.attributes());
|
442
|
+
return original;
|
443
|
+
};
|
444
|
+
Model.prototype.toJSON = function() {
|
445
|
+
return this.attributes();
|
446
|
+
};
|
447
|
+
Model.prototype.toString = function() {
|
448
|
+
return "<" + this.constructor.className + " (" + (JSON.stringify(this)) + ")>";
|
449
|
+
};
|
450
|
+
Model.prototype.exists = function() {
|
451
|
+
return this.id && this.id in this.constructor.records;
|
452
|
+
};
|
453
|
+
Model.prototype.update = function() {
|
454
|
+
var clone, records;
|
455
|
+
this.trigger('beforeUpdate', this);
|
456
|
+
records = this.constructor.records;
|
457
|
+
records[this.id].load(this.attributes());
|
458
|
+
clone = records[this.id].clone();
|
459
|
+
this.trigger('update', clone);
|
460
|
+
return this.trigger('change', clone, 'update');
|
461
|
+
};
|
462
|
+
Model.prototype.create = function() {
|
463
|
+
var clone, records;
|
464
|
+
this.trigger('beforeCreate', this);
|
465
|
+
if (!this.id) {
|
466
|
+
this.id = guid();
|
467
|
+
}
|
468
|
+
this.newRecord = false;
|
469
|
+
records = this.constructor.records;
|
470
|
+
records[this.id] = this.dup(false);
|
471
|
+
clone = records[this.id].clone();
|
472
|
+
this.trigger('create', clone);
|
473
|
+
return this.trigger('change', clone, 'create');
|
474
|
+
};
|
475
|
+
Model.prototype.bind = function(events, callback) {
|
476
|
+
var binder, unbinder;
|
477
|
+
this.constructor.bind(events, binder = __bind(function(record) {
|
478
|
+
if (record && this.eql(record)) {
|
479
|
+
return callback.apply(this, arguments);
|
480
|
+
}
|
481
|
+
}, this));
|
482
|
+
this.constructor.bind('unbind', unbinder = __bind(function(record) {
|
483
|
+
if (record && this.eql(record)) {
|
484
|
+
this.constructor.unbind(events, binder);
|
485
|
+
return this.constructor.unbind('unbind', unbinder);
|
486
|
+
}
|
487
|
+
}, this));
|
488
|
+
return binder;
|
489
|
+
};
|
490
|
+
Model.prototype.trigger = function() {
|
491
|
+
var _ref;
|
492
|
+
return (_ref = this.constructor).trigger.apply(_ref, arguments);
|
493
|
+
};
|
494
|
+
Model.prototype.unbind = function() {
|
495
|
+
return this.trigger('unbind', this);
|
496
|
+
};
|
497
|
+
return Model;
|
498
|
+
})();
|
499
|
+
Controller = (function() {
|
500
|
+
__extends(Controller, Module);
|
501
|
+
Controller.include(Events);
|
502
|
+
Controller.include(Log);
|
503
|
+
Controller.prototype.eventSplitter = /^(\w+)\s*(.*)$/;
|
504
|
+
Controller.prototype.tag = 'div';
|
505
|
+
function Controller(options) {
|
506
|
+
this.release = __bind(this.release, this);
|
507
|
+
var key, value, _ref;
|
508
|
+
this.options = options;
|
509
|
+
_ref = this.options;
|
510
|
+
for (key in _ref) {
|
511
|
+
value = _ref[key];
|
512
|
+
this[key] = value;
|
513
|
+
}
|
514
|
+
if (!this.el) {
|
515
|
+
this.el = document.createElement(this.tag);
|
516
|
+
}
|
517
|
+
this.el = $(this.el);
|
518
|
+
if (this.className) {
|
519
|
+
this.el.addClass(this.className);
|
520
|
+
}
|
521
|
+
this.release(function() {
|
522
|
+
return this.el.remove();
|
523
|
+
});
|
524
|
+
if (!this.events) {
|
525
|
+
this.events = this.constructor.events;
|
526
|
+
}
|
527
|
+
if (!this.elements) {
|
528
|
+
this.elements = this.constructor.elements;
|
529
|
+
}
|
530
|
+
if (this.events) {
|
531
|
+
this.delegateEvents();
|
532
|
+
}
|
533
|
+
if (this.elements) {
|
534
|
+
this.refreshElements();
|
535
|
+
}
|
536
|
+
Controller.__super__.constructor.apply(this, arguments);
|
537
|
+
}
|
538
|
+
Controller.prototype.release = function(callback) {
|
539
|
+
if (typeof callback === 'function') {
|
540
|
+
return this.bind('release', callback);
|
541
|
+
} else {
|
542
|
+
return this.trigger('release');
|
543
|
+
}
|
544
|
+
};
|
545
|
+
Controller.prototype.$ = function(selector) {
|
546
|
+
return $(selector, this.el);
|
547
|
+
};
|
548
|
+
Controller.prototype.delegateEvents = function() {
|
549
|
+
var eventName, key, match, method, selector, _ref, _results;
|
550
|
+
_ref = this.events;
|
551
|
+
_results = [];
|
552
|
+
for (key in _ref) {
|
553
|
+
method = _ref[key];
|
554
|
+
if (typeof method !== 'function') {
|
555
|
+
method = this.proxy(this[method]);
|
556
|
+
}
|
557
|
+
match = key.match(this.eventSplitter);
|
558
|
+
eventName = match[1];
|
559
|
+
selector = match[2];
|
560
|
+
_results.push(selector === '' ? this.el.bind(eventName, method) : this.el.delegate(selector, eventName, method));
|
561
|
+
}
|
562
|
+
return _results;
|
563
|
+
};
|
564
|
+
Controller.prototype.refreshElements = function() {
|
565
|
+
var key, value, _ref, _results;
|
566
|
+
_ref = this.elements;
|
567
|
+
_results = [];
|
568
|
+
for (key in _ref) {
|
569
|
+
value = _ref[key];
|
570
|
+
_results.push(this[value] = this.$(key));
|
571
|
+
}
|
572
|
+
return _results;
|
573
|
+
};
|
574
|
+
Controller.prototype.delay = function(func, timeout) {
|
575
|
+
return setTimeout(this.proxy(func), timeout || 0);
|
576
|
+
};
|
577
|
+
Controller.prototype.html = function(element) {
|
578
|
+
this.el.html(element.el || element);
|
579
|
+
this.refreshElements();
|
580
|
+
return this.el;
|
581
|
+
};
|
582
|
+
Controller.prototype.append = function() {
|
583
|
+
var e, elements, _ref;
|
584
|
+
elements = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
585
|
+
elements = (function() {
|
586
|
+
var _i, _len, _results;
|
587
|
+
_results = [];
|
588
|
+
for (_i = 0, _len = elements.length; _i < _len; _i++) {
|
589
|
+
e = elements[_i];
|
590
|
+
_results.push(e.el || e);
|
591
|
+
}
|
592
|
+
return _results;
|
593
|
+
})();
|
594
|
+
(_ref = this.el).append.apply(_ref, elements);
|
595
|
+
this.refreshElements();
|
596
|
+
return this.el;
|
597
|
+
};
|
598
|
+
Controller.prototype.appendTo = function(element) {
|
599
|
+
this.el.appendTo(element.el || element);
|
600
|
+
this.refreshElements();
|
601
|
+
return this.el;
|
602
|
+
};
|
603
|
+
Controller.prototype.prepend = function() {
|
604
|
+
var e, elements, _ref;
|
605
|
+
elements = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
606
|
+
elements = (function() {
|
607
|
+
var _i, _len, _results;
|
608
|
+
_results = [];
|
609
|
+
for (_i = 0, _len = elements.length; _i < _len; _i++) {
|
610
|
+
e = elements[_i];
|
611
|
+
_results.push(e.el || e);
|
612
|
+
}
|
613
|
+
return _results;
|
614
|
+
})();
|
615
|
+
(_ref = this.el).prepend.apply(_ref, elements);
|
616
|
+
this.refreshElements();
|
617
|
+
return this.el;
|
618
|
+
};
|
619
|
+
Controller.prototype.replace = function(element) {
|
620
|
+
var previous, _ref;
|
621
|
+
_ref = [this.el, element.el || element], previous = _ref[0], this.el = _ref[1];
|
622
|
+
previous.replaceWith(this.el);
|
623
|
+
this.delegateEvents();
|
624
|
+
this.refreshElements();
|
625
|
+
return this.el;
|
626
|
+
};
|
627
|
+
return Controller;
|
628
|
+
})();
|
629
|
+
$ = this.jQuery || this.Zepto || function(element) {
|
630
|
+
return element;
|
631
|
+
};
|
632
|
+
if (typeof Object.create !== 'function') {
|
633
|
+
Object.create = function(o) {
|
634
|
+
var Func;
|
635
|
+
Func = function() {};
|
636
|
+
Func.prototype = o;
|
637
|
+
return new Func();
|
638
|
+
};
|
639
|
+
}
|
640
|
+
isArray = function(value) {
|
641
|
+
return Object.prototype.toString.call(value) === '[object Array]';
|
642
|
+
};
|
643
|
+
isBlank = function(value) {
|
644
|
+
var key;
|
645
|
+
if (!value) {
|
646
|
+
return true;
|
647
|
+
}
|
648
|
+
for (key in value) {
|
649
|
+
return false;
|
650
|
+
}
|
651
|
+
return true;
|
652
|
+
};
|
653
|
+
makeArray = function(args) {
|
654
|
+
return Array.prototype.slice.call(args, 0);
|
655
|
+
};
|
656
|
+
guid = function() {
|
657
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
658
|
+
var r, v;
|
659
|
+
r = Math.random() * 16 | 0;
|
660
|
+
v = c === 'x' ? r : r & 3 | 8;
|
661
|
+
return v.toString(16);
|
662
|
+
}).toUpperCase();
|
663
|
+
};
|
664
|
+
Spine = this.Spine = {};
|
665
|
+
if (typeof module !== "undefined" && module !== null) {
|
666
|
+
module.exports = Spine;
|
667
|
+
}
|
668
|
+
Spine.version = '0.0.9';
|
669
|
+
Spine.isArray = isArray;
|
670
|
+
Spine.isBlank = isBlank;
|
671
|
+
Spine.$ = $;
|
672
|
+
Spine.Events = Events;
|
673
|
+
Spine.Log = Log;
|
674
|
+
Spine.Module = Module;
|
675
|
+
Spine.Controller = Controller;
|
676
|
+
Spine.Model = Model;
|
677
|
+
Module.extend.call(Spine, Events);
|
678
|
+
Module.create = Module.sub = Controller.create = Controller.sub = Model.sub = function(instances, statics) {
|
679
|
+
var result;
|
680
|
+
result = (function() {
|
681
|
+
__extends(result, this);
|
682
|
+
function result() {
|
683
|
+
result.__super__.constructor.apply(this, arguments);
|
684
|
+
}
|
685
|
+
return result;
|
686
|
+
}).call(this);
|
687
|
+
if (instances) {
|
688
|
+
result.include(instances);
|
689
|
+
}
|
690
|
+
if (statics) {
|
691
|
+
result.extend(statics);
|
692
|
+
}
|
693
|
+
if (typeof result.unbind === "function") {
|
694
|
+
result.unbind();
|
695
|
+
}
|
696
|
+
return result;
|
697
|
+
};
|
698
|
+
Model.setup = function(name, attributes) {
|
699
|
+
var Instance;
|
700
|
+
if (attributes == null) {
|
701
|
+
attributes = [];
|
702
|
+
}
|
703
|
+
Instance = (function() {
|
704
|
+
__extends(Instance, this);
|
705
|
+
function Instance() {
|
706
|
+
Instance.__super__.constructor.apply(this, arguments);
|
707
|
+
}
|
708
|
+
return Instance;
|
709
|
+
}).call(this);
|
710
|
+
Instance.configure.apply(Instance, [name].concat(__slice.call(attributes)));
|
711
|
+
return Instance;
|
712
|
+
};
|
713
|
+
Module.init = Controller.init = Model.init = function(a1, a2, a3, a4, a5) {
|
714
|
+
return new this(a1, a2, a3, a4, a5);
|
715
|
+
};
|
716
|
+
Spine.Class = Module;
|
717
|
+
}).call(this);
|