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

@ -60,6 +60,12 @@ Ajax =
clearQueue: ->
@queue []
config:
loadMethod: 'GET'
updateMethod: 'PUT'
createMethod: 'POST'
destroyMethod: 'DELETE'
class Base
defaults:
dataType: 'json'
@ -118,7 +124,7 @@ class Collection extends Base
record = new @model(id: id)
@ajaxQueue(
params, {
type: 'GET'
type: options.method or Ajax.config.loadMethod
url: options.url or Ajax.getURL(record)
parallel: options.parallel
}
@ -128,7 +134,7 @@ class Collection extends Base
all: (params, options = {}) ->
@ajaxQueue(
params, {
type: 'GET'
type: options.method or Ajax.config.loadMethod
url: options.url or Ajax.getURL(@model)
parallel: options.parallel
}
@ -159,7 +165,7 @@ class Singleton extends Base
reload: (params, options = {}) ->
@ajaxQueue(
params, {
type: 'GET'
type: options.method or Ajax.config.loadMethod
url: options.url
parallel: options.parallel
}, @record
@ -169,7 +175,7 @@ class Singleton extends Base
create: (params, options = {}) ->
@ajaxQueue(
params, {
type: 'POST'
type: options.method or Ajax.config.createMethod
contentType: 'application/json'
data: @record.toJSON()
url: options.url or Ajax.getCollectionURL(@record)
@ -181,7 +187,7 @@ class Singleton extends Base
update: (params, options = {}) ->
@ajaxQueue(
params, {
type: 'PUT'
type: options.method or Ajax.config.updateMethod
contentType: 'application/json'
data: @record.toJSON()
url: options.url
@ -193,7 +199,7 @@ class Singleton extends Base
destroy: (params, options = {}) ->
@ajaxQueue(
params, {
type: 'DELETE'
type: options.method or Ajax.config.destroyMethod
url: options.url
parallel: options.parallel
}, @record

View file

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

View file

@ -6,13 +6,47 @@ namedParam = /:([\w\d]+)/g
splatParam = /\*([\w\d]+)/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
@historySupport: window.history?.pushState?
@routes: []
@options:
trigger: true
history: false
@ -20,16 +54,12 @@ class Spine.Route extends Spine.Module
replace: false
redirect: false
@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, callback))
@routers: []
@setup: (options = {}) ->
@options = $.extend({}, @options, options)
if (@options.history)
if @options.history
@history = @historySupport and @options.history
return if @options.shim
@ -65,11 +95,11 @@ class Spine.Route extends Spine.Module
@trigger('navigate', @path)
route = @matchRoute(@path, options) if options.trigger
routes = @matchRoutes(@path, options) if options.trigger
return if options.shim
if !route
unless routes.length
if typeof options.redirect is 'function'
return options.redirect.apply this, [@path, options]
else
@ -83,6 +113,25 @@ class Spine.Route extends Spine.Module
else
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
@getPath: ->
@ -97,58 +146,43 @@ class Spine.Route extends Spine.Module
@getHost: ->
"#{window.location.protocol}//#{window.location.host}"
@change: ->
@change: =>
path = @getPath()
return if path is @path
@path = path
@matchRoute(@path)
@matchRoutes(@path)
@matchRoute: (path, options) ->
for route in @routes when route.match(path, options)
@trigger('change', route, path)
return route
@matchRoutes: (path, options)->
matches = []
for router in @routers.concat [@router]
match = router.matchRoute path, options
matches.push match if match
@trigger('change', matches, path) if matches.length
matches
@redirect: (path) ->
window.location = path
constructor: (@path, @callback) ->
@names = []
constructor: ->
@routes = []
if typeof path is 'string'
namedParam.lastIndex = 0
while (match = namedParam.exec(path)) != null
@names.push(match[1])
matchRoute: (path, options) ->
for route in @routes when route.match(path, options)
return route
splatParam.lastIndex = 0
while (match = splatParam.exec(path)) != null
@names.push(match[1])
trigger: (args...) ->
args.splice(1, 0, this)
@constructor.trigger(args...)
path = path.replace(escapeRegExp, '\\$&')
.replace(namedParam, '([^\/]*)')
.replace(splatParam, '(.*?)')
Route.router = new Route
@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
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) ->
@route(key, value) for key, value of routes
@ -156,4 +190,6 @@ Spine.Controller.include
navigate: ->
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) ->
return if @irecords[id] then true else false
@addRecord: (record) ->
@addRecord: (record, options = {}) ->
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
@irecords[record.id] ?= record
@irecords[record.cid] ?= record
@records.push(record)
@irecords[record.id] = record
@irecords[record.cid] = record
@refresh: (values, options = {}) ->
@deleteAll() if options.clear
records = @fromJSON(values)
records = [records] unless isArray(records)
@addRecord(record) for record in records
@addRecord(record, options) for record in records
@sort()
result = @cloneArray(records)
@ -252,8 +252,13 @@ class Model extends Module
if typeof objects is 'string'
objects = JSON.parse(objects)
if isArray(objects)
(new @(value) for value in objects)
for value in objects
if value instanceof this
value
else
new @(value)
else
return objects if objects instanceof this
new @(objects)
@fromForm: ->
@ -298,7 +303,8 @@ class Model extends Module
load: (atts) ->
if atts.id then @id = atts.id
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)
else
@[key] = value
@ -354,20 +360,22 @@ class Model extends Module
@id = id
@save()
remove: ->
remove: (options = {}) ->
# Remove record from model
records = @constructor.records.slice(0)
for record, i in records when @eql(record)
records.splice(i, 1)
break
@constructor.records = records
# Remove the ID and CID
delete @constructor.irecords[@id]
delete @constructor.irecords[@cid]
if options.clear
# Remove the ID and CID indexes
delete @constructor.irecords[@id]
delete @constructor.irecords[@cid]
destroy: (options = {}) ->
options.clear ?= true
@trigger('beforeDestroy', options)
@remove()
@remove(options)
@destroyed = true
# handle events
@trigger('destroy', options)
@ -626,7 +634,7 @@ makeArray = (args) ->
Spine = @Spine = {}
module?.exports = Spine
Spine.version = '1.3.0'
Spine.version = '1.3.1'
Spine.isArray = isArray
Spine.isBlank = isBlank
Spine.$ = $