Updated to spine 1.3.1.

This commit is contained in:
Martin Edenhofer 2014-04-06 13:30:47 +02:00
parent c1c8d89fd3
commit f7cfc1a943
4 changed files with 144 additions and 85 deletions

View file

@ -9,13 +9,13 @@ Ajax =
@generateURL(object) @generateURL(object)
else else
@generateURL(object, encodeURIComponent(object.id)) @generateURL(object, encodeURIComponent(object.id))
getCollectionURL: (object) -> getCollectionURL: (object) ->
@generateURL(object) @generateURL(object)
getScope: (object) -> getScope: (object) ->
object.scope?() or object.scope object.scope?() or object.scope
getCollection: (object) -> getCollection: (object) ->
if object.url isnt object.generateURL if object.url isnt object.generateURL
if typeof object.url is 'function' if typeof object.url is 'function'
@ -60,6 +60,12 @@ Ajax =
clearQueue: -> clearQueue: ->
@queue [] @queue []
config:
loadMethod: 'GET'
updateMethod: 'PUT'
createMethod: 'POST'
destroyMethod: 'DELETE'
class Base class Base
defaults: defaults:
dataType: 'json' dataType: 'json'
@ -104,7 +110,7 @@ class Base
[promise, statusText, ''] [promise, statusText, '']
) )
promise promise
@queue request @queue request
promise promise
@ -118,7 +124,7 @@ class Collection extends Base
record = new @model(id: id) record = new @model(id: id)
@ajaxQueue( @ajaxQueue(
params, { params, {
type: 'GET' type: options.method or Ajax.config.loadMethod
url: options.url or Ajax.getURL(record) url: options.url or Ajax.getURL(record)
parallel: options.parallel parallel: options.parallel
} }
@ -128,7 +134,7 @@ class Collection extends Base
all: (params, options = {}) -> all: (params, options = {}) ->
@ajaxQueue( @ajaxQueue(
params, { params, {
type: 'GET' type: options.method or Ajax.config.loadMethod
url: options.url or Ajax.getURL(@model) url: options.url or Ajax.getURL(@model)
parallel: options.parallel parallel: options.parallel
} }
@ -159,7 +165,7 @@ class Singleton extends Base
reload: (params, options = {}) -> reload: (params, options = {}) ->
@ajaxQueue( @ajaxQueue(
params, { params, {
type: 'GET' type: options.method or Ajax.config.loadMethod
url: options.url url: options.url
parallel: options.parallel parallel: options.parallel
}, @record }, @record
@ -169,7 +175,7 @@ class Singleton extends Base
create: (params, options = {}) -> create: (params, options = {}) ->
@ajaxQueue( @ajaxQueue(
params, { params, {
type: 'POST' type: options.method or Ajax.config.createMethod
contentType: 'application/json' contentType: 'application/json'
data: @record.toJSON() data: @record.toJSON()
url: options.url or Ajax.getCollectionURL(@record) url: options.url or Ajax.getCollectionURL(@record)
@ -181,7 +187,7 @@ class Singleton extends Base
update: (params, options = {}) -> update: (params, options = {}) ->
@ajaxQueue( @ajaxQueue(
params, { params, {
type: 'PUT' type: options.method or Ajax.config.updateMethod
contentType: 'application/json' contentType: 'application/json'
data: @record.toJSON() data: @record.toJSON()
url: options.url url: options.url
@ -193,7 +199,7 @@ class Singleton extends Base
destroy: (params, options = {}) -> destroy: (params, options = {}) ->
@ajaxQueue( @ajaxQueue(
params, { params, {
type: 'DELETE' type: options.method or Ajax.config.destroyMethod
url: options.url url: options.url
parallel: options.parallel parallel: options.parallel
}, @record }, @record
@ -233,16 +239,16 @@ GenerateURL =
Include = Include =
ajax: -> new Singleton(this) ajax: -> new Singleton(this)
generateURL: GenerateURL.include generateURL: GenerateURL.include
url: GenerateURL.include url: GenerateURL.include
Extend = Extend =
ajax: -> new Collection(this) ajax: -> new Collection(this)
generateURL: GenerateURL.extend generateURL: GenerateURL.extend
url: GenerateURL.extend url: GenerateURL.extend
Model.Ajax = Model.Ajax =

View file

@ -1,5 +1,6 @@
Spine = @Spine or require('spine') Spine = @Spine or require('spine')
$ = Spine.$ $ = Spine.$
class Spine.Manager extends Spine.Module class Spine.Manager extends Spine.Module
@include Spine.Events @include Spine.Events
@ -31,6 +32,7 @@ class Spine.Manager extends Spine.Module
current.activate(args...) if current current.activate(args...) if current
Spine.Controller.include Spine.Controller.include
active: (args...) -> active: (args...) ->
if typeof args[0] is 'function' if typeof args[0] is 'function'
@ -45,11 +47,12 @@ Spine.Controller.include
activate: -> activate: ->
@el.addClass('active') @el.addClass('active')
@ this
deactivate: -> deactivate: ->
@el.removeClass('active') @el.removeClass('active')
@ this
class Spine.Stack extends Spine.Controller class Spine.Stack extends Spine.Controller
controllers: {} controllers: {}
@ -61,10 +64,11 @@ class Spine.Stack extends Spine.Controller
super super
@manager = new Spine.Manager @manager = new Spine.Manager
@router = Spine.Route?.create()
for key, value of @controllers for key, value of @controllers
throw Error "'@#{ key }' already assigned - choose a different name" if @[key]? throw Error "'@#{ key }' already assigned" if @[key]?
@[key] = new value(stack: @) @[key] = new value(stack: this)
@add(@[key]) @add(@[key])
for key, value of @routes for key, value of @routes
@ -79,5 +83,10 @@ class Spine.Stack extends Spine.Controller
@manager.add(controller) @manager.add(controller)
@append(controller) @append(controller)
module?.exports = Spine.Manager release: =>
@router?.destroy()
super
module?.exports = Spine.Manager
module?.exports.Stack = Spine.Stack module?.exports.Stack = Spine.Stack

View file

@ -6,13 +6,47 @@ namedParam = /:([\w\d]+)/g
splatParam = /\*([\w\d]+)/g splatParam = /\*([\w\d]+)/g
escapeRegExp = /[-[\]{}()+?.,\\^$|#\s]/g escapeRegExp = /[-[\]{}()+?.,\\^$|#\s]/g
class Spine.Route extends Spine.Module
class Path extends Spine.Module
constructor: (@path, @callback) ->
@names = []
if typeof path is 'string'
namedParam.lastIndex = 0
while (match = namedParam.exec(path)) != null
@names.push(match[1])
splatParam.lastIndex = 0
while (match = splatParam.exec(path)) != null
@names.push(match[1])
path = path.replace(escapeRegExp, '\\$&')
.replace(namedParam, '([^\/]*)')
.replace(splatParam, '(.*?)')
@route = new RegExp("^#{path}$")
else
@route = path
match: (path, options = {}) ->
return false unless match = @route.exec(path)
options.match = match
params = match.slice(1)
if @names.length
for param, i in params
options[@names[i]] = param
Route.trigger('before', this)
@callback.call(null, options) isnt false
class Route extends Spine.Module
@extend Spine.Events @extend Spine.Events
@historySupport: window.history?.pushState? @historySupport: window.history?.pushState?
@routes: []
@options: @options:
trigger: true trigger: true
history: false history: false
@ -20,16 +54,12 @@ class Spine.Route extends Spine.Module
replace: false replace: false
redirect: false redirect: false
@add: (path, callback) -> @routers: []
if (typeof path is 'object' and path not instanceof RegExp)
@add(key, value) for key, value of path
else
@routes.push(new @(path, callback))
@setup: (options = {}) -> @setup: (options = {}) ->
@options = $.extend({}, @options, options) @options = $.extend({}, @options, options)
if (@options.history) if @options.history
@history = @historySupport and @options.history @history = @historySupport and @options.history
return if @options.shim return if @options.shim
@ -65,11 +95,11 @@ class Spine.Route extends Spine.Module
@trigger('navigate', @path) @trigger('navigate', @path)
route = @matchRoute(@path, options) if options.trigger routes = @matchRoutes(@path, options) if options.trigger
return if options.shim return if options.shim
if !route unless routes.length
if typeof options.redirect is 'function' if typeof options.redirect is 'function'
return options.redirect.apply this, [@path, options] return options.redirect.apply this, [@path, options]
else else
@ -83,6 +113,25 @@ class Spine.Route extends Spine.Module
else else
window.location.hash = @path window.location.hash = @path
@create: ->
router = new this
@routers.push router
router
@add: (path, callback) ->
#@router ?= new this
@router.add path, callback
add: (path, callback) ->
if typeof path is 'object' and path not instanceof RegExp
@add(key, value) for key, value of path
else
@routes.push(new Path(path, callback))
destroy: ->
@routes.length = 0
@constructor.routers = (r for r in @constructor.routers when r isnt this)
# Private # Private
@getPath: -> @getPath: ->
@ -97,58 +146,43 @@ class Spine.Route extends Spine.Module
@getHost: -> @getHost: ->
"#{window.location.protocol}//#{window.location.host}" "#{window.location.protocol}//#{window.location.host}"
@change: -> @change: =>
path = @getPath() path = @getPath()
return if path is @path return if path is @path
@path = path @path = path
@matchRoute(@path) @matchRoutes(@path)
@matchRoute: (path, options) -> @matchRoutes: (path, options)->
for route in @routes when route.match(path, options) matches = []
@trigger('change', route, path) for router in @routers.concat [@router]
return route match = router.matchRoute path, options
matches.push match if match
@trigger('change', matches, path) if matches.length
matches
@redirect: (path) -> @redirect: (path) ->
window.location = path window.location = path
constructor: (@path, @callback) -> constructor: ->
@names = [] @routes = []
if typeof path is 'string' matchRoute: (path, options) ->
namedParam.lastIndex = 0 for route in @routes when route.match(path, options)
while (match = namedParam.exec(path)) != null return route
@names.push(match[1])
splatParam.lastIndex = 0 trigger: (args...) ->
while (match = splatParam.exec(path)) != null args.splice(1, 0, this)
@names.push(match[1]) @constructor.trigger(args...)
path = path.replace(escapeRegExp, '\\$&') Route.router = new Route
.replace(namedParam, '([^\/]*)')
.replace(splatParam, '(.*?)')
@route = new RegExp("^#{path}$")
else
@route = path
match: (path, options = {}) ->
match = @route.exec(path)
return false unless match
options.match = match
params = match.slice(1)
if @names.length
for param, i in params
options[@names[i]] = param
@.constructor.trigger('before', @)
@callback.call(null, options) isnt false
# Coffee-script bug
Spine.Route.change = Spine.Route.proxy(Spine.Route.change)
Spine.Controller.include Spine.Controller.include
route: (path, callback) -> route: (path, callback) ->
Spine.Route.add(path, @proxy(callback)) if @router instanceof Spine.Route
@router.add(path, @proxy(callback))
else
Spine.Route.add(path, @proxy(callback))
routes: (routes) -> routes: (routes) ->
@route(key, value) for key, value of routes @route(key, value) for key, value of routes
@ -156,4 +190,6 @@ Spine.Controller.include
navigate: -> navigate: ->
Spine.Route.navigate.apply(Spine.Route, arguments) Spine.Route.navigate.apply(Spine.Route, arguments)
module?.exports = Spine.Route Route.Path = Path
Spine.Route = Route
module?.exports = Route

View file

@ -157,21 +157,21 @@ class Model extends Module
@exists: (id) -> @exists: (id) ->
return if @irecords[id] then true else false return if @irecords[id] then true else false
@addRecord: (record) -> @addRecord: (record, options = {}) ->
if record.id and @irecords[record.id] if record.id and @irecords[record.id]
@irecords[record.id].remove() @irecords[record.id].remove(options)
record = @irecords[record.id].load(record) unless options.clear
record.id or= record.cid record.id or= record.cid
@irecords[record.id] ?= record
@irecords[record.cid] ?= record
@records.push(record) @records.push(record)
@irecords[record.id] = record
@irecords[record.cid] = record
@refresh: (values, options = {}) -> @refresh: (values, options = {}) ->
@deleteAll() if options.clear @deleteAll() if options.clear
records = @fromJSON(values) records = @fromJSON(values)
records = [records] unless isArray(records) records = [records] unless isArray(records)
@addRecord(record) for record in records @addRecord(record, options) for record in records
@sort() @sort()
result = @cloneArray(records) result = @cloneArray(records)
@ -252,8 +252,13 @@ class Model extends Module
if typeof objects is 'string' if typeof objects is 'string'
objects = JSON.parse(objects) objects = JSON.parse(objects)
if isArray(objects) if isArray(objects)
(new @(value) for value in objects) for value in objects
if value instanceof this
value
else
new @(value)
else else
return objects if objects instanceof this
new @(objects) new @(objects)
@fromForm: -> @fromForm: ->
@ -298,7 +303,8 @@ class Model extends Module
load: (atts) -> load: (atts) ->
if atts.id then @id = atts.id if atts.id then @id = atts.id
for key, value of atts for key, value of atts
if atts.hasOwnProperty(key) and typeof @[key] is 'function' if typeof @[key] is 'function'
continue if typeof value is 'function'
@[key](value) @[key](value)
else else
@[key] = value @[key] = value
@ -354,20 +360,22 @@ class Model extends Module
@id = id @id = id
@save() @save()
remove: -> remove: (options = {}) ->
# Remove record from model # Remove record from model
records = @constructor.records.slice(0) records = @constructor.records.slice(0)
for record, i in records when @eql(record) for record, i in records when @eql(record)
records.splice(i, 1) records.splice(i, 1)
break break
@constructor.records = records @constructor.records = records
# Remove the ID and CID if options.clear
delete @constructor.irecords[@id] # Remove the ID and CID indexes
delete @constructor.irecords[@cid] delete @constructor.irecords[@id]
delete @constructor.irecords[@cid]
destroy: (options = {}) -> destroy: (options = {}) ->
options.clear ?= true
@trigger('beforeDestroy', options) @trigger('beforeDestroy', options)
@remove() @remove(options)
@destroyed = true @destroyed = true
# handle events # handle events
@trigger('destroy', options) @trigger('destroy', options)
@ -626,7 +634,7 @@ makeArray = (args) ->
Spine = @Spine = {} Spine = @Spine = {}
module?.exports = Spine module?.exports = Spine
Spine.version = '1.3.0' Spine.version = '1.3.1'
Spine.isArray = isArray Spine.isArray = isArray
Spine.isBlank = isBlank Spine.isBlank = isBlank
Spine.$ = $ Spine.$ = $