WordPress/wp-includes/js/media/controllers/state-machine.js

125 lines
3.0 KiB
JavaScript

/*globals _, Backbone */
/**
* wp.media.controller.StateMachine
*
* A state machine keeps track of state. It is in one state at a time,
* and can change from one state to another.
*
* States are stored as models in a Backbone collection.
*
* @since 3.5.0
*
* @class
* @augments Backbone.Model
* @mixin
* @mixes Backbone.Events
*
* @param {Array} states
*/
var StateMachine = function( states ) {
// @todo This is dead code. The states collection gets created in media.view.Frame._createStates.
this.states = new Backbone.Collection( states );
};
// Use Backbone's self-propagating `extend` inheritance method.
StateMachine.extend = Backbone.Model.extend;
_.extend( StateMachine.prototype, Backbone.Events, {
/**
* Fetch a state.
*
* If no `id` is provided, returns the active state.
*
* Implicitly creates states.
*
* Ensure that the `states` collection exists so the `StateMachine`
* can be used as a mixin.
*
* @since 3.5.0
*
* @param {string} id
* @returns {wp.media.controller.State} Returns a State model
* from the StateMachine collection
*/
state: function( id ) {
this.states = this.states || new Backbone.Collection();
// Default to the active state.
id = id || this._state;
if ( id && ! this.states.get( id ) ) {
this.states.add({ id: id });
}
return this.states.get( id );
},
/**
* Sets the active state.
*
* Bail if we're trying to select the current state, if we haven't
* created the `states` collection, or are trying to select a state
* that does not exist.
*
* @since 3.5.0
*
* @param {string} id
*
* @fires wp.media.controller.State#deactivate
* @fires wp.media.controller.State#activate
*
* @returns {wp.media.controller.StateMachine} Returns itself to allow chaining
*/
setState: function( id ) {
var previous = this.state();
if ( ( previous && id === previous.id ) || ! this.states || ! this.states.get( id ) ) {
return this;
}
if ( previous ) {
previous.trigger('deactivate');
this._lastState = previous.id;
}
this._state = id;
this.state().trigger('activate');
return this;
},
/**
* Returns the previous active state.
*
* Call the `state()` method with no parameters to retrieve the current
* active state.
*
* @since 3.5.0
*
* @returns {wp.media.controller.State} Returns a State model
* from the StateMachine collection
*/
lastState: function() {
if ( this._lastState ) {
return this.state( this._lastState );
}
}
});
// Map all event binding and triggering on a StateMachine to its `states` collection.
_.each([ 'on', 'off', 'trigger' ], function( method ) {
/**
* @returns {wp.media.controller.StateMachine} Returns itself to allow chaining.
*/
StateMachine.prototype[ method ] = function() {
// Ensure that the `states` collection exists so the `StateMachine`
// can be used as a mixin.
this.states = this.states || new Backbone.Collection();
// Forward the method to the `states` collection.
this.states[ method ].apply( this.states, arguments );
return this;
};
});
module.exports = StateMachine;