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 StateEventEmitters, a callback is normally a function,
but may also take the form of a string, which, when the client state
emits 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 @itemsset
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
idkey
Retrieves the id string associated with the bound callback.
key: ( callback ) ->
return key if value is callback for own key, value of @itemskeys
Returns the set of id strings associated with all bound callbacks.
keys: ->
key for own key of @itemsadd
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 = @::addremove
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 = @::removeempty
Removes all callbacks, and returns the number removed.
empty: ->
return 0 unless n = @length
@items = {}
@length = 0
nemit
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 = nullInterpret 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 ] = itemUnbox 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