state = require './state-function'
State = require './state'
{ O } = state
module.exports =
StateEventEmitter
A State
defines a StateEventEmitter
for each of its event types.
For the purposes of StateEventEmitter
s, a callback is normally a function,
but may also take the form of a string, which, when the client state
emit
s the event type associated with this
emitter, will be interpreted as
an implicit command for the emitting state to change
to the target state
named by the string.
class StateEventEmitter
{ isArray } = O
guid = 0
constructor: ( @state ) ->
@items = {}
@length = 0
get: ( id ) ->
@items[ id ]
getAll
Returns an array of all callbacks bound to this emitter.
getAll: ->
value for own key, value of @items
set
Adds or replaces a callback bound to a specific key.
id
: string | numbercallback
: function | string
set: ( id, callback ) ->
{ items } = this
@length += 1 unless id of items
items[ id ] = callback
id
key
Retrieves the id
string associated with the bound callback
.
key: ( callback ) ->
return key if value is callback for own key, value of @items
keys
Returns the set of id
strings associated with all bound callbacks.
keys: ->
key for own key of @items
add
Binds a callback and optional context object.
add: ( callback, context ) ->
id = guid += 1
@items[ id ] = if context? then [ callback, context ] else callback
@length += 1
id
@::on = @::bind = @::add
remove
Unbinds a callback, identified either by its numeric key or direct reference.
id
: string | number | function
remove: ( id ) ->
{ items } = this
callback = items[ if typeof id is 'function' then @key id else id ]
return no unless callback
delete items[ id ]
@length -= 1
callback
@::off = @::unbind = @::remove
empty
Removes all callbacks, and returns the number removed.
empty: ->
return 0 unless n = @length
@items = {}
@length = 0
n
emit
Invokes all bound callbacks with the provided array of args
. Callbacks
registered with an explicit context are invoked with that stored context.
Callbacks that are state-bound functions are invoked in the context of the
provided autostate
, while unbound functions are invoked in the context of
its owner
.
emit: ( args, autostate = @state ) ->
throw TypeError unless owner = autostate?.owner
for own key, item of @items
fn = context = null
Interpret a string or State
as an order to transition to the implicated
State
after all the callbacks have been invoked.
if typeof item is 'string' or item instanceof State
eventualTarget = item
continue
if typeof item is 'function' then fn = item
else if isArray item then [ fn, context ] = item
Unbox any state-bound functions.
else if item?.type is 'state-bound-function'
{ fn } = item
context or = autostate
fn.apply context or owner, args
@state.change eventualTarget if eventualTarget
@::trigger = @::emit
destroy: ->
do @empty
@state = @items = null
true