Skip to content

Commit 784a16f

Browse files
committed
Merge commit 'b5e3918837f4c6902ffa33346fcb6ec2e40962e2' into muti_wildcard
2 parents 2ad0cb9 + b5e3918 commit 784a16f

9 files changed

Lines changed: 127 additions & 29 deletions

File tree

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright (c) 2012, 2013, 2014, Jake Gordon and contributors
1+
Copyright (c) 2012, 2013, 2014, 2015, Jake Gordon and contributors
22

33
Permission is hereby granted, free of charge, to any person obtaining a copy
44
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Javascript Finite State Machine (v2.3.2)
1+
Javascript Finite State Machine (v2.3.5)
22
========================================
33

44
This standalone javascript micro-framework provides a finite state machine for your pleasure.
@@ -7,6 +7,11 @@ This standalone javascript micro-framework provides a finite state machine for y
77
* You can find a [description here](http://codeincomplete.com/posts/2013/1/26/javascript_state_machine_v2_2_0/)
88
* You can find a [working demo here](http://codeincomplete.com/posts/2011/8/19/javascript_state_machine_v2/example/)
99

10+
This library has also been ported to:
11+
12+
* [Go](https://github.com/looplab/fsm) by @maxpersson
13+
* [Python](https://github.com/oxplot/fysom) by @oxplot
14+
1015
Download
1116
========
1217

@@ -50,10 +55,11 @@ In its simplest form, create a standalone state machine using:
5055

5156
along with the following members:
5257

53-
* fsm.current - contains the current state
54-
* fsm.is(s) - return true if state `s` is the current state
55-
* fsm.can(e) - return true if event `e` can be fired in the current state
56-
* fsm.cannot(e) - return true if event `e` cannot be fired in the current state
58+
* fsm.current - contains the current state
59+
* fsm.is(s) - return true if state `s` is the current state
60+
* fsm.can(e) - return true if event `e` can be fired in the current state
61+
* fsm.cannot(e) - return true if event `e` cannot be fired in the current state
62+
* fsm.transitions() - return list of events that are allowed from the current state
5763

5864
Multiple 'from' and 'to' states for a single event
5965
==================================================
@@ -262,7 +268,7 @@ Initialization Options
262268
How the state machine should initialize can depend on your application requirements, so
263269
the library provides a number of simple options.
264270

265-
By default, if you dont specify any initial state, the state machine will be in the `'none'`
271+
By default, if you don't specify any initial state, the state machine will be in the `'none'`
266272
state and you would need to provide an event to take it out of this state:
267273

268274
var fsm = StateMachine.create({

RELEASE_NOTES.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
Version 2.3.5 (January 20 2014)
2+
-------------------------------
3+
4+
* fix for broken transitions() method (issue #74)
5+
6+
Version 2.3.4 (January 17 2014)
7+
-------------------------------
8+
9+
* helper method to list which events are allowed from the current state (issue #71 - thanks to @mgoldsborough and @chopj)
10+
11+
Version 2.3.3 (October 17 2014)
12+
-------------------------------
13+
14+
* added web worker compatability (issue #65 - thanks to @offirmo)
15+
116
Version 2.3.2 (March 16 2014)
217
-----------------------------
318

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "javascript-state-machine",
3-
"version": "2.3.2",
3+
"version": "2.3.5",
44
"homepage": "https://github.com/jakesgordon/javascript-state-machine",
55
"authors": [
66
"Jake Gordon <jake@codeincomplete.com>"

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
"devDependencies": {
1010
"qunit": "~0.6.2"
1111
},
12-
"version": "2.3.2"
12+
"version": "2.3.5"
1313
}

state-machine.js

100644100755
Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
Javascript State Machine Library - https://github.com/jakesgordon/javascript-state-machine
44
5-
Copyright (c) 2012, 2013, 2014, Jake Gordon and contributors
5+
Copyright (c) 2012, 2013, 2014, 2015, Jake Gordon and contributors
66
Released under the MIT license - https://github.com/jakesgordon/javascript-state-machine/blob/master/LICENSE
77
88
*/
@@ -13,7 +13,7 @@
1313

1414
//---------------------------------------------------------------------------
1515

16-
VERSION: "2.3.2",
16+
VERSION: "2.3.5",
1717

1818
//---------------------------------------------------------------------------
1919

@@ -37,18 +37,23 @@
3737

3838
create: function(cfg, target) {
3939

40-
var initial = (typeof cfg.initial == 'string') ? { state: cfg.initial } : cfg.initial; // allow for a simple string, or an object with { state: 'foo', event: 'setup', defer: true|false }
41-
var terminal = cfg.terminal || cfg['final'];
42-
var fsm = target || cfg.target || {};
43-
var events = cfg.events || [];
44-
var callbacks = cfg.callbacks || {};
45-
var map = {};
40+
var initial = (typeof cfg.initial == 'string') ? { state: cfg.initial } : cfg.initial; // allow for a simple string, or an object with { state: 'foo', event: 'setup', defer: true|false }
41+
var terminal = cfg.terminal || cfg['final'];
42+
var fsm = target || cfg.target || {};
43+
var events = cfg.events || [];
44+
var callbacks = cfg.callbacks || {};
45+
var map = {}; // track state transitions allowed for an event { event: { from: [ to ] } }
46+
var transitions = {}; // track events allowed from a state { state: [ event ] }
4647

4748
var add = function(e) {
4849
var from = (e.from instanceof Array) ? e.from : (e.from ? [e.from] : [StateMachine.WILDCARD]); // allow 'wildcard' transition if 'from' is not specified
4950
map[e.name] = map[e.name] || {};
50-
for (var n = 0 ; n < from.length ; n++)
51+
for (var n = 0 ; n < from.length ; n++) {
52+
transitions[from[n]] = transitions[from[n]] || [];
53+
transitions[from[n]].push(e.name);
54+
5155
map[e.name][from[n]] = e.to || from[n]; // allow no-op transition if 'to' is not specified
56+
}
5257
};
5358

5459
if (initial) {
@@ -69,13 +74,13 @@
6974
fsm[name] = callbacks[name]
7075
}
7176

72-
fsm.current = 'none';
73-
fsm.is = function(state) { return (state instanceof Array) ? (state.indexOf(this.current) >= 0) : (this.current === state); };
74-
fsm.can = function(event) { return !this.transition && (map[event].hasOwnProperty(this.current) || map[event].hasOwnProperty(StateMachine.WILDCARD)); }
75-
fsm.cannot = function(event) { return !this.can(event); };
76-
fsm.error = cfg.error || function(name, from, to, args, error, msg, e) { throw e || msg; }; // default behavior when something unexpected happens is to throw an exception, but caller can override this behavior if desired (see github issue #3 and #17)
77-
78-
fsm.isFinished = function() { return this.is(terminal); };
77+
fsm.current = 'none';
78+
fsm.is = function(state) { return (state instanceof Array) ? (state.indexOf(this.current) >= 0) : (this.current === state); };
79+
fsm.can = function(event) { return !this.transition && (map[event].hasOwnProperty(this.current) || map[event].hasOwnProperty(StateMachine.WILDCARD)); }
80+
fsm.cannot = function(event) { return !this.can(event); };
81+
fsm.transitions = function() { return transitions[this.current]; };
82+
fsm.isFinished = function() { return this.is(terminal); };
83+
fsm.error = cfg.error || function(name, from, to, args, error, msg, e) { throw e || msg; }; // default behavior when something unexpected happens is to throw an exception, but caller can override this behavior if desired (see github issue #3 and #17)
7984

8085
if (initial && !initial.defer)
8186
fsm[initial.event]();
@@ -209,9 +214,14 @@
209214
//========
210215
// BROWSER
211216
//========
212-
else if (window) {
217+
else if (typeof window !== 'undefined') {
213218
window.StateMachine = StateMachine;
214219
}
220+
//===========
221+
// WEB WORKER
222+
//===========
223+
else if (typeof self !== 'undefined') {
224+
self.StateMachine = StateMachine;
225+
}
215226

216227
}());
217-

state-machine.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/test_advanced.js

100644100755
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ test("callbacks are called when appropriate for multiple 'from' and 'to' transit
209209

210210
test("callbacks are called when appropriate for prototype based state machine", function() {
211211

212-
myFSM = function() {
212+
var myFSM = function() {
213213
this.called = [];
214214
this.startup();
215215
};

test/test_basics.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,73 @@ test("is", function() {
111111

112112
//-----------------------------------------------------------------------------
113113

114+
test("transitions", function() {
115+
116+
var fsm = StateMachine.create({
117+
initial: 'green',
118+
events: [
119+
{ name: 'warn', from: 'green', to: 'yellow' },
120+
{ name: 'panic', from: 'yellow', to: 'red' },
121+
{ name: 'calm', from: 'red', to: 'yellow' },
122+
{ name: 'clear', from: 'yellow', to: 'green' }
123+
]});
124+
125+
equal(fsm.current, 'green', 'current state should be yellow');
126+
deepEqual(fsm.transitions(), ['warn'], 'current transition(s) should be yellow');
127+
128+
fsm.warn();
129+
equal(fsm.current, 'yellow', 'current state should be yellow');
130+
deepEqual(fsm.transitions(), ['panic', 'clear'], 'current transition(s) should be panic and clear');
131+
132+
fsm.panic();
133+
equal(fsm.current, 'red', 'current state should be red');
134+
deepEqual(fsm.transitions(), ['calm'], 'current transition(s) should be calm');
135+
136+
fsm.calm();
137+
equal(fsm.current, 'yellow', 'current state should be yellow');
138+
deepEqual(fsm.transitions(), ['panic', 'clear'], 'current transion(s) should be panic and clear');
139+
140+
fsm.clear();
141+
equal(fsm.current, 'green', 'current state should be green');
142+
deepEqual(fsm.transitions(), ['warn'], 'current transion(s) should be warn');
143+
});
144+
145+
//-----------------------------------------------------------------------------
146+
147+
test("transitions with multiple from states", function() {
148+
149+
var fsm = StateMachine.create({
150+
events: [
151+
{ name: 'start', from: 'none', to: 'green' },
152+
{ name: 'warn', from: ['green', 'red'], to: 'yellow' },
153+
{ name: 'panic', from: ['green', 'yellow'], to: 'red' },
154+
{ name: 'clear', from: ['red', 'yellow'], to: 'green' }
155+
]
156+
});
157+
158+
equal(fsm.current, 'none', 'current state should be none');
159+
deepEqual(fsm.transitions(), ['start'], 'current transition(s) should be start');
160+
161+
fsm.start();
162+
equal(fsm.current, 'green', 'current state should be green');
163+
deepEqual(fsm.transitions(), ['warn', 'panic'], 'current transition(s) should be warn and panic');
164+
165+
fsm.warn();
166+
equal(fsm.current, 'yellow', 'current state should be yellow');
167+
deepEqual(fsm.transitions(), ['panic', 'clear'], 'current transition(s) should be panic and clear');
168+
169+
fsm.panic();
170+
equal(fsm.current, 'red', 'current state should be red');
171+
deepEqual(fsm.transitions(), ['warn', 'clear'], 'current transition(s) should be warn and clear');
172+
173+
fsm.clear();
174+
equal(fsm.current, 'green', 'current state should be green');
175+
deepEqual(fsm.transitions(), ['warn', 'panic'], 'current transition(s) should be warn and panic');
176+
177+
});
178+
179+
//-----------------------------------------------------------------------------
180+
114181
test("isFinished", function() {
115182

116183
var fsm = StateMachine.create({

0 commit comments

Comments
 (0)