Comparing version 1.3.0 to 2.0.0
{ | ||
"name": "Stately.js", | ||
"main": "Stately.js", | ||
"version": "1.3.0", | ||
"version": "2.0.0", | ||
"homepage": "https://github.com/fschaefer/Stately.js", | ||
@@ -6,0 +6,0 @@ "authors": [ |
@@ -29,3 +29,3 @@ { | ||
"main": "Stately.js", | ||
"version": "1.3.0", | ||
"version": "2.0.0", | ||
"directories": { | ||
@@ -32,0 +32,0 @@ "test": "tests" |
102
README.md
@@ -65,4 +65,3 @@ ![Stately.js Logo](https://github.com/fschaefer/Stately.js/raw/master/misc/Stately.js.png) | ||
the current name of the machines state, `getMachineEvents()`, returning possible | ||
events in the current state, and `bind()` and `unbind()` methods, to register | ||
callbacks to receive `notifications` when the machine transitions into another state. | ||
events in the current state. | ||
@@ -197,4 +196,3 @@ The `statesObject` is an object with `stateObject` objects attached as | ||
Because `this` refers to the `stateStore`, it is also possible to call an | ||
action from another state (note: this won't trigger the `notification` | ||
callbacks): | ||
action from another state (note: this won't trigger the `notification`s): | ||
@@ -220,12 +218,14 @@ ```js | ||
### Notifications | ||
### Special event hook functions | ||
Once in a while, it is useful to get a `notification` when the machine | ||
transitions into another state. Therefore the `stateMachine` object has | ||
`bind(callback)` and `unbind(callback)` to register and unregister notification | ||
handlers that get called when the state changes. A notification callback has | ||
the following form: | ||
transitions into another state. Therefore there are some special event names | ||
reserved for event functions, namely `onEnter`, `onLeave` (triggered | ||
when entering / leaving a state), `onBefore<eventname>` and `onAfter<eventname>` | ||
(triggered before or after calling an event). | ||
The event function has the following signature: | ||
```js | ||
function notification (event, oldState, newState) { | ||
function (event, oldState, newState) { | ||
... | ||
@@ -239,13 +239,4 @@ } | ||
Inside the `notification`, `this` refers to the internal `stateStore`. | ||
Inside these functions, `this` refers to the internal `stateStore`. | ||
### Hooks | ||
Beside the notification system via `bind` and `unbind`, there is an alternative | ||
way to attach hooks that are triggered when the state of the machine changes. | ||
Possible hooks are `onenterSTATE` (or as shortcut `onSTATE`) | ||
and `onleaveSTATE` for states and `onbeforeEVENT` and `onafterEVENT` for | ||
events. Hook functions have the same signature as notifications bound with | ||
`bind`. | ||
## Examples | ||
@@ -312,4 +303,22 @@ | ||
```js | ||
function reporter(event, oldState, newState) { | ||
var transition = oldState + ' => ' + newState; | ||
switch (transition) { | ||
/* | ||
... | ||
case 'STOPPED => PLAYING': | ||
case 'PLAYING => PAUSED': | ||
... | ||
*/ | ||
default: | ||
console.log(transition); | ||
break; | ||
} | ||
} | ||
var radio = Stately.machine({ | ||
'STOPPED': { | ||
onEnter: reporter, | ||
play: function () { | ||
@@ -320,2 +329,3 @@ return this.PLAYING; | ||
'PLAYING': { | ||
onEnter: reporter, | ||
stop: function () { | ||
@@ -329,2 +339,3 @@ return this.STOPPED; | ||
'PAUSED': { | ||
onEnter: reporter, | ||
play: function () { | ||
@@ -337,17 +348,2 @@ return this.PLAYING; | ||
} | ||
}).bind(function (event, oldState, newState) { | ||
var transition = oldState + ' => ' + newState; | ||
switch (transition) { | ||
/* | ||
... | ||
case 'STOPPED => PLAYING': | ||
case 'PLAYING => PAUSED': | ||
... | ||
*/ | ||
default: | ||
console.log(transition); | ||
break; | ||
} | ||
}); | ||
@@ -363,37 +359,3 @@ | ||
### Radio (more declarative) | ||
```js | ||
var radio = Stately.machine({ | ||
'STOPPED': { | ||
'play': /* => */ 'PLAYING' | ||
}, | ||
'PLAYING': { | ||
'stop': /* => */ 'STOPPED', | ||
'pause': /* => */ 'PAUSED' | ||
}, | ||
'PAUSED': { | ||
'play': /* => */ 'PLAYING', | ||
'stop': /* => */ 'STOPPED' | ||
} | ||
}); | ||
radio.onleaveSTOPPED = function (event, oldState, newState) { | ||
// ... | ||
}; | ||
radio.onenterSTOPPED = function (event, oldState, newState) { | ||
// ... | ||
}; | ||
radio.onPLAYING = function (event, oldState, newState) { | ||
// ... | ||
}; | ||
radio.onPAUSED = function (event, oldState, newState) { | ||
// ... | ||
}; | ||
``` | ||
## jsFiddles | ||
* http://jsfiddle.net/sz2hG/ | ||
* http://jsfiddle.net/FloHimself/sz2hG/108/ |
@@ -7,3 +7,3 @@ /* | ||
* | ||
* Version: 1.3.0 | ||
* Version: 2.0.0 | ||
* | ||
@@ -52,17 +52,20 @@ */ | ||
var | ||
currentState, | ||
function resolveSpecialEventFn(stateName, fnName) { | ||
notificationStore = [], | ||
for (var property in stateStore[stateName]) { | ||
notify = function () { | ||
if (stateStore[stateName].hasOwnProperty(property)) { | ||
var notifications = notificationStore.slice(); | ||
if (property.toLowerCase() === fnName.toLowerCase()) { | ||
for (var i = 0, l = notifications.length; i < l; i++) { | ||
return stateStore[stateName][property]; | ||
notifications[i].apply(this, arguments); | ||
} | ||
} | ||
}, | ||
} | ||
} | ||
var | ||
currentState, | ||
stateStore = { | ||
@@ -99,18 +102,16 @@ | ||
onEnterState = stateMachine['onenter' + currentState.name] || stateMachine['on' + currentState.name]; | ||
onLeaveState = resolveSpecialEventFn(lastState.name, "onLeave"); | ||
if (onEnterState && typeof onEnterState === 'function') { | ||
if (onLeaveState && typeof onLeaveState === 'function') { | ||
onEnterState.call(stateStore, eventName, lastState.name, nextState.name); | ||
onLeaveState.call(stateStore, eventName, lastState.name, currentState.name); | ||
} | ||
onLeaveState = stateMachine['onleave' + lastState.name]; | ||
onEnterState = resolveSpecialEventFn(currentState.name, "onEnter"); | ||
if (onLeaveState && typeof onLeaveState === 'function') { | ||
if (onEnterState && typeof onEnterState === 'function') { | ||
onLeaveState.call(stateStore, eventName, lastState.name, nextState.name); | ||
onEnterState.call(stateStore, eventName, lastState.name, nextState.name); | ||
} | ||
notify.call(stateStore, eventName, lastState.name, nextState.name); | ||
return this; | ||
@@ -143,33 +144,4 @@ }, | ||
getMachineEvents: stateStore.getMachineEvents, | ||
getMachineEvents: stateStore.getMachineEvents | ||
bind: function bind(callback) { | ||
if (callback) { | ||
notificationStore.push(callback); | ||
} | ||
return this; | ||
}, | ||
unbind: function unbind(callback) { | ||
if (!callback) { | ||
notificationStore = []; | ||
} else { | ||
for (var i = 0, l = notificationStore.length; i < l; i++) { | ||
if (notificationStore[i] === callback) { | ||
notificationStore.splice(i, 1); | ||
} | ||
} | ||
} | ||
return this; | ||
} | ||
}, | ||
@@ -200,3 +172,3 @@ | ||
onBeforeEvent = stateMachine['onbefore' + eventName]; | ||
onBeforeEvent = resolveSpecialEventFn(currentState.name, "onBefore" + eventName); | ||
@@ -243,3 +215,3 @@ if (onBeforeEvent && typeof onBeforeEvent === 'function') { | ||
onAfterEvent = stateMachine['onafter' + eventName] || stateMachine['on' + eventName]; | ||
onAfterEvent = resolveSpecialEventFn(currentState.name, "onAfter" + eventName); | ||
@@ -279,3 +251,9 @@ if (onAfterEvent && typeof onAfterEvent === 'function') { | ||
if (typeof stateStore[stateName][eventName] === 'function') { | ||
if ( | ||
typeof stateStore[stateName][eventName] === 'function' | ||
&& !/^onEnter$/i.test(eventName) | ||
&& !/^onLeave$/i.test(eventName) | ||
&& !/^onBefore/i.test(eventName) | ||
&& !/^onAfter/i.test(eventName) | ||
) { | ||
@@ -282,0 +260,0 @@ stateMachine[eventName] = transition(stateName, eventName, stateMachine[eventName]); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
172605
15
204
353
1