/**
* PendingElement is a mixin that is used to create elements that notify users that something is
* happening and that they should wait before proceeding. The pending state is visually represented
* with a pending texture that appears in the head of a pending
* {@link OO.ui.ProcessDialog process dialog} or in the input field of a
* {@link OO.ui.TextInputWidget text input widget}.
*
* Currently, {@link OO.ui.ActionWidget Action widgets}, which mix in this class, can also be marked
* as pending, but only when used in {@link OO.ui.MessageDialog message dialogs}. The behavior is
* not currently supported for action widgets used in process dialogs.
*
* @example
* function MessageDialog( config ) {
* MessageDialog.super.call( this, config );
* }
* OO.inheritClass( MessageDialog, OO.ui.MessageDialog );
*
* MessageDialog.static.name = 'myMessageDialog';
* MessageDialog.static.actions = [
* { action: 'save', label: 'Done', flags: 'primary' },
* { label: 'Cancel', flags: 'safe' }
* ];
*
* MessageDialog.prototype.initialize = function () {
* MessageDialog.super.prototype.initialize.apply( this, arguments );
* this.content = new OO.ui.PanelLayout( { padded: true } );
* this.content.$element.append( '<p>Click the \'Done\' action widget to see its pending ' +
* 'state. Note that action widgets can be marked pending in message dialogs but not ' +
* 'process dialogs.</p>' );
* this.$body.append( this.content.$element );
* };
* MessageDialog.prototype.getBodyHeight = function () {
* return 100;
* }
* MessageDialog.prototype.getActionProcess = function ( action ) {
* if ( action === 'save' ) {
* this.getActions().get({actions: 'save'})[0].pushPending();
* return new OO.ui.Process()
* .next( 1000 )
* .next( () => {
* this.getActions().get({actions: 'save'})[0].popPending();
* } );
* }
* return MessageDialog.super.prototype.getActionProcess.call( this, action );
* };
*
* const windowManager = new OO.ui.WindowManager();
* $( document.body ).append( windowManager.$element );
*
* const dialog = new MessageDialog();
* windowManager.addWindows( [ dialog ] );
* windowManager.openWindow( dialog );
*
* @abstract
* @class
*
* @constructor
* @param {Object} [config] Configuration options
* @param {jQuery} [config.$pending] Element to mark as pending, defaults to this.$element
*/
OO.ui.mixin.PendingElement = function OoUiMixinPendingElement( config ) {
// Configuration initialization
config = config || {};
// Properties
this.pending = 0;
this.$pending = null;
// Initialisation
this.setPendingElement( config.$pending || this.$element );
};
/* Setup */
OO.initClass( OO.ui.mixin.PendingElement );
/* Methods */
/**
* Set the pending element (and clean up any existing one).
*
* @param {jQuery} $pending The element to set to pending.
*/
OO.ui.mixin.PendingElement.prototype.setPendingElement = function ( $pending ) {
if ( this.$pending ) {
this.$pending.removeClass( 'oo-ui-pendingElement-pending' );
}
this.$pending = $pending;
if ( this.pending > 0 ) {
this.$pending.addClass( 'oo-ui-pendingElement-pending' );
}
};
/**
* Check if an element is pending.
*
* @return {boolean} Element is pending
*/
OO.ui.mixin.PendingElement.prototype.isPending = function () {
return !!this.pending;
};
/**
* Increase the pending counter. The pending state will remain active until the counter is zero
* (i.e., the number of calls to #pushPending and #popPending is the same).
*
* @chainable
* @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.PendingElement.prototype.pushPending = function () {
if ( this.pending === 0 ) {
this.$pending.addClass( 'oo-ui-pendingElement-pending' );
this.updateThemeClasses();
}
this.pending++;
return this;
};
/**
* Decrease the pending counter. The pending state will remain active until the counter is zero
* (i.e., the number of calls to #pushPending and #popPending is the same).
*
* @chainable
* @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.PendingElement.prototype.popPending = function () {
if ( this.pending === 1 ) {
this.$pending.removeClass( 'oo-ui-pendingElement-pending' );
this.updateThemeClasses();
}
this.pending = Math.max( 0, this.pending - 1 );
return this;
};