/*!
- * OOjs UI v0.11.1
+ * OOjs UI v0.11.3
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2015 OOjs Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2015-05-05T00:40:50Z
+ * Date: 2015-05-12T12:15:37Z
*/
( function ( OO ) {
*/
OO.ui.ButtonElement.prototype.onClick = function ( e ) {
if ( !this.isDisabled() && e.which === 1 ) {
- this.emit( 'click' );
+ if ( this.emit( 'click' ) ) {
+ return false;
+ }
}
- return false;
};
/**
*/
OO.ui.ButtonElement.prototype.onKeyPress = function ( e ) {
if ( !this.isDisabled() && ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER ) ) {
- this.emit( 'click' );
- return false;
+ if ( this.emit( 'click' ) ) {
+ return false;
+ }
}
};
};
/**
- * Select and highlight the first selectable item in the menu.
+ * Highlight the first selectable item in the menu.
*
* @private
* @chainable
*/
OO.ui.LookupElement.prototype.initializeLookupMenuSelection = function () {
if ( !this.lookupMenu.getSelectedItem() ) {
- this.lookupMenu.selectItem( this.lookupMenu.getFirstSelectableItem() );
+ this.lookupMenu.highlightItem( this.lookupMenu.getFirstSelectableItem() );
}
- this.lookupMenu.highlightItem( this.lookupMenu.getSelectedItem() );
};
/**
'oo-ui-tool ' + 'oo-ui-tool-name-' +
this.constructor.static.name.replace( /^([^\/]+)\/([^\/]+).*$/, '$1-$2' )
)
+ .toggleClass( 'oo-ui-tool-with-label', this.constructor.static.displayBothIconAndLabel )
.append( this.$link );
this.setTitle( config.title || this.constructor.static.title );
};
*/
OO.ui.Tool.static.title = '';
+/**
+ * Whether this tool should be displayed with both title and label when used in a bar tool group.
+ * Normally only the icon is displayed, or only the label if no icon is given.
+ *
+ * @static
+ * @inheritable
+ * @property {boolean}
+ */
+OO.ui.Tool.static.displayBothIconAndLabel = false;
+
/**
* Tool can be automatically added to catch-all groups.
*
/**
* Collection of tool groups.
*
- * @example
- * // Basic OOjs UI toolbar example
+ * The following is a minimal example using several tools and tool groups.
*
+ * @example
* // Create the toolbar
* var toolFactory = new OO.ui.ToolFactory();
* var toolGroupFactory = new OO.ui.ToolGroupFactory();
* // Create a class inheriting from OO.ui.Tool
* function PictureTool() {
* PictureTool.super.apply( this, arguments );
+ * }
+ * OO.inheritClass( PictureTool, OO.ui.Tool );
+ * // Each tool must have a 'name' (used as an internal identifier, see later) and at least one
+ * // of 'icon' and 'title' (displayed icon and text).
+ * PictureTool.static.name = 'picture';
+ * PictureTool.static.icon = 'picture';
+ * PictureTool.static.title = 'Insert picture';
+ * // Defines the action that will happen when this tool is selected (clicked).
+ * PictureTool.prototype.onSelect = function () {
+ * $area.text( 'Picture tool clicked!' );
+ * // Never display this tool as "active" (selected).
+ * this.setActive( false );
+ * };
+ * // Make this tool available in our toolFactory and thus our toolbar
+ * toolFactory.register( PictureTool );
+ *
+ * // Register two more tools, nothing interesting here
+ * function SettingsTool() {
+ * SettingsTool.super.apply( this, arguments );
+ * }
+ * OO.inheritClass( SettingsTool, OO.ui.Tool );
+ * SettingsTool.static.name = 'settings';
+ * SettingsTool.static.icon = 'settings';
+ * SettingsTool.static.title = 'Change settings';
+ * SettingsTool.prototype.onSelect = function () {
+ * $area.text( 'Settings tool clicked!' );
+ * this.setActive( false );
+ * };
+ * toolFactory.register( SettingsTool );
+ *
+ * // Register two more tools, nothing interesting here
+ * function StuffTool() {
+ * StuffTool.super.apply( this, arguments );
+ * }
+ * OO.inheritClass( StuffTool, OO.ui.Tool );
+ * StuffTool.static.name = 'stuff';
+ * StuffTool.static.icon = 'ellipsis';
+ * StuffTool.static.title = 'More stuff';
+ * StuffTool.prototype.onSelect = function () {
+ * $area.text( 'More stuff tool clicked!' );
+ * this.setActive( false );
* };
+ * toolFactory.register( StuffTool );
+ *
+ * // This is a PopupTool. Rather than having a custom 'onSelect' action, it will display a
+ * // little popup window (a PopupWidget).
+ * function HelpTool( toolGroup, config ) {
+ * OO.ui.PopupTool.call( this, toolGroup, $.extend( { popup: {
+ * padded: true,
+ * label: 'Help',
+ * head: true
+ * } }, config ) );
+ * this.popup.$body.append( '<p>I am helpful!</p>' );
+ * }
+ * OO.inheritClass( HelpTool, OO.ui.PopupTool );
+ * HelpTool.static.name = 'help';
+ * HelpTool.static.icon = 'help';
+ * HelpTool.static.title = 'Help';
+ * toolFactory.register( HelpTool );
+ *
+ * // Finally define which tools and in what order appear in the toolbar. Each tool may only be
+ * // used once (but not all defined tools must be used).
+ * toolbar.setup( [
+ * {
+ * // 'bar' tool groups display tools' icons only, side-by-side.
+ * type: 'bar',
+ * include: [ 'picture', 'help' ]
+ * },
+ * {
+ * // 'list' tool groups display both the titles and icons, in a dropdown list.
+ * type: 'list',
+ * indicator: 'down',
+ * label: 'More',
+ * include: [ 'settings', 'stuff' ]
+ * }
+ * // Note how the tools themselves are toolgroup-agnostic - the same tool can be displayed
+ * // either in a 'list' or a 'bar'. There is a 'menu' tool group too, not showcased here,
+ * // since it's more complicated to use. (See the next example snippet on this page.)
+ * ] );
+ *
+ * // Create some UI around the toolbar and place it in the document
+ * var frame = new OO.ui.PanelLayout( {
+ * expanded: false,
+ * framed: true
+ * } );
+ * var contentFrame = new OO.ui.PanelLayout( {
+ * expanded: false,
+ * padded: true
+ * } );
+ * frame.$element.append(
+ * toolbar.$element,
+ * contentFrame.$element.append( $area )
+ * );
+ * $( 'body' ).append( frame.$element );
+ *
+ * // Here is where the toolbar is actually built. This must be done after inserting it into the
+ * // document.
+ * toolbar.initialize();
+ *
+ * The following example extends the previous one to illustrate 'menu' tool groups and the usage of
+ * 'updateState' event.
+ *
+ * @example
+ * // Create the toolbar
+ * var toolFactory = new OO.ui.ToolFactory();
+ * var toolGroupFactory = new OO.ui.ToolGroupFactory();
+ * var toolbar = new OO.ui.Toolbar( toolFactory, toolGroupFactory );
+ *
+ * // We will be placing status text in this element when tools are used
+ * var $area = $( '<p>' ).text( 'Toolbar example' );
+ *
+ * // Define the tools that we're going to place in our toolbar
+ *
+ * // Create a class inheriting from OO.ui.Tool
+ * function PictureTool() {
+ * PictureTool.super.apply( this, arguments );
+ * }
* OO.inheritClass( PictureTool, OO.ui.Tool );
* // Each tool must have a 'name' (used as an internal identifier, see later) and at least one
* // of 'icon' and 'title' (displayed icon and text).
* // Defines the action that will happen when this tool is selected (clicked).
* PictureTool.prototype.onSelect = function () {
* $area.text( 'Picture tool clicked!' );
+ * // Never display this tool as "active" (selected).
* this.setActive( false );
* };
* // The toolbar can be synchronized with the state of some external stuff, like a text
* // editor's editing area, highlighting the tools (e.g. a 'bold' tool would be shown as active
* // when the text cursor was inside bolded text). Here we simply disable this feature.
* PictureTool.prototype.onUpdateState = function () {
- * this.setActive( false );
* };
* // Make this tool available in our toolFactory and thus our toolbar
* toolFactory.register( PictureTool );
* // Register two more tools, nothing interesting here
* function SettingsTool() {
* SettingsTool.super.apply( this, arguments );
- * };
+ * this.reallyActive = false;
+ * }
* OO.inheritClass( SettingsTool, OO.ui.Tool );
* SettingsTool.static.name = 'settings';
* SettingsTool.static.icon = 'settings';
* SettingsTool.static.title = 'Change settings';
* SettingsTool.prototype.onSelect = function () {
* $area.text( 'Settings tool clicked!' );
- * this.setActive( false );
+ * // Toggle the active state on each click
+ * this.reallyActive = !this.reallyActive;
+ * this.setActive( this.reallyActive );
+ * // To update the menu label
+ * this.toolbar.emit( 'updateState' );
* };
* SettingsTool.prototype.onUpdateState = function () {
- * this.setActive( false );
* };
* toolFactory.register( SettingsTool );
*
* // Register two more tools, nothing interesting here
* function StuffTool() {
* StuffTool.super.apply( this, arguments );
- * };
+ * this.reallyActive = false;
+ * }
* OO.inheritClass( StuffTool, OO.ui.Tool );
* StuffTool.static.name = 'stuff';
* StuffTool.static.icon = 'ellipsis';
* StuffTool.static.title = 'More stuff';
* StuffTool.prototype.onSelect = function () {
* $area.text( 'More stuff tool clicked!' );
- * this.setActive( false );
+ * // Toggle the active state on each click
+ * this.reallyActive = !this.reallyActive;
+ * this.setActive( this.reallyActive );
+ * // To update the menu label
+ * this.toolbar.emit( 'updateState' );
* };
* StuffTool.prototype.onUpdateState = function () {
- * this.setActive( false );
* };
* toolFactory.register( StuffTool );
*
* head: true
* } }, config ) );
* this.popup.$body.append( '<p>I am helpful!</p>' );
- * };
+ * }
* OO.inheritClass( HelpTool, OO.ui.PopupTool );
* HelpTool.static.name = 'help';
* HelpTool.static.icon = 'help';
* include: [ 'picture', 'help' ]
* },
* {
- * // 'list' tool groups display both the titles and icons, in a dropdown list.
- * type: 'list',
+ * // 'menu' tool groups display both the titles and icons, in a dropdown menu.
+ * // Menu label indicates which items are selected.
+ * type: 'menu',
* indicator: 'down',
- * label: 'More',
* include: [ 'settings', 'stuff' ]
* }
- * // Note how the tools themselves are toolgroup-agnostic - the same tool can be displayed
- * // either in a 'list' or a 'bar'. There is a 'menu' tool group too, not showcased here.
* ] );
*
* // Create some UI around the toolbar and place it in the document
* @fires submit
*/
OO.ui.FormLayout.prototype.onFormSubmit = function () {
- this.emit( 'submit' );
- return false;
+ if ( this.emit( 'submit' ) ) {
+ return false;
+ }
};
/**
OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.ClippableElement );
OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.TabIndexedElement );
-/* Static Properties */
-
/* Methods */
/**
/* Static Properties */
-OO.ui.ListToolGroup.static.accelTooltips = true;
-
OO.ui.ListToolGroup.static.name = 'list';
/* Methods */
/* Static Properties */
-OO.ui.MenuToolGroup.static.accelTooltips = true;
-
OO.ui.MenuToolGroup.static.name = 'menu';
/* Methods */
// Properties
this.innerToolGroup = this.createGroup( this.constructor.static.groupConfig );
+ // Events
+ this.innerToolGroup.connect( this, { disable: 'onToolGroupDisable' } );
+
// Initialization
this.$link.remove();
this.$element
return false;
};
+/**
+ * Synchronize disabledness state of the tool with the inner toolgroup.
+ *
+ * @private
+ * @param {boolean} disabled Element is disabled
+ */
+OO.ui.ToolGroupTool.prototype.onToolGroupDisable = function ( disabled ) {
+ this.setDisabled( disabled );
+};
+
/**
* Handle the toolbar state being updated.
*
return OO.ui.ButtonElement.prototype.onMouseUp.call( this, e );
};
-/**
- * @inheritdoc
- */
-OO.ui.ButtonWidget.prototype.onClick = function ( e ) {
- var ret = OO.ui.ButtonElement.prototype.onClick.call( this, e );
- if ( this.href ) {
- return true;
- }
- return ret;
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.ButtonWidget.prototype.onKeyPress = function ( e ) {
- var ret = OO.ui.ButtonElement.prototype.onKeyPress.call( this, e );
- if ( this.href ) {
- return true;
- }
- return ret;
-};
-
/**
* Get hyperlink location.
*
// Events
this.$input.on( {
keypress: this.onKeyPress.bind( this ),
- blur: this.setValidityFlag.bind( this )
+ blur: this.onBlur.bind( this )
} );
this.$input.one( {
focus: this.onElementAttach.bind( this )
}
if ( config.required ) {
this.$input.attr( 'required', 'required' );
+ this.$input.attr( 'aria-required', 'true' );
}
if ( this.label || config.autosize ) {
this.installParentChangeDetector();
}
};
+/**
+ * Handle blur events.
+ *
+ * @private
+ * @param {jQuery.Event} e Blur event
+ */
+OO.ui.TextInputWidget.prototype.onBlur = function () {
+ this.setValidityFlag();
+};
+
/**
* Handle element attach events.
*
/**
* Sets the 'invalid' flag appropriately.
+ *
+ * @param {boolean} [isValid] Optionally override validation result
*/
-OO.ui.TextInputWidget.prototype.setValidityFlag = function () {
- var widget = this;
- this.isValid().done( function ( valid ) {
- if ( !valid ) {
- widget.$input.attr( 'aria-invalid', 'true' );
- } else {
- widget.$input.removeAttr( 'aria-invalid' );
- }
- widget.setFlags( { invalid: !valid } );
- } );
+OO.ui.TextInputWidget.prototype.setValidityFlag = function ( isValid ) {
+ var widget = this,
+ setFlag = function ( valid ) {
+ if ( !valid ) {
+ widget.$input.attr( 'aria-invalid', 'true' );
+ } else {
+ widget.$input.removeAttr( 'aria-invalid' );
+ }
+ widget.setFlags( { invalid: !valid } );
+ };
+
+ if ( isValid !== undefined ) {
+ setFlag( isValid );
+ } else {
+ this.isValid().done( setFlag );
+ }
};
/**
this.anchor = null;
this.width = config.width !== undefined ? config.width : 320;
this.height = config.height !== undefined ? config.height : null;
- // Validate alignment and transform deprecated values
- if ( [ 'left', 'right', 'force-left', 'force-right', 'backwards', 'forwards', 'center' ].indexOf( config.align ) > -1 ) {
- this.align = { left: 'force-right', right: 'force-left' }[ config.align ] || config.align;
- } else {
- this.align = 'center';
- }
+ this.setAlignment( config.align );
this.closeButton = new OO.ui.ButtonWidget( { framed: false, icon: 'close' } );
this.onMouseDownHandler = this.onMouseDown.bind( this );
this.onDocumentKeyDownHandler = this.onDocumentKeyDown.bind( this );
return this;
};
+/**
+ * Set popup alignment
+ * @param {string} align Alignment of the popup, `center`, `force-left`, `force-right`,
+ * `backwards` or `forwards`.
+ */
+OO.ui.PopupWidget.prototype.setAlignment = function ( align ) {
+ // Validate alignment and transform deprecated values
+ if ( [ 'left', 'right', 'force-left', 'force-right', 'backwards', 'forwards', 'center' ].indexOf( align ) > -1 ) {
+ this.align = { left: 'force-right', right: 'force-left' }[ align ] || align;
+ } else {
+ this.align = 'center';
+ }
+};
+
+/**
+ * Get popup alignment
+ * @return {string} align Alignment of the popup, `center`, `force-left`, `force-right`,
+ * `backwards` or `forwards`.
+ */
+OO.ui.PopupWidget.prototype.getAlignment = function () {
+ return this.align;
+};
+
/**
* Progress bars visually display the status of an operation, such as a download,
* and can be either determinate or indeterminate:
*
* [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options
*
+ * @abstract
* @class
* @extends OO.ui.Widget
* @mixins OO.ui.GroupElement