Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Spine Update #4

Merged
merged 1 commit into from

2 participants

@jaitaiwan

This pull request is to update the example to use the latest spine. It removes the use of the "destroy" method and adds the use of the "release" method.

@maccman maccman merged commit c08dd5f into maccman:master
@maccman
Owner

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
2  index.html
@@ -10,7 +10,7 @@
<script src="lib/jquery.tmpl.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/spine.js" type="text/javascript" charset="utf-8"></script>
- <script src="lib/spine.local.js" type="text/javascript" charset="utf-8"></script>
+ <script src="lib/local.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/application.js" type="text/javascript" charset="utf-8"></script>
<script type="text/x-jquery-tmpl" id="taskTemplate">
View
55 lib/application.js
@@ -1,31 +1,33 @@
(function() {
var $, Task, TaskApp, Tasks;
- 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); }; };
+ 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); }; };
+
$ = jQuery;
+
Task = (function() {
+
__extends(Task, Spine.Model);
+
function Task() {
Task.__super__.constructor.apply(this, arguments);
}
+
Task.configure("Task", "name", "done");
+
Task.extend(Spine.Model.Local);
+
Task.active = function() {
return this.select(function(item) {
return !item.done;
});
};
+
Task.done = function() {
return this.select(function(item) {
return !!item.done;
});
};
+
Task.destroyDone = function() {
var rec, _i, _len, _ref, _results;
_ref = this.done();
@@ -36,10 +38,15 @@
}
return _results;
};
+
return Task;
+
})();
+
Tasks = (function() {
+
__extends(Tasks, Spine.Controller);
+
Tasks.prototype.events = {
"change input[type=checkbox]": "toggle",
"click .destroy": "remove",
@@ -47,56 +54,67 @@
"keypress input[type=text]": "blurOnEnter",
"blur input[type=text]": "close"
};
+
Tasks.prototype.elements = {
"input[type=text]": "input"
};
+
function Tasks() {
this.render = __bind(this.render, this); Tasks.__super__.constructor.apply(this, arguments);
this.item.bind("update", this.render);
- this.item.bind("destroy", __bind(function() {
- return this.trigger('destroy');
- }, this));
+ this.item.bind("destroy", this.release);
}
+
Tasks.prototype.render = function() {
this.replace($("#taskTemplate").tmpl(this.item));
return this;
};
+
Tasks.prototype.toggle = function() {
this.item.done = !this.item.done;
return this.item.save();
};
+
Tasks.prototype.remove = function() {
return this.item.destroy();
};
+
Tasks.prototype.edit = function() {
this.el.addClass("editing");
return this.input.focus();
};
+
Tasks.prototype.blurOnEnter = function(e) {
- if (e.keyCode === 13) {
- return e.target.blur();
- }
+ if (e.keyCode === 13) return e.target.blur();
};
+
Tasks.prototype.close = function() {
this.el.removeClass("editing");
return this.item.updateAttributes({
name: this.input.val()
});
};
+
return Tasks;
+
})();
+
TaskApp = (function() {
+
__extends(TaskApp, Spine.Controller);
+
TaskApp.prototype.events = {
"submit form": "create",
"click .clear": "clear"
};
+
TaskApp.prototype.elements = {
".items": "items",
".countVal": "count",
".clear": "clear",
"form input": "input"
};
+
function TaskApp() {
this.renderCount = __bind(this.renderCount, this);
this.addAll = __bind(this.addAll, this);
@@ -106,6 +124,7 @@
Task.bind("refresh change", this.renderCount);
Task.fetch();
}
+
TaskApp.prototype.addOne = function(task) {
var view;
view = new Tasks({
@@ -113,9 +132,11 @@
});
return this.items.append(view.render().el);
};
+
TaskApp.prototype.addAll = function() {
return Task.each(this.addOne);
};
+
TaskApp.prototype.create = function(e) {
e.preventDefault();
Task.create({
@@ -123,9 +144,11 @@
});
return this.input.val("");
};
+
TaskApp.prototype.clear = function() {
return Task.destroyDone();
};
+
TaskApp.prototype.renderCount = function() {
var active, inactive;
active = Task.active().length;
@@ -137,11 +160,15 @@
return this.clear.hide();
}
};
+
return TaskApp;
+
})();
+
$(function() {
return new TaskApp({
el: $("#tasks")
});
});
+
}).call(this);
View
2  lib/spine.local.js → lib/local.js
@@ -1,6 +1,6 @@
(function() {
if (typeof Spine === "undefined" || Spine === null) {
- Spine = require("spine");
+ Spine = require('spine');
}
Spine.Model.Local = {
extended: function() {
View
127 lib/spine.js
@@ -1,5 +1,5 @@
(function() {
- var $, Controller, Events, Log, Model, Module, Spine, guid, isArray, makeArray, moduleKeywords;
+ var $, Controller, Events, Log, Model, Module, Spine, guid, isArray, isBlank, makeArray, moduleKeywords;
var __slice = Array.prototype.slice, __indexOf = Array.prototype.indexOf || function(item) {
for (var i = 0, l = this.length; i < l; i++) {
if (this[i] === item) return i;
@@ -25,6 +25,12 @@
}
return this;
},
+ one: function(ev, callback) {
+ return this.bind(ev, function() {
+ this.unbind(ev, arguments.callee);
+ return callback.apply(this, arguments);
+ });
+ },
trigger: function() {
var args, callback, ev, list, _i, _len, _ref;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
@@ -176,21 +182,24 @@
}
};
Model.refresh = function(values, options) {
- var record, _i, _len, _ref;
+ var record, records, _i, _len;
if (options == null) {
options = {};
}
if (options.clear) {
this.records = {};
}
- _ref = this.fromJSON(values);
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- record = _ref[_i];
+ records = this.fromJSON(values);
+ if (!isArray(records)) {
+ records = [records];
+ }
+ for (_i = 0, _len = records.length; _i < _len; _i++) {
+ record = records[_i];
record.newRecord = false;
record.id || (record.id = guid());
this.records[record.id] = record;
}
- this.trigger('refresh');
+ this.trigger('refresh', !options.clear && records);
return this;
};
Model.select = function(callback) {
@@ -319,6 +328,10 @@
return new this(objects);
}
};
+ Model.fromForm = function() {
+ var _ref;
+ return (_ref = new this).fromForm.apply(_ref, arguments);
+ };
Model.recordsValues = function() {
var key, result, value, _ref;
result = [];
@@ -354,13 +367,16 @@
};
Model.prototype.validate = function() {};
Model.prototype.load = function(atts) {
- var key, value, _results;
- _results = [];
+ var key, value;
for (key in atts) {
value = atts[key];
- _results.push(this[key] = value);
+ if (typeof this[key] === 'function') {
+ this[key](value);
+ } else {
+ this[key] = value;
+ }
}
- return _results;
+ return this;
};
Model.prototype.attributes = function() {
var key, result, _i, _len, _ref;
@@ -368,9 +384,17 @@
_ref = this.constructor.attributes;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
key = _ref[_i];
- result[key] = this[key];
+ if (key in this) {
+ if (typeof this[key] === 'function') {
+ result[key] = this[key]();
+ } else {
+ result[key] = this[key];
+ }
+ }
+ }
+ if (this.id) {
+ result.id = this.id;
}
- result.id = this.id;
return result;
};
Model.prototype.eql = function(rec) {
@@ -378,20 +402,16 @@
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));
};
Model.prototype.save = function() {
- var error;
+ var error, record;
error = this.validate();
if (error) {
- this.trigger('error', this, error);
+ this.trigger('error', error);
return false;
}
- this.trigger('beforeSave', this);
- if (this.newRecord) {
- this.create();
- } else {
- this.update();
- }
- this.trigger('save', this);
- return this;
+ this.trigger('beforeSave');
+ record = this.newRecord ? this.create() : this.update();
+ this.trigger('save');
+ return record;
};
Model.prototype.updateAttribute = function(name, value) {
this[name] = value;
@@ -411,11 +431,11 @@
return this.save();
};
Model.prototype.destroy = function() {
- this.trigger('beforeDestroy', this);
+ this.trigger('beforeDestroy');
delete this.constructor.records[this.id];
this.destroyed = true;
- this.trigger('destroy', this);
- this.trigger('change', this, 'destroy');
+ this.trigger('destroy');
+ this.trigger('change', 'destroy');
this.unbind();
return this;
};
@@ -447,21 +467,32 @@
Model.prototype.toString = function() {
return "<" + this.constructor.className + " (" + (JSON.stringify(this)) + ")>";
};
+ Model.prototype.fromForm = function(form) {
+ var key, result, _i, _len, _ref;
+ result = {};
+ _ref = $(form).serializeArray();
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ key = _ref[_i];
+ result[key.name] = key.value;
+ }
+ return this.load(result);
+ };
Model.prototype.exists = function() {
return this.id && this.id in this.constructor.records;
};
Model.prototype.update = function() {
var clone, records;
- this.trigger('beforeUpdate', this);
+ this.trigger('beforeUpdate');
records = this.constructor.records;
records[this.id].load(this.attributes());
clone = records[this.id].clone();
- this.trigger('update', clone);
- return this.trigger('change', clone, 'update');
+ clone.trigger('update');
+ clone.trigger('change', 'update');
+ return clone;
};
Model.prototype.create = function() {
var clone, records;
- this.trigger('beforeCreate', this);
+ this.trigger('beforeCreate');
if (!this.id) {
this.id = guid();
}
@@ -469,8 +500,9 @@
records = this.constructor.records;
records[this.id] = this.dup(false);
clone = records[this.id].clone();
- this.trigger('create', clone);
- return this.trigger('change', clone, 'create');
+ clone.trigger('create');
+ clone.trigger('change', 'create');
+ return clone;
};
Model.prototype.bind = function(events, callback) {
var binder, unbinder;
@@ -488,11 +520,13 @@
return binder;
};
Model.prototype.trigger = function() {
- var _ref;
- return (_ref = this.constructor).trigger.apply(_ref, arguments);
+ var args, _ref;
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ args.splice(1, 0, this);
+ return (_ref = this.constructor).trigger.apply(_ref, args);
};
Model.prototype.unbind = function() {
- return this.trigger('unbind', this);
+ return this.trigger('unbind');
};
return Model;
})();
@@ -500,10 +534,10 @@
__extends(Controller, Module);
Controller.include(Events);
Controller.include(Log);
- Controller.prototype.eventSplitter = /^(\w+)\s*(.*)$/;
+ Controller.prototype.eventSplitter = /^(\S+)\s*(.*)$/;
Controller.prototype.tag = 'div';
function Controller(options) {
- this.destroy = __bind(this.destroy, this);
+ this.release = __bind(this.release, this);
var key, value, _ref;
this.options = options;
_ref = this.options;
@@ -518,7 +552,7 @@
if (this.className) {
this.el.addClass(this.className);
}
- this.destroy(function() {
+ this.release(function() {
return this.el.remove();
});
if (!this.events) {
@@ -535,11 +569,11 @@
}
Controller.__super__.constructor.apply(this, arguments);
}
- Controller.prototype.destroy = function(callback) {
+ Controller.prototype.release = function(callback) {
if (typeof callback === 'function') {
- return this.bind('destroy', callback);
+ return this.bind('release', callback);
} else {
- return this.trigger('destroy');
+ return this.trigger('release');
}
};
Controller.prototype.$ = function(selector) {
@@ -640,6 +674,16 @@
isArray = function(value) {
return Object.prototype.toString.call(value) === '[object Array]';
};
+ isBlank = function(value) {
+ var key;
+ if (!value) {
+ return true;
+ }
+ for (key in value) {
+ return false;
+ }
+ return true;
+ };
makeArray = function(args) {
return Array.prototype.slice.call(args, 0);
};
@@ -655,8 +699,9 @@
if (typeof module !== "undefined" && module !== null) {
module.exports = Spine;
}
- Spine.version = '2.0.1';
+ Spine.version = '1.0.3';
Spine.isArray = isArray;
+ Spine.isBlank = isBlank;
Spine.$ = $;
Spine.Events = Events;
Spine.Log = Log;
View
2  src/application.coffee
@@ -28,7 +28,7 @@ class Tasks extends Spine.Controller
constructor: ->
super
@item.bind("update", @render)
- @item.bind("destroy", @destroy)
+ @item.bind("destroy", @release)
render: =>
@replace($("#taskTemplate").tmpl(@item))
View
2  src/spine.local.coffee → src/local.coffee
@@ -1,4 +1,4 @@
-Spine ?= require("spine")
+Spine ?= require('spine')
Spine.Model.Local =
extended: ->
View
96 src/spine.coffee
@@ -7,6 +7,11 @@ Events =
calls[name] or= []
calls[name].push(callback)
@
+
+ one: (ev, callback) ->
+ @bind ev, ->
+ @unbind(ev, arguments.callee)
+ callback.apply(@, arguments)
trigger: (args...) ->
ev = args.shift()
@@ -15,8 +20,8 @@ Events =
return false unless list
for callback in list
- if callback.apply(this, args) is false
- break
+ if callback.apply(@, args) is false
+ break
true
unbind: (ev, callback) ->
@@ -110,13 +115,16 @@ class Model extends Module
@refresh: (values, options = {}) ->
@records = {} if options.clear
-
- for record in @fromJSON(values)
+ records = @fromJSON(values)
+
+ records = [records] unless isArray(records)
+
+ for record in records
record.newRecord = false
record.id or= guid()
@records[record.id] = record
- @trigger('refresh')
+ @trigger('refresh', not options.clear and records)
@
@select: (callback) ->
@@ -193,6 +201,9 @@ class Model extends Module
(new @(value) for value in objects)
else
new @(objects)
+
+ @fromForm: ->
+ (new this).fromForm(arguments...)
# Private
@@ -224,12 +235,20 @@ class Model extends Module
load: (atts) ->
for key, value of atts
- @[key] = value
+ if typeof @[key] is 'function'
+ @[key](value)
+ else
+ @[key] = value
+ @
attributes: ->
result = {}
- result[key] = @[key] for key in @constructor.attributes
- result.id = @id
+ for key in @constructor.attributes when key of @
+ if typeof @[key] is 'function'
+ result[key] = @[key]()
+ else
+ result[key] = @[key]
+ result.id = @id if @id
result
eql: (rec) ->
@@ -239,13 +258,13 @@ class Model extends Module
save: ->
error = @validate()
if error
- @trigger('error', @, error)
+ @trigger('error', error)
return false
- @trigger('beforeSave', @)
- if @newRecord then @create() else @update()
- @trigger('save', @)
- @
+ @trigger('beforeSave')
+ record = if @newRecord then @create() else @update()
+ @trigger('save')
+ record
updateAttribute: (name, value) ->
@[name] = value
@@ -264,11 +283,11 @@ class Model extends Module
@save()
destroy: ->
- @trigger('beforeDestroy', @)
+ @trigger('beforeDestroy')
delete @constructor.records[@id]
@destroyed = true
- @trigger('destroy', @)
- @trigger('change', @, 'destroy')
+ @trigger('destroy')
+ @trigger('change', 'destroy')
@unbind()
@
@@ -294,6 +313,12 @@ class Model extends Module
toString: ->
"<#{@constructor.className} (#{JSON.stringify(@)})>"
+
+ fromForm: (form) ->
+ result = {}
+ for key in $(form).serializeArray()
+ result[key.name] = key.value
+ @load(result)
exists: ->
@id && @id of @constructor.records
@@ -301,22 +326,24 @@ class Model extends Module
# Private
update: ->
- @trigger('beforeUpdate', @)
+ @trigger('beforeUpdate')
records = @constructor.records
records[@id].load @attributes()
clone = records[@id].clone()
- @trigger('update', clone)
- @trigger('change', clone, 'update')
+ clone.trigger('update')
+ clone.trigger('change', 'update')
+ clone
create: ->
- @trigger('beforeCreate', @)
+ @trigger('beforeCreate')
@id = guid() unless @id
@newRecord = false
records = @constructor.records
records[@id] = @dup(false)
clone = records[@id].clone()
- @trigger('create', clone)
- @trigger('change', clone, 'create')
+ clone.trigger('create')
+ clone.trigger('change', 'create')
+ clone
bind: (events, callback) ->
@constructor.bind events, binder = (record) =>
@@ -328,17 +355,18 @@ class Model extends Module
@constructor.unbind('unbind', unbinder)
binder
- trigger: ->
- @constructor.trigger(arguments...)
+ trigger: (args...) ->
+ args.splice(1, 0, @)
+ @constructor.trigger(args...)
unbind: ->
- @trigger('unbind', @)
+ @trigger('unbind')
class Controller extends Module
@include Events
@include Log
- eventSplitter: /^(\w+)\s*(.*)$/
+ eventSplitter: /^(\S+)\s*(.*)$/
tag: 'div'
constructor: (options) ->
@@ -352,7 +380,7 @@ class Controller extends Module
@el.addClass(@className) if @className
- @destroy -> @el.remove()
+ @release -> @el.remove()
@events = @constructor.events unless @events
@elements = @constructor.elements unless @elements
@@ -362,11 +390,11 @@ class Controller extends Module
super
- destroy: (callback) =>
+ release: (callback) =>
if typeof callback is 'function'
- @bind 'destroy', callback
+ @bind 'release', callback
else
- @trigger 'destroy'
+ @trigger 'release'
$: (selector) -> $(selector, @el)
@@ -432,6 +460,11 @@ unless typeof Object.create is 'function'
isArray = (value) ->
Object::toString.call(value) is '[object Array]'
+
+isBlank = (value) ->
+ return true unless value
+ return false for key of value
+ true
makeArray = (args) ->
Array.prototype.slice.call(args, 0)
@@ -448,8 +481,9 @@ guid = ->
Spine = @Spine = {}
module?.exports = Spine
-Spine.version = '2.0.1'
+Spine.version = '1.0.5'
Spine.isArray = isArray
+Spine.isBlank = isBlank
Spine.$ = $
Spine.Events = Events
Spine.Log = Log
Something went wrong with that request. Please try again.