diff --git a/addons/base_import/__openerp__.py b/addons/base_import/__openerp__.py index eff20bc90ab..bb527e7b49d 100644 --- a/addons/base_import/__openerp__.py +++ b/addons/base_import/__openerp__.py @@ -33,6 +33,7 @@ Re-implement openerp's file import system: ], 'js': [ 'static/lib/select2/select2.js', + 'static/lib/javascript-state-machine/state-machine.js', 'static/src/js/import.js', ], 'qweb': ['static/src/xml/import.xml'], diff --git a/addons/base_import/static/lib/javascript-state-machine/LICENSE b/addons/base_import/static/lib/javascript-state-machine/LICENSE new file mode 100644 index 00000000000..8ad703ca4ef --- /dev/null +++ b/addons/base_import/static/lib/javascript-state-machine/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2012 Jake Gordon and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/addons/base_import/static/lib/javascript-state-machine/README.md b/addons/base_import/static/lib/javascript-state-machine/README.md new file mode 100644 index 00000000000..64c045e69d7 --- /dev/null +++ b/addons/base_import/static/lib/javascript-state-machine/README.md @@ -0,0 +1,327 @@ +Javascript Finite State Machine (v2.1.0) +======================================== + +This standalone javascript micro-framework provides a finite state machine for your pleasure. + + * You can find the [code here](https://github.com/jakesgordon/javascript-state-machine) + * You can find a [description here](http://codeincomplete.com/posts/2011/8/19/javascript_state_machine_v2/) + * You can find a [working demo here](http://codeincomplete.com/posts/2011/8/19/javascript_state_machine_v2/example/) + +Download +======== + +You can download [state-machine.js](https://github.com/jakesgordon/javascript-state-machine/raw/master/state-machine.js), +or the [minified version](https://github.com/jakesgordon/javascript-state-machine/raw/master/state-machine.min.js) + +Alternatively: + + git clone git@github.com:jakesgordon/javascript-state-machine + + + * All code is in state-machine.js + * Minified version provided in state-machine.min.js + * No 3rd party library is required + * Demo can be found in /index.html + * QUnit tests can be found in /test/index.html + +Usage +===== + +Include `state-machine.min.js` in your application. + +In its simplest form, create a standalone state machine using: + + var fsm = StateMachine.create({ + initial: 'green', + events: [ + { name: 'warn', from: 'green', to: 'yellow' }, + { name: 'panic', from: 'yellow', to: 'red' }, + { name: 'calm', from: 'red', to: 'yellow' }, + { name: 'clear', from: 'yellow', to: 'green' } + ]}); + +... will create an object with a method for each event: + + * fsm.warn() - transition from 'green' to 'yellow' + * fsm.panic() - transition from 'yellow' to 'red' + * fsm.calm() - transition from 'red' to 'yellow' + * fsm.clear() - transition from 'yellow' to 'green' + +along with the following members: + + * fsm.current - contains the current state + * fsm.is(s) - return true if state `s` is the current state + * fsm.can(e) - return true if event `e` can be fired in the current state + * fsm.cannot(e) - return true if event `e` cannot be fired in the current state + +Multiple 'from' and 'to' states for a single event +================================================== + +If an event is allowed **from** multiple states, and always transitions to the same +state, then simply provide an array of states in the `from` attribute of an event. However, +if an event is allowed from multiple states, but should transition **to** a different +state depending on the current state, then provide multiple event entries with +the same name: + + var fsm = StateMachine.create({ + initial: 'hungry', + events: [ + { name: 'eat', from: 'hungry', to: 'satisfied' }, + { name: 'eat', from: 'satisfied', to: 'full' }, + { name: 'eat', from: 'full', to: 'sick' }, + { name: 'rest', from: ['hungry', 'satisfied', 'full', 'sick'], to: 'hungry' }, + ]}); + +This example will create an object with 2 event methods: + + * fsm.eat() + * fsm.rest() + +The `rest` event will always transition to the `hungry` state, while the `eat` event +will transition to a state that is dependent on the current state. + +>> NOTE: The `rest` event could use a wildcard '*' for the 'from' state if it should be +allowed from any current state. + +>> NOTE: The `rest` event in the above example can also be specified as multiple events with +the same name if you prefer the verbose approach. + +Callbacks +========= + +4 callbacks are available if your state machine has methods using the following naming conventions: + + * onbefore**event** - fired before the event + * onleave**state** - fired when leaving the old state + * onenter**state** - fired when entering the new state + * onafter**event** - fired after the event + +You can affect the event in 3 ways: + + * return `false` from an `onbeforeevent` handler to cancel the event. + * return `false` from an `onleavestate` handler to cancel the event. + * return `ASYNC` from an `onleavestate` handler to perform an asynchronous state transition (see next section) + +For convenience, the 2 most useful callbacks can be shortened: + + * on**event** - convenience shorthand for onafter**event** + * on**state** - convenience shorthand for onenter**state** + +In addition, a generic `onchangestate()` callback can be used to call a single function for _all_ state changes: + +All callbacks will be passed the same arguments: + + * **event** name + * **from** state + * **to** state + * _(followed by any arguments you passed into the original event method)_ + +Callbacks can be specified when the state machine is first created: + + var fsm = StateMachine.create({ + initial: 'green', + events: [ + { name: 'warn', from: 'green', to: 'yellow' }, + { name: 'panic', from: 'yellow', to: 'red' }, + { name: 'calm', from: 'red', to: 'yellow' }, + { name: 'clear', from: 'yellow', to: 'green' } + ], + callbacks: { + onpanic: function(event, from, to, msg) { alert('panic! ' + msg); }, + onclear: function(event, from, to, msg) { alert('thanks to ' + msg); }, + ongreen: function(event, from, to) { document.body.className = 'green'; }, + onyellow: function(event, from, to) { document.body.className = 'yellow'; }, + onred: function(event, from, to) { document.body.className = 'red'; }, + } + }); + + fsm.panic('killer bees'); + fsm.clear('sedatives in the honey pots'); + ... + +Additionally, they can be added and removed from the state machine at any time: + + fsm.ongreen = null; + fsm.onyellow = null; + fsm.onred = null; + fsm.onchangestate = function(event, from, to) { document.body.className = to; }; + +Asynchronous State Transitions +============================== + +Sometimes, you need to execute some asynchronous code during a state transition and ensure the +new state is not entered until your code has completed. + +A good example of this is when you transition out of a `menu` state, perhaps you want to gradually +fade the menu away, or slide it off the screen and don't want to transition to your `game` state +until after that animation has been performed. + +You can now return `StateMachine.ASYNC` from your `onleavestate` handler and the state machine +will be _'put on hold'_ until you are ready to trigger the transition using the new `transition()` +method. + +For example, using jQuery effects: + + var fsm = StateMachine.create({ + + initial: 'menu', + + events: [ + { name: 'play', from: 'menu', to: 'game' }, + { name: 'quit', from: 'game', to: 'menu' } + ], + + callbacks: { + + onentermenu: function() { $('#menu').show(); }, + onentergame: function() { $('#game').show(); }, + + onleavemenu: function() { + $('#menu').fadeOut('fast', function() { + fsm.transition(); + }); + return StateMachine.ASYNC; // tell StateMachine to defer next state until we call transition (in fadeOut callback above) + }, + + onleavegame: function() { + $('#game').slideDown('slow', function() { + fsm.transition(); + }; + return StateMachine.ASYNC; // tell StateMachine to defer next state until we call transition (in slideDown callback above) + } + + } + }); + + +State Machine Classes +===================== + +You can also turn all instances of a _class_ into an FSM by applying +the state machine functionality to the prototype, including your callbacks +in your prototype, and providing a `startup` event for use when constructing +instances: + + MyFSM = function() { // my constructor function + this.startup(); + }; + + MyFSM.prototype = { + + onpanic: function(event, from, to) { alert('panic'); }, + onclear: function(event, from, to) { alert('all is clear'); }, + + // my other prototype methods + + }; + + StateMachine.create({ + target: MyFSM.prototype, + events: [ + { name: 'startup', from: 'none', to: 'green' }, + { name: 'warn', from: 'green', to: 'yellow' }, + { name: 'panic', from: 'yellow', to: 'red' }, + { name: 'calm', from: 'red', to: 'yellow' }, + { name: 'clear', from: 'yellow', to: 'green' } + ]}); + + +This should be easy to adjust to fit your appropriate mechanism for object construction. + +Initialization Options +====================== + +How the state machine should initialize can depend on your application requirements, so +the library provides a number of simple options. + +By default, if you dont specify any initial state, the state machine will be in the `'none'` +state and you would need to provide an event to take it out of this state: + + var fsm = StateMachine.create({ + events: [ + { name: 'startup', from: 'none', to: 'green' }, + { name: 'panic', from: 'green', to: 'red' }, + { name: 'calm', from: 'red', to: 'green' }, + ]}); + alert(fsm.current); // "none" + fsm.startup(); + alert(fsm.current); // "green" + +If you specify the name of your initial event (as in all the earlier examples), then an +implicit `startup` event will be created for you and fired when the state machine is constructed. + + var fsm = StateMachine.create({ + initial: 'green', + events: [ + { name: 'panic', from: 'green', to: 'red' }, + { name: 'calm', from: 'red', to: 'green' }, + ]}); + alert(fsm.current); // "green" + +If your object already has a `startup` method you can use a different name for the initial event + + var fsm = StateMachine.create({ + initial: { state: 'green', event: 'init' }, + events: [ + { name: 'panic', from: 'green', to: 'red' }, + { name: 'calm', from: 'red', to: 'green' }, + ]}); + alert(fsm.current); // "green" + +Finally, if you want to wait to call the initial state transition event until a later date you +can `defer` it: + + var fsm = StateMachine.create({ + initial: { state: 'green', event: 'init', defer: true }, + events: [ + { name: 'panic', from: 'green', to: 'red' }, + { name: 'calm', from: 'red', to: 'green' }, + ]}); + alert(fsm.current); // "none" + fsm.init(); + alert(fsm.current); // "green" + +Of course, we have now come full circle, this last example is pretty much functionally the +same as the first example in this section where you simply define your own startup event. + +So you have a number of choices available to you when initializing your state machine. + +Handling Failures +====================== + +By default, if you try to call an event method that is not allowed in the current state, the +state machine will throw an exception. If you prefer to handle the problem yourself, you can +define a custom `error` handler: + + var fsm = StateMachine.create({ + initial: 'green', + error: function(eventName, from, to, args, errorCode, errorMessage) { + return 'event ' + eventName + ' was naughty :- ' + errorMessage; + }, + events: [ + { name: 'panic', from: 'green', to: 'red' }, + { name: 'calm', from: 'red', to: 'green' }, + ]}); + alert(fsm.calm()); // "event calm was naughty :- event not allowed in current state green" + +Release Notes +============= + +See [RELEASE NOTES](https://github.com/jakesgordon/javascript-state-machine/blob/master/RELEASE_NOTES.md) file. + +License +======= + +See [LICENSE](https://github.com/jakesgordon/javascript-state-machine/blob/master/LICENSE) file. + +Contact +======= + +If you have any ideas, feedback, requests or bug reports, you can reach me at +[jake@codeincomplete.com](mailto:jake@codeincomplete.com), or via +my website: [Code inComplete](http://codeincomplete.com/posts/2011/8/19/javascript_state_machine_v2/) + + + + + diff --git a/addons/base_import/static/lib/javascript-state-machine/RELEASE_NOTES.md b/addons/base_import/static/lib/javascript-state-machine/RELEASE_NOTES.md new file mode 100644 index 00000000000..06abf402d38 --- /dev/null +++ b/addons/base_import/static/lib/javascript-state-machine/RELEASE_NOTES.md @@ -0,0 +1,32 @@ +Version 2.1.0 (January 7th 2012) +-------------------------------- + + * Wrapped in self executing function to be more easily used with loaders like `require.js` or `curl.js` (issue #15) + * Allow event to be cancelled by returning `false` from `onleavestate` handler (issue #13) - WARNING: this breaks backward compatibility for async transitions (you now need to return `StateMachine.ASYNC` instead of `false`) + * Added explicit return values for event methods (issue #12) + * Added support for wildcard events that can be fired 'from' any state (issue #11) + * Added support for no-op events that transition 'to' the same state (issue #5) + * extended custom error callback to handle any exceptions caused by caller provided callbacks + * added custom error callback to override exception when an illegal state transition is attempted (thanks to cboone) + * fixed typos (thanks to cboone) + * fixed issue #4 - ensure before/after event hooks are called even if the event doesn't result in a state change + +Version 2.0.0 (August 19th 2011) +-------------------------------- + + * adding support for asynchronous state transitions (see README) - with lots of qunit tests (see test/async.js). + * consistent arguments for ALL callbacks, first 3 args are ALWAYS event name, from state and to state, followed by whatever arguments the user passed to the original event method. + * added a generic `onchangestate(event,from,to)` callback to detect all state changes with a single function. + * allow callbacks to be declared at creation time (instead of having to attach them afterwards) + * renamed 'hooks' => 'callbacks' + * [read more...](http://codeincomplete.com/posts/2011/8/19/javascript_state_machine_v2/) + +Version 1.2.0 (June 21st 2011) +------------------------------ + * allows the same event to transition to different states, depending on the current state (see 'Multiple...' section in README.md) + * [read more...](http://codeincomplete.com/posts/2011/6/21/javascript_state_machine_v1_2_0/) + +Version 1.0.0 (June 1st 2011) +----------------------------- + * initial version + * [read more...](http://codeincomplete.com/posts/2011/6/1/javascript_state_machine/) diff --git a/addons/base_import/static/lib/javascript-state-machine/Rakefile b/addons/base_import/static/lib/javascript-state-machine/Rakefile new file mode 100644 index 00000000000..beb8702a7f0 --- /dev/null +++ b/addons/base_import/static/lib/javascript-state-machine/Rakefile @@ -0,0 +1,8 @@ + +desc "create minified version of state-machine.js" +task :minify do + require File.expand_path(File.join(File.dirname(__FILE__), 'minifier/minifier')) + Minifier.enabled = true + Minifier.minify('state-machine.js') +end + diff --git a/addons/base_import/static/lib/javascript-state-machine/index.html b/addons/base_import/static/lib/javascript-state-machine/index.html new file mode 100644 index 00000000000..2d6cb62617b --- /dev/null +++ b/addons/base_import/static/lib/javascript-state-machine/index.html @@ -0,0 +1,39 @@ + + +
+