Merge "Align "What's this" vertically"
[lhc/web/wiklou.git] / resources / lib / oojs-ui / oojs-ui-core.js
index a988269..c92ab4d 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.22.4
+ * OOjs UI v0.23.0
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2017 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2017-08-03T19:36:51Z
+ * Date: 2017-09-05T21:23:58Z
  */
 ( function ( OO ) {
 
@@ -362,6 +362,8 @@ OO.ui.infuse = function ( idOrNode ) {
                'ooui-toolgroup-expand': 'More',
                // Label for the fake tool that collapses the full list of tools in a toolbar group
                'ooui-toolgroup-collapse': 'Fewer',
+               // Default label for the tooltip for the button that removes a tag item
+               'ooui-item-remove': 'Remove',
                // Default label for the accept button of a confirmation dialog
                'ooui-dialog-message-accept': 'OK',
                // Default label for the reject button of a confirmation dialog
@@ -659,7 +661,7 @@ OO.ui.Element.static.tagName = 'div';
 OO.ui.Element.static.infuse = function ( idOrNode ) {
        var obj = OO.ui.Element.static.unsafeInfuse( idOrNode, false );
        // Verify that the type matches up.
-       // FIXME: uncomment after T89721 is fixed (see T90929)
+       // FIXME: uncomment after T89721 is fixed, see T90929.
        /*
        if ( !( obj instanceof this['class'] ) ) {
                throw new Error( 'Infusion type mismatch!' );
@@ -681,7 +683,7 @@ OO.ui.Element.static.infuse = function ( idOrNode ) {
  */
 OO.ui.Element.static.unsafeInfuse = function ( idOrNode, domPromise ) {
        // look for a cached result of a previous infusion.
-       var id, $elem, data, cls, parts, parent, obj, top, state, infusedChildren;
+       var id, $elem, error, data, cls, parts, parent, obj, top, state, infusedChildren;
        if ( typeof idOrNode === 'string' ) {
                id = idOrNode;
                $elem = $( document.getElementById( id ) );
@@ -690,7 +692,14 @@ OO.ui.Element.static.unsafeInfuse = function ( idOrNode, domPromise ) {
                id = $elem.attr( 'id' );
        }
        if ( !$elem.length ) {
-               throw new Error( 'Widget not found: ' + id );
+               if ( typeof idOrNode === 'string' ) {
+                       error = 'Widget not found: ' + idOrNode;
+               } else if ( idOrNode && idOrNode.selector ) {
+                       error = 'Widget not found: ' + idOrNode.selector;
+               } else {
+                       error = 'Widget not found';
+               }
+               throw new Error( error );
        }
        if ( $elem[ 0 ].oouiInfused ) {
                $elem = $elem[ 0 ].oouiInfused;
@@ -735,12 +744,7 @@ OO.ui.Element.static.unsafeInfuse = function ( idOrNode, domPromise ) {
        parts = data._.split( '.' );
        cls = OO.getProp.apply( OO, [ window ].concat( parts ) );
        if ( cls === undefined ) {
-               // The PHP output might be old and not including the "OO.ui" prefix
-               // TODO: Remove this back-compat after next major release
-               cls = OO.getProp.apply( OO, [ OO.ui ].concat( parts ) );
-               if ( cls === undefined ) {
-                       throw new Error( 'Unknown widget type: id: ' + id + ', class: ' + data._ );
-               }
+               throw new Error( 'Unknown widget type: id: ' + id + ', class: ' + data._ );
        }
 
        // Verify that we're creating an OO.ui.Element instance
@@ -796,7 +800,7 @@ OO.ui.Element.static.unsafeInfuse = function ( idOrNode, domPromise ) {
                if ( $elem[ 0 ] !== obj.$element[ 0 ] ) {
                        $elem.replaceWith( obj.$element );
                        // This element is now gone from the DOM, but if anyone is holding a reference to it,
-                       // let's allow them to OO.ui.infuse() it and do what they expect (T105828).
+                       // let's allow them to OO.ui.infuse() it and do what they expect, see T105828.
                        // Do not use jQuery.data(), as using it on detached nodes leaks memory in 1.x line by design.
                        $elem[ 0 ].oouiInfused = obj.$element;
                }
@@ -2679,8 +2683,8 @@ OO.ui.mixin.IconElement.prototype.setIcon = function ( icon ) {
  * @chainable
  */
 OO.ui.mixin.IconElement.prototype.setIconTitle = function ( iconTitle ) {
-       iconTitle = typeof iconTitle === 'function' ||
-               ( typeof iconTitle === 'string' && iconTitle.length ) ?
+       iconTitle =
+               ( typeof iconTitle === 'function' || ( typeof iconTitle === 'string' && iconTitle.length ) ) ?
                        OO.ui.resolveMsg( iconTitle ) : null;
 
        if ( this.iconTitle !== iconTitle ) {
@@ -2848,8 +2852,8 @@ OO.ui.mixin.IndicatorElement.prototype.setIndicator = function ( indicator ) {
  * @chainable
  */
 OO.ui.mixin.IndicatorElement.prototype.setIndicatorTitle = function ( indicatorTitle ) {
-       indicatorTitle = typeof indicatorTitle === 'function' ||
-               ( typeof indicatorTitle === 'string' && indicatorTitle.length ) ?
+       indicatorTitle =
+               ( typeof indicatorTitle === 'function' || ( typeof indicatorTitle === 'string' && indicatorTitle.length ) ) ?
                        OO.ui.resolveMsg( indicatorTitle ) : null;
 
        if ( this.indicatorTitle !== indicatorTitle ) {
@@ -4834,7 +4838,7 @@ OO.ui.mixin.ClippableElement.prototype.clip = function () {
        clipHeight = allotedHeight < naturalHeight;
 
        if ( clipWidth ) {
-               // The order matters here. If overflow is not set first, Chrome displays bogus scrollbars. (T157672)
+               // The order matters here. If overflow is not set first, Chrome displays bogus scrollbars. See T157672.
                // Forcing a reflow is a smaller workaround than calling reconsiderScrollbars() for this case.
                this.$clippable.css( 'overflowX', 'scroll' );
                void this.$clippable[ 0 ].offsetHeight; // Force reflow
@@ -4850,7 +4854,7 @@ OO.ui.mixin.ClippableElement.prototype.clip = function () {
                } );
        }
        if ( clipHeight ) {
-               // The order matters here. If overflow is not set first, Chrome displays bogus scrollbars. (T157672)
+               // The order matters here. If overflow is not set first, Chrome displays bogus scrollbars. See T157672.
                // Forcing a reflow is a smaller workaround than calling reconsiderScrollbars() for this case.
                this.$clippable.css( 'overflowY', 'scroll' );
                void this.$clippable[ 0 ].offsetHeight; // Force reflow
@@ -6069,7 +6073,7 @@ OO.ui.SelectWidget.prototype.onFocus = function ( event ) {
        } else {
                // One of the options got focussed (and the event bubbled up here).
                // They can't be tabbed to, but they can be activated using accesskeys.
-               item = this.getTargetItem( event );
+               item = this.findTargetItem( event );
        }
 
        if ( item ) {
@@ -6096,7 +6100,7 @@ OO.ui.SelectWidget.prototype.onMouseDown = function ( e ) {
 
        if ( !this.isDisabled() && e.which === OO.ui.MouseButtons.LEFT ) {
                this.togglePressed( true );
-               item = this.getTargetItem( e );
+               item = this.findTargetItem( e );
                if ( item && item.isSelectable() ) {
                        this.pressItem( item );
                        this.selecting = item;
@@ -6118,7 +6122,7 @@ OO.ui.SelectWidget.prototype.onMouseUp = function ( e ) {
 
        this.togglePressed( false );
        if ( !this.selecting ) {
-               item = this.getTargetItem( e );
+               item = this.findTargetItem( e );
                if ( item && item.isSelectable() ) {
                        this.selecting = item;
                }
@@ -6145,7 +6149,7 @@ OO.ui.SelectWidget.prototype.onMouseMove = function ( e ) {
        var item;
 
        if ( !this.isDisabled() && this.pressed ) {
-               item = this.getTargetItem( e );
+               item = this.findTargetItem( e );
                if ( item && item !== this.selecting && item.isSelectable() ) {
                        this.pressItem( item );
                        this.selecting = item;
@@ -6165,7 +6169,7 @@ OO.ui.SelectWidget.prototype.onMouseOver = function ( e ) {
                return;
        }
        if ( !this.isDisabled() ) {
-               item = this.getTargetItem( e );
+               item = this.findTargetItem( e );
                this.highlightItem( item && item.isHighlightable() ? item : null );
        }
        return false;
@@ -6363,7 +6367,7 @@ OO.ui.SelectWidget.prototype.getItemMatcher = function ( s, exact ) {
                s = s.normalize();
        }
        s = exact ? s.trim() : s.replace( /^\s+/, '' );
-       re = '^\\s*' + s.replace( /([\\{}()|.?*+\-\^$\[\]])/g, '\\$1' ).replace( /\s+/g, '\\s+' );
+       re = '^\\s*' + s.replace( /([\\{}()|.?*+\-^$[\]])/g, '\\$1' ).replace( /\s+/g, '\\s+' );
        if ( exact ) {
                re += '\\s*$';
        }
@@ -6418,8 +6422,12 @@ OO.ui.SelectWidget.prototype.onToggle = function ( visible ) {
  * @param {jQuery.Event} e
  * @return {OO.ui.OptionWidget|null} Outline item widget, `null` if none was found
  */
-OO.ui.SelectWidget.prototype.getTargetItem = function ( e ) {
-       return $( e.target ).closest( '.oo-ui-optionWidget' ).data( 'oo-ui-optionWidget' ) || null;
+OO.ui.SelectWidget.prototype.findTargetItem = function ( e ) {
+       var $option = $( e.target ).closest( '.oo-ui-optionWidget' );
+       if ( !$option.closest( '.oo-ui-selectWidget' ).is( this.$element ) ) {
+               return null;
+       }
+       return $option.data( 'oo-ui-optionWidget' ) || null;
 };
 
 /**
@@ -7054,9 +7062,9 @@ OO.ui.MenuSelectWidget.prototype.onDocumentMouseDown = function ( e ) {
        if (
                this.isVisible() &&
                !OO.ui.contains(
-                               this.$element.add( this.$widget ).add( this.$autoCloseIgnore ).get(),
-                               e.target,
-                               true
+                       this.$element.add( this.$widget ).add( this.$autoCloseIgnore ).get(),
+                       e.target,
+                       true
                )
        ) {
                this.toggle( false );
@@ -8147,51 +8155,6 @@ OO.ui.CheckboxMultiselectWidget.prototype.simulateLabelClick = function () {
        this.focus();
 };
 
-/**
- * FloatingMenuSelectWidget was a menu that would stick under a specified
- * container, even when it is inserted elsewhere in the document.
- * This functionality is now included in MenuSelectWidget, and FloatingMenuSelectWidget
- * is preserved for backwards-compatibility.
- *
- * @class
- * @extends OO.ui.MenuSelectWidget
- * @deprecated since v0.21.3, use MenuSelectWidget instead.
- *
- * @constructor
- * @param {OO.ui.Widget} [inputWidget] Widget to provide the menu for.
- *   Deprecated, omit this parameter and specify `$container` instead.
- * @param {Object} [config] Configuration options
- * @cfg {jQuery} [$container=inputWidget.$element] Element to render menu under
- */
-OO.ui.FloatingMenuSelectWidget = function OoUiFloatingMenuSelectWidget( inputWidget, config ) {
-       OO.ui.warnDeprecation( 'FloatingMenuSelectWidget is deprecated. Use the MenuSelectWidget instead.' );
-
-       // Allow 'inputWidget' parameter and config for backwards compatibility
-       if ( OO.isPlainObject( inputWidget ) && config === undefined ) {
-               config = inputWidget;
-               inputWidget = config.inputWidget;
-       }
-
-       // Configuration initialization
-       config = config || {};
-
-       // Properties
-       this.inputWidget = inputWidget; // For backwards compatibility
-       this.$container = config.$floatableContainer || config.$container || this.inputWidget.$element;
-
-       // Parent constructor
-       OO.ui.FloatingMenuSelectWidget.parent.call( this, $.extend( {}, config, { $floatableContainer: this.$container } ) );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-floatingMenuSelectWidget' );
-       // For backwards compatibility
-       this.$element.addClass( 'oo-ui-textInputMenuSelectWidget' );
-};
-
-/* Setup */
-
-OO.inheritClass( OO.ui.FloatingMenuSelectWidget, OO.ui.MenuSelectWidget );
-
 /**
  * Progress bars visually display the status of an operation, such as a download,
  * and can be either determinate or indeterminate:
@@ -8372,7 +8335,7 @@ OO.mixinClass( OO.ui.InputWidget, OO.ui.mixin.AccessKeyedElement );
  */
 OO.ui.InputWidget.static.reusePreInfuseDOM = function ( node, config ) {
        config = OO.ui.InputWidget.parent.static.reusePreInfuseDOM( node, config );
-       // Reusing $input lets browsers preserve inputted values across page reloads (T114134)
+       // Reusing `$input` lets browsers preserve inputted values across page reloads, see T114134.
        config.$input = $( node ).find( '.oo-ui-inputWidget-input' );
        return config;
 };
@@ -9588,7 +9551,7 @@ OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) {
        }, config );
 
        if ( config.multiline ) {
-               OO.ui.warnDeprecation( 'TextInputWidget: config.multiline is deprecated. Use the MultilineTextInputWidget instead. See T130434 for details.' );
+               OO.ui.warnDeprecation( 'TextInputWidget: config.multiline is deprecated. Use the MultilineTextInputWidget instead. See T130434.' );
                return new OO.ui.MultilineTextInputWidget( config );
        }