Skip to content

Commit bd46a21

Browse files
brunoskonradyoshuawuyts
authored andcommitted
Implements Parallel (#4)
* Creates parallel state constructor - It follows description from README.md * Udpates README.md to remove "to be implemented" flag from Parallel * Change code to extract scope and event name for parallel emit * Removes constructor assertions for instantiation and input type * Fix typo: s/collon/colon * Rewrite arrow function to regular function syntax for `state` getter * Fixes typos collon and remove to be implemented from README
1 parent 1b65a38 commit bd46a21

File tree

4 files changed

+101
-2
lines changed

4 files changed

+101
-2
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ machine.join('next', nanostate('review', {
7979
}))
8080
```
8181

82-
## Parallel (to be implemented)
83-
To be implemented. Sometimes there's multiple parallel states that need
82+
## Parallel
83+
Sometimes there's multiple parallel states that need
8484
expressing; `nanostate.parallel` helps with that. For example when editing
8585
text, a particular piece of text might be `bold`, `italic` and `underlined` at
8686
the same time. The trick is that all of these states operate in parallel

index.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
var Nanobus = require('nanobus')
22
var assert = require('assert')
3+
var Parallelstate = require('./parallel-state')
34

45
module.exports = Nanostate
56

@@ -23,3 +24,7 @@ Nanostate.prototype.emit = function (eventName) {
2324
this.state = nextState
2425
Nanobus.prototype.emit.call(this, eventName)
2526
}
27+
28+
Nanostate.parallel = function (transitions) {
29+
return new Parallelstate(transitions)
30+
}

parallel-state.js

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
var Nanobus = require('nanobus')
2+
var assert = require('assert')
3+
4+
module.exports = Parallelstate
5+
6+
function Parallelstate (transitions) {
7+
assert.equal(typeof transitions, 'object', 'nanostate: transitions should be type object')
8+
9+
this.scopes = Object.keys(transitions)
10+
this.transitions = transitions
11+
12+
Object.defineProperty(this, 'state', {
13+
get: function () {
14+
return this.scopes.reduce(function (state, scope) {
15+
state[scope] = transitions[scope].state
16+
return state
17+
}, {})
18+
}
19+
})
20+
21+
Nanobus.call(this)
22+
}
23+
24+
Parallelstate.prototype = Object.create(Nanobus.prototype)
25+
26+
Parallelstate.prototype.emit = function (eventName) {
27+
var hasColon = eventName.indexOf(':') >= 0
28+
assert.ok(hasColon, `nanostate.emit: invalid transition ${this.state} -> ${eventName}. For parallel nanostate eventName must have a colon ":"`)
29+
30+
var eventNameSplitted = eventName.split(':')
31+
var scope = eventNameSplitted[0]
32+
var event = eventNameSplitted[1]
33+
assert.ok(scope, `nanostate.emit: invalid scope ${scope} for parallel emitting`)
34+
35+
this.transitions[scope].emit(event)
36+
37+
Nanobus.prototype.emit.call(this, eventName)
38+
}

test.js

+56
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,59 @@ function move (assert, machine, states) {
3636
assert.equal(machine.state, expected, `from ${initial} to ${expected}`)
3737
})
3838
}
39+
40+
var createParallelTransitions = () => ({
41+
bold: nanostate('off', {
42+
on: { 'toggle': 'off' },
43+
off: { 'toggle': 'on' }
44+
}),
45+
underline: nanostate('off', {
46+
on: { 'toggle': 'off' },
47+
off: { 'toggle': 'on' }
48+
}),
49+
italics: nanostate('off', {
50+
on: { 'toggle': 'off' },
51+
off: { 'toggle': 'on' }
52+
}),
53+
list: nanostate('none', {
54+
none: { bullets: 'bullets', numbers: 'numbers' },
55+
bullets: { none: 'none', numbers: 'numbers' },
56+
numbers: { bullets: 'bullets', none: 'none' }
57+
})
58+
})
59+
60+
tape('create parallel state', (assert) => {
61+
var machine = nanostate.parallel(createParallelTransitions())
62+
63+
machine.emit('bold:toggle')
64+
assert.deepEqual(machine.state, {
65+
bold: 'on', underline: 'off', italics: 'off', list: 'none'
66+
})
67+
68+
assert.end()
69+
})
70+
71+
tape('change states in parallel machine', (assert) => {
72+
var machine = nanostate.parallel(createParallelTransitions())
73+
74+
machine.emit('underline:toggle')
75+
machine.emit('list:numbers')
76+
assert.deepEqual(machine.state, {
77+
bold: 'off', underline: 'on', italics: 'off', list: 'numbers'
78+
})
79+
80+
machine.emit('bold:toggle')
81+
machine.emit('underline:toggle')
82+
machine.emit('italics:toggle')
83+
machine.emit('list:bullets')
84+
assert.deepEqual(machine.state, {
85+
bold: 'on', underline: 'off', italics: 'on', list: 'bullets'
86+
})
87+
88+
machine.emit('list:none')
89+
assert.deepEqual(machine.state, {
90+
bold: 'on', underline: 'off', italics: 'on', list: 'none'
91+
})
92+
93+
assert.end()
94+
})

0 commit comments

Comments
 (0)