Example #1
0
stately.define = function (callback) {
  var machine = new EventEmitter ()
    , privateState = null
    , validTransition = function (from, to) {
      var allowedTransitions = machine.transitions [from]
      if (from === to) return true
      else if (typeof allowedTransitions === 'undefined')
        machine.emit('error', new Error ("attempting to transition from unknown state: " + from))
      else if (typeof allowedTransitions === 'string') return to === allowedTransitions
      else return allowedTransitions.indexOf (to) !== -1
    }

  machine.transition = function (desiredState) {
    var stateBefore = privateState
    if (validTransition (privateState, desiredState)) {
      machine.emit ('beforeTransition', privateState, desiredState)
      machine.emit ('beforeTransition:' + privateState + ":" + desiredState)
      machine.emit ('beforeExit:' + privateState)
      machine.emit ('beforeEnter:' + desiredState)
      privateState = desiredState
      machine.emit ('afterExit:' + stateBefore)
      machine.emit ('afterEnter:' + desiredState)
      machine.emit ('afterTransition:' + stateBefore + ":" + desiredState)
      machine.emit ('afterTransition', stateBefore, desiredState)
      return true
    } else {
      machine.emit ('illegalTransition', privateState, desiredState)
      machine.emit ('illegalTransition:' + privateState + ':' + desiredState)
      return false
    }
  }
  
  'illegalTransition beforeTransition afterTransition'.split(" ").forEach (function (evt) {
    machine [evt] = function () {
      if (arguments.length === 1) machine.addListener (evt, arguments [0])
      else machine.addListener (evt + ":" + arguments [0] + ":" + arguments [1], arguments [2])
    }
  })

  'beforeExit beforeEnter afterExit afterEnter'.split(" ").forEach (function (evt) {
    machine [evt] = function (state, fn) { machine.addListener (evt + ":" + state, fn) }
  })
  
  machine.start = function () {
    privateState = machine.startState
    return true
  }

  machine.__defineSetter__ ("state", function (desiredState) { machine.transition (desiredState) })
  machine.__defineGetter__ ("state", function () { return privateState })

  callback (machine)
  
  return machine
}