spine-rails 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|