Merge "Fix typo in apierror message"
[lhc/web/wiklou.git] / resources / lib / ooui / oojs-ui-widgets.js
index be90a20..a51b7af 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.29.5
+ * OOUI v0.30.2
  * https://www.mediawiki.org/wiki/OOUI
  *
- * Copyright 2011–2018 OOUI Team and other contributors.
+ * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2018-11-08T22:38:07Z
+ * Date: 2019-01-23T01:14:20Z
  */
 ( function ( OO ) {
 
@@ -1288,7 +1288,7 @@ OO.ui.PageLayout.prototype.setActive = function ( active ) {
  *         ],
  *         continuous: true
  *     } );
- *     $( 'body' ).append( myStack.$element );
+ *     $( document.body ).append( myStack.$element );
  *
  * @class
  * @extends OO.ui.PanelLayout
@@ -1301,7 +1301,9 @@ OO.ui.PageLayout.prototype.setActive = function ( active ) {
  */
 OO.ui.StackLayout = function OoUiStackLayout( config ) {
        // Configuration initialization
-       config = $.extend( { scrollable: true }, config );
+       // Make the layout scrollable in continuous mode, otherwise each
+       // panel is responsible for its own scrolling.
+       config = $.extend( { scrollable: !!( config && config.continuous ) }, config );
 
        // Parent constructor
        OO.ui.StackLayout.parent.call( this, config );
@@ -1612,7 +1614,7 @@ OO.ui.StackLayout.prototype.updateHiddenState = function ( items, selectedItem )
  *     menuLayout.$content.append(
  *         contentPanel.$element.append( '<b>Content panel</b>', '<p>Note that the menu is positioned relative to the content panel: top, bottom, after, before.</p>')
  *     );
- *     $( 'body' ).append( menuLayout.$element );
+ *     $( document.body ).append( menuLayout.$element );
  *
  * If menu size needs to be overridden, it can be accomplished using CSS similar to the snippet
  * below. MenuLayout's CSS will override the appropriate values with 'auto' or '0' to display the
@@ -1846,7 +1848,7 @@ OO.ui.MenuLayout.prototype.resetScroll = function () {
  *     } );
  *
  *     booklet.addPages( [ page1, page2 ] );
- *     $( 'body' ).append( booklet.$element );
+ *     $( document.body ).append( booklet.$element );
  *
  * @class
  * @extends OO.ui.MenuLayout
@@ -2112,7 +2114,7 @@ OO.ui.BookletLayout.prototype.toggleOutline = function ( show ) {
                        // outline controls are present, delay matches transition on `.oo-ui-menuLayout-menu`.
                        setTimeout( function () {
                                OO.ui.Element.static.reconsiderScrollbars( booklet.outlinePanel.$element[ 0 ] );
-                       }, 200 );
+                       }, OO.ui.theme.getDialogTransitionDuration() );
                }
        }
 
@@ -2357,6 +2359,7 @@ OO.ui.BookletLayout.prototype.setPage = function ( name ) {
                                ) {
                                        $focused = previousPage.$element.find( ':focus' );
                                        if ( $focused.length ) {
+                                               // eslint-disable-next-line jquery/no-event-shorthand
                                                $focused[ 0 ].blur();
                                        }
                                }
@@ -2369,6 +2372,7 @@ OO.ui.BookletLayout.prototype.setPage = function ( name ) {
                                // blurred when it was hidden, but browsers are not very consistent about this.
                                $focused = previousPage.$element.find( ':focus' );
                                if ( $focused.length ) {
+                                       // eslint-disable-next-line jquery/no-event-shorthand
                                        $focused[ 0 ].blur();
                                }
                        }
@@ -2437,7 +2441,7 @@ OO.ui.BookletLayout.prototype.selectFirstSelectablePage = function () {
  *     var index = new OO.ui.IndexLayout();
  *
  *     index.addTabPanels( [ tabPanel1, tabPanel2 ] );
- *     $( 'body' ).append( index.$element );
+ *     $( document.body ).append( index.$element );
  *
  * @class
  * @extends OO.ui.MenuLayout
@@ -2824,6 +2828,7 @@ OO.ui.IndexLayout.prototype.setTabPanel = function ( name ) {
                                ) {
                                        $focused = previousTabPanel.$element.find( ':focus' );
                                        if ( $focused.length ) {
+                                               // eslint-disable-next-line jquery/no-event-shorthand
                                                $focused[ 0 ].blur();
                                        }
                                }
@@ -2836,6 +2841,7 @@ OO.ui.IndexLayout.prototype.setTabPanel = function ( name ) {
                                // blurred when it was hidden, but browsers are not very consistent about this.
                                $focused = previousTabPanel.$element.find( ':focus' );
                                if ( $focused.length ) {
+                                       // eslint-disable-next-line jquery/no-event-shorthand
                                        $focused[ 0 ].blur();
                                }
                        }
@@ -2865,6 +2871,7 @@ OO.ui.IndexLayout.prototype.selectFirstSelectableTabPanel = function () {
  * @abstract
  * @class
  * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.TitledElement
  *
  * @constructor
  * @param {Object} [config] Configuration options
@@ -2878,6 +2885,9 @@ OO.ui.ToggleWidget = function OoUiToggleWidget( config ) {
        // Parent constructor
        OO.ui.ToggleWidget.parent.call( this, config );
 
+       // Mixin constructor
+       OO.ui.mixin.TitledElement.call( this, config );
+
        // Properties
        this.value = null;
 
@@ -2889,6 +2899,7 @@ OO.ui.ToggleWidget = function OoUiToggleWidget( config ) {
 /* Setup */
 
 OO.inheritClass( OO.ui.ToggleWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.ToggleWidget, OO.ui.mixin.TitledElement );
 
 /* Events */
 
@@ -2941,14 +2952,14 @@ OO.ui.ToggleWidget.prototype.setValue = function ( value ) {
  *     @example
  *     // Toggle buttons in the 'off' and 'on' state.
  *     var toggleButton1 = new OO.ui.ToggleButtonWidget( {
- *         label: 'Toggle Button off'
- *     } );
- *     var toggleButton2 = new OO.ui.ToggleButtonWidget( {
- *         label: 'Toggle Button on',
- *         value: true
- *     } );
+ *             label: 'Toggle Button off'
+ *         } ),
+ *         toggleButton2 = new OO.ui.ToggleButtonWidget( {
+ *             label: 'Toggle Button on',
+ *             value: true
+ *         } );
  *     // Append the buttons to the DOM.
- *     $( 'body' ).append( toggleButton1.$element, toggleButton2.$element );
+ *     $( document.body ).append( toggleButton1.$element, toggleButton2.$element );
  *
  * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Buttons_and_Switches#Toggle_buttons
  *
@@ -2958,7 +2969,6 @@ OO.ui.ToggleWidget.prototype.setValue = function ( value ) {
  * @mixins OO.ui.mixin.IconElement
  * @mixins OO.ui.mixin.IndicatorElement
  * @mixins OO.ui.mixin.LabelElement
- * @mixins OO.ui.mixin.TitledElement
  * @mixins OO.ui.mixin.FlaggedElement
  * @mixins OO.ui.mixin.TabIndexedElement
  *
@@ -2979,7 +2989,6 @@ OO.ui.ToggleButtonWidget = function OoUiToggleButtonWidget( config ) {
        OO.ui.mixin.IconElement.call( this, config );
        OO.ui.mixin.IndicatorElement.call( this, config );
        OO.ui.mixin.LabelElement.call( this, config );
-       OO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$button } ) );
        OO.ui.mixin.FlaggedElement.call( this, config );
        OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$button } ) );
 
@@ -2991,6 +3000,7 @@ OO.ui.ToggleButtonWidget = function OoUiToggleButtonWidget( config ) {
        this.$element
                .addClass( 'oo-ui-toggleButtonWidget' )
                .append( this.$button );
+       this.setTitledElement( this.$button );
 };
 
 /* Setup */
@@ -3000,7 +3010,6 @@ OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.ButtonElement );
 OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.IconElement );
 OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.IndicatorElement );
 OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.LabelElement );
-OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.TitledElement );
 OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.FlaggedElement );
 OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.TabIndexedElement );
 
@@ -3060,20 +3069,25 @@ OO.ui.ToggleButtonWidget.prototype.setButtonElement = function ( $button ) {
  *
  *     @example
  *     // Toggle switches in the 'off' and 'on' position.
- *     var toggleSwitch1 = new OO.ui.ToggleSwitchWidget();
- *     var toggleSwitch2 = new OO.ui.ToggleSwitchWidget( {
- *         value: true
- *     } );
- *
- *     // Create a FieldsetLayout to layout and label switches
- *     var fieldset = new OO.ui.FieldsetLayout( {
- *        label: 'Toggle switches'
- *     } );
+ *     var toggleSwitch1 = new OO.ui.ToggleSwitchWidget(),
+ *         toggleSwitch2 = new OO.ui.ToggleSwitchWidget( {
+ *             value: true
+ *         } );
+ *         // Create a FieldsetLayout to layout and label switches.
+ *         fieldset = new OO.ui.FieldsetLayout( {
+ *             label: 'Toggle switches'
+ *         } );
  *     fieldset.addItems( [
- *         new OO.ui.FieldLayout( toggleSwitch1, { label: 'Off', align: 'top' } ),
- *         new OO.ui.FieldLayout( toggleSwitch2, { label: 'On', align: 'top' } )
+ *         new OO.ui.FieldLayout( toggleSwitch1, {
+ *             label: 'Off',
+ *             align: 'top'
+ *         } ),
+ *         new OO.ui.FieldLayout( toggleSwitch2, {
+ *             label: 'On',
+ *             align: 'top'
+ *         } )
  *     ] );
- *     $( 'body' ).append( fieldset.$element );
+ *     $( document.body ).append( fieldset.$element );
  *
  * @class
  * @extends OO.ui.ToggleWidget
@@ -3527,7 +3541,6 @@ OO.mixinClass( OO.ui.OutlineSelectWidget, OO.ui.mixin.TabIndexedElement );
  * @mixins OO.ui.mixin.ButtonElement
  * @mixins OO.ui.mixin.IconElement
  * @mixins OO.ui.mixin.IndicatorElement
- * @mixins OO.ui.mixin.TitledElement
  *
  * @constructor
  * @param {Object} [config] Configuration options
@@ -3543,12 +3556,12 @@ OO.ui.ButtonOptionWidget = function OoUiButtonOptionWidget( config ) {
        OO.ui.mixin.ButtonElement.call( this, config );
        OO.ui.mixin.IconElement.call( this, config );
        OO.ui.mixin.IndicatorElement.call( this, config );
-       OO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$button } ) );
 
        // Initialization
        this.$element.addClass( 'oo-ui-buttonOptionWidget' );
        this.$button.append( this.$icon, this.$label, this.$indicator );
        this.$element.append( this.$button );
+       this.setTitledElement( this.$button );
 };
 
 /* Setup */
@@ -3557,7 +3570,6 @@ OO.inheritClass( OO.ui.ButtonOptionWidget, OO.ui.OptionWidget );
 OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.mixin.ButtonElement );
 OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.mixin.IconElement );
 OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.mixin.IndicatorElement );
-OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.mixin.TitledElement );
 
 /* Static Properties */
 
@@ -3598,29 +3610,26 @@ OO.ui.ButtonOptionWidget.prototype.setSelected = function ( state ) {
  * the [OOUI documentation on MediaWiki] [1] for more information.
  *
  *     @example
- *     // Example: A ButtonSelectWidget that contains three ButtonOptionWidgets
+ *     // A ButtonSelectWidget that contains three ButtonOptionWidgets.
  *     var option1 = new OO.ui.ButtonOptionWidget( {
- *         data: 1,
- *         label: 'Option 1',
- *         title: 'Button option 1'
- *     } );
- *
- *     var option2 = new OO.ui.ButtonOptionWidget( {
- *         data: 2,
- *         label: 'Option 2',
- *         title: 'Button option 2'
- *     } );
- *
- *     var option3 = new OO.ui.ButtonOptionWidget( {
- *         data: 3,
- *         label: 'Option 3',
- *         title: 'Button option 3'
- *     } );
- *
- *     var buttonSelect=new OO.ui.ButtonSelectWidget( {
- *         items: [ option1, option2, option3 ]
- *     } );
- *     $( 'body' ).append( buttonSelect.$element );
+ *             data: 1,
+ *             label: 'Option 1',
+ *             title: 'Button option 1'
+ *         } ),
+ *         option2 = new OO.ui.ButtonOptionWidget( {
+ *             data: 2,
+ *             label: 'Option 2',
+ *             title: 'Button option 2'
+ *         } ),
+ *         option3 = new OO.ui.ButtonOptionWidget( {
+ *             data: 3,
+ *             label: 'Option 3',
+ *             title: 'Button option 3'
+ *         } ),
+ *         buttonSelect = new OO.ui.ButtonSelectWidget( {
+ *             items: [ option1, option2, option3 ]
+ *         } );
+ *     $( document.body ).append( buttonSelect.$element );
  *
  * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Selects_and_Options
  *
@@ -3929,7 +3938,7 @@ OO.ui.TagItemWidget.prototype.remove = function () {
 OO.ui.TagItemWidget.prototype.onKeyDown = function ( e ) {
        var movement;
 
-       if ( !this.isDisabled() && !this.isFixed() && e.keyCode === OO.ui.Keys.BACKSPACE || e.keyCode === OO.ui.Keys.DELETE ) {
+       if ( !this.isDisabled() && !this.isFixed() && ( e.keyCode === OO.ui.Keys.BACKSPACE || e.keyCode === OO.ui.Keys.DELETE ) ) {
                this.remove();
                return false;
        } else if ( e.keyCode === OO.ui.Keys.ENTER ) {
@@ -4007,13 +4016,13 @@ OO.ui.TagItemWidget.prototype.isValid = function () {
  * a menu and a popup respectively.
  *
  *     @example
- *     // Example: A basic TagMultiselectWidget.
+ *     // A TagMultiselectWidget.
  *     var widget = new OO.ui.TagMultiselectWidget( {
  *         inputPosition: 'outline',
  *         allowedValues: [ 'Option 1', 'Option 2', 'Option 3' ],
  *         selected: [ 'Option 1' ]
  *     } );
- *     $( 'body' ).append( widget.$element );
+ *     $( document.body ).append( widget.$element );
  *
  * @class
  * @extends OO.ui.Widget
@@ -4023,6 +4032,7 @@ OO.ui.TagItemWidget.prototype.isValid = function () {
  * @mixins OO.ui.mixin.IconElement
  * @mixins OO.ui.mixin.TabIndexedElement
  * @mixins OO.ui.mixin.FlaggedElement
+ * @mixins OO.ui.mixin.TitledElement
  *
  * @constructor
  * @param {Object} config Configuration object
@@ -4031,10 +4041,10 @@ OO.ui.TagItemWidget.prototype.isValid = function () {
  *  replace the input widget used in the TagMultiselectWidget. If not given,
  *  TagMultiselectWidget creates its own.
  * @cfg {boolean} [inputPosition='inline'] Position of the input. Options are:
- *     - inline: The input is invisible, but exists inside the tag list, so
- *             the user types into the tag groups to add tags.
- *     - outline: The input is underneath the tag area.
- *     - none: No input supplied
+ *  - inline: The input is invisible, but exists inside the tag list, so
+ *    the user types into the tag groups to add tags.
+ *  - outline: The input is underneath the tag area.
+ *  - none: No input supplied
  * @cfg {boolean} [allowEditTags=true] Allow editing of the tags by clicking them
  * @cfg {boolean} [allowArbitrary=false] Allow data items to be added even if
  *  not present in the menu.
@@ -4073,6 +4083,7 @@ OO.ui.TagMultiselectWidget = function OoUiTagMultiselectWidget( config ) {
        OO.ui.mixin.TabIndexedElement.call( this, config );
        OO.ui.mixin.FlaggedElement.call( this, config );
        OO.ui.mixin.DraggableGroupElement.call( this, config );
+       OO.ui.mixin.TitledElement.call( this, config );
 
        this.toggleDraggable(
                config.allowReordering === undefined ?
@@ -4205,6 +4216,7 @@ OO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.IndicatorElement );
 OO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.IconElement );
 OO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.TabIndexedElement );
 OO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.FlaggedElement );
+OO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.TitledElement );
 
 /* Static properties */
 
@@ -4488,6 +4500,9 @@ OO.ui.TagMultiselectWidget.prototype.setDisabled = function ( isDisabled ) {
        OO.ui.TagMultiselectWidget.parent.prototype.setDisabled.call( this, isDisabled );
 
        if ( this.hasInput && this.input ) {
+               if ( !isDisabled ) {
+                       this.updateInputSize();
+               }
                this.input.setDisabled( !!isDisabled && !this.isUnderLimit() );
        }
 
@@ -4634,10 +4649,10 @@ OO.ui.TagMultiselectWidget.prototype.getValue = function () {
  *  This object must contain at least a data key. Example:
  *  { data: 'foo', label: 'Foo item' }
  *  For multiple items, use an array of objects. For example:
- *   [
- *     { data: 'foo', label: 'Foo item' },
- *     { data: 'bar', label: 'Bar item' }
- *      ]
+ *  [
+ *     { data: 'foo', label: 'Foo item' },
+ *     { data: 'bar', label: 'Bar item' }
+ *  ]
  *  Value can also be added with plaintext array, for example:
  *  [ 'foo', 'bar', 'bla' ] or a single string, like 'foo'
  */
@@ -4899,9 +4914,9 @@ OO.ui.TagMultiselectWidget.prototype.isValid = function () {
  * to use a popup. The popup can be configured to have a default input to insert values into the widget.
  *
  *     @example
- *     // Example: A basic PopupTagMultiselectWidget.
+ *     // A PopupTagMultiselectWidget.
  *     var widget = new OO.ui.PopupTagMultiselectWidget();
- *     $( 'body' ).append( widget.$element );
+ *     $( document.body ).append( widget.$element );
  *
  *     // Example: A PopupTagMultiselectWidget with an external popup.
  *     var popupInput = new OO.ui.TextInputWidget(),
@@ -4911,7 +4926,7 @@ OO.ui.TagMultiselectWidget.prototype.isValid = function () {
  *               $content: popupInput.$element
  *            }
  *         } );
- *     $( 'body' ).append( widget.$element );
+ *     $( document.body ).append( widget.$element );
  *
  * @class
  * @extends OO.ui.TagMultiselectWidget
@@ -4924,6 +4939,7 @@ OO.ui.TagMultiselectWidget.prototype.isValid = function () {
  * @cfg {OO.ui.InputWidget} [popupInput] An input widget inside the popup that will be
  *  focused when the popup is opened and will be used as replacement for the
  *  general input in the widget.
+ * @deprecated
  */
 OO.ui.PopupTagMultiselectWidget = function OoUiPopupTagMultiselectWidget( config ) {
        var defaultInput,
@@ -4983,6 +4999,9 @@ OO.ui.PopupTagMultiselectWidget = function OoUiPopupTagMultiselectWidget( config
        this.$element
                .append( this.popup.$element )
                .addClass( 'oo-ui-popupTagMultiselectWidget' );
+
+       // Deprecation warning
+       OO.ui.warnDeprecation( 'PopupTagMultiselectWidget: Deprecated widget. Use MenuTagMultiselectWidget instead. See T208821.' );
 };
 
 /* Initialization */
@@ -5056,7 +5075,7 @@ OO.ui.PopupTagMultiselectWidget.prototype.addTagByPopupValue = function ( data,
  * to use a menu of selectable options.
  *
  *     @example
- *     // Example: A basic MenuTagMultiselectWidget.
+ *     // A basic MenuTagMultiselectWidget.
  *     var widget = new OO.ui.MenuTagMultiselectWidget( {
  *         inputPosition: 'outline',
  *         options: [
@@ -5066,7 +5085,7 @@ OO.ui.PopupTagMultiselectWidget.prototype.addTagByPopupValue = function ( data,
  *         ],
  *         selected: [ 'option1', 'option2' ]
  *     } );
- *     $( 'body' ).append( widget.$element );
+ *     $( document.body ).append( widget.$element );
  *
  * @class
  * @extends OO.ui.TagMultiselectWidget
@@ -5116,6 +5135,9 @@ OO.ui.MenuTagMultiselectWidget = function OoUiMenuTagMultiselectWidget( config )
                .append( this.menu.$element );
        this.$element
                .addClass( 'oo-ui-menuTagMultiselectWidget' );
+       // Remove MenuSelectWidget's generic focus owner ARIA attribute
+       // TODO: Should this widget have a `role` that is compatible with this attribute?
+       this.menu.$focusOwner.removeAttr( 'aria-expanded' );
        // TagMultiselectWidget already does this, but it doesn't work right because this.menu is not yet
        // set up while the parent constructor runs, and #getAllowedValues rejects everything.
        if ( config.selected ) {
@@ -5171,11 +5193,11 @@ OO.ui.MenuTagMultiselectWidget.prototype.onInputChange = function () {
  * @param {OO.ui.OptionWidget} menuItem Chosen menu item
  */
 OO.ui.MenuTagMultiselectWidget.prototype.onMenuChoose = function ( menuItem ) {
-       // Add tag
-       this.addTag( menuItem.getData(), menuItem.getLabel() );
        if ( this.hasInput && this.clearInputOnChoose ) {
                this.input.setValue( '' );
        }
+       // Add tag
+       this.addTag( menuItem.getData(), menuItem.getLabel() );
 };
 
 /**
@@ -5190,6 +5212,11 @@ OO.ui.MenuTagMultiselectWidget.prototype.onMenuToggle = function ( isVisible ) {
        } else {
                this.initializeMenuSelection();
        }
+       setTimeout( function () {
+               // Remove MenuSelectWidget's generic focus owner ARIA attribute
+               // TODO: Should this widget have a `role` that is compatible with this attribute?
+               this.menu.$focusOwner.removeAttr( 'aria-expanded' );
+       }.bind( this ) );
 };
 
 /**
@@ -5239,7 +5266,11 @@ OO.ui.MenuTagMultiselectWidget.prototype.setDisabled = function ( isDisabled ) {
  */
 OO.ui.MenuTagMultiselectWidget.prototype.initializeMenuSelection = function () {
        if ( !this.menu.findSelectedItem() ) {
-               this.menu.highlightItem( this.menu.findFirstSelectableItem() );
+               this.menu.highlightItem(
+                       this.allowArbitrary ?
+                               null :
+                               this.menu.findFirstSelectableItem()
+               );
        }
 };
 
@@ -5352,14 +5383,14 @@ OO.ui.MenuTagMultiselectWidget.prototype.getAllowedValues = function () {
 
 /**
  * SelectFileWidgets allow for selecting files, using the HTML5 File API. These
- * widgets can be configured with {@link OO.ui.mixin.IconElement icons} and {@link
- * OO.ui.mixin.IndicatorElement indicators}.
+ * widgets can be configured with {@link OO.ui.mixin.IconElement icons}, {@link
+ * OO.ui.mixin.IndicatorElement indicators} and {@link OO.ui.mixin.TitledElement titles}.
  * Please see the [OOUI documentation on MediaWiki] [1] for more information and examples.
  *
  *     @example
- *     // Example of a file select widget
+ *     // A file select widget.
  *     var selectFile = new OO.ui.SelectFileWidget();
- *     $( 'body' ).append( selectFile.$element );
+ *     $( document.body ).append( selectFile.$element );
  *
  * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets
  *
@@ -5369,6 +5400,7 @@ OO.ui.MenuTagMultiselectWidget.prototype.getAllowedValues = function () {
  * @mixins OO.ui.mixin.IndicatorElement
  * @mixins OO.ui.mixin.PendingElement
  * @mixins OO.ui.mixin.LabelElement
+ * @mixins OO.ui.mixin.TitledElement
  *
  * @constructor
  * @param {Object} [config] Configuration options
@@ -5401,6 +5433,7 @@ OO.ui.SelectFileWidget = function OoUiSelectFileWidget( config ) {
        OO.ui.mixin.IndicatorElement.call( this, config );
        OO.ui.mixin.PendingElement.call( this, $.extend( {}, config, { $pending: this.$info } ) );
        OO.ui.mixin.LabelElement.call( this, config );
+       OO.ui.mixin.TitledElement.call( this, config );
 
        // Properties
        this.$info = $( '<span>' );
@@ -5427,7 +5460,7 @@ OO.ui.SelectFileWidget = function OoUiSelectFileWidget( config ) {
        this.clearButton = new OO.ui.ButtonWidget( {
                classes: [ 'oo-ui-selectFileWidget-clearButton' ],
                framed: false,
-               icon: 'close',
+               icon: 'clear',
                disabled: this.disabled
        } );
 
@@ -5487,6 +5520,7 @@ OO.mixinClass( OO.ui.SelectFileWidget, OO.ui.mixin.IconElement );
 OO.mixinClass( OO.ui.SelectFileWidget, OO.ui.mixin.IndicatorElement );
 OO.mixinClass( OO.ui.SelectFileWidget, OO.ui.mixin.PendingElement );
 OO.mixinClass( OO.ui.SelectFileWidget, OO.ui.mixin.LabelElement );
+OO.mixinClass( OO.ui.SelectFileWidget, OO.ui.mixin.TitledElement );
 
 /* Static Properties */