Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

stately.js

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

stately.js - npm Package Compare versions

Comparing version 1.0.0 to 1.1.0

2

package.json

@@ -36,3 +36,3 @@ {

"main": "Stately.js",
"version": "1.0.0"
"version": "1.1.0"
}

@@ -8,2 +8,28 @@ ![Stately.js Logo](https://github.com/fschaefer/Stately.js/raw/master/misc/Stately.js.png)

## Installation
In Node.js you can install Stately.js with `npm`:
$ npm install stately.js
and include it to your project by:
var Stately = require('stately.js');
In browsers you can include it directly by adding it to the document head section:
<script type="text/javascript" src="https://raw.github.com/fschaefer/Stately.js/master/Stately.js"></script>
<script type="text/javascript">
// use Stately
</script>
or with Asynchronous Module Definition by e.g.:
<script type="text/javascript" src="https://raw.github.com/jrburke/requirejs/master/require.js"></script>
<script type="text/javascript">
require(['https://raw.github.com/fschaefer/Stately.js/master/Stately.js'], function (Stately) {
// use Stately
});
</script>
## Usage

@@ -10,0 +36,0 @@

@@ -21,42 +21,29 @@ /*

var
//helper to identify options type
toString = Object.prototype.toString,
//custom exception for invalid states
InvalidStateError = (function () {
//custom event constructor
function InvalidStateError(message) {
//set error name
this.name = 'InvalidStateError';
//the error message
this.message = message;
}
//inherit from error object
InvalidStateError.prototype = new Error();
//set custom error constructor
InvalidStateError.prototype.constructor = InvalidStateError;
//return custom event
return InvalidStateError;
})();
//constructor
function Stately(statesObject) {
//if statesObject is a function
if (typeof statesObject === 'function') {
//avaluate it
statesObject = statesObject();
}
//if no valid statesObject provided
if (toString.call(statesObject) !== '[object Object]') {
//bail out
throw new InvalidStateError('Stately.js: Invalid states object: `' + statesObject + '`.');

@@ -66,18 +53,12 @@ }

var
//current state of the machine
currentState,
//storage for notification callbacks
notificationStore = [],
//notify callbacks about a transition
notify = function () {
//make copy of notification storage
var notifications = notificationStore.slice();
//walk over stored callbacks
for (var i = 0, l = notifications.length; i < l; i++) {
//and notify them
notifications[i].apply(this, arguments);

@@ -87,94 +68,65 @@ }

//storage for machine states
stateStore = {
//evaluates the current state
getMachineState: function getMachineState() {
//return current state as string
return currentState.name;
},
//function to transition into another state
setMachineState: function setMachineState(nextState /*, eventName */) {
var
//event that triggered the transition
eventName = arguments[1],
//before state hook
onBeforeState,
//enter state hook
onEnterState,
//leave state hook
onLeaveState,
//store last machine state
lastState = currentState;
//if state machine cannot handle returned state
if (!nextState || !nextState.name || !stateStore[nextState.name]) {
//throw invalid state exception
throw new InvalidStateError('Stately.js: Transitioned into invalid state: `' + setMachineState.caller + '`.');
}
//transition into next state
currentState = nextState;
//retrieve enter state hook
onBeforeState = stateMachine['onbefore' + currentState.name];
//if a hook is attached
if (onBeforeState && typeof onBeforeState === 'function') {
//apply it
onBeforeState.call(stateStore, eventName, lastState.name, nextState.name);
}
//retrieve enter state hook
onEnterState = stateMachine['onenter' + currentState.name] || stateMachine['on' + currentState.name];
//if a hook is attached
if (onEnterState && typeof onEnterState === 'function') {
//apply it
onEnterState.call(stateStore, eventName, lastState.name, nextState.name);
}
//retrieve leave state hook
onLeaveState = stateMachine['onleave' + currentState.name];
onLeaveState = stateMachine['onleave' + lastState.name];
//if a hook is attached
if (onLeaveState && typeof onLeaveState === 'function') {
//apply it
onLeaveState.call(stateStore, eventName, lastState.name, nextState.name);
}
//notify notification callbacks about transition
notify.call(stateStore, eventName, lastState.name, nextState.name);
//return the state store
return this;
},
//function returns the possible events in current state
getMachineEvents: function getMachineEvents() {
//storage for the events in current state
var events = [];
//walk over the events of the current state
for (var property in currentState) {
//ensure to only walk over own properties
if (currentState.hasOwnProperty(property)) {
//if it is an event function
if (typeof currentState[property] === 'function') {
//store it in events storage
events.push(property);

@@ -185,3 +137,2 @@ }

//return the possible events
return events;

@@ -192,32 +143,22 @@ }

//the state machine
stateMachine = {
//copy function to public state machine object
getMachineState: stateStore.getMachineState,
//copy function to public state machine object
getMachineEvents: stateStore.getMachineEvents,
//store a new notification callback
bind: function bind(callback) {
//if we have a new notification callback
if (callback) {
//store it in notification storage
notificationStore.push(callback);
}
//return the state machine
return this;
},
//remove a notification callback from storage
unbind: function unbind(callback) {
//if no callback is given
if (!callback) {
//reset notification storage
notificationStore = [];

@@ -227,9 +168,6 @@

//walk over stored callbacks
for (var i = 0, l = notificationStore.length; i < l; i++) {
//if callback is found in notification storage
if (notificationStore[i] === callback) {
//remove it
notificationStore.splice(i, 1);

@@ -240,3 +178,2 @@ }

//return the state machine
return this;

@@ -246,55 +183,38 @@ }

//event decorator factory function
transition = function transition(stateName, eventName, nextEvent) {
//the decorator
return function event() {
var
//before event hook
onBeforeEvent,
//after event hook
onAfterEvent,
//new state machine changed into
nextState,
//return the state machine if no event returns something
eventValue = stateMachine;
//if attached event handler doesn't handle this event
if (stateStore[stateName] !== currentState) {
//try other events in chain
if (nextEvent) {
//let next event function handle this event
eventValue = nextEvent.apply(stateStore, arguments);
}
//or return value of action
return eventValue;
}
//retrieve before event hook
onBeforeEvent = stateMachine['onbefore' + eventName];
//if a hook is attached
if (onBeforeEvent && typeof onBeforeEvent === 'function') {
//apply it
onBeforeEvent.call(stateStore, eventName, currentState.name, currentState.name);
}
//run action
eventValue = stateStore[stateName][eventName].apply(stateStore, arguments);
//check return value of action
if (typeof eventValue === 'undefined') {
//nothing returned, stay in current state
nextState = currentState;
//return state machine
eventValue = stateMachine;

@@ -304,6 +224,4 @@

//if state store object is returned ('this' in action function) stay in current state
nextState = (eventValue === stateStore ? currentState : eventValue);
//return state machine
eventValue = stateMachine;

@@ -313,23 +231,16 @@

//else first element is next state
nextState = eventValue[0];
//second element is return value
eventValue = eventValue[1];
}
//retrieve after event hook
onAfterEvent = stateMachine['onafter' + eventName] || stateMachine['on' + eventName];
//if a hook is attached
if (onAfterEvent && typeof onAfterEvent === 'function') {
//apply it
onAfterEvent.call(stateStore, eventName, currentState.name, nextState.name);
}
//transition into next state
stateStore.setMachineState(nextState, eventName);
//return desired value
return eventValue;

@@ -339,27 +250,18 @@ };

//walk over states object
for (var stateName in statesObject) {
//check own properties
if (statesObject.hasOwnProperty(stateName)) {
//store states in storage
stateStore[stateName] = statesObject[stateName];
//walk over events
for (var eventName in stateStore[stateName]) {
//check for own property
if (stateStore[stateName].hasOwnProperty(eventName)) {
//if type is a string, assume it is a state
if (typeof stateStore[stateName][eventName] === 'string') {
//decorate it
stateStore[stateName][eventName] = (function (stateName) {
//with a function
return function event() {
//returning the given state
return this[stateName];

@@ -371,6 +273,4 @@ };

//if type function
if (typeof stateStore[stateName][eventName] === 'function') {
//assign decorated events to state machine
stateMachine[eventName] = transition(stateName, eventName, stateMachine[eventName]);

@@ -381,9 +281,6 @@ }

//attach states name to object in storage
stateStore[stateName].name = stateName;
//initial state is the first passed in state
if (!currentState) {
//make initial state the current state
currentState = stateStore[stateName];

@@ -394,14 +291,10 @@ }

//if there is no initial state
if (!currentState) {
//throw invalid state exception
throw new InvalidStateError('Stately.js: Invalid initial state.');
}
//return the new state machine
return stateMachine;
}
//a factory for new machines
Stately.machine = function machine(statesObject) {

@@ -411,8 +304,6 @@ return new Stately(statesObject);

//InvalidStateError exception
Stately.InvalidStateError = InvalidStateError;
//export Stately object
return Stately;
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc