UNPKG

17.7 kBJavaScriptView Raw
1(function() {
2 var Events, Model, Module, createObject, isArray, isBlank, makeArray,
3 __hasProp = {}.hasOwnProperty,
4 __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; },
5 __slice = [].slice;
6
7 Events = require("./events");
8
9 Module = require("./module");
10
11 Model = (function(_super) {
12 __extends(Model, _super);
13
14 Model.extend(Events);
15
16 Model.records = [];
17
18 Model.irecords = {};
19
20 Model.attributes = [];
21
22 Model.configure = function() {
23 var attributes, name;
24 name = arguments[0], attributes = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
25 this.className = name;
26 this.deleteAll();
27 if (attributes.length) {
28 this.attributes = attributes;
29 }
30 this.attributes && (this.attributes = makeArray(this.attributes));
31 this.attributes || (this.attributes = []);
32 this.unbind();
33 return this;
34 };
35
36 Model.toString = function() {
37 return "" + this.className + "(" + (this.attributes.join(", ")) + ")";
38 };
39
40 Model.find = function(id) {
41 var record;
42 record = this.exists(id);
43 if (!record) {
44 throw new Error("\"" + this.className + "\" model could not find a record for the ID \"" + id + "\"");
45 }
46 return record;
47 };
48
49 Model.exists = function(id) {
50 var _ref;
51 return (_ref = this.irecords[id]) != null ? _ref.clone() : void 0;
52 };
53
54 Model.addRecord = function(record) {
55 if (record.id && this.irecords[record.id]) {
56 this.irecords[record.id].remove();
57 }
58 record.id || (record.id = record.cid);
59 this.records.push(record);
60 this.irecords[record.id] = record;
61 return this.irecords[record.cid] = record;
62 };
63
64 Model.refresh = function(values, options) {
65 var record, records, result, _i, _len;
66 if (options == null) {
67 options = {};
68 }
69 if (options.clear) {
70 this.deleteAll();
71 }
72 records = this.fromJSON(values);
73 if (!isArray(records)) {
74 records = [records];
75 }
76 for (_i = 0, _len = records.length; _i < _len; _i++) {
77 record = records[_i];
78 this.addRecord(record);
79 }
80 this.sort();
81 result = this.cloneArray(records);
82 this.trigger('refresh', result, options);
83 return result;
84 };
85
86 Model.select = function(callback) {
87 var record, _i, _len, _ref, _results;
88 _ref = this.records;
89 _results = [];
90 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
91 record = _ref[_i];
92 if (callback(record)) {
93 _results.push(record.clone());
94 }
95 }
96 return _results;
97 };
98
99 Model.findByAttribute = function(name, value) {
100 var record, _i, _len, _ref;
101 _ref = this.records;
102 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
103 record = _ref[_i];
104 if (record[name] === value) {
105 return record.clone();
106 }
107 }
108 return null;
109 };
110
111 Model.findAllByAttribute = function(name, value) {
112 return this.select(function(item) {
113 return item[name] === value;
114 });
115 };
116
117 Model.each = function(callback) {
118 var record, _i, _len, _ref, _results;
119 _ref = this.records;
120 _results = [];
121 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
122 record = _ref[_i];
123 _results.push(callback(record.clone()));
124 }
125 return _results;
126 };
127
128 Model.all = function() {
129 return this.cloneArray(this.records);
130 };
131
132 Model.first = function() {
133 var _ref;
134 return (_ref = this.records[0]) != null ? _ref.clone() : void 0;
135 };
136
137 Model.last = function() {
138 var _ref;
139 return (_ref = this.records[this.records.length - 1]) != null ? _ref.clone() : void 0;
140 };
141
142 Model.count = function() {
143 return this.records.length;
144 };
145
146 Model.deleteAll = function() {
147 this.records = [];
148 return this.irecords = {};
149 };
150
151 Model.destroyAll = function(options) {
152 var record, _i, _len, _ref, _results;
153 _ref = this.records;
154 _results = [];
155 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
156 record = _ref[_i];
157 _results.push(record.destroy(options));
158 }
159 return _results;
160 };
161
162 Model.update = function(id, atts, options) {
163 return this.find(id).updateAttributes(atts, options);
164 };
165
166 Model.create = function(atts, options) {
167 var record;
168 record = new this(atts);
169 return record.save(options);
170 };
171
172 Model.destroy = function(id, options) {
173 return this.find(id).destroy(options);
174 };
175
176 Model.change = function(callbackOrParams) {
177 if (typeof callbackOrParams === 'function') {
178 return this.bind('change', callbackOrParams);
179 } else {
180 return this.trigger.apply(this, ['change'].concat(__slice.call(arguments)));
181 }
182 };
183
184 Model.fetch = function(callbackOrParams) {
185 if (typeof callbackOrParams === 'function') {
186 return this.bind('fetch', callbackOrParams);
187 } else {
188 return this.trigger.apply(this, ['fetch'].concat(__slice.call(arguments)));
189 }
190 };
191
192 Model.toJSON = function() {
193 return this.records;
194 };
195
196 Model.fromJSON = function(objects) {
197 var value, _i, _len, _results;
198 if (!objects) {
199 return;
200 }
201 if (typeof objects === 'string') {
202 objects.replace(/\Id/g, 'id');
203 objects = JSON.parse(objects);
204 }
205 if (isArray(objects)) {
206 _results = [];
207 for (_i = 0, _len = objects.length; _i < _len; _i++) {
208 value = objects[_i];
209 if (value.Id) {
210 value.id = value.Id;
211 }
212 _results.push(new this(value));
213 }
214 return _results;
215 } else {
216 if (objects.Id) {
217 objects.id = objects.Id;
218 }
219 return new this(objects);
220 }
221 };
222
223 Model.fromForm = function() {
224 var _ref;
225 return (_ref = new this).fromForm.apply(_ref, arguments);
226 };
227
228 Model.sort = function() {
229 if (this.comparator) {
230 this.records.sort(this.comparator);
231 }
232 return this;
233 };
234
235 Model.cloneArray = function(array) {
236 var value, _i, _len, _results;
237 _results = [];
238 for (_i = 0, _len = array.length; _i < _len; _i++) {
239 value = array[_i];
240 _results.push(value.clone());
241 }
242 return _results;
243 };
244
245 Model.idCounter = 0;
246
247 Model.uid = function(prefix) {
248 var uid;
249 if (prefix == null) {
250 prefix = '';
251 }
252 uid = prefix + this.idCounter++;
253 if (this.exists(uid)) {
254 uid = this.uid(prefix);
255 }
256 return uid;
257 };
258
259 function Model(atts) {
260 Model.__super__.constructor.apply(this, arguments);
261 if (atts) {
262 this.load(atts);
263 }
264 this.cid = (atts != null ? atts.cid : void 0) || this.constructor.uid('c-');
265 }
266
267 Model.prototype.isNew = function() {
268 return !this.exists();
269 };
270
271 Model.prototype.isValid = function() {
272 return !this.validate();
273 };
274
275 Model.prototype.validate = function() {};
276
277 Model.prototype.load = function(atts) {
278 var key, value;
279 if (atts.id) {
280 this.id = atts.id;
281 }
282 for (key in atts) {
283 value = atts[key];
284 if (atts.hasOwnProperty(key) && typeof this[key] === 'function') {
285 this[key](value);
286 } else {
287 this[key] = value;
288 }
289 }
290 return this;
291 };
292
293 Model.prototype.get = function(attr) {
294 return this[attr];
295 };
296
297 Model.prototype.set = function(attr, value) {
298 return this[attr] = value;
299 };
300
301 Model.prototype.attributes = function() {
302 var key, result, _i, _len, _ref;
303 result = {};
304 _ref = this.constructor.attributes;
305 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
306 key = _ref[_i];
307 if (key in this) {
308 if (typeof this[key] === 'function') {
309 result[key] = this[key]();
310 } else {
311 result[key] = this[key];
312 }
313 }
314 }
315 if (this.id) {
316 result.id = this.id;
317 }
318 return result;
319 };
320
321 Model.prototype.eql = function(rec) {
322 return !!(rec && rec.constructor === this.constructor && (rec.cid === this.cid) || (rec.id && rec.id === this.id));
323 };
324
325 Model.prototype.save = function(options) {
326 var error, record;
327 if (options == null) {
328 options = {};
329 }
330 if (options.validate !== false) {
331 error = this.validate();
332 if (error) {
333 this.trigger('error', error);
334 return false;
335 }
336 }
337 this.trigger('beforeSave', options);
338 record = this.isNew() ? this.create(options) : this.update(options);
339 this.stripCloneAttrs();
340 this.trigger('save', options);
341 return record;
342 };
343
344 Model.prototype.stripCloneAttrs = function() {
345 var key, value;
346 if (this.hasOwnProperty('cid')) {
347 return;
348 }
349 for (key in this) {
350 if (!__hasProp.call(this, key)) continue;
351 value = this[key];
352 if (this.constructor.attributes.indexOf(key) > -1) {
353 delete this[key];
354 }
355 }
356 return this;
357 };
358
359 Model.prototype.updateAttribute = function(name, value, options) {
360 var atts;
361 atts = {};
362 atts[name] = value;
363 return this.updateAttributes(atts, options);
364 };
365
366 Model.prototype.updateAttributes = function(atts, options) {
367 this.load(atts);
368 return this.save(options);
369 };
370
371 Model.prototype.changeID = function(id) {
372 var records;
373 if (id === this.id) {
374 return;
375 }
376 records = this.constructor.irecords;
377 records[id] = records[this.id];
378 delete records[this.id];
379 this.id = id;
380 return this.save();
381 };
382
383 Model.prototype.remove = function() {
384 var i, record, records, _i, _len;
385 records = this.constructor.records.slice(0);
386 for (i = _i = 0, _len = records.length; _i < _len; i = ++_i) {
387 record = records[i];
388 if (!(this.eql(record))) {
389 continue;
390 }
391 records.splice(i, 1);
392 break;
393 }
394 this.constructor.records = records;
395 delete this.constructor.irecords[this.id];
396 return delete this.constructor.irecords[this.cid];
397 };
398
399 Model.prototype.destroy = function(options) {
400 if (options == null) {
401 options = {};
402 }
403 this.trigger('beforeDestroy', options);
404 this.remove();
405 this.destroyed = true;
406 this.trigger('destroy', options);
407 this.trigger('change', 'destroy', options);
408 if (this.listeningTo) {
409 this.stopListening();
410 }
411 this.unbind();
412 return this;
413 };
414
415 Model.prototype.dup = function(newRecord) {
416 var atts;
417 if (newRecord == null) {
418 newRecord = true;
419 }
420 atts = this.attributes();
421 if (newRecord) {
422 delete atts.id;
423 } else {
424 atts.cid = this.cid;
425 }
426 return new this.constructor(atts);
427 };
428
429 Model.prototype.clone = function() {
430 return createObject(this);
431 };
432
433 Model.prototype.reload = function() {
434 var original;
435 if (this.isNew()) {
436 return this;
437 }
438 original = this.constructor.find(this.id);
439 this.load(original.attributes());
440 return original;
441 };
442
443 Model.prototype.refresh = function(data) {
444 var root;
445 root = this.constructor.irecords[this.id];
446 root.load(data);
447 this.trigger('refresh');
448 return this;
449 };
450
451 Model.prototype.toJSON = function() {
452 return this.attributes();
453 };
454
455 Model.prototype.toString = function() {
456 return "<" + this.constructor.className + " (" + (JSON.stringify(this)) + ")>";
457 };
458
459 Model.prototype.fromForm = function(form) {
460 var result;
461 result = {};
462
463 /*
464 for checkbox in $(form).find('[type=checkbox]:not([value])')
465 result[checkbox.name] = $(checkbox).prop('checked')
466
467 for checkbox in $(form).find('[type=checkbox][name$="[]"]')
468 name = checkbox.name.replace(/\[\]$/, '')
469 result[name] or= []
470 result[name].push checkbox.value if $(checkbox).prop('checked')
471
472 for key in $(form).serializeArray()
473 result[key.name] or= key.value
474 */
475 return this.load(result);
476 };
477
478 Model.prototype.exists = function() {
479 return this.constructor.exists(this.id);
480 };
481
482 Model.prototype.update = function(options) {
483 var clone, records;
484 this.trigger('beforeUpdate', options);
485 records = this.constructor.irecords;
486 records[this.id].load(this.attributes());
487 this.constructor.sort();
488 clone = records[this.id].clone();
489 clone.trigger('update', options);
490 clone.trigger('change', 'update', options);
491 return clone;
492 };
493
494 Model.prototype.create = function(options) {
495 var clone, record;
496 this.trigger('beforeCreate', options);
497 this.id || (this.id = this.cid);
498 record = this.dup(false);
499 this.constructor.addRecord(record);
500 this.constructor.sort();
501 clone = record.clone();
502 clone.trigger('create', options);
503 clone.trigger('change', 'create', options);
504 return clone;
505 };
506
507 Model.prototype.bind = function(events, callback) {
508 var binder, singleEvent, _fn, _i, _len, _ref;
509 this.constructor.bind(events, binder = (function(_this) {
510 return function(record) {
511 if (record && _this.eql(record)) {
512 return callback.apply(_this, arguments);
513 }
514 };
515 })(this));
516 _ref = events.split(' ');
517 _fn = (function(_this) {
518 return function(singleEvent) {
519 var unbinder;
520 return _this.constructor.bind("unbind", unbinder = function(record, event, cb) {
521 if (record && _this.eql(record)) {
522 if (event && event !== singleEvent) {
523 return;
524 }
525 if (cb && cb !== callback) {
526 return;
527 }
528 _this.constructor.unbind(singleEvent, binder);
529 return _this.constructor.unbind("unbind", unbinder);
530 }
531 });
532 };
533 })(this);
534 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
535 singleEvent = _ref[_i];
536 _fn(singleEvent);
537 }
538 return this;
539 };
540
541 Model.prototype.one = function(events, callback) {
542 var handler;
543 return this.bind(events, handler = (function(_this) {
544 return function() {
545 _this.unbind(events, handler);
546 return callback.apply(_this, arguments);
547 };
548 })(this));
549 };
550
551 Model.prototype.trigger = function() {
552 var args, _ref;
553 args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
554 args.splice(1, 0, this);
555 return (_ref = this.constructor).trigger.apply(_ref, args);
556 };
557
558 Model.prototype.listenTo = function() {
559 return Events.listenTo.apply(this, arguments);
560 };
561
562 Model.prototype.listenToOnce = function() {
563 return Events.listenToOnce.apply(this, arguments);
564 };
565
566 Model.prototype.stopListening = function() {
567 return Events.stopListening.apply(this, arguments);
568 };
569
570 Model.prototype.unbind = function(events, callback) {
571 var event, _i, _len, _ref, _results;
572 if (arguments.length === 0) {
573 return this.trigger('unbind');
574 } else if (events) {
575 _ref = events.split(' ');
576 _results = [];
577 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
578 event = _ref[_i];
579 _results.push(this.trigger('unbind', event, callback));
580 }
581 return _results;
582 }
583 };
584
585 return Model;
586
587 })(Module);
588
589 Model.prototype.on = Model.prototype.bind;
590
591 Model.prototype.off = Model.prototype.unbind;
592
593 createObject = Object.create || function(o) {
594 var Func;
595 Func = function() {};
596 Func.prototype = o;
597 return new Func();
598 };
599
600 isArray = function(value) {
601 return Object.prototype.toString.call(value) === '[object Array]';
602 };
603
604 isBlank = function(value) {
605 var key;
606 if (!value) {
607 return true;
608 }
609 for (key in value) {
610 return false;
611 }
612 return true;
613 };
614
615 makeArray = function(args) {
616 return Array.prototype.slice.call(args, 0);
617 };
618
619 Model.isBlank = isBlank;
620
621 Model.sub = function(instances, statics) {
622 var Result;
623 Result = (function(_super) {
624 __extends(Result, _super);
625
626 function Result() {
627 return Result.__super__.constructor.apply(this, arguments);
628 }
629
630 return Result;
631
632 })(this);
633 if (instances) {
634 Result.include(instances);
635 }
636 if (statics) {
637 Result.extend(statics);
638 }
639 if (typeof Result.unbind === "function") {
640 Result.unbind();
641 }
642 return Result;
643 };
644
645 Model.setup = function(name, attributes) {
646 var Instance;
647 if (attributes == null) {
648 attributes = [];
649 }
650 Instance = (function(_super) {
651 __extends(Instance, _super);
652
653 function Instance() {
654 return Instance.__super__.constructor.apply(this, arguments);
655 }
656
657 return Instance;
658
659 })(this);
660 Instance.configure.apply(Instance, [name].concat(__slice.call(attributes)));
661 return Instance;
662 };
663
664 Model.host = "";
665
666 if (typeof module !== "undefined" && module !== null) {
667 module.exports = Model;
668 }
669
670}).call(this);