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

242 lines
4.7 KiB
JavaScript

/*globals _, Backbone */
/**
* wp.media.controller.State
*
* A state is a step in a workflow that when set will trigger the controllers
* for the regions to be updated as specified in the frame.
*
* A state has an event-driven lifecycle:
*
* 'ready' triggers when a state is added to a state machine's collection.
* 'activate' triggers when a state is activated by a state machine.
* 'deactivate' triggers when a state is deactivated by a state machine.
* 'reset' is not triggered automatically. It should be invoked by the
* proper controller to reset the state to its default.
*
* @class
* @augments Backbone.Model
*/
var State = Backbone.Model.extend({
/**
* Constructor.
*
* @since 3.5.0
*/
constructor: function() {
this.on( 'activate', this._preActivate, this );
this.on( 'activate', this.activate, this );
this.on( 'activate', this._postActivate, this );
this.on( 'deactivate', this._deactivate, this );
this.on( 'deactivate', this.deactivate, this );
this.on( 'reset', this.reset, this );
this.on( 'ready', this._ready, this );
this.on( 'ready', this.ready, this );
/**
* Call parent constructor with passed arguments
*/
Backbone.Model.apply( this, arguments );
this.on( 'change:menu', this._updateMenu, this );
},
/**
* Ready event callback.
*
* @abstract
* @since 3.5.0
*/
ready: function() {},
/**
* Activate event callback.
*
* @abstract
* @since 3.5.0
*/
activate: function() {},
/**
* Deactivate event callback.
*
* @abstract
* @since 3.5.0
*/
deactivate: function() {},
/**
* Reset event callback.
*
* @abstract
* @since 3.5.0
*/
reset: function() {},
/**
* @access private
* @since 3.5.0
*/
_ready: function() {
this._updateMenu();
},
/**
* @access private
* @since 3.5.0
*/
_preActivate: function() {
this.active = true;
},
/**
* @access private
* @since 3.5.0
*/
_postActivate: function() {
this.on( 'change:menu', this._menu, this );
this.on( 'change:titleMode', this._title, this );
this.on( 'change:content', this._content, this );
this.on( 'change:toolbar', this._toolbar, this );
this.frame.on( 'title:render:default', this._renderTitle, this );
this._title();
this._menu();
this._toolbar();
this._content();
this._router();
},
/**
* @access private
* @since 3.5.0
*/
_deactivate: function() {
this.active = false;
this.frame.off( 'title:render:default', this._renderTitle, this );
this.off( 'change:menu', this._menu, this );
this.off( 'change:titleMode', this._title, this );
this.off( 'change:content', this._content, this );
this.off( 'change:toolbar', this._toolbar, this );
},
/**
* @access private
* @since 3.5.0
*/
_title: function() {
this.frame.title.render( this.get('titleMode') || 'default' );
},
/**
* @access private
* @since 3.5.0
*/
_renderTitle: function( view ) {
view.$el.text( this.get('title') || '' );
},
/**
* @access private
* @since 3.5.0
*/
_router: function() {
var router = this.frame.router,
mode = this.get('router'),
view;
this.frame.$el.toggleClass( 'hide-router', ! mode );
if ( ! mode ) {
return;
}
this.frame.router.render( mode );
view = router.get();
if ( view && view.select ) {
view.select( this.frame.content.mode() );
}
},
/**
* @access private
* @since 3.5.0
*/
_menu: function() {
var menu = this.frame.menu,
mode = this.get('menu'),
view;
this.frame.$el.toggleClass( 'hide-menu', ! mode );
if ( ! mode ) {
return;
}
menu.mode( mode );
view = menu.get();
if ( view && view.select ) {
view.select( this.id );
}
},
/**
* @access private
* @since 3.5.0
*/
_updateMenu: function() {
var previous = this.previous('menu'),
menu = this.get('menu');
if ( previous ) {
this.frame.off( 'menu:render:' + previous, this._renderMenu, this );
}
if ( menu ) {
this.frame.on( 'menu:render:' + menu, this._renderMenu, this );
}
},
/**
* Create a view in the media menu for the state.
*
* @access private
* @since 3.5.0
*
* @param {media.view.Menu} view The menu view.
*/
_renderMenu: function( view ) {
var menuItem = this.get('menuItem'),
title = this.get('title'),
priority = this.get('priority');
if ( ! menuItem && title ) {
menuItem = { text: title };
if ( priority ) {
menuItem.priority = priority;
}
}
if ( ! menuItem ) {
return;
}
view.set( this.id, menuItem );
}
});
_.each(['toolbar','content'], function( region ) {
/**
* @access private
*/
State.prototype[ '_' + region ] = function() {
var mode = this.get( region );
if ( mode ) {
this.frame[ region ].render( mode );
}
};
});
module.exports = State;