etgryphon / stativus Goto Github PK
View Code? Open in Web Editor NEWStatecharts for the rest of us...in javascript
Home Page: www.stativ.us
License: Other
Statecharts for the rest of us...in javascript
Home Page: www.stativ.us
License: Other
Isn't it necessary to allow us passing arguments to enterState() from goToState()?
Eg.
Idle -[:USER_TYPED_SOME_WORDS]-> Translating
Here when user types a word I call this.goToState('translating') from userTypedAWord event handler.
But for this to work I have to pass the words typed in.
Wouldn't this be a good thing to do?
this.goToState('translating', word1, word2 ...)
In this way it works just like this.sendEvent() where you can pass custom arguments.
At first i thought this was a bug, but apparently not.
var app = Stativus.createStatechart()
app.addState('root', {
initialSubstate: 'sub1',
clean: function() {
console.log('clean')
},
goToSub2: function() {
this.goToState('sub2')
}
})
app.addState('sub1', {
parentState: 'root',
enterState: function() {
var self = this
setTimeout(function() {
self.sendEvent('goToSub2')
}, 2000)
},
exitState: function() {
console.log('exit sub1')
this.sendEvent('clean')
}
})
app.addState('sub2', {
parentState: 'root',
})
Outputs:
ENTER: root stativus-evt-min.js:502
ENTER: sub1 stativus-evt-min.js:502
EVENT: root fires [goToSub2] with 0 argument(s) stativus-evt-min.js:457
exit sub1 app.js:1
EXIT: sub1 stativus-evt-min.js:513
ENTER: sub2 stativus-evt-min.js:502
EVENT: root fires [clean] with 0 argument(s) stativus-evt-min.js:457
clean
Notice exit sub1
is output, then the app leaves the state then the clean
function is actually fired after sub2
is already entered??
Can you explain what is going on here, it's likely this is a stupid question, but I expected the event handler to be triggered before the state was exit.
Here are my states:
application (substatesAreConcurrent: true)
application.routing
application.session (initialSubstate: "checking")
application.session.checking // this.goToState("application.session.loggedout")
application.session.loggedout
application.session.loggedin
The problem is when application.session.checking goes to application.session.loggedout, application.routing is exited. Shouldn't concurrent states be independent of each other?
When an event is sent but there is no handler for it (using statechart.sendEvent() and not this.sendEvent()), that event is not logged in the console.
Wouldn't it be better if the event is logged, and then log the event handler/s that is handling the event.
Eg.
statechart.sendEvent("showUser", "Foo");
will show this log if no handler is there:
EVENT: "showUser" is fired with 1 argument ["Foo"]
And if there are multiple handlers they will all be logged:
EVENT: "showUser" is fired with 1 argument ["Foo"]
HANDLER: StateB handled the event
HANDLER: StateA handled the event
This would give us more of what is happening so we don't need to console.log() in some places to figure things out.
Is there a way to check if a state is active/entered?
At the moment I have to do like this in all my states I test:
enterState: function() { pageOneIsEntered = true },
exitState: function() { pageOneIsEntered = false }
I was hoping that you could do something like:
statechart.isStateActive("PageOne")
// or
var states = statechart.getActiveStates()
// I can now check if a state is in the array.
// or
var states = statechart.getAllStates()
// I can now check if a state's isActive property is set to true.
This would make writing tests simple since you could send some events then just assert that the states are active.
It seems that knowing how to make a statechart properly requires a lot of knowledge.
I suggest there are some links in the README providing external information about statecharting:
Here are some good ones I found:
http://www3.informatik.uni-erlangen.de/Lectures/UMLEmbSys/WS2001/slides/Statecharts.pdf
http://www.agilemodeling.com/artifacts/stateMachineDiagram.htm
http://santos.cis.ksu.edu/771-Distribution/Reading/uml-section3.73-94.pdf
http://www.tutorialspoint.com/uml/uml_statechart_diagram.htm
http://www.developer.com/design/article.php/2238131/State-Diagram-in-UML.htm
http://www.slideshare.net/erant/uml-statechart-diagrams
http://www.uml.org.cn/UMLApplication/pdf/bestbook.pdf
http://www.boost.org/doc/libs/1_41_0/libs/statechart/doc/tutorial.html
Using the following code:
/*globals Stativus $*/
var statechart = Stativus.createStatechart();
statechart.addState('state_one', {
initialSubstate: 'substate_one',
actions: {
"#boom click": 'go'
}
});
statechart.addState('state_two', {
actions: {
"#boom click": 'go'
},
go: function(evt){
this.goToHistoryState('state_one');
}
});
statechart.addState('substate_one', {
parentState: 'state_one',
go: function(evt){
this.goToState('substate_two');
}
});
statechart.addState('substate_two', {
parentState: 'state_one',
go: function(evt){
this.goToState('state_two');
}
});
I love the ability to dynamically add states through statechart.addState()
In this way you can have your states in multiple files.
But many times I wanna add one state in the same file that contains other states eg.
Yi.addState("STORE", {
initialSubstate: "STORE_LOADING"
});
Yi.addState("STORE_LOADING", {
parentState: "STORE"
});
Yi.addState("STORE_OPENED", {
parentState: "STORE"
});
It would save a lot of time and look cleaner (less code, better structure and DRY) if you could do:
Yi.addState("STORE", {
initialSubstate: "LOADING",
states: [{
name "LOADING"
}, {
name: "READY"
}]
});
What do you think?
There should be coma like this:
statechart.addState("#state-two", {
enterState: function(){
$('#state-two').show(); // Using JQuery, but you can use whatever...
},
exitState: function(){
$('#state-two').hide(); // Using JQuery, but you can use whatever...
},
fireEvent: function(){
this.goToState('#state-one');
}
});
When I started to use "option 3" for adding states I was making the code more DRY. But what got me even more amazed was that I was creating a statechart blueprint that gives me a great overview over the whole statechart. It's easier to develop, maintain and debug.
The code below is in Coffeescript which makes it makes it even more clean. If you haven't used Coffeescript you can just dump the code in http://js2coffee.org
statechart.addState "MAIN"
initialSubstate: "MAIN_LOADING"
enterState: @enterState()
states: [
[
"MAIN_LOADING", mainLoading
"show": -> @goToState "MAIN_SHOWN"; yes
]
[
"MAIN_SHOWN", loader, init
initialSubstate: "VIEW"
states: [
[
"VIEW"
initialSubstate: "BUY"
states: [
[
"BUY"
initialSubstate: "BUY_LOADING"
states: [
[
"BUY_LOADING", buyLoading, loader
"show": -> @goToState "BUY_SHOWN"; yes
"hide": -> @goToState "BUY_HIDDEN"; yes
]
[
"BUY_SHOWN"
]
[
"BUY_HIDDEN"
]
]
]
]
]
]
]
]
The "problem" is that the parent state "Main" doesn't follow the option 3 convention. I think it would be cleaner and consistent if you could write it like this instead:
statechart.addStates [
"MAIN", main, init
initialSubstate: "MAIN_LOADING"
states: [
[
"MAIN_LOADING", mainLoading
"show": -> @goToState "MAIN_SHOWN"; yes
]
[
"MAIN_SHOWN", loader, init
initialSubstate: "VIEW"
states: [
[
"VIEW"
initialSubstate: "BUY"
states: [
[
"BUY"
initialSubstate: "BUY_LOADING"
states: [
[
"BUY_LOADING", buyLoading, loader
"show": -> @goToState "BUY_SHOWN"; yes
"hide": -> @goToState "BUY_HIDDEN"; yes
]
[
"BUY_SHOWN"
]
[
"BUY_HIDDEN"
]
]
]
]
]
]
]
]
]
In this way the statechart blueprint has a consistent structure and the parent state will have the same DRY benefits like the others.
A good method for testing purpose is hasState() since now I can only test if a state is entered not if the state is really there in the statechart. Would help to cover up more edge cases.
##### States
class Mood extends Yie.State
class Happy extends Yie.State
class Angry extends Yie.State
class Sad extends Yie.State
##### Statecharts
class Soul extends Yie.Statechart
init: ->
@state Mood, ->
@state Happy, ->
@state Angry, ->
@state Sad, ->
##### Statemachines
class Person extends Yie.Statemachine
statechart: Soul
person = new Person
person.isInState("Mood").should.be.true
person.isInState("Happy").should.be.true
person.isInState("Angry").should.be.false
person.isInState("Sad").should.be.false
What do you think?
Hey Evin - I may be missing something, but I've stripped this example as far down as I could and still am able to reproduce this issue. Any thoughts?
var statechart;
if(require) // I'm using node to make this easier to test
statechart = require('./stativus').createStatechart();
else
statechart = Stativus.createStatechart();
////////////////////////////////////////////
// MY STATES:
// application
// - page (#nav and #content are concurrent)
// - page#nav
// - page#nav#first <-- BUG, NEVER LOADS
// - page#content
////////////////////////////////////////////
statechart.addState('application', {
});
statechart.addState('page', {
parentState: 'application'
, substatesAreConcurrent: true
, states: [
{
name: 'page#nav'
, enterState: function(){ console.log('nav loaded'); } //<-- fires
, states:[
{
name: 'page#nav#first'
, enterState: function(){ console.log('nav.1 loaded'); } //<-- never fires
}
]
},
{
name: 'page#content'
, enterState: function(){ console.log('content loaded'); } //<-- fires
}
]
});
statechart.initStates('page#nav#first');
console.log(statechart.currentState().map(function(state){ return state.name; }));
// the above line should print something like:
// ['page#nav#first', 'page#nav', 'page#content', 'page', 'application']
// instead, it prints:
// ['page#nav', 'page#content', 'page', 'application']
// WHERE IS 'page#nav#first' ???
I wonder if it's mandatory for a parent to either use:
initialSubstate
OR
substatesAreConcurrent
Is it possible/good practice to not enter a substate/substates and let the parent enter later on when an event occurs?
Editing this issue again (3rd time) since I either implement concurrent state in a complete wrong way or there is a much bigger issue going on with the way the parent state chart tree is parsed. Example based on https://gist.github.com/1388244:
var sc = Stativus.createStatechart();
sc.addState('StateA1', {
globalConcurrentState: 'default_states',
initialSubstate: 'StateA1B1',
states: [{
name: 'StateA1B1',
substatesAreConcurrent: true,
states: [{
name: 'StateA1B1-A',
test: function() {}
},{
name: 'StateA1B1-B',
test: function() {}
}]
},
{
name: 'StateA1B2',
initialSubstate: 'StateA1B2-A',
states: [
{ name: 'StateA1B2-A' },
{ name: 'StateA1B2-B' }
]
}
]
});
sc.addState('StateA2', {
globalConcurrentState: 'modal_states',
states: [
{ name: 'StateA2B1' },
{ name: 'StateA2B2' }
]
});
sc.initStates({'default_states': 'StateA1', 'modal_states': 'StateA2'});
sc.goToState('StateA1B2', 'default_states');
EXIT: StateA1B1
ENTER: StateA1B2
HISTORY STATE: For StateA1 => history state set to: StateA1B2
ENTER: StateA1B2-A
HISTORY STATE: For StateA1B2 => history state set to: StateA1B2-A
Note: No EXIT on 'StateA1B1-A' or 'StateA1B1-B'
sc.goToState('StateA1B1', 'default_states');
EXIT: StateA1B2-A
EXIT: StateA1B2
ENTER: StateA1B1
ENTER: StateA1B1-A
ENTER: StateA1B1-B
..switching back and forth between the two states a few times..
sc.goToState('StateA1B2', 'default_states');
sc.sendEvent('test');
This will fire the test
event multiple times (as the states were never exited) even so at this point we are not even in the StateA1B1
state:
EVENT: StateA1B1-B fires [test] with 0 argument(s)
EVENT: StateA1B1-A fires [test] with 0 argument(s)
EVENT: StateA1B1-B fires [test] with 0 argument(s)
EVENT: StateA1B1-A fires [test] with 0 argument(s)
EVENT: StateA1B1-B fires [test] with 0 argument(s)
EVENT: StateA1B1-A fires [test] with 0 argument(s)
EVENT: StateA1B1-B fires [test] with 0 argument(s)
EVENT: StateA1B1-A fires [test] with 0 argument(s)
Thanks in advance for any feedback!
Sometimes you might have states where the same thing is happening in the enterState or exitState. Instead of repeating that code everywhere, if you could create a behavior that you just add to the state, it would help keep things DRY.
For example:
statechart.addBehavior('noSearchBar', {
enterState: function() {
$('#search').hide();
},
exitState: function() {
$('#search').show();
}
});
statechart.addState('profile', {
parentState: 'loggedIn',
behaviors: ['noSearchBar']
});
statechart.addState('activity', {
parentState: 'loggedIn',
behaviors: ['noSearchBar'],
enterState: function() {
// other stuff happens here also
}
});
I downloaded Stativus and did:
require("./stativus");
var statechart = Statechart.create();
statechart.addState("Test")
statechart.initStates("Test")
It seems to work except that the console displayed:
ENTER: undefined
I guess it's just something small going on making it behave like this. Could this be fixed so it's Node.js compatible? Would be good to be able to use it both on backend and frontend. Also for testing purpose it would be faster to run it on server side.
http://jsfiddle.net/johnnywengluu/Yrbk6/4/
I get "EVENT: sing with 0 argument(s) found NO state to handle the event" although I have event handler that handles the event.
TDD! :)
After a time the state names will have a very long namespace.
If I need to change a namespace, I have to do it in every state name.
me.application.myStatechart.addState("platform.application.sellers", {
parentState: "platform.application",
initialSubstate: "platform.application.sellers.loading"
});
Wouldn't this be better for the eyes?
me.application.myStatechart.addState("platform.application.sellers", {
initialSubstate: "loading"
});
No parentState and namespace for initialSubstate since its implicitly defined in the state name.
Here are my states:
application (substatesAreConcurrent)
application.routing (substatesAreConcurrent)
application.routing.state1
application.routing.state2
application.routing.state3
The problem here is that application.routing isn't entered.
If I have application set to initialSubstate: "application.routing" instead it works.
Should this be the default behavior?
Does it has something to do with globalConcurrentState?
Is there a technique you recommend for this?
I remember in Ki you could pass data from parent state to child state.
This is a feature that is very practical, since now the parent state could do some logic and pass the data to it's child states.
This is not possible right now:
When adding states using the advanced layout I get an error when the some substates have identical name.
Eg. I have "loggedIn" and "loggedOut" siblingstates, each one having one "main" substate.
What I have to do now is to have it like this:
...
name: 'loggedIn',
initialSubstate: 'loggedIn.main',
states: [{
name: 'loggedIn.main'
}]
}, {
name: 'loggedOut',
initialSubstate: 'loggedOut.main',
states: [{
name: 'loggedOut.main'
}]
Would it be a good feature to allow same name on substates (eg. stativus automatically append the prefix to make it a full path "loggedIn.main" when I add "main")?
Then I could do:
...
name: 'loggedIn',
initialSubstate: 'main',
states: [{
name: 'main'
}]
}, {
name: 'loggedOut',
initialSubstate: 'main',
states: [{
name: 'main'
}]
Since if not, then having multiple nesting levels would create really long names, and if you change an ancestor state name you have to change them all etc.
I am using substatesAreConcurrent and have multiple substates. Still the substates aren't entered correctly:
http://jsfiddle.net/9XMFV/4/
http://jsfiddle.net/jVbMe/4/
The substates aren't entered. Seems to only work if you are entering one of the substates at the time.
Bug?
UPDATE:
I think this bug is the same as the above ones. Just to be sure I have made an example that hopefully will pass if the above one is fixed. This example is using one of the new features defining a state in an array (love this feature, the code is so much more DRY :))
When root is using substatesAreConcurrent it seems that it will somehow render substates twice (in my local app this was really weird).
In this simple demo you can see that the event handler that should only be fired once is fired twice now.
Using intitialSubstate will solve this matter. Clearly a bug.
We are trying to implement the following patter:
A modal wizard with multiple steps.
We are implementing as a State, that represents the wizard, and multiple substrates that represent the wizard steps.
This is a pattern that we use extensively: we expect to have many different wizards. Most steps are simple: once the wizard septs consider the work is valid, the next button can be enabled.
Other steps are more complex: as when some transaction needs to be done with a server.
Some steps might be useful in several wizards.
We got One Wizard perfectly working with Stativus, but the problem is now re-using it.
While Stativ allows reusing functions, Reusing substrates is not so easy. Apparently the main limitation is substate names cannot appear more than once globally.
It would be very nice to have one: ProfileWizard, state, and a SignUPWizard... even those having substates with same name: Step1...StepN
We understand the potential conflict: if a gotoState("Sept2") was issued, with several wizards instantiated. But that is not an actual use case: Having a different ParentState, i.e. the wizard name should be enough.
Is this something that can be implemented?
Is it possible to reuse States(with substrates) as a whole by just doing minor changes?
Thanks and regards!
After reading some texts it seems that an event should always trigger a state transition. Is this correct?
Eg. if I wanan display something when someone has pressed a button, instead of placing the code in the event handler, I place it in enterState() in the state transitioned to? Is this better than placing things in event handlers directly?
How do I know when to place logic in event handlers and when to place it in states (enterState)?
Could you say that if new actions (events) should be available after I pressed the button I should put it in a state. If not, then I have it in an event handler?
There are two global variables used in Stativus: State and Statechart.
Could these names be namespaced (eg. Stativus.State and Stativus.Statechart)? This would reduce risk for errors when someone is including the library.
Spent quite of a time trying to figure out what the problem was. I had State inside a file :)
I have two states - both parented by 'base'
http://cl.ly/0F0O1N2N3i2h1L1l3n3D
If I'm in production_list and sendEvent('viewCall', aCall) which is defined in 'base' state and looks like:
viewCall:function(aCall) {
aController.set('content',aCall);
this.goToState('call_detail');
}
I see the exit_state for the production_list and production states
I see only the enter state for 'calls' - e.g. it never transitions to the desired substate.
In goToState, I see it determine the correct common state = 'base' . I would expect cascadeEnterSubstates to transition through 'calls' and then enter call_detail
Any thoughts?
statechart.addState("Sub3", {
parentState:"Main",
initialSubstate:"Sub31",
Timeout:function() {
this.goToState("End");
}
});
statechart.addState("Sub31", {
parentState:"Sub3",
Tr31_32:function() {
this.goToState("Sub32");
}
});
statechart.addState("Sub32", {
parentState:"Sub3",
Timeout:function() {
this.goToState("Sub31");
}
});
statechart.sendEvent('Timeout');
"Timeout" event is handled by both a parent state "Sub3" and its substate "Sub32". Who should handle the event when there are 2 choices?
Say we are in Sub32 and "Timeout" event is fired, my testing with the debug version shows that the statechart will enter Sub31 and then immediately exit Sub3 and enter End i.e. "Timeout" is fired in the Sub32 first and then in Sub3 immediately. So the same event is handled twice - one by the substate another the parent. Is this the right semantic? My understanding is that ONLY the substate should handle the Timeout event if it can handle it. Only when the current substate does not handle the given event should the parent state handle it.
The 'Timeout event for the parent State Sub3 should be the default action only when the substate cannot handle it. But if the substate can handle the event, there is no point to invoke Sub3's handler, too.
I encountered a really weird behavior:
http://jsfiddle.net/johnnywengluu/7fje2/6/
When entering the "#application .loading" state for the first time it will enter "#sellers" state.
But when "#application .loading" state is re-entered when clicking in any one of the textfields, it won't enter "#sellers" state again.
However, if I wrap the goToState inside an event, it works:
http://jsfiddle.net/johnnywengluu/7fje2/7/
Why is this?
I have a Hide and Show state.
In the Hide state I have showSignIn event handler.
From a state I send a "showSignIn" event and I see these lines in the log:
EXIT: store.front.sign_in.Hide
ENTER: store.front.sign_in.Show
EVENT: store.front.sign_in.Hide fires [showSignIn] with 0 argument(s)
Shouldn't the EVENT row be the first log message. That would make the debugging easier: event -> state transition.
I have submitted a pull request to add support for Internet Explorer 6.0+
This will address stativus support for Internet Explorer 6.0+ (windows XP SP2 base install). The lag of forEach and indexOf support in <IE9 raises a permission denied error on production installations right now.
I have some thoughts about how this statechart should operate.
When it comes to one substate at a time I have some cases where I have a parent state with no initialSubstate (since you said that was ok).
In the parent state's enterState() I will check the URL hash what substate to enter (so that the user can send the link to another user and he/she will see the same page). It could be Search, Books, Users etc.
However, for concurrent substates I am forced to use substatesAreConcurrent. That means all substates are entered immediately after enterState() of the parent is run. The enterState() can no longer choose to enter the substates or not, or picking which ones to enter.
Isn't it better if I could choose which parallell substates to enter in the parent's enterState()? Eg. a webstore may have a Shopping cart and a Store view (Search, Books, Users etc).
Then in the parent's enterState() I could choose to either enter both Store and ShoppingCart, only Store but not ShoppingCart (maybe the user isn't buying stuff) or none of them.
Maybe my suggestion for a more dynamic approach is against how a statechart should work.
The static architecture right now forces me to have the concurrent states entered upfront. I could accomplish the same thing by having a Hidden and a Showing substate in each state. So when the ShoppingCart is entered it will immediately be Hidden til I switch to it's Showing substate.
Is this static approach a better one and follows the principles of a statechart?
Before I chose to dynamically enter a substate I used to use initialSubstate: "loading" in the parent. It always entered a Loading state and in there I switched to the appropriate state. Now I don't have initialSubstate and is having the "routing logic" in the parent's enterState directly without having to go through a loading substate.
It seems that if this is okay then it should be a dynamical solution for substatesAreConcurrent too.
Maybe this is not a bug, but I don't understand why an event would trigger all event handlers in the chain:
http://jsfiddle.net/johnnywengluu/mSG4d/1/
Shouldn't it only triggers the first one that is handling the event, and not propagate throughout the chain?
When using substatesAreConcurrent I'll get 2 weird behaviors.
http://jsfiddle.net/johnnywengluu/qYvLP/6/
(Look at the bottom of the code).
I think I found a bug.
I have two concurrent states which registers an event handler with the same name.
However, when I fire the event, only one of them is triggered. I haven't returned "true" so the event should propagate.
I have recreated this weird behavior here: http://jsfiddle.net/johnnywengluu/ythns/1/
This is a good example of how useful nested states are. If the nested states bug is fixed first, I can recreate this code so that it will be simpler to get the statechart. Would want the nested architecture too in my real app or else it is too much anti-DRY and high typo risk.
In today's environment a lot of things need to be asynchronous.
enterState() and exitState() doesn't support it at the moment.
Eg. I wanna make an ajax call in enterState() and enter the appropriate substate after I have the response and have set things up.
Suggestion: A simple way to achieve this would be to give me a callback in enterState(ready) that I call when it's completed.
I wonder if there is any difference between using statechart.sendEvent() and this.sendEvent() from a state.
There are some cases where the nested states won't work properly:
http://jsfiddle.net/johnnywengluu/9XMFV/2/
http://jsfiddle.net/johnnywengluu/jVbMe/2/
http://jsfiddle.net/johnnywengluu/cqKGs/3/
Seems that substatesAreConcurrent won't work for states[].
Found another minor bug:
This one works normally: http://jsfiddle.net/johnnywengluu/XKRqj/2/
This one doesn't since there is no hash in the array: http://jsfiddle.net/johnnywengluu/XKRqj/4/
This one works since there is a hash in the array: http://jsfiddle.net/johnnywengluu/XKRqj/5/
Another example but using initialSubstate: http://jsfiddle.net/johnnywengluu/XKRqj/6/
Reasons for fix:
There are times I need to check if there is data stored for only the current state.
That is I don't care if the parent states hold the data with the same name.
Would it make sense to have something like
this.getData('view', false)
to only check for "view" in the current state and not propagate to the parent states if nothing is found?
Right now if you're in a child state you can't navigate to any of the parent states in the tree via goToState. The call to _checkAllCurrentStates checks prevents goToState from continuing when it detects this condition.
What is the correct way to navigate back to a parent state from a child?
Example use case: Let's say of I have table of data that lists models fetched from the server, it does this within state "mydata.list". Above the list is an "Add New Record Button" when that's clicked I want to continuing displaying the list while also adding a form above the list to create a new entry. So I create a substate of "mydata.list" and I call it "mydata.list.new". Let's say the user clicks cancel on the form, I want to remove the form from the DOM and continue displaying the list. Ideally I would like to exit "mydata.list.new" and return to "mydata.list". But that navigation isn't supported.
Only alternative I found is to create a another state on the same level as "mydata.list" and call it "mydata.resetlist". I go to that state when the form is cancelled and then from there I can navigate back to "mydata.list" via goToState. Only downside is it causes the list state to exit and re-enter which I'd prefer to avoid.
One thing I don't quite get is initStates() and initState().
http://jsfiddle.net/johnnywengluu/XKRqj/11/
How is it supposed to be used?
In this demo I just enters a lot of states, the end state will be Browse state, but suddenly it exits from it for no reason (I think).
http://jsfiddle.net/johnnywengluu/rewAc/13/
Why is this?
If you have a parent state with an actions
hash, but the event is in the current sub-state...its not being triggered.
Since the new update I haven't been able to go to another state:
http://jsfiddle.net/johnnywengluu/gMbUy/2/
Even this won't work:
I found that I often need to include a Timeout event in various substates (e.g. waiting for AJAX response). Currently, the way I achieve this is to update a single global startTime variable in all my substate's enterstate function and have some routine to generate the Timeout event by checking against this startTime variable. But this cause duplicate code in all my substates' enterstate function.
I think timeout is such a universal event that some sort of built-in support is appropriate. Perhaps, the simplest way is to expose an automatically updated global variable in statechart object that shows the time that the last change of state occurred.
I have a global state that is entered but when I use statechart.inState("Default") I get:
[TypeError: Cannot call method 'forEach' of undefined]
It works for the substates.
I started using Stativus on a Backbone project that also uses require.js. I just wrapped everything in a define function but it would be great if there was native support for using AMD loaders.
At the moment I am setting up a lot of custom console.log() lines.
It would ease out the development process if there was a debug version of Stativus that would output:
That would save a lot of time for us who are living in a statechart :)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.