Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Updated spine and brought application up to speed with changes.

  • Loading branch information...
commit 0ed99714f74d4ed2d7bb37956bd364d1f21f96d2 1 parent f8a1d0c
Daniel Holmes jaitaiwan authored
2  index.html
@@ -10,7 +10,7 @@
10 10 <script src="lib/jquery.tmpl.js" type="text/javascript" charset="utf-8"></script>
11 11
12 12 <script src="lib/spine.js" type="text/javascript" charset="utf-8"></script>
13   - <script src="lib/spine.local.js" type="text/javascript" charset="utf-8"></script>
  13 + <script src="lib/local.js" type="text/javascript" charset="utf-8"></script>
14 14 <script src="lib/application.js" type="text/javascript" charset="utf-8"></script>
15 15
16 16 <script type="text/x-jquery-tmpl" id="taskTemplate">
55 lib/application.js
... ... @@ -1,31 +1,33 @@
1 1 (function() {
2 2 var $, Task, TaskApp, Tasks;
3   - var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
4   - for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
5   - function ctor() { this.constructor = child; }
6   - ctor.prototype = parent.prototype;
7   - child.prototype = new ctor;
8   - child.__super__ = parent.prototype;
9   - return child;
10   - }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
  3 + var __hasProp = Object.prototype.hasOwnProperty, __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; }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
  4 +
11 5 $ = jQuery;
  6 +
12 7 Task = (function() {
  8 +
13 9 __extends(Task, Spine.Model);
  10 +
14 11 function Task() {
15 12 Task.__super__.constructor.apply(this, arguments);
16 13 }
  14 +
17 15 Task.configure("Task", "name", "done");
  16 +
18 17 Task.extend(Spine.Model.Local);
  18 +
19 19 Task.active = function() {
20 20 return this.select(function(item) {
21 21 return !item.done;
22 22 });
23 23 };
  24 +
24 25 Task.done = function() {
25 26 return this.select(function(item) {
26 27 return !!item.done;
27 28 });
28 29 };
  30 +
29 31 Task.destroyDone = function() {
30 32 var rec, _i, _len, _ref, _results;
31 33 _ref = this.done();
@@ -36,10 +38,15 @@
36 38 }
37 39 return _results;
38 40 };
  41 +
39 42 return Task;
  43 +
40 44 })();
  45 +
41 46 Tasks = (function() {
  47 +
42 48 __extends(Tasks, Spine.Controller);
  49 +
43 50 Tasks.prototype.events = {
44 51 "change input[type=checkbox]": "toggle",
45 52 "click .destroy": "remove",
@@ -47,56 +54,67 @@
47 54 "keypress input[type=text]": "blurOnEnter",
48 55 "blur input[type=text]": "close"
49 56 };
  57 +
50 58 Tasks.prototype.elements = {
51 59 "input[type=text]": "input"
52 60 };
  61 +
53 62 function Tasks() {
54 63 this.render = __bind(this.render, this); Tasks.__super__.constructor.apply(this, arguments);
55 64 this.item.bind("update", this.render);
56   - this.item.bind("destroy", __bind(function() {
57   - return this.trigger('destroy');
58   - }, this));
  65 + this.item.bind("destroy", this.release);
59 66 }
  67 +
60 68 Tasks.prototype.render = function() {
61 69 this.replace($("#taskTemplate").tmpl(this.item));
62 70 return this;
63 71 };
  72 +
64 73 Tasks.prototype.toggle = function() {
65 74 this.item.done = !this.item.done;
66 75 return this.item.save();
67 76 };
  77 +
68 78 Tasks.prototype.remove = function() {
69 79 return this.item.destroy();
70 80 };
  81 +
71 82 Tasks.prototype.edit = function() {
72 83 this.el.addClass("editing");
73 84 return this.input.focus();
74 85 };
  86 +
75 87 Tasks.prototype.blurOnEnter = function(e) {
76   - if (e.keyCode === 13) {
77   - return e.target.blur();
78   - }
  88 + if (e.keyCode === 13) return e.target.blur();
79 89 };
  90 +
80 91 Tasks.prototype.close = function() {
81 92 this.el.removeClass("editing");
82 93 return this.item.updateAttributes({
83 94 name: this.input.val()
84 95 });
85 96 };
  97 +
86 98 return Tasks;
  99 +
87 100 })();
  101 +
88 102 TaskApp = (function() {
  103 +
89 104 __extends(TaskApp, Spine.Controller);
  105 +
90 106 TaskApp.prototype.events = {
91 107 "submit form": "create",
92 108 "click .clear": "clear"
93 109 };
  110 +
94 111 TaskApp.prototype.elements = {
95 112 ".items": "items",
96 113 ".countVal": "count",
97 114 ".clear": "clear",
98 115 "form input": "input"
99 116 };
  117 +
100 118 function TaskApp() {
101 119 this.renderCount = __bind(this.renderCount, this);
102 120 this.addAll = __bind(this.addAll, this);
@@ -106,6 +124,7 @@
106 124 Task.bind("refresh change", this.renderCount);
107 125 Task.fetch();
108 126 }
  127 +
109 128 TaskApp.prototype.addOne = function(task) {
110 129 var view;
111 130 view = new Tasks({
@@ -113,9 +132,11 @@
113 132 });
114 133 return this.items.append(view.render().el);
115 134 };
  135 +
116 136 TaskApp.prototype.addAll = function() {
117 137 return Task.each(this.addOne);
118 138 };
  139 +
119 140 TaskApp.prototype.create = function(e) {
120 141 e.preventDefault();
121 142 Task.create({
@@ -123,9 +144,11 @@
123 144 });
124 145 return this.input.val("");
125 146 };
  147 +
126 148 TaskApp.prototype.clear = function() {
127 149 return Task.destroyDone();
128 150 };
  151 +
129 152 TaskApp.prototype.renderCount = function() {
130 153 var active, inactive;
131 154 active = Task.active().length;
@@ -137,11 +160,15 @@
137 160 return this.clear.hide();
138 161 }
139 162 };
  163 +
140 164 return TaskApp;
  165 +
141 166 })();
  167 +
142 168 $(function() {
143 169 return new TaskApp({
144 170 el: $("#tasks")
145 171 });
146 172 });
  173 +
147 174 }).call(this);
2  lib/spine.local.js → lib/local.js
... ... @@ -1,6 +1,6 @@
1 1 (function() {
2 2 if (typeof Spine === "undefined" || Spine === null) {
3   - Spine = require("spine");
  3 + Spine = require('spine');
4 4 }
5 5 Spine.Model.Local = {
6 6 extended: function() {
127 lib/spine.js
... ... @@ -1,5 +1,5 @@
1 1 (function() {
2   - var $, Controller, Events, Log, Model, Module, Spine, guid, isArray, makeArray, moduleKeywords;
  2 + var $, Controller, Events, Log, Model, Module, Spine, guid, isArray, isBlank, makeArray, moduleKeywords;
3 3 var __slice = Array.prototype.slice, __indexOf = Array.prototype.indexOf || function(item) {
4 4 for (var i = 0, l = this.length; i < l; i++) {
5 5 if (this[i] === item) return i;
@@ -25,6 +25,12 @@
25 25 }
26 26 return this;
27 27 },
  28 + one: function(ev, callback) {
  29 + return this.bind(ev, function() {
  30 + this.unbind(ev, arguments.callee);
  31 + return callback.apply(this, arguments);
  32 + });
  33 + },
28 34 trigger: function() {
29 35 var args, callback, ev, list, _i, _len, _ref;
30 36 args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
@@ -176,21 +182,24 @@
176 182 }
177 183 };
178 184 Model.refresh = function(values, options) {
179   - var record, _i, _len, _ref;
  185 + var record, records, _i, _len;
180 186 if (options == null) {
181 187 options = {};
182 188 }
183 189 if (options.clear) {
184 190 this.records = {};
185 191 }
186   - _ref = this.fromJSON(values);
187   - for (_i = 0, _len = _ref.length; _i < _len; _i++) {
188   - record = _ref[_i];
  192 + records = this.fromJSON(values);
  193 + if (!isArray(records)) {
  194 + records = [records];
  195 + }
  196 + for (_i = 0, _len = records.length; _i < _len; _i++) {
  197 + record = records[_i];
189 198 record.newRecord = false;
190 199 record.id || (record.id = guid());
191 200 this.records[record.id] = record;
192 201 }
193   - this.trigger('refresh');
  202 + this.trigger('refresh', !options.clear && records);
194 203 return this;
195 204 };
196 205 Model.select = function(callback) {
@@ -319,6 +328,10 @@
319 328 return new this(objects);
320 329 }
321 330 };
  331 + Model.fromForm = function() {
  332 + var _ref;
  333 + return (_ref = new this).fromForm.apply(_ref, arguments);
  334 + };
322 335 Model.recordsValues = function() {
323 336 var key, result, value, _ref;
324 337 result = [];
@@ -354,13 +367,16 @@
354 367 };
355 368 Model.prototype.validate = function() {};
356 369 Model.prototype.load = function(atts) {
357   - var key, value, _results;
358   - _results = [];
  370 + var key, value;
359 371 for (key in atts) {
360 372 value = atts[key];
361   - _results.push(this[key] = value);
  373 + if (typeof this[key] === 'function') {
  374 + this[key](value);
  375 + } else {
  376 + this[key] = value;
  377 + }
362 378 }
363   - return _results;
  379 + return this;
364 380 };
365 381 Model.prototype.attributes = function() {
366 382 var key, result, _i, _len, _ref;
@@ -368,9 +384,17 @@
368 384 _ref = this.constructor.attributes;
369 385 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
370 386 key = _ref[_i];
371   - result[key] = this[key];
  387 + if (key in this) {
  388 + if (typeof this[key] === 'function') {
  389 + result[key] = this[key]();
  390 + } else {
  391 + result[key] = this[key];
  392 + }
  393 + }
  394 + }
  395 + if (this.id) {
  396 + result.id = this.id;
372 397 }
373   - result.id = this.id;
374 398 return result;
375 399 };
376 400 Model.prototype.eql = function(rec) {
@@ -378,20 +402,16 @@
378 402 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 403 };
380 404 Model.prototype.save = function() {
381   - var error;
  405 + var error, record;
382 406 error = this.validate();
383 407 if (error) {
384   - this.trigger('error', this, error);
  408 + this.trigger('error', error);
385 409 return false;
386 410 }
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;
  411 + this.trigger('beforeSave');
  412 + record = this.newRecord ? this.create() : this.update();
  413 + this.trigger('save');
  414 + return record;
395 415 };
396 416 Model.prototype.updateAttribute = function(name, value) {
397 417 this[name] = value;
@@ -411,11 +431,11 @@
411 431 return this.save();
412 432 };
413 433 Model.prototype.destroy = function() {
414   - this.trigger('beforeDestroy', this);
  434 + this.trigger('beforeDestroy');
415 435 delete this.constructor.records[this.id];
416 436 this.destroyed = true;
417   - this.trigger('destroy', this);
418   - this.trigger('change', this, 'destroy');
  437 + this.trigger('destroy');
  438 + this.trigger('change', 'destroy');
419 439 this.unbind();
420 440 return this;
421 441 };
@@ -447,21 +467,32 @@
447 467 Model.prototype.toString = function() {
448 468 return "<" + this.constructor.className + " (" + (JSON.stringify(this)) + ")>";
449 469 };
  470 + Model.prototype.fromForm = function(form) {
  471 + var key, result, _i, _len, _ref;
  472 + result = {};
  473 + _ref = $(form).serializeArray();
  474 + for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  475 + key = _ref[_i];
  476 + result[key.name] = key.value;
  477 + }
  478 + return this.load(result);
  479 + };
450 480 Model.prototype.exists = function() {
451 481 return this.id && this.id in this.constructor.records;
452 482 };
453 483 Model.prototype.update = function() {
454 484 var clone, records;
455   - this.trigger('beforeUpdate', this);
  485 + this.trigger('beforeUpdate');
456 486 records = this.constructor.records;
457 487 records[this.id].load(this.attributes());
458 488 clone = records[this.id].clone();
459   - this.trigger('update', clone);
460   - return this.trigger('change', clone, 'update');
  489 + clone.trigger('update');
  490 + clone.trigger('change', 'update');
  491 + return clone;
461 492 };
462 493 Model.prototype.create = function() {
463 494 var clone, records;
464   - this.trigger('beforeCreate', this);
  495 + this.trigger('beforeCreate');
465 496 if (!this.id) {
466 497 this.id = guid();
467 498 }
@@ -469,8 +500,9 @@
469 500 records = this.constructor.records;
470 501 records[this.id] = this.dup(false);
471 502 clone = records[this.id].clone();
472   - this.trigger('create', clone);
473   - return this.trigger('change', clone, 'create');
  503 + clone.trigger('create');
  504 + clone.trigger('change', 'create');
  505 + return clone;
474 506 };
475 507 Model.prototype.bind = function(events, callback) {
476 508 var binder, unbinder;
@@ -488,11 +520,13 @@
488 520 return binder;
489 521 };
490 522 Model.prototype.trigger = function() {
491   - var _ref;
492   - return (_ref = this.constructor).trigger.apply(_ref, arguments);
  523 + var args, _ref;
  524 + args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  525 + args.splice(1, 0, this);
  526 + return (_ref = this.constructor).trigger.apply(_ref, args);
493 527 };
494 528 Model.prototype.unbind = function() {
495   - return this.trigger('unbind', this);
  529 + return this.trigger('unbind');
496 530 };
497 531 return Model;
498 532 })();
@@ -500,10 +534,10 @@
500 534 __extends(Controller, Module);
501 535 Controller.include(Events);
502 536 Controller.include(Log);
503   - Controller.prototype.eventSplitter = /^(\w+)\s*(.*)$/;
  537 + Controller.prototype.eventSplitter = /^(\S+)\s*(.*)$/;
504 538 Controller.prototype.tag = 'div';
505 539 function Controller(options) {
506   - this.destroy = __bind(this.destroy, this);
  540 + this.release = __bind(this.release, this);
507 541 var key, value, _ref;
508 542 this.options = options;
509 543 _ref = this.options;
@@ -518,7 +552,7 @@
518 552 if (this.className) {
519 553 this.el.addClass(this.className);
520 554 }
521   - this.destroy(function() {
  555 + this.release(function() {
522 556 return this.el.remove();
523 557 });
524 558 if (!this.events) {
@@ -535,11 +569,11 @@
535 569 }
536 570 Controller.__super__.constructor.apply(this, arguments);
537 571 }
538   - Controller.prototype.destroy = function(callback) {
  572 + Controller.prototype.release = function(callback) {
539 573 if (typeof callback === 'function') {
540   - return this.bind('destroy', callback);
  574 + return this.bind('release', callback);
541 575 } else {
542   - return this.trigger('destroy');
  576 + return this.trigger('release');
543 577 }
544 578 };
545 579 Controller.prototype.$ = function(selector) {
@@ -640,6 +674,16 @@
640 674 isArray = function(value) {
641 675 return Object.prototype.toString.call(value) === '[object Array]';
642 676 };
  677 + isBlank = function(value) {
  678 + var key;
  679 + if (!value) {
  680 + return true;
  681 + }
  682 + for (key in value) {
  683 + return false;
  684 + }
  685 + return true;
  686 + };
643 687 makeArray = function(args) {
644 688 return Array.prototype.slice.call(args, 0);
645 689 };
@@ -655,8 +699,9 @@
655 699 if (typeof module !== "undefined" && module !== null) {
656 700 module.exports = Spine;
657 701 }
658   - Spine.version = '2.0.1';
  702 + Spine.version = '1.0.3';
659 703 Spine.isArray = isArray;
  704 + Spine.isBlank = isBlank;
660 705 Spine.$ = $;
661 706 Spine.Events = Events;
662 707 Spine.Log = Log;
2  src/application.coffee
@@ -28,7 +28,7 @@ class Tasks extends Spine.Controller
28 28 constructor: ->
29 29 super
30 30 @item.bind("update", @render)
31   - @item.bind("destroy", @destroy)
  31 + @item.bind("destroy", @release)
32 32
33 33 render: =>
34 34 @replace($("#taskTemplate").tmpl(@item))
2  src/spine.local.coffee → src/local.coffee
... ... @@ -1,4 +1,4 @@
1   -Spine ?= require("spine")
  1 +Spine ?= require('spine')
2 2
3 3 Spine.Model.Local =
4 4 extended: ->
96 src/spine.coffee
@@ -7,6 +7,11 @@ Events =
7 7 calls[name] or= []
8 8 calls[name].push(callback)
9 9 @
  10 +
  11 + one: (ev, callback) ->
  12 + @bind ev, ->
  13 + @unbind(ev, arguments.callee)
  14 + callback.apply(@, arguments)
10 15
11 16 trigger: (args...) ->
12 17 ev = args.shift()
@@ -15,8 +20,8 @@ Events =
15 20 return false unless list
16 21
17 22 for callback in list
18   - if callback.apply(this, args) is false
19   - break
  23 + if callback.apply(@, args) is false
  24 + break
20 25 true
21 26
22 27 unbind: (ev, callback) ->
@@ -110,13 +115,16 @@ class Model extends Module
110 115
111 116 @refresh: (values, options = {}) ->
112 117 @records = {} if options.clear
113   -
114   - for record in @fromJSON(values)
  118 + records = @fromJSON(values)
  119 +
  120 + records = [records] unless isArray(records)
  121 +
  122 + for record in records
115 123 record.newRecord = false
116 124 record.id or= guid()
117 125 @records[record.id] = record
118 126
119   - @trigger('refresh')
  127 + @trigger('refresh', not options.clear and records)
120 128 @
121 129
122 130 @select: (callback) ->
@@ -193,6 +201,9 @@ class Model extends Module
193 201 (new @(value) for value in objects)
194 202 else
195 203 new @(objects)
  204 +
  205 + @fromForm: ->
  206 + (new this).fromForm(arguments...)
196 207
197 208 # Private
198 209
@@ -224,12 +235,20 @@ class Model extends Module
224 235
225 236 load: (atts) ->
226 237 for key, value of atts
227   - @[key] = value
  238 + if typeof @[key] is 'function'
  239 + @[key](value)
  240 + else
  241 + @[key] = value
  242 + @
228 243
229 244 attributes: ->
230 245 result = {}
231   - result[key] = @[key] for key in @constructor.attributes
232   - result.id = @id
  246 + for key in @constructor.attributes when key of @
  247 + if typeof @[key] is 'function'
  248 + result[key] = @[key]()
  249 + else
  250 + result[key] = @[key]
  251 + result.id = @id if @id
233 252 result
234 253
235 254 eql: (rec) ->
@@ -239,13 +258,13 @@ class Model extends Module
239 258 save: ->
240 259 error = @validate()
241 260 if error
242   - @trigger('error', @, error)
  261 + @trigger('error', error)
243 262 return false
244 263
245   - @trigger('beforeSave', @)
246   - if @newRecord then @create() else @update()
247   - @trigger('save', @)
248   - @
  264 + @trigger('beforeSave')
  265 + record = if @newRecord then @create() else @update()
  266 + @trigger('save')
  267 + record
249 268
250 269 updateAttribute: (name, value) ->
251 270 @[name] = value
@@ -264,11 +283,11 @@ class Model extends Module
264 283 @save()
265 284
266 285 destroy: ->
267   - @trigger('beforeDestroy', @)
  286 + @trigger('beforeDestroy')
268 287 delete @constructor.records[@id]
269 288 @destroyed = true
270   - @trigger('destroy', @)
271   - @trigger('change', @, 'destroy')
  289 + @trigger('destroy')
  290 + @trigger('change', 'destroy')
272 291 @unbind()
273 292 @
274 293
@@ -294,6 +313,12 @@ class Model extends Module
294 313
295 314 toString: ->
296 315 "<#{@constructor.className} (#{JSON.stringify(@)})>"
  316 +
  317 + fromForm: (form) ->
  318 + result = {}
  319 + for key in $(form).serializeArray()
  320 + result[key.name] = key.value
  321 + @load(result)
297 322
298 323 exists: ->
299 324 @id && @id of @constructor.records
@@ -301,22 +326,24 @@ class Model extends Module
301 326 # Private
302 327
303 328 update: ->
304   - @trigger('beforeUpdate', @)
  329 + @trigger('beforeUpdate')
305 330 records = @constructor.records
306 331 records[@id].load @attributes()
307 332 clone = records[@id].clone()
308   - @trigger('update', clone)
309   - @trigger('change', clone, 'update')
  333 + clone.trigger('update')
  334 + clone.trigger('change', 'update')
  335 + clone
310 336
311 337 create: ->
312   - @trigger('beforeCreate', @)
  338 + @trigger('beforeCreate')
313 339 @id = guid() unless @id
314 340 @newRecord = false
315 341 records = @constructor.records
316 342 records[@id] = @dup(false)
317 343 clone = records[@id].clone()
318   - @trigger('create', clone)
319   - @trigger('change', clone, 'create')
  344 + clone.trigger('create')
  345 + clone.trigger('change', 'create')
  346 + clone
320 347
321 348 bind: (events, callback) ->
322 349 @constructor.bind events, binder = (record) =>
@@ -328,17 +355,18 @@ class Model extends Module
328 355 @constructor.unbind('unbind', unbinder)
329 356 binder
330 357
331   - trigger: ->
332   - @constructor.trigger(arguments...)
  358 + trigger: (args...) ->
  359 + args.splice(1, 0, @)
  360 + @constructor.trigger(args...)
333 361
334 362 unbind: ->
335   - @trigger('unbind', @)
  363 + @trigger('unbind')
336 364
337 365 class Controller extends Module
338 366 @include Events
339 367 @include Log
340 368
341   - eventSplitter: /^(\w+)\s*(.*)$/
  369 + eventSplitter: /^(\S+)\s*(.*)$/
342 370 tag: 'div'
343 371
344 372 constructor: (options) ->
@@ -352,7 +380,7 @@ class Controller extends Module
352 380
353 381 @el.addClass(@className) if @className
354 382
355   - @destroy -> @el.remove()
  383 + @release -> @el.remove()
356 384
357 385 @events = @constructor.events unless @events
358 386 @elements = @constructor.elements unless @elements
@@ -362,11 +390,11 @@ class Controller extends Module
362 390
363 391 super
364 392
365   - destroy: (callback) =>
  393 + release: (callback) =>
366 394 if typeof callback is 'function'
367   - @bind 'destroy', callback
  395 + @bind 'release', callback
368 396 else
369   - @trigger 'destroy'
  397 + @trigger 'release'
370 398
371 399 $: (selector) -> $(selector, @el)
372 400
@@ -432,6 +460,11 @@ unless typeof Object.create is 'function'
432 460
433 461 isArray = (value) ->
434 462 Object::toString.call(value) is '[object Array]'
  463 +
  464 +isBlank = (value) ->
  465 + return true unless value
  466 + return false for key of value
  467 + true
435 468
436 469 makeArray = (args) ->
437 470 Array.prototype.slice.call(args, 0)
@@ -448,8 +481,9 @@ guid = ->
448 481 Spine = @Spine = {}
449 482 module?.exports = Spine
450 483
451   -Spine.version = '2.0.1'
  484 +Spine.version = '1.0.5'
452 485 Spine.isArray = isArray
  486 +Spine.isBlank = isBlank
453 487 Spine.$ = $
454 488 Spine.Events = Events
455 489 Spine.Log = Log

0 comments on commit 0ed9971

Please sign in to comment.
Something went wrong with that request. Please try again.