/*!
- * OOUI v0.29.2
+ * OOUI v0.29.4
* https://www.mediawiki.org/wiki/OOUI
*
* Copyright 2011–2018 OOUI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2018-10-08T22:42:55Z
+ * Date: 2018-11-07T00:58:30Z
*/
( function ( OO ) {
// Label for the file selection widget when no file is currently selected
'ooui-selectfile-placeholder': 'No file is selected',
// Label for the file selection widget's drop target
- 'ooui-selectfile-dragdrop-placeholder': 'Drop file here'
+ 'ooui-selectfile-dragdrop-placeholder': 'Drop file here',
+ // Label for the help icon attached to a form field
+ 'ooui-field-help': 'Help'
};
/**
* @param {boolean} [show] Make element visible, omit to toggle visibility
* @fires visible
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.Element.prototype.toggle = function ( show ) {
show = show === undefined ? !this.visible : !!show;
*
* @param {Mixed} data Element data
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.Element.prototype.setData = function ( data ) {
this.data = data;
*
* @param {string} id
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.Element.prototype.setElementId = function ( id ) {
this.elementId = id;
*
* @param {OO.ui.mixin.GroupElement|null} group Group element, null if none
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.Element.prototype.setElementGroup = function ( group ) {
this.elementGroup = group;
OO.inheritClass( OO.ui.Layout, OO.ui.Element );
OO.mixinClass( OO.ui.Layout, OO.EventEmitter );
+/* Methods */
+
+/**
+ * Reset scroll offsets
+ *
+ * @chainable
+ * @return {OO.ui.Layout} The layout, for chaining
+ */
+OO.ui.Layout.prototype.resetScroll = function () {
+ this.$element[ 0 ].scrollTop = 0;
+ // TODO: Reset scrollLeft in an RTL-aware manner, see OO.ui.Element.static.getScrollLeft.
+
+ return this;
+};
+
/**
* Widgets are compositions of one or more OOUI elements that users can both view
* and interact with. All widgets can be configured and modified via a standard API,
*
* @param {boolean} disabled Disable widget
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.Widget.prototype.setDisabled = function ( disabled ) {
var isDisabled;
* Update the disabled state, in case of changes in parent widget.
*
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.Widget.prototype.updateDisabled = function () {
this.setDisabled( this.disabled );
*
* @param {jQuery} $tabIndexed Element that should use the tabindex functionality
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.TabIndexedElement.prototype.setTabIndexedElement = function ( $tabIndexed ) {
var tabIndex = this.tabIndex;
*
* @param {string|number|null} tabIndex Tabindex value, or `null` for no tabindex
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.TabIndexedElement.prototype.setTabIndex = function ( tabIndex ) {
tabIndex = /^-?\d+$/.test( tabIndex ) ? Number( tabIndex ) : null;
*
* @private
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.TabIndexedElement.prototype.updateTabIndex = function () {
if ( this.$tabIndexed ) {
* Focus this element.
*
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.TabIndexedElement.prototype.focus = function () {
if ( !this.isDisabled() ) {
* Blur this element.
*
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.TabIndexedElement.prototype.blur = function () {
this.$tabIndexed.blur();
} );
// Add `role="button"` on `<a>` elements, where it's needed
- // `toUppercase()` is added for XHTML documents
+ // `toUpperCase()` is added for XHTML documents
if ( this.$button.prop( 'tagName' ).toUpperCase() === 'A' ) {
this.$button.attr( 'role', 'button' );
}
*
* @protected
* @param {jQuery.Event} e Mouse down event
+ * @return {undefined/boolean} False to prevent default if event is handled
*/
OO.ui.mixin.ButtonElement.prototype.onMouseDown = function ( e ) {
if ( this.isDisabled() || e.which !== OO.ui.MouseButtons.LEFT ) {
* @protected
* @param {jQuery.Event} e Mouse click event
* @fires click
+ * @return {undefined/boolean} False to prevent default if event is handled
*/
OO.ui.mixin.ButtonElement.prototype.onClick = function ( e ) {
if ( !this.isDisabled() && e.which === OO.ui.MouseButtons.LEFT ) {
* @protected
* @param {jQuery.Event} e Key press event
* @fires click
+ * @return {undefined/boolean} False to prevent default if event is handled
*/
OO.ui.mixin.ButtonElement.prototype.onKeyPress = function ( e ) {
if ( !this.isDisabled() && ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER ) ) {
*
* @param {boolean} [framed] Make button framed, omit to toggle
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.ButtonElement.prototype.toggleFramed = function ( framed ) {
framed = framed === undefined ? !this.framed : !!framed;
* @protected
* @param {boolean} value Make button active
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.ButtonElement.prototype.setActive = function ( value ) {
this.active = !!value;
* @param {OO.ui.Element[]} items An array of items to add to the group
* @param {number} [index] Index of the insertion point
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.GroupElement.prototype.addItems = function ( items, index ) {
// Mixin method
*
* @param {OO.ui.Element[]} items An array of items to remove
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.GroupElement.prototype.removeItems = function ( items ) {
var i, len, item, index;
* To remove only a subset of items from a group, use the #removeItems method.
*
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.GroupElement.prototype.clearItems = function () {
var i, len;
return this;
};
+/**
+ * LabelElement is often mixed into other classes to generate a label, which
+ * helps identify the function of an interface element.
+ * See the [OOUI documentation on MediaWiki] [1] for more information.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Icons,_Indicators,_and_Labels#Labels
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$label] The label element created by the class. If this
+ * configuration is omitted, the label element will use a generated `<span>`.
+ * @cfg {jQuery|string|Function|OO.ui.HtmlSnippet} [label] The label text. The label can be specified
+ * as a plaintext string, a jQuery selection of elements, or a function that will produce a string
+ * in the future. See the [OOUI documentation on MediaWiki] [2] for examples.
+ * [2]: https://www.mediawiki.org/wiki/OOUI/Widgets/Icons,_Indicators,_and_Labels#Labels
+ * @cfg {boolean} [invisibleLabel] Whether the label should be visually hidden (but still accessible
+ * to screen-readers).
+ */
+OO.ui.mixin.LabelElement = function OoUiMixinLabelElement( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties
+ this.$label = null;
+ this.label = null;
+ this.invisibleLabel = null;
+
+ // Initialization
+ this.setLabel( config.label || this.constructor.static.label );
+ this.setLabelElement( config.$label || $( '<span>' ) );
+ this.setInvisibleLabel( config.invisibleLabel );
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.mixin.LabelElement );
+
+/* Events */
+
+/**
+ * @event labelChange
+ * @param {string} value
+ */
+
+/* Static Properties */
+
+/**
+ * The label text. The label can be specified as a plaintext string, a function that will
+ * produce a string in the future, or `null` for no label. The static value will
+ * be overridden if a label is specified with the #label config option.
+ *
+ * @static
+ * @inheritable
+ * @property {string|Function|null}
+ */
+OO.ui.mixin.LabelElement.static.label = null;
+
+/* Static methods */
+
+/**
+ * Highlight the first occurrence of the query in the given text
+ *
+ * @param {string} text Text
+ * @param {string} query Query to find
+ * @param {Function} [compare] Optional string comparator, e.g. Intl.Collator().compare
+ * @return {jQuery} Text with the first match of the query
+ * sub-string wrapped in highlighted span
+ */
+OO.ui.mixin.LabelElement.static.highlightQuery = function ( text, query, compare ) {
+ var i, tLen, qLen,
+ offset = -1,
+ $result = $( '<span>' );
+
+ if ( compare ) {
+ tLen = text.length;
+ qLen = query.length;
+ for ( i = 0; offset === -1 && i <= tLen - qLen; i++ ) {
+ if ( compare( query, text.slice( i, i + qLen ) ) === 0 ) {
+ offset = i;
+ }
+ }
+ } else {
+ offset = text.toLowerCase().indexOf( query.toLowerCase() );
+ }
+
+ if ( !query.length || offset === -1 ) {
+ $result.text( text );
+ } else {
+ $result.append(
+ document.createTextNode( text.slice( 0, offset ) ),
+ $( '<span>' )
+ .addClass( 'oo-ui-labelElement-label-highlight' )
+ .text( text.slice( offset, offset + query.length ) ),
+ document.createTextNode( text.slice( offset + query.length ) )
+ );
+ }
+ return $result.contents();
+};
+
+/* Methods */
+
+/**
+ * Set the label element.
+ *
+ * If an element is already set, it will be cleaned up before setting up the new element.
+ *
+ * @param {jQuery} $label Element to use as label
+ */
+OO.ui.mixin.LabelElement.prototype.setLabelElement = function ( $label ) {
+ if ( this.$label ) {
+ this.$label.removeClass( 'oo-ui-labelElement-label' ).empty();
+ }
+
+ this.$label = $label.addClass( 'oo-ui-labelElement-label' );
+ this.setLabelContent( this.label );
+};
+
+/**
+ * Set the label.
+ *
+ * An empty string will result in the label being hidden. A string containing only whitespace will
+ * be converted to a single ` `.
+ *
+ * @param {jQuery|string|OO.ui.HtmlSnippet|Function|null} label Label nodes; text; a function that returns nodes or
+ * text; or null for no label
+ * @chainable
+ * @return {OO.ui.Element} The element, for chaining
+ */
+OO.ui.mixin.LabelElement.prototype.setLabel = function ( label ) {
+ label = typeof label === 'function' ? OO.ui.resolveMsg( label ) : label;
+ label = ( ( typeof label === 'string' || label instanceof jQuery ) && label.length ) || ( label instanceof OO.ui.HtmlSnippet && label.toString().length ) ? label : null;
+
+ if ( this.label !== label ) {
+ if ( this.$label ) {
+ this.setLabelContent( label );
+ }
+ this.label = label;
+ this.emit( 'labelChange' );
+ }
+
+ this.$element.toggleClass( 'oo-ui-labelElement', !!this.label && !this.invisibleLabel );
+
+ return this;
+};
+
+/**
+ * Set whether the label should be visually hidden (but still accessible to screen-readers).
+ *
+ * @param {boolean} invisibleLabel
+ * @chainable
+ * @return {OO.ui.Element} The element, for chaining
+ */
+OO.ui.mixin.LabelElement.prototype.setInvisibleLabel = function ( invisibleLabel ) {
+ invisibleLabel = !!invisibleLabel;
+
+ if ( this.invisibleLabel !== invisibleLabel ) {
+ this.invisibleLabel = invisibleLabel;
+ this.emit( 'labelChange' );
+ }
+
+ this.$label.toggleClass( 'oo-ui-labelElement-invisible', this.invisibleLabel );
+ // Pretend that there is no label, a lot of CSS has been written with this assumption
+ this.$element.toggleClass( 'oo-ui-labelElement', !!this.label && !this.invisibleLabel );
+
+ return this;
+};
+
+/**
+ * Set the label as plain text with a highlighted query
+ *
+ * @param {string} text Text label to set
+ * @param {string} query Substring of text to highlight
+ * @param {Function} [compare] Optional string comparator, e.g. Intl.Collator().compare
+ * @chainable
+ * @return {OO.ui.Element} The element, for chaining
+ */
+OO.ui.mixin.LabelElement.prototype.setHighlightedQuery = function ( text, query, compare ) {
+ return this.setLabel( this.constructor.static.highlightQuery( text, query, compare ) );
+};
+
+/**
+ * Get the label.
+ *
+ * @return {jQuery|string|Function|null} Label nodes; text; a function that returns nodes or
+ * text; or null for no label
+ */
+OO.ui.mixin.LabelElement.prototype.getLabel = function () {
+ return this.label;
+};
+
+/**
+ * Set the content of the label.
+ *
+ * Do not call this method until after the label element has been set by #setLabelElement.
+ *
+ * @private
+ * @param {jQuery|string|Function|null} label Label nodes; text; a function that returns nodes or
+ * text; or null for no label
+ */
+OO.ui.mixin.LabelElement.prototype.setLabelContent = function ( label ) {
+ if ( typeof label === 'string' ) {
+ if ( label.match( /^\s*$/ ) ) {
+ // Convert whitespace only string to a single non-breaking space
+ this.$label.html( ' ' );
+ } else {
+ this.$label.text( label );
+ }
+ } else if ( label instanceof OO.ui.HtmlSnippet ) {
+ this.$label.html( label.toString() );
+ } else if ( label instanceof jQuery ) {
+ this.$label.empty().append( label );
+ } else {
+ this.$label.empty();
+ }
+};
+
/**
* IconElement is often mixed into other classes to generate an icon.
* Icons are graphics, about the size of normal text. They are used to aid the user
* @param {Object|string|null} icon A symbolic icon name, a {@link #icon map of icon names} keyed
* by language code, or `null` to remove the icon.
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.IconElement.prototype.setIcon = function ( icon ) {
icon = OO.isPlainObject( icon ) ? OO.ui.getLocalValue( icon, null, 'default' ) : icon;
* @param {string|Function|null} iconTitle A text string used as the icon title,
* a function that returns title text, or `null` for no title.
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.IconElement.prototype.setIconTitle = function ( iconTitle ) {
iconTitle =
*
* @param {string|null} indicator Symbolic name of indicator, or `null` for no indicator
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.IndicatorElement.prototype.setIndicator = function ( indicator ) {
indicator = typeof indicator === 'string' && indicator.length ? indicator.trim() : null;
* @param {string|Function|null} indicatorTitle Indicator title text, a function that returns text, or
* `null` for no indicator title
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.IndicatorElement.prototype.setIndicatorTitle = function ( indicatorTitle ) {
indicatorTitle =
return this.indicatorTitle;
};
-/**
- * LabelElement is often mixed into other classes to generate a label, which
- * helps identify the function of an interface element.
- * See the [OOUI documentation on MediaWiki] [1] for more information.
- *
- * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Icons,_Indicators,_and_Labels#Labels
- *
- * @abstract
- * @class
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {jQuery} [$label] The label element created by the class. If this
- * configuration is omitted, the label element will use a generated `<span>`.
- * @cfg {jQuery|string|Function|OO.ui.HtmlSnippet} [label] The label text. The label can be specified
- * as a plaintext string, a jQuery selection of elements, or a function that will produce a string
- * in the future. See the [OOUI documentation on MediaWiki] [2] for examples.
- * [2]: https://www.mediawiki.org/wiki/OOUI/Widgets/Icons,_Indicators,_and_Labels#Labels
- */
-OO.ui.mixin.LabelElement = function OoUiMixinLabelElement( config ) {
- // Configuration initialization
- config = config || {};
-
- // Properties
- this.$label = null;
- this.label = null;
-
- // Initialization
- this.setLabel( config.label || this.constructor.static.label );
- this.setLabelElement( config.$label || $( '<span>' ) );
-};
-
-/* Setup */
-
-OO.initClass( OO.ui.mixin.LabelElement );
-
-/* Events */
-
-/**
- * @event labelChange
- * @param {string} value
- */
-
-/* Static Properties */
-
-/**
- * The label text. The label can be specified as a plaintext string, a function that will
- * produce a string in the future, or `null` for no label. The static value will
- * be overridden if a label is specified with the #label config option.
- *
- * @static
- * @inheritable
- * @property {string|Function|null}
- */
-OO.ui.mixin.LabelElement.static.label = null;
-
-/* Static methods */
-
-/**
- * Highlight the first occurrence of the query in the given text
- *
- * @param {string} text Text
- * @param {string} query Query to find
- * @param {Function} [compare] Optional string comparator, e.g. Intl.Collator().compare
- * @return {jQuery} Text with the first match of the query
- * sub-string wrapped in highlighted span
- */
-OO.ui.mixin.LabelElement.static.highlightQuery = function ( text, query, compare ) {
- var i, tLen, qLen,
- offset = -1,
- $result = $( '<span>' );
-
- if ( compare ) {
- tLen = text.length;
- qLen = query.length;
- for ( i = 0; offset === -1 && i <= tLen - qLen; i++ ) {
- if ( compare( query, text.slice( i, i + qLen ) ) === 0 ) {
- offset = i;
- }
- }
- } else {
- offset = text.toLowerCase().indexOf( query.toLowerCase() );
- }
-
- if ( !query.length || offset === -1 ) {
- $result.text( text );
- } else {
- $result.append(
- document.createTextNode( text.slice( 0, offset ) ),
- $( '<span>' )
- .addClass( 'oo-ui-labelElement-label-highlight' )
- .text( text.slice( offset, offset + query.length ) ),
- document.createTextNode( text.slice( offset + query.length ) )
- );
- }
- return $result.contents();
-};
-
-/* Methods */
-
-/**
- * Set the label element.
- *
- * If an element is already set, it will be cleaned up before setting up the new element.
- *
- * @param {jQuery} $label Element to use as label
- */
-OO.ui.mixin.LabelElement.prototype.setLabelElement = function ( $label ) {
- if ( this.$label ) {
- this.$label.removeClass( 'oo-ui-labelElement-label' ).empty();
- }
-
- this.$label = $label.addClass( 'oo-ui-labelElement-label' );
- this.setLabelContent( this.label );
-};
-
-/**
- * Set the label.
- *
- * An empty string will result in the label being hidden. A string containing only whitespace will
- * be converted to a single ` `.
- *
- * @param {jQuery|string|OO.ui.HtmlSnippet|Function|null} label Label nodes; text; a function that returns nodes or
- * text; or null for no label
- * @chainable
- */
-OO.ui.mixin.LabelElement.prototype.setLabel = function ( label ) {
- label = typeof label === 'function' ? OO.ui.resolveMsg( label ) : label;
- label = ( ( typeof label === 'string' || label instanceof jQuery ) && label.length ) || ( label instanceof OO.ui.HtmlSnippet && label.toString().length ) ? label : null;
-
- if ( this.label !== label ) {
- if ( this.$label ) {
- this.setLabelContent( label );
- }
- this.label = label;
- this.emit( 'labelChange' );
- }
-
- this.$element.toggleClass( 'oo-ui-labelElement', !!this.label );
-
- return this;
-};
-
-/**
- * Set the label as plain text with a highlighted query
- *
- * @param {string} text Text label to set
- * @param {string} query Substring of text to highlight
- * @param {Function} [compare] Optional string comparator, e.g. Intl.Collator().compare
- * @chainable
- */
-OO.ui.mixin.LabelElement.prototype.setHighlightedQuery = function ( text, query, compare ) {
- return this.setLabel( this.constructor.static.highlightQuery( text, query, compare ) );
-};
-
-/**
- * Get the label.
- *
- * @return {jQuery|string|Function|null} Label nodes; text; a function that returns nodes or
- * text; or null for no label
- */
-OO.ui.mixin.LabelElement.prototype.getLabel = function () {
- return this.label;
-};
-
-/**
- * Set the content of the label.
- *
- * Do not call this method until after the label element has been set by #setLabelElement.
- *
- * @private
- * @param {jQuery|string|Function|null} label Label nodes; text; a function that returns nodes or
- * text; or null for no label
- */
-OO.ui.mixin.LabelElement.prototype.setLabelContent = function ( label ) {
- if ( typeof label === 'string' ) {
- if ( label.match( /^\s*$/ ) ) {
- // Convert whitespace only string to a single non-breaking space
- this.$label.html( ' ' );
- } else {
- this.$label.text( label );
- }
- } else if ( label instanceof OO.ui.HtmlSnippet ) {
- this.$label.html( label.toString() );
- } else if ( label instanceof jQuery ) {
- this.$label.empty().append( label );
- } else {
- this.$label.empty();
- }
-};
-
/**
* The FlaggedElement class is an attribute mixin, meaning that it is used to add
* additional functionality to an element created by another class. The class provides
* Clear all flags.
*
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
* @fires flag
*/
OO.ui.mixin.FlaggedElement.prototype.clearFlags = function () {
* or an object keyed by flag name with a boolean value that indicates whether the flag should
* be added (`true`) or removed (`false`).
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
* @fires flag
*/
OO.ui.mixin.FlaggedElement.prototype.setFlags = function ( flags ) {
/**
* Set the titled element.
*
- * This method is used to retarget a titledElement mixin so that its functionality applies to the specified element.
+ * This method is used to retarget a TitledElement mixin so that its functionality applies to the specified element.
* If an element is already set, the mixin’s effect on that element is removed before the new element is set up.
*
* @param {jQuery} $titled Element that should use the 'titled' functionality
*
* @param {string|Function|null} title Title text, a function that returns text, or `null` for no title
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.TitledElement.prototype.setTitle = function ( title ) {
title = typeof title === 'function' ? OO.ui.resolveMsg( title ) : title;
*
* @protected
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.TitledElement.prototype.updateTitle = function () {
var title = this.getTitle();
* This method is used to retarget a AccessKeyedElement mixin so that its functionality applies to the specified element.
* If an element is already set, the mixin's effect on that element is removed before the new element is set up.
*
- * @param {jQuery} $accessKeyed Element that should use the 'accesskeyes' functionality
+ * @param {jQuery} $accessKeyed Element that should use the 'accesskeyed' functionality
*/
OO.ui.mixin.AccessKeyedElement.prototype.setAccessKeyedElement = function ( $accessKeyed ) {
if ( this.$accessKeyed ) {
*
* @param {string|Function|null} accessKey Key, a function that returns a key, or `null` for no accesskey
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.AccessKeyedElement.prototype.setAccessKey = function ( accessKey ) {
accessKey = typeof accessKey === 'string' ? OO.ui.resolveMsg( accessKey ) : null;
* Set hyperlink location.
*
* @param {string|null} href Hyperlink location, null to remove
+ * @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.ButtonWidget.prototype.setHref = function ( href ) {
href = typeof href === 'string' ? href : null;
*
* @private
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.ButtonWidget.prototype.updateHref = function () {
if ( this.href !== null && !this.isDisabled() ) {
* Set hyperlink target.
*
* @param {string|null} target Hyperlink target, null to remove
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.ButtonWidget.prototype.setTarget = function ( target ) {
target = typeof target === 'string' ? target : null;
* Set search engine traversal hint.
*
* @param {boolean} noFollow True if search engines should avoid traversing this hyperlink
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.ButtonWidget.prototype.setNoFollow = function ( noFollow ) {
noFollow = typeof noFollow === 'boolean' ? noFollow : true;
* Focus the widget
*
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.ButtonGroupWidget.prototype.focus = function () {
if ( !this.isDisabled() ) {
* @extends OO.ui.Widget
* @mixins OO.ui.mixin.IconElement
* @mixins OO.ui.mixin.TitledElement
+ * @mixins OO.ui.mixin.LabelElement
* @mixins OO.ui.mixin.FlaggedElement
*
* @constructor
// Mixin constructors
OO.ui.mixin.IconElement.call( this, $.extend( {}, config, { $icon: this.$element } ) );
OO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$element } ) );
+ OO.ui.mixin.LabelElement.call( this, $.extend( {}, config, { $label: this.$element, invisibleLabel: true } ) );
OO.ui.mixin.FlaggedElement.call( this, $.extend( {}, config, { $flagged: this.$element } ) );
// Initialization
this.$element.addClass( 'oo-ui-iconWidget' );
+ // Remove class added by LabelElement initialization. It causes unexpected CSS to apply when
+ // nested in other widgets, because this widget used to not mix in LabelElement.
+ this.$element.removeClass( 'oo-ui-labelElement-label' );
};
/* Setup */
OO.inheritClass( OO.ui.IconWidget, OO.ui.Widget );
OO.mixinClass( OO.ui.IconWidget, OO.ui.mixin.IconElement );
OO.mixinClass( OO.ui.IconWidget, OO.ui.mixin.TitledElement );
+OO.mixinClass( OO.ui.IconWidget, OO.ui.mixin.LabelElement );
OO.mixinClass( OO.ui.IconWidget, OO.ui.mixin.FlaggedElement );
/* Static Properties */
* @extends OO.ui.Widget
* @mixins OO.ui.mixin.IndicatorElement
* @mixins OO.ui.mixin.TitledElement
+ * @mixins OO.ui.mixin.LabelElement
*
* @constructor
* @param {Object} [config] Configuration options
// Mixin constructors
OO.ui.mixin.IndicatorElement.call( this, $.extend( {}, config, { $indicator: this.$element } ) );
OO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$element } ) );
+ OO.ui.mixin.LabelElement.call( this, $.extend( {}, config, { $label: this.$element, invisibleLabel: true } ) );
// Initialization
this.$element.addClass( 'oo-ui-indicatorWidget' );
+ // Remove class added by LabelElement initialization. It causes unexpected CSS to apply when
+ // nested in other widgets, because this widget used to not mix in LabelElement.
+ this.$element.removeClass( 'oo-ui-labelElement-label' );
};
/* Setup */
OO.inheritClass( OO.ui.IndicatorWidget, OO.ui.Widget );
OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.mixin.IndicatorElement );
OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.mixin.TitledElement );
+OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.mixin.LabelElement );
/* Static Properties */
* (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 ) {
* (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 ) {
* 'center': Vertically align the center with $floatableContainer's center
* @cfg {string} [horizontalPosition='start'] Where to position $floatable horizontally:
* 'before': Directly before $floatableContainer, aligning f's end edge with fC's start edge
- * 'after': Directly after $floatableContainer, algining f's start edge with fC's end edge
+ * 'after': Directly after $floatableContainer, aligning f's start edge with fC's end edge
* 'start': Align the start (left in LTR, right in RTL) edge with $floatableContainer's start edge
* 'end': Align the end (right in LTR, left in RTL) edge with $floatableContainer's end edge
* 'center': Horizontally align the center with $floatableContainer's center
*
* @param {boolean} [positioning] Enable positioning, omit to toggle
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.FloatableElement.prototype.togglePositioning = function ( positioning ) {
var closestScrollableOfContainer;
if ( this.positioning !== positioning ) {
this.positioning = positioning;
- this.needsCustomPosition =
- this.verticalPostion !== 'below' ||
- this.horizontalPosition !== 'start' ||
- !OO.ui.contains( this.$floatableContainer[ 0 ], this.$floatable[ 0 ] );
-
closestScrollableOfContainer = OO.ui.Element.static.getClosestScrollableContainer( this.$floatableContainer[ 0 ] );
// If the scrollable is the root, we have to listen to scroll events
// on the window because of browser inconsistencies.
* This should only be done when both of them are attached to the DOM and visible.
*
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.FloatableElement.prototype.position = function () {
if ( !this.positioning ) {
this.$floatable.removeClass( 'oo-ui-element-hidden' );
}
- if ( !this.needsCustomPosition ) {
- return this;
- }
-
this.$floatable.css( this.computePosition() );
// We updated the position, so re-evaluate the clipping state.
*
* @param {boolean} [clipping] Enable clipping, omit to toggle
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.ClippableElement.prototype.toggleClipping = function ( clipping ) {
clipping = clipping === undefined ? !this.clipping : !!clipping;
* beyond the edge, something reasonable will happen before clip() is called.
*
* @chainable
+ * @return {OO.ui.Element} The element, for chaining
*/
OO.ui.mixin.ClippableElement.prototype.clip = function () {
var extraHeight, extraWidth, viewportSpacing,
*
* @param {boolean} disabled Disable widget
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.mixin.GroupWidget.prototype.setDisabled = function ( disabled ) {
var i, len;
*
* @param {OO.ui.mixin.GroupElement|null} group Group element, null if none
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.mixin.ItemWidget.prototype.setElementGroup = function ( group ) {
// Parent method
*
* @param {boolean} [state=false] Select option
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.OptionWidget.prototype.setSelected = function ( state ) {
if ( this.constructor.static.selectable ) {
*
* @param {boolean} [state=false] Highlight option
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.OptionWidget.prototype.setHighlighted = function ( state ) {
if ( this.constructor.static.highlightable ) {
*
* @param {boolean} [state=false] Press option
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.OptionWidget.prototype.setPressed = function ( state ) {
if ( this.constructor.static.pressable ) {
*
* @private
* @param {jQuery.Event} e Mouse down event
+ * @return {undefined/boolean} False to prevent default if event is handled
*/
OO.ui.SelectWidget.prototype.onMouseDown = function ( e ) {
var item;
*
* @private
* @param {MouseEvent} e Mouse up event
+ * @return {undefined/boolean} False to prevent default if event is handled
*/
OO.ui.SelectWidget.prototype.onDocumentMouseUp = function ( e ) {
var item;
*
* @private
* @param {jQuery.Event} e Mouse over event
+ * @return {undefined/boolean} False to prevent default if event is handled
*/
OO.ui.SelectWidget.prototype.onMouseOver = function ( e ) {
var item;
*
* @private
* @param {jQuery.Event} e Mouse over event
+ * @return {undefined/boolean} False to prevent default if event is handled
*/
OO.ui.SelectWidget.prototype.onMouseLeave = function () {
if ( !this.isDisabled() ) {
*
* @protected
* @param {KeyboardEvent} e Key press event
+ * @return {undefined/boolean} False to prevent default if event is handled
*/
OO.ui.SelectWidget.prototype.onDocumentKeyPress = function ( e ) {
var c, filter, item;
// Deprecated alias since 0.28.3
OO.ui.SelectWidget.prototype.unbindKeyPressListener = function () {
- OO.ui.warnDeprecation( 'unbindDocumentKeyPressListener is deprecated, use unbindDocumentKeyPressListener instead' );
+ OO.ui.warnDeprecation( 'unbindKeyPressListener is deprecated, use unbindDocumentKeyPressListener instead' );
this.unbindDocumentKeyPressListener.apply( this, arguments );
};
* @param {OO.ui.OptionWidget} [item] Item to highlight, omit for no highlight
* @fires highlight
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.SelectWidget.prototype.highlightItem = function ( item ) {
var i, len, highlighted,
* @param {boolean} [prefix=false] Allow a prefix match, if only a single item matches
* @fires select
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.SelectWidget.prototype.selectItemByLabel = function ( label, prefix ) {
var itemFromLabel = this.getItemFromLabel( label, !!prefix );
* @param {Object|string} [data] Value of the item to select, omit to deselect all
* @fires select
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.SelectWidget.prototype.selectItemByData = function ( data ) {
var itemFromData = this.findItemFromData( data );
* @param {OO.ui.OptionWidget} [item] Item to select, omit to deselect all
* @fires select
* @chainable
- */
+ * @return {OO.ui.Widget} The widget, for chaining
+*/
OO.ui.SelectWidget.prototype.selectItem = function ( item ) {
var i, len, selected,
changed = false;
* @param {OO.ui.OptionWidget} [item] Item to press, omit to depress all
* @fires press
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.SelectWidget.prototype.pressItem = function ( item ) {
var i, len, pressed,
* @param {OO.ui.OptionWidget} item Item to choose
* @fires choose
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.SelectWidget.prototype.chooseItem = function ( item ) {
if ( item ) {
* @param {number} [index] Index to insert items after
* @fires add
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.SelectWidget.prototype.addItems = function ( items, index ) {
// Mixin method
* @param {OO.ui.OptionWidget[]} items Items to remove
* @fires remove
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.SelectWidget.prototype.removeItems = function ( items ) {
var i, len, item;
*
* @fires remove
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.SelectWidget.prototype.clearItems = function () {
var items = this.items.slice();
*
* @param {OO.ui.OptionWidget} item Item to choose
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.MenuSelectWidget.prototype.chooseItem = function ( item ) {
OO.ui.MenuSelectWidget.parent.prototype.chooseItem.call( this, item );
click: this.onClick.bind( this ),
keydown: this.onKeyDown.bind( this ),
// Hack? Handle type-to-search when menu is not expanded and not handling its own events
- keypress: this.menu.onKeyPressHandler,
+ keypress: this.menu.onDocumentKeyPressHandler,
blur: this.menu.clearKeyPressBuffer.bind( this.menu )
} );
this.menu.connect( this, {
*
* @private
* @param {jQuery.Event} e Mouse click event
+ * @return {undefined/boolean} False to prevent default if event is handled
*/
OO.ui.DropdownWidget.prototype.onClick = function ( e ) {
if ( !this.isDisabled() && e.which === OO.ui.MouseButtons.LEFT ) {
*
* @private
* @param {jQuery.Event} e Key down event
+ * @return {undefined/boolean} False to prevent default if event is handled
*/
OO.ui.DropdownWidget.prototype.onKeyDown = function ( e ) {
if (
*
* @param {boolean} [state=false] Select option
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.MultioptionWidget.prototype.setSelected = function ( state ) {
state = !!state;
*
* @param {OO.ui.MultioptionWidget[]} items Items to select
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.MultiselectWidget.prototype.selectItems = function ( items ) {
this.items.forEach( function ( item ) {
*
* @param {Object[]|string[]} datas Values of items to select
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.MultiselectWidget.prototype.selectItemsByData = function ( datas ) {
var items,
* Focus the widget
*
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.CheckboxMultiselectWidget.prototype.focus = function () {
var item;
*
* @param {string} dir Text directionality: 'ltr', 'rtl' or 'auto'
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.InputWidget.prototype.setDir = function ( dir ) {
this.$input.prop( 'dir', dir );
* @param {string} value New value
* @fires change
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.InputWidget.prototype.setValue = function ( value ) {
value = this.cleanUpValue( value );
*
* @param {string} id
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.InputWidget.prototype.setInputId = function ( id ) {
this.$input.attr( 'id', id );
* @param {jQuery|string|Function|null} label Label nodes, text, a function that returns nodes or
* text, or `null` for no label
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.ButtonInputWidget.prototype.setLabel = function ( label ) {
if ( typeof label === 'function' ) {
*
* @param {string} value New value
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.ButtonInputWidget.prototype.setValue = function ( value ) {
if ( !this.useInputTag ) {
*
* @param {boolean} state `true` for selected
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.CheckboxInputWidget.prototype.setSelected = function ( state ) {
state = !!state;
*
* @param {Object[]} options Array of menu options in the format `{ data: …, label: … }`
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.DropdownInputWidget.prototype.setOptions = function ( options ) {
var value = this.getValue();
*
* @param {boolean} state `true` for selected
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.RadioInputWidget.prototype.setSelected = function ( state ) {
// RadioInputWidget doesn't track its state.
*
* @param {Object[]} options Array of menu options in the format `{ data: …, label: … }`
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.RadioSelectInputWidget.prototype.setOptions = function ( options ) {
var value = this.getValue();
*
* @param {Object[]} options Array of menu options in the format `{ data: …, label: …, disabled: … }`
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.CheckboxMultiselectInputWidget.prototype.setOptions = function ( options ) {
var value = this.getValue();
*
* @private
* @param {jQuery.Event} e Mouse down event
+ * @return {undefined/boolean} False to prevent default if event is handled
*/
OO.ui.TextInputWidget.prototype.onIconMouseDown = function ( e ) {
if ( e.which === OO.ui.MouseButtons.LEFT ) {
*
* @private
* @param {jQuery.Event} e Mouse down event
+ * @return {undefined/boolean} False to prevent default if event is handled
*/
OO.ui.TextInputWidget.prototype.onIndicatorMouseDown = function ( e ) {
if ( e.which === OO.ui.MouseButtons.LEFT ) {
*
* @param {boolean} state Make input read-only
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.TextInputWidget.prototype.setReadOnly = function ( state ) {
this.readOnly = !!state;
*
* @param {boolean} state Make input required
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.TextInputWidget.prototype.setRequired = function ( state ) {
this.required = !!state;
* @param {number} from Select from offset
* @param {number} [to] Select to offset, defaults to from
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.TextInputWidget.prototype.selectRange = function ( from, to ) {
var isBackwards, start, end,
* Focus the input and select the entire text.
*
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.TextInputWidget.prototype.select = function () {
return this.selectRange( 0, this.getInputLength() );
* Focus the input and move the cursor to the start.
*
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.TextInputWidget.prototype.moveCursorToStart = function () {
return this.selectRange( 0 );
* Focus the input and move the cursor to the end.
*
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.TextInputWidget.prototype.moveCursorToEnd = function () {
return this.selectRange( this.getInputLength() );
*
* @param {string} content Content to be inserted
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.TextInputWidget.prototype.insertContent = function ( content ) {
var start, end,
* @param {string} pre Content to be inserted before the selection
* @param {string} post Content to be inserted after the selection
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.TextInputWidget.prototype.encapsulateContent = function ( pre, post ) {
var start, end,
*
* @param {string} labelPosition Label position, 'before' or 'after'
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.TextInputWidget.prototype.setLabelPosition = function ( labelPosition ) {
this.labelPosition = labelPosition;
* something causes the label to be mispositioned.
*
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.TextInputWidget.prototype.updatePosition = function () {
var after = this.labelPosition === 'after';
*
* @private
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.TextInputWidget.prototype.positionLabel = function () {
var after, rtl, property, newCss;
* This only affects multiline inputs that are {@link #autosize autosized}.
*
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
* @fires resize
*/
OO.ui.MultilineTextInputWidget.prototype.adjustSize = function () {
*
* @param {Object[]} options Array of menu options in the format `{ data: …, label: … }`
* @chainable
+ * @return {OO.ui.Widget} The widget, for chaining
*/
OO.ui.ComboBoxInputWidget.prototype.setOptions = function ( options ) {
this.getMenu()
* - accessed via a help icon that appears in the upper right corner of the rendered field layout, or
* - shown as a subtle explanation below the label.
*
- * If the help text is brief, or is essential to always espose it, set `helpInline` to `true`. If it
+ * If the help text is brief, or is essential to always expose it, set `helpInline` to `true`. If it
* is long or not essential, leave `helpInline` to its default, `false`.
*
* Please see the [OOUI documentation on MediaWiki] [1] for examples and more information.
* @private
* @param {string} value Alignment mode, either 'left', 'right', 'top' or 'inline'
* @chainable
+ * @return {OO.ui.BookletLayout} The layout, for chaining
*/
OO.ui.FieldLayout.prototype.setAlignment = function ( value ) {
if ( value !== this.align ) {
* @param {Array} errors Error messages about the widget, which will be displayed below the widget.
* The array may contain strings or OO.ui.HtmlSnippet instances.
* @chainable
+ * @return {OO.ui.BookletLayout} The layout, for chaining
*/
OO.ui.FieldLayout.prototype.setErrors = function ( errors ) {
this.errors = errors.slice();
* @param {Array} notices Notices about the widget, which will be displayed below the widget.
* The array may contain strings or OO.ui.HtmlSnippet instances.
* @chainable
+ * @return {OO.ui.BookletLayout} The layout, for chaining
*/
OO.ui.FieldLayout.prototype.setNotices = function ( notices ) {
this.notices = notices.slice();
classes: [ 'oo-ui-fieldLayout-help' ],
framed: false,
icon: 'info',
- label: OO.ui.msg( 'ooui-field-help' )
+ label: OO.ui.msg( 'ooui-field-help' ),
+ invisibleLabel: true
} );
if ( help instanceof OO.ui.HtmlSnippet ) {
helpWidget.getPopup().$body.html( help.toString() );
classes: [ 'oo-ui-fieldsetLayout-help' ],
framed: false,
icon: 'info',
- label: OO.ui.msg( 'ooui-field-help' )
+ label: OO.ui.msg( 'ooui-field-help' ),
+ invisibleLabel: true
} );
if ( config.help instanceof OO.ui.HtmlSnippet ) {
this.popupButtonWidget.getPopup().$body.html( config.help.toString() );
* @private
* @param {jQuery.Event} e Submit event
* @fires submit
+ * @return {OO.ui.FormLayout} The layout, for chaining
*/
OO.ui.FormLayout.prototype.onFormSubmit = function () {
if ( this.emit( 'submit' ) ) {
*
* @private
* @param {jQuery.Event} event
+ * @return {undefined/boolean} False to prevent default if event is handled
*/
OO.ui.NumberInputWidget.prototype.onWheel = function ( event ) {
var delta = 0;
*
* @private
* @param {jQuery.Event} e Key down event
+ * @return {undefined/boolean} False to prevent default if event is handled
*/
OO.ui.NumberInputWidget.prototype.onKeyDown = function ( e ) {
if ( !this.isDisabled() ) {