/*!
* VisualEditor UserInterface ContextItem class.
*
* @copyright See AUTHORS.txt
*/
/**
* Item in a context.
*
* @class
* @extends OO.ui.Widget
*
* @constructor
* @param {ve.ui.LinearContext} context Context the item is in
* @param {ve.dm.Model} [model] Model the item is related to
* @param {Object} [config] Configuration options
*/
ve.ui.ContextItem = function VeUiContextItem( context, model, config ) {
// Parent constructor
ve.ui.ContextItem.super.call( this, config );
// Properties
this.context = context;
this.model = model;
this.fragment = null;
// Events
this.$element.on( 'mousedown', () => {
// Deactivate so context is not automatically closed
// by null selection
context.getSurface().getView().deactivate();
} );
this.$element.on( 'keydown', ( e ) => {
// Pressing escape while focus is in the context should
// return focus to the surface
if ( e.keyCode === OO.ui.Keys.ESCAPE && context.getSurface().getView().isDeactivated() ) {
context.getSurface().getView().activate();
return false;
}
} );
// Initialization
this.$element.addClass( 've-ui-contextItem' );
};
/* Inheritance */
OO.inheritClass( ve.ui.ContextItem, OO.ui.Widget );
/* Events */
/**
* The context executed a ve.ui.Command
*
* @event ve.ui.ContextItem#command
*/
/* Static Properties */
/**
* Whether this item exclusively handles any model class
*
* @static
* @property {boolean}
* @inheritable
*/
ve.ui.ContextItem.static.exclusive = true;
ve.ui.ContextItem.static.commandName = null;
/**
* Sort order of the context item within the context
*
* Items are sorted top to bottom in ascending order. Negative values are allowed.
*
* @static
* @property {number}
* @inheritable
*/
ve.ui.ContextItem.static.sortOrder = 0;
/**
* Annotation or node models this item is related to.
*
* Used by #isCompatibleWith.
*
* @static
* @property {Function[]}
* @inheritable
*/
ve.ui.ContextItem.static.modelClasses = [];
/**
* Context items (by name) which this context item suppresses.
*
* See ve.ui.ModeledFactory.
*
* @static
* @property {string[]}
* @inheritable
*/
ve.ui.ContextItem.static.suppresses = [];
/* Methods */
/**
* Check if this item is compatible with a given model.
*
* @static
* @inheritable
* @param {ve.dm.Model} model Model to check
* @return {boolean} Item can be used with model
*/
ve.ui.ContextItem.static.isCompatibleWith = function ( model ) {
return ve.isInstanceOfAny( model, this.modelClasses );
};
/**
* Check if model is a node
*
* @return {boolean} Model is a node
*/
ve.ui.ContextItem.prototype.isNode = function () {
return this.model && this.model instanceof ve.dm.Node;
};
/**
* Get the command for this item.
*
* @return {ve.ui.Command}
*/
ve.ui.ContextItem.prototype.getCommand = function () {
return this.context.getSurface().commandRegistry.lookup( this.constructor.static.commandName );
};
/**
* Get a surface fragment covering the related model node, or the current selection otherwise
*
* @return {ve.dm.SurfaceFragment} Surface fragment
*/
ve.ui.ContextItem.prototype.getFragment = function () {
if ( !this.fragment ) {
const surfaceModel = this.context.getSurface().getModel();
this.fragment = this.isNode() ?
surfaceModel.getLinearFragment( this.model.getOuterRange() ) :
surfaceModel.getFragment();
}
return this.fragment;
};
/**
* Check if the context's surface is readOnly
*
* @return {boolean} Context's surface is readOnly
*/
ve.ui.ContextItem.prototype.isReadOnly = function () {
return this.context.getSurface().isReadOnly();
};
/**
* Check whether this context item represents the same content as another
*
* @param {ve.ui.ContextItem} other
* @return {boolean}
*/
ve.ui.ContextItem.prototype.equals = function ( other ) {
return this.constructor.static.name === other.constructor.static.name &&
this.getFragment().getSelection().equals( other.getFragment().getSelection() );
};
/**
* Setup the item.
*
* @param {boolean} refreshing If this is a reconstruction/refresh of a context
* @return {ve.ui.ContextItem}
* @chainable
*/
ve.ui.ContextItem.prototype.setup = function () {
return this;
};
/**
* Teardown the item.
*
* @return {ve.ui.ContextItem}
* @chainable
*/
ve.ui.ContextItem.prototype.teardown = function () {
return this;
};