X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=resources%2Flib%2Foojs-ui%2Foojs-ui-core.js;h=12e5ef66b6e9a25dd0f57ae71d840e8371f3783b;hb=ac5eeba3444fe1a43170d39876406d509b766555;hp=b3a901200f7282fb7660f00fc359a53dc6e0a2ca;hpb=47818f1b44a3525dff1c07778aaef65d06b8ae89;p=lhc%2Fweb%2Fwiklou.git diff --git a/resources/lib/oojs-ui/oojs-ui-core.js b/resources/lib/oojs-ui/oojs-ui-core.js index b3a901200f..12e5ef66b6 100644 --- a/resources/lib/oojs-ui/oojs-ui-core.js +++ b/resources/lib/oojs-ui/oojs-ui-core.js @@ -1,12 +1,12 @@ /*! - * OOjs UI v0.24.3 - * https://www.mediawiki.org/wiki/OOjs_UI + * OOUI v0.25.2 + * https://www.mediawiki.org/wiki/OOUI * - * Copyright 2011–2017 OOjs UI Team and other contributors. + * Copyright 2011–2018 OOUI Team and other contributors. * Released under the MIT license * http://oojs.mit-license.org * - * Date: 2017-11-28T23:28:05Z + * Date: 2018-02-07T00:27:24Z */ ( function ( OO ) { @@ -68,7 +68,7 @@ OO.ui.elementId = 0; */ OO.ui.generateElementId = function () { OO.ui.elementId++; - return 'oojsui-' + OO.ui.elementId; + return 'ooui-' + OO.ui.elementId; }; /** @@ -411,7 +411,7 @@ OO.ui.infuse = function ( idOrNode ) { * * $.i18n().load( languageMap ).done( function() { * // Replace the built-in `msg` only once we've loaded the internationalization. - * // OOjs UI uses `OO.ui.deferMsg` for all initially-loaded messages. So long as + * // OOUI uses `OO.ui.deferMsg` for all initially-loaded messages. So long as * // you put off creating any widgets until this promise is complete, no English * // will be displayed. * OO.ui.msg = $.i18n; @@ -556,12 +556,26 @@ OO.ui.getViewportSpacing = function () { }; }; +/** + * Get the default overlay, which is used by various widgets when they are passed `$overlay: true`. + * See . + * + * @return {jQuery} Default overlay node + */ +OO.ui.getDefaultOverlay = function () { + if ( !OO.ui.$defaultOverlay ) { + OO.ui.$defaultOverlay = $( '
' ).addClass( 'oo-ui-defaultOverlay' ); + $( 'body' ).append( OO.ui.$defaultOverlay ); + } + return OO.ui.$defaultOverlay; +}; + /*! * Mixin namespace. */ /** - * Namespace for OOjs UI mixins. + * Namespace for OOUI mixins. * * Mixins are named according to the type of object they are intended to * be mixed in to. For example, OO.ui.mixin.GroupElement is intended to be @@ -584,9 +598,9 @@ OO.ui.mixin = {}; * @constructor * @param {Object} [config] Configuration options * @cfg {string[]} [classes] The names of the CSS classes to apply to the element. CSS styles are added - * to the top level (e.g., the outermost div) of the element. See the [OOjs UI documentation on MediaWiki][2] + * to the top level (e.g., the outermost div) of the element. See the [OOUI documentation on MediaWiki][2] * for an example. - * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Buttons_and_Switches#cssExample + * [2]: https://www.mediawiki.org/wiki/OOUI/Widgets/Buttons_and_Switches#cssExample * @cfg {string} [id] The HTML id attribute used in the rendered tag. * @cfg {string} [text] Text to insert * @cfg {Array} [content] An array of content elements to append (after #text). @@ -812,16 +826,16 @@ OO.ui.Element.static.unsafeInfuse = function ( idOrNode, domPromise ) { // rebuild widget // eslint-disable-next-line new-cap obj = new cls( data ); + // If anyone is holding a reference to the old DOM element, + // 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; // now replace old DOM with this new DOM. if ( top ) { // An efficient constructor might be able to reuse the entire DOM tree of the original element, // so only mutate the DOM if we need to. 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, 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; } top.resolve(); } @@ -1620,7 +1634,7 @@ OO.inheritClass( OO.ui.Layout, OO.ui.Element ); OO.mixinClass( OO.ui.Layout, OO.EventEmitter ); /** - * Widgets are compositions of one or more OOjs UI elements that users can both view + * 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, * and their state can change dynamically according to a model. * @@ -2069,9 +2083,9 @@ OO.ui.mixin.TabIndexedElement.prototype.simulateLabelClick = function () { /** * ButtonElement is often mixed into other classes to generate a button, which is a clickable * interface element that can be configured with access keys for accessibility. - * See the [OOjs UI documentation on MediaWiki] [1] for examples. + * See the [OOUI documentation on MediaWiki] [1] for examples. * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Buttons_and_Switches#Buttons + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Buttons_and_Switches#Buttons * * @abstract * @class @@ -2326,12 +2340,12 @@ OO.ui.mixin.ButtonElement.prototype.isActive = function () { }; /** - * Any OOjs UI widget that contains other widgets (such as {@link OO.ui.ButtonWidget buttons} or + * Any OOUI widget that contains other widgets (such as {@link OO.ui.ButtonWidget buttons} or * {@link OO.ui.OptionWidget options}) mixes in GroupElement. Adding, removing, and clearing * items from the group is done through the interface the class provides. - * For more information, please see the [OOjs UI documentation on MediaWiki] [1]. + * For more information, please see the [OOUI documentation on MediaWiki] [1]. * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Elements/Groups + * [1]: https://www.mediawiki.org/wiki/OOUI/Elements/Groups * * @abstract * @mixins OO.EmitterList @@ -2389,15 +2403,15 @@ OO.ui.mixin.GroupElement.prototype.setGroupElement = function ( $group ) { }; /** - * Get an item by its data. + * Find an item by its data. * * Only the first item with matching data will be returned. To return all matching items, - * use the #getItemsFromData method. + * use the #findItemsFromData method. * * @param {Object} data Item data to search for * @return {OO.ui.Element|null} Item with equivalent data, `null` if none exists */ -OO.ui.mixin.GroupElement.prototype.getItemFromData = function ( data ) { +OO.ui.mixin.GroupElement.prototype.findItemFromData = function ( data ) { var i, len, item, hash = OO.getHash( data ); @@ -2412,14 +2426,26 @@ OO.ui.mixin.GroupElement.prototype.getItemFromData = function ( data ) { }; /** - * Get items by their data. + * Get an item by its data. + * + * @deprecated Since v0.25.0; use {@link #findItemFromData} instead. + * @param {Object} data Item data to search for + * @return {OO.ui.Element|null} Item with equivalent data, `null` if none exists + */ +OO.ui.mixin.GroupElement.prototype.getItemFromData = function ( data ) { + OO.ui.warnDeprecation( 'GroupElement#getItemFromData. Deprecated function. Use findItemFromData instead. See T76630' ); + return this.findItemFromData( data ); +}; + +/** + * Find items by their data. * - * All items with matching data will be returned. To return only the first match, use the #getItemFromData method instead. + * All items with matching data will be returned. To return only the first match, use the #findItemFromData method instead. * * @param {Object} data Item data to search for * @return {OO.ui.Element[]} Items with equivalent data */ -OO.ui.mixin.GroupElement.prototype.getItemsFromData = function ( data ) { +OO.ui.mixin.GroupElement.prototype.findItemsFromData = function ( data ) { var i, len, item, hash = OO.getHash( data ), items = []; @@ -2434,6 +2460,18 @@ OO.ui.mixin.GroupElement.prototype.getItemsFromData = function ( data ) { return items; }; +/** + * Find items by their data. + * + * @deprecated Since v0.25.0; use {@link #findItemsFromData} instead. + * @param {Object} data Item data to search for + * @return {OO.ui.Element[]} Items with equivalent data + */ +OO.ui.mixin.GroupElement.prototype.getItemsFromData = function ( data ) { + OO.ui.warnDeprecation( 'GroupElement#getItemsFromData. Deprecated function. Use findItemsFromData instead. See T76630' ); + return this.findItemsFromData( data ); +}; + /** * Add items to the group. * @@ -2552,10 +2590,10 @@ OO.ui.mixin.GroupElement.prototype.clearItems = function () { * 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 * in locating a control or to convey information in a space-efficient way. See the - * [OOjs UI documentation on MediaWiki] [1] for a list of icons + * [OOUI documentation on MediaWiki] [1] for a list of icons * included in the library. * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Icons + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Icons,_Indicators,_and_Labels#Icons * * @abstract * @class @@ -2581,8 +2619,8 @@ OO.ui.mixin.GroupElement.prototype.clearItems = function () { * Example of an i18n map: * * { default: 'bold-a', en: 'bold-b', de: 'bold-f' } - * See the [OOjs UI documentation on MediaWiki] [2] for a list of icons included in the library. - * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Icons + * See the [OOUI documentation on MediaWiki] [2] for a list of icons included in the library. + * [2]: https://www.mediawiki.org/wiki/OOUI/Widgets/Icons,_Indicators,_and_Labels#Icons * @cfg {string|Function} [iconTitle] A text string used as the icon title, or a function that returns title * text. The icon title is displayed when users move the mouse over the icon. */ @@ -2748,9 +2786,9 @@ OO.ui.mixin.IconElement.prototype.getIconTitle = function () { * that opens a menu instead of performing an action directly, for example). * * For a list of indicators included in the library, please see the - * [OOjs UI documentation on MediaWiki] [1]. + * [OOUI documentation on MediaWiki] [1]. * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Indicators + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Icons,_Indicators,_and_Labels#Indicators * * @abstract * @class @@ -2759,10 +2797,10 @@ OO.ui.mixin.IconElement.prototype.getIconTitle = function () { * @param {Object} [config] Configuration options * @cfg {jQuery} [$indicator] The indicator element created by the class. If this * configuration is omitted, the indicator element will use a generated ``. - * @cfg {string} [indicator] Symbolic name of the indicator (e.g., ‘alert’ or ‘down’). - * See the [OOjs UI documentation on MediaWiki][2] for a list of indicators included + * @cfg {string} [indicator] Symbolic name of the indicator (e.g., ‘clear’ or ‘down’). + * See the [OOUI documentation on MediaWiki][2] for a list of indicators included * in the library. - * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Indicators + * [2]: https://www.mediawiki.org/wiki/OOUI/Widgets/Icons,_Indicators,_and_Labels#Indicators * @cfg {string|Function} [indicatorTitle] A text string used as the indicator title, * or a function that returns title text. The indicator title is displayed when users move * the mouse over the indicator. @@ -2789,7 +2827,7 @@ OO.initClass( OO.ui.mixin.IndicatorElement ); /* Static Properties */ /** - * Symbolic name of the indicator (e.g., ‘alert’ or ‘down’). + * Symbolic name of the indicator (e.g., ‘clear’ or ‘down’). * The static property will be overridden if the #indicator configuration is used. * * @static @@ -2835,7 +2873,7 @@ OO.ui.mixin.IndicatorElement.prototype.setIndicatorElement = function ( $indicat }; /** - * Set the indicator by its symbolic name: ‘alert’, ‘down’, ‘next’, ‘previous’, ‘required’, ‘up’. Use `null` to remove the indicator. + * Set the indicator by its symbolic name: ‘clear’, ‘down’, ‘required’, ‘search’, ‘up’. Use `null` to remove the indicator. * * @param {string|null} indicator Symbolic name of indicator, or `null` for no indicator * @chainable @@ -2890,7 +2928,7 @@ OO.ui.mixin.IndicatorElement.prototype.setIndicatorTitle = function ( indicatorT }; /** - * Get the symbolic name of the indicator (e.g., ‘alert’ or ‘down’). + * Get the symbolic name of the indicator (e.g., ‘clear’ or ‘down’). * * @return {string} Symbolic name of indicator */ @@ -2912,9 +2950,9 @@ OO.ui.mixin.IndicatorElement.prototype.getIndicatorTitle = function () { /** * LabelElement is often mixed into other classes to generate a label, which * helps identify the function of an interface element. - * See the [OOjs UI documentation on MediaWiki] [1] for more information. + * See the [OOUI documentation on MediaWiki] [1] for more information. * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Labels + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Icons,_Indicators,_and_Labels#Labels * * @abstract * @class @@ -2925,8 +2963,8 @@ OO.ui.mixin.IndicatorElement.prototype.getIndicatorTitle = function () { * configuration is omitted, the label element will use a generated ``. * @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 [OOjs UI documentation on MediaWiki] [2] for examples. - * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Labels + * 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 @@ -3111,7 +3149,6 @@ OO.ui.mixin.LabelElement.prototype.setLabelContent = function ( label ) { * * - **progressive**: Progressive styling is applied to convey that the widget will move the user forward in a process. * - **destructive**: Destructive styling is applied to convey that the widget will remove something. - * - **constructive**: Constructive styling is deprecated since v0.23.2 and equivalent to progressive. * * The flags affect the appearance of the buttons: * @@ -3128,9 +3165,9 @@ OO.ui.mixin.LabelElement.prototype.setLabelContent = function ( label ) { * $( 'body' ).append( button1.$element, button2.$element ); * * {@link OO.ui.ActionWidget ActionWidgets}, which are a special kind of button that execute an action, use these flags: **primary** and **safe**. - * Please see the [OOjs UI documentation on MediaWiki] [1] for more information. + * Please see the [OOUI documentation on MediaWiki] [1] for more information. * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Elements/Flagged + * [1]: https://www.mediawiki.org/wiki/OOUI/Elements/Flagged * * @abstract * @class @@ -3138,8 +3175,8 @@ OO.ui.mixin.LabelElement.prototype.setLabelContent = function ( label ) { * @constructor * @param {Object} [config] Configuration options * @cfg {string|string[]} [flags] The name or names of the flags (e.g., 'progressive' or 'primary') to apply. - * Please see the [OOjs UI documentation on MediaWiki] [2] for more information about available flags. - * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Elements/Flagged + * Please see the [OOUI documentation on MediaWiki] [2] for more information about available flags. + * [2]: https://www.mediawiki.org/wiki/OOUI/Elements/Flagged * @cfg {jQuery} [$flagged] The flagged element. By default, * the flagged functionality is applied to the element created by the class ($element). * If a different element is specified, the flagged functionality will be applied to it instead. @@ -3579,10 +3616,10 @@ OO.ui.mixin.AccessKeyedElement.prototype.formatTitleWithAccessKey = function ( t /** * ButtonWidget is a generic widget for buttons. A wide variety of looks, * feels, and functionality can be customized via the class’s configuration options - * and methods. Please see the [OOjs UI documentation on MediaWiki] [1] for more information + * and methods. Please see the [OOUI documentation on MediaWiki] [1] for more information * and examples. * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Buttons_and_Switches + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Buttons_and_Switches * * @example * // A button widget @@ -3887,7 +3924,7 @@ OO.ui.ButtonGroupWidget.prototype.simulateLabelClick = function () { /** * IconWidget is a generic widget for {@link OO.ui.mixin.IconElement icons}. In general, IconWidgets should be used with OO.ui.LabelWidget, - * which creates a label that identifies the icon’s function. See the [OOjs UI documentation on MediaWiki] [1] + * which creates a label that identifies the icon’s function. See the [OOUI documentation on MediaWiki] [1] * for a list of icons included in the library. * * @example @@ -3902,7 +3939,7 @@ OO.ui.ButtonGroupWidget.prototype.simulateLabelClick = function () { * } ); * $( 'body' ).append( myIcon.$element, iconLabel.$element ); * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Icons + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Icons,_Indicators,_and_Labels#Icons * * @class * @extends OO.ui.Widget @@ -3946,23 +3983,23 @@ OO.ui.IconWidget.static.tagName = 'span'; /** * IndicatorWidgets create indicators, which are small graphics that are generally used to draw - * attention to the status of an item or to clarify the function of a control. For a list of - * indicators included in the library, please see the [OOjs UI documentation on MediaWiki][1]. + * attention to the status of an item or to clarify the function within a control. For a list of + * indicators included in the library, please see the [OOUI documentation on MediaWiki][1]. * * @example * // Example of an indicator widget * var indicator1 = new OO.ui.IndicatorWidget( { - * indicator: 'alert' + * indicator: 'required' * } ); * * // Create a fieldset layout to add a label * var fieldset = new OO.ui.FieldsetLayout(); * fieldset.addItems( [ - * new OO.ui.FieldLayout( indicator1, { label: 'An alert indicator:' } ) + * new OO.ui.FieldLayout( indicator1, { label: 'A required indicator:' } ) * ] ); * $( 'body' ).append( fieldset.$element ); * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Indicators + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Icons,_Indicators,_and_Labels#Indicators * * @class * @extends OO.ui.Widget @@ -4061,7 +4098,6 @@ OO.ui.LabelWidget = function OoUiLabelWidget( config ) { } else { this.$label.on( 'click', function () { this.input.simulateLabelClick(); - return false; }.bind( this ) ); } } @@ -4258,6 +4294,7 @@ OO.ui.mixin.FloatableElement = function OoUiMixinFloatableElement( config ) { this.$floatableContainer = null; this.$floatableWindow = null; this.$floatableClosestScrollable = null; + this.floatableOutOfView = false; this.onFloatableScrollHandler = this.position.bind( this ); this.onFloatableWindowResizeHandler = this.position.bind( this ); @@ -4461,6 +4498,15 @@ OO.ui.mixin.FloatableElement.prototype.isElementInViewport = function ( $element elemRect.left <= contRect.right && elemRect.right >= contRect.left; }; +/** + * Check if the floatable is hidden to the user because it was offscreen. + * + * @return {boolean} Floatable is out of view + */ +OO.ui.mixin.FloatableElement.prototype.isFloatableOutOfView = function () { + return this.floatableOutOfView; +}; + /** * Position the floatable below its container. * @@ -4487,7 +4533,8 @@ OO.ui.mixin.FloatableElement.prototype.position = function () { return this; } - if ( this.hideWhenOutOfView && !this.isElementInViewport( this.$floatableContainer, this.$floatableClosestScrollable ) ) { + this.floatableOutOfView = this.hideWhenOutOfView && !this.isElementInViewport( this.$floatableContainer, this.$floatableClosestScrollable ); + if ( this.floatableOutOfView ) { this.$floatable.addClass( 'oo-ui-element-hidden' ); return this; } else { @@ -5022,7 +5069,7 @@ OO.ui.mixin.ClippableElement.prototype.clip = function () { /** * PopupWidget is a container for content. The popup is overlaid and positioned absolutely. * By default, each popup has an anchor that points toward its origin. - * Please see the [OOjs UI documentation on Mediawiki] [1] for more information and examples. + * Please see the [OOUI documentation on Mediawiki] [1] for more information and examples. * * Unlike most widgets, PopupWidget is initially hidden and must be shown by calling #toggle. * @@ -5038,7 +5085,7 @@ OO.ui.mixin.ClippableElement.prototype.clip = function () { * // To display the popup, toggle the visibility to 'true'. * popup.toggle( true ); * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Popups + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Popups * * @class * @extends OO.ui.Widget @@ -5075,16 +5122,16 @@ OO.ui.mixin.ClippableElement.prototype.clip = function () { * 'above' and 'below', or between 'before' and 'after', if there is not enough space in the * desired direction to display the popup without clipping * @cfg {jQuery} [$container] Constrain the popup to the boundaries of the specified container. - * See the [OOjs UI docs on MediaWiki][3] for an example. - * [3]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Popups#containerExample + * See the [OOUI docs on MediaWiki][3] for an example. + * [3]: https://www.mediawiki.org/wiki/OOUI/Widgets/Popups#containerExample * @cfg {number} [containerPadding=10] Padding between the popup and its container, specified as a number of pixels. * @cfg {jQuery} [$content] Content to append to the popup's body * @cfg {jQuery} [$footer] Content to append to the popup's footer * @cfg {boolean} [autoClose=false] Automatically close the popup when it loses focus. * @cfg {jQuery} [$autoCloseIgnore] Elements that will not close the popup when clicked. - * This config option is only relevant if #autoClose is set to `true`. See the [OOjs UI docs on MediaWiki][2] + * This config option is only relevant if #autoClose is set to `true`. See the [OOUI documentation on MediaWiki][2] * for an example. - * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Popups#autocloseExample + * [2]: https://www.mediawiki.org/wiki/OOUI/Widgets/Popups#autocloseExample * @cfg {boolean} [head=false] Show a popup header that contains a #label (if specified) and close * button. * @cfg {boolean} [padded=false] Add padding to the popup's body @@ -5361,13 +5408,13 @@ OO.ui.PopupWidget.prototype.toggle = function ( show ) { if ( this.autoFlip ) { if ( this.popupPosition === 'above' || this.popupPosition === 'below' ) { - if ( this.isClippedVertically() ) { + if ( this.isClippedVertically() || this.isFloatableOutOfView() ) { // If opening the popup in the normal direction causes it to be clipped, open // in the opposite one instead normalHeight = this.$element.height(); this.isAutoFlipped = !this.isAutoFlipped; this.position(); - if ( this.isClippedVertically() ) { + if ( this.isClippedVertically() || this.isFloatableOutOfView() ) { // If that also causes it to be clipped, open in whichever direction // we have more space oppositeHeight = this.$element.height(); @@ -5379,7 +5426,7 @@ OO.ui.PopupWidget.prototype.toggle = function ( show ) { } } if ( this.popupPosition === 'before' || this.popupPosition === 'after' ) { - if ( this.isClippedHorizontally() ) { + if ( this.isClippedHorizontally() || this.isFloatableOutOfView() ) { // If opening the popup in the normal direction causes it to be clipped, open // in the opposite one instead normalWidth = this.$element.width(); @@ -5389,7 +5436,7 @@ OO.ui.PopupWidget.prototype.toggle = function ( show ) { this.toggleClipping( false ); this.position(); this.toggleClipping( true ); - if ( this.isClippedHorizontally() ) { + if ( this.isClippedHorizontally() || this.isFloatableOutOfView() ) { // If that also causes it to be clipped, open in whichever direction // we have more space oppositeWidth = this.$element.width(); @@ -5776,7 +5823,7 @@ OO.ui.mixin.PopupElement.prototype.getPopup = function () { * @cfg {jQuery} [$overlay] Render the popup into a separate layer. This configuration is useful in cases where * the expanded popup is larger than its containing `
`. The specified overlay layer is usually on top of the * containing `
` and has a larger area. By default, the popup uses relative positioning. - * See . + * See . */ OO.ui.PopupButtonWidget = function OoUiPopupButtonWidget( config ) { // Configuration initialization @@ -5789,7 +5836,7 @@ OO.ui.PopupButtonWidget = function OoUiPopupButtonWidget( config ) { OO.ui.mixin.PopupElement.call( this, config ); // Properties - this.$overlay = config.$overlay || this.$element; + this.$overlay = ( config.$overlay === true ? OO.ui.getDefaultOverlay() : config.$overlay ) || this.$element; // Events this.connect( this, { click: 'onAction' } ); @@ -5923,9 +5970,9 @@ OO.ui.mixin.ItemWidget.prototype.setElementGroup = function ( group ) { * OptionWidgets are special elements that can be selected and configured with data. The * data is often unique for each option, but it does not have to be. OptionWidgets are used * with OO.ui.SelectWidget to create a selection of mutually exclusive options. For more information - * and examples, please see the [OOjs UI documentation on MediaWiki][1]. + * and examples, please see the [OOUI documentation on MediaWiki][1]. * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Selects_and_Options * * @class * @extends OO.ui.Widget @@ -6020,7 +6067,7 @@ OO.ui.OptionWidget.static.scrollIntoViewOnSelect = false; * @return {boolean} Item is selectable */ OO.ui.OptionWidget.prototype.isSelectable = function () { - return this.constructor.static.selectable && !this.isDisabled() && this.isVisible(); + return this.constructor.static.selectable && !this.disabled && this.isVisible(); }; /** @@ -6031,7 +6078,7 @@ OO.ui.OptionWidget.prototype.isSelectable = function () { * @return {boolean} Item is highlightable */ OO.ui.OptionWidget.prototype.isHighlightable = function () { - return this.constructor.static.highlightable && !this.isDisabled() && this.isVisible(); + return this.constructor.static.highlightable && !this.disabled && this.isVisible(); }; /** @@ -6041,7 +6088,7 @@ OO.ui.OptionWidget.prototype.isHighlightable = function () { * @return {boolean} Item is pressable */ OO.ui.OptionWidget.prototype.isPressable = function () { - return this.constructor.static.pressable && !this.isDisabled() && this.isVisible(); + return this.constructor.static.pressable && !this.disabled && this.isVisible(); }; /** @@ -6146,13 +6193,13 @@ OO.ui.OptionWidget.prototype.getMatchText = function () { }; /** - * A SelectWidget is of a generic selection of options. The OOjs UI library contains several types of + * A SelectWidget is of a generic selection of options. The OOUI library contains several types of * select widgets, including {@link OO.ui.ButtonSelectWidget button selects}, * {@link OO.ui.RadioSelectWidget radio selects}, and {@link OO.ui.MenuSelectWidget * menu selects}. * * This class should be used together with OO.ui.OptionWidget or OO.ui.DecoratedOptionWidget. For more - * information, please see the [OOjs UI documentation on MediaWiki][1]. + * information, please see the [OOUI documentation on MediaWiki][1]. * * @example * // Example of a select widget with three options @@ -6174,7 +6221,7 @@ OO.ui.OptionWidget.prototype.getMatchText = function () { * } ); * $( 'body' ).append( select.$element ); * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Selects_and_Options * * @abstract * @class @@ -6185,8 +6232,8 @@ OO.ui.OptionWidget.prototype.getMatchText = function () { * @param {Object} [config] Configuration options * @cfg {OO.ui.OptionWidget[]} [items] An array of options to add to the select. * Options are created with {@link OO.ui.OptionWidget OptionWidget} classes. See - * the [OOjs UI documentation on MediaWiki] [2] for examples. - * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options + * the [OOUI documentation on MediaWiki] [2] for examples. + * [2]: https://www.mediawiki.org/wiki/OOUI/Widgets/Selects_and_Options */ OO.ui.SelectWidget = function OoUiSelectWidget( config ) { // Configuration initialization @@ -6299,7 +6346,7 @@ OO.ui.SelectWidget.prototype.onFocus = function ( event ) { if ( event.target === this.$element[ 0 ] ) { // This widget was focussed, e.g. by the user tabbing to it. // The styles for focus state depend on one of the items being selected. - if ( !this.getSelectedItem() ) { + if ( !this.findSelectedItem() ) { item = this.findFirstSelectableItem(); } } else { @@ -6436,7 +6483,7 @@ OO.ui.SelectWidget.prototype.onMouseLeave = function () { OO.ui.SelectWidget.prototype.onKeyDown = function ( e ) { var nextItem, handled = false, - currentItem = this.findHighlightedItem() || this.getSelectedItem(); + currentItem = this.findHighlightedItem() || this.findSelectedItem(); if ( !this.isDisabled() && this.isVisible() ) { switch ( e.keyCode ) { @@ -6562,7 +6609,7 @@ OO.ui.SelectWidget.prototype.onKeyPress = function ( e ) { } this.keyPressBufferTimer = setTimeout( this.clearKeyPressBuffer.bind( this ), 1500 ); - item = this.findHighlightedItem() || this.getSelectedItem(); + item = this.findHighlightedItem() || this.findSelectedItem(); if ( this.keyPressBuffer === c ) { // Common (if weird) special case: typing "xxxx" will cycle through all @@ -6670,11 +6717,11 @@ OO.ui.SelectWidget.prototype.findTargetItem = function ( e ) { }; /** - * Get selected item. + * Find selected item. * * @return {OO.ui.OptionWidget|null} Selected item, `null` if no item is selected */ -OO.ui.SelectWidget.prototype.getSelectedItem = function () { +OO.ui.SelectWidget.prototype.findSelectedItem = function () { var i, len; for ( i = 0, len = this.items.length; i < len; i++ ) { @@ -6685,6 +6732,17 @@ OO.ui.SelectWidget.prototype.getSelectedItem = function () { return null; }; +/** + * Get selected item. + * + * @deprecated Since v0.25.0; use {@link #findSelectedItem} instead. + * @return {OO.ui.OptionWidget|null} Selected item, `null` if no item is selected + */ +OO.ui.SelectWidget.prototype.getSelectedItem = function () { + OO.ui.warnDeprecation( 'SelectWidget#getSelectedItem: Deprecated function. Use findSelectedItem instead. See T76630.' ); + return this.findSelectedItem(); +}; + /** * Find highlighted item. * @@ -6701,17 +6759,6 @@ OO.ui.SelectWidget.prototype.findHighlightedItem = function () { return null; }; -/** - * Get highlighted item. - * - * @deprecated 0.23.1 Use {@link #findHighlightedItem} instead. - * @return {OO.ui.OptionWidget|null} Highlighted item, `null` if no item is highlighted - */ -OO.ui.SelectWidget.prototype.getHighlightedItem = function () { - OO.ui.warnDeprecation( 'SelectWidget#getHighlightedItem: Deprecated function. Use findHighlightedItem instead. See T76630.' ); - return this.findHighlightedItem(); -}; - /** * Toggle pressed state. * @@ -6829,7 +6876,7 @@ OO.ui.SelectWidget.prototype.selectItemByLabel = function ( label, prefix ) { * @chainable */ OO.ui.SelectWidget.prototype.selectItemByData = function ( data ) { - var itemFromData = this.getItemFromData( data ); + var itemFromData = this.findItemFromData( data ); if ( data === undefined || !itemFromData ) { return this.selectItem(); } @@ -6960,24 +7007,6 @@ OO.ui.SelectWidget.prototype.findRelativeSelectableItem = function ( item, direc return null; }; -/** - * Get an option by its position relative to the specified item (or to the start of the option array, - * if item is `null`). The direction in which to search through the option array is specified with a - * number: -1 for reverse (the default) or 1 for forward. The method will return an option, or - * `null` if there are no options in the array. - * - * @deprecated 0.23.1 Use {@link #findRelativeSelectableItem} instead - * @param {OO.ui.OptionWidget|null} item Item to describe the start position, or `null` to start at the beginning of the array. - * @param {number} direction Direction to move in: -1 to move backward, 1 to move forward - * @param {Function} [filter] Only consider items for which this function returns - * true. Function takes an OO.ui.OptionWidget and returns a boolean. - * @return {OO.ui.OptionWidget|null} Item at position, `null` if there are no items in the select - */ -OO.ui.SelectWidget.prototype.getRelativeSelectableItem = function ( item, direction, filter ) { - OO.ui.warnDeprecation( 'SelectWidget#getRelativeSelectableItem: Deprecated function. Use findRelativeSelectableItem instead. See T76630.' ); - return this.findRelativeSelectableItem( item, direction, filter ); -}; - /** * Find the next selectable item or `null` if there are no selectable items. * Disabled options and menu-section markers and breaks are not selectable. @@ -6988,18 +7017,6 @@ OO.ui.SelectWidget.prototype.findFirstSelectableItem = function () { return this.findRelativeSelectableItem( null, 1 ); }; -/** - * Get the next selectable item or `null` if there are no selectable items. - * Disabled options and menu-section markers and breaks are not selectable. - * - * @deprecated 0.23.1 Use {@link OO.ui.SelectWidget#findFirstSelectableItem} instead. - * @return {OO.ui.OptionWidget|null} Item, `null` if there aren't any selectable items - */ -OO.ui.SelectWidget.prototype.getFirstSelectableItem = function () { - OO.ui.warnDeprecation( 'SelectWidget#getFirstSelectableItem: Deprecated function. Use findFirstSelectableItem instead. See T76630.' ); - return this.findFirstSelectableItem(); -}; - /** * Add an array of options to the select. Optionally, an index number can be used to * specify an insertion point. @@ -7086,7 +7103,7 @@ OO.ui.SelectWidget.prototype.setFocusOwner = function ( $focusOwner ) { * with an {@link OO.ui.mixin.IconElement icon} and/or {@link OO.ui.mixin.IndicatorElement indicator}. * This class is used with OO.ui.SelectWidget to create a selection of mutually exclusive * options. For more information about options and selects, please see the - * [OOjs UI documentation on MediaWiki][1]. + * [OOUI documentation on MediaWiki][1]. * * @example * // Decorated options in a select widget @@ -7106,7 +7123,7 @@ OO.ui.SelectWidget.prototype.setFocusOwner = function ( $focusOwner ) { * } ); * $( 'body' ).append( select.$element ); * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Selects_and_Options * * @class * @extends OO.ui.OptionWidget @@ -7140,9 +7157,9 @@ OO.mixinClass( OO.ui.DecoratedOptionWidget, OO.ui.mixin.IndicatorElement ); /** * MenuOptionWidget is an option widget that looks like a menu item. The class is used with * OO.ui.MenuSelectWidget to create a menu of mutually exclusive options. Please see - * the [OOjs UI documentation on MediaWiki] [1] for more information. + * the [OOUI documentation on MediaWiki] [1] for more information. * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Selects_and_Options#Menu_selects_and_options * * @class * @extends OO.ui.DecoratedOptionWidget @@ -7254,8 +7271,8 @@ OO.ui.MenuSectionOptionWidget.static.highlightable = false; * * Unlike most widgets, MenuSelectWidget is initially hidden and must be shown by calling #toggle. * - * Please see the [OOjs UI documentation on MediaWiki][1] for more information. - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options + * Please see the [OOUI documentation on MediaWiki][1] for more information. + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Selects_and_Options * * @class * @extends OO.ui.SelectWidget @@ -7355,7 +7372,7 @@ OO.ui.MenuSelectWidget.prototype.onDocumentMouseDown = function ( e ) { * @inheritdoc */ OO.ui.MenuSelectWidget.prototype.onKeyDown = function ( e ) { - var currentItem = this.findHighlightedItem() || this.getSelectedItem(); + var currentItem = this.findHighlightedItem() || this.findSelectedItem(); if ( !this.isDisabled() && this.isVisible() ) { switch ( e.keyCode ) { @@ -7593,11 +7610,11 @@ OO.ui.MenuSelectWidget.prototype.toggle = function ( visible ) { this.togglePositioning( !!this.$floatableContainer ); this.toggleClipping( true ); - if ( this.isClippedVertically() ) { + if ( this.isClippedVertically() || this.isFloatableOutOfView() ) { // If opening the menu downwards causes it to be clipped, flip it to open upwards instead belowHeight = this.$element.height(); this.setVerticalPosition( 'above' ); - if ( this.isClippedVertically() ) { + if ( this.isClippedVertically() || this.isFloatableOutOfView() ) { // If opening upwards also causes it to be clipped, flip it to open in whichever direction // we have more space aboveHeight = this.$element.height(); @@ -7611,9 +7628,9 @@ OO.ui.MenuSelectWidget.prototype.toggle = function ( visible ) { this.$focusOwner.attr( 'aria-expanded', 'true' ); - if ( this.getSelectedItem() ) { - this.$focusOwner.attr( 'aria-activedescendant', this.getSelectedItem().getElementId() ); - this.getSelectedItem().scrollElementIntoView( { duration: 0 } ); + if ( this.findSelectedItem() ) { + this.$focusOwner.attr( 'aria-activedescendant', this.findSelectedItem().getElementId() ); + this.findSelectedItem().scrollElementIntoView( { duration: 0 } ); } // Auto-hide @@ -7670,11 +7687,11 @@ OO.ui.MenuSelectWidget.prototype.toggle = function ( visible ) { * * dropDown.getMenu().selectItemByData( 'b' ); * - * dropDown.getMenu().getSelectedItem().getData(); // returns 'b' + * dropDown.getMenu().findSelectedItem().getData(); // returns 'b' * - * For more information, please see the [OOjs UI documentation on MediaWiki] [1]. + * For more information, please see the [OOUI documentation on MediaWiki] [1]. * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Selects_and_Options#Menu_selects_and_options * * @class * @extends OO.ui.Widget @@ -7690,7 +7707,7 @@ OO.ui.MenuSelectWidget.prototype.toggle = function ( visible ) { * @cfg {jQuery} [$overlay] Render the menu into a separate layer. This configuration is useful in cases where * the expanded menu is larger than its containing `
`. The specified overlay layer is usually on top of the * containing `
` and has a larger area. By default, the menu uses relative positioning. - * See . + * See . */ OO.ui.DropdownWidget = function OoUiDropdownWidget( config ) { // Configuration initialization @@ -7700,8 +7717,8 @@ OO.ui.DropdownWidget = function OoUiDropdownWidget( config ) { OO.ui.DropdownWidget.parent.call( this, config ); // Properties (must be set before TabIndexedElement constructor call) - this.$handle = this.$( '' ); - this.$overlay = config.$overlay || this.$element; + this.$handle = $( '' ); + this.$overlay = ( config.$overlay === true ? OO.ui.getDefaultOverlay() : config.$overlay ) || this.$element; // Mixin constructors OO.ui.mixin.IconElement.call( this, config ); @@ -7849,9 +7866,9 @@ OO.ui.DropdownWidget.prototype.onKeyDown = function ( e ) { /** * RadioOptionWidget is an option widget that looks like a radio button. * The class is used with OO.ui.RadioSelectWidget to create a selection of radio options. - * Please see the [OOjs UI documentation on MediaWiki] [1] for more information. + * Please see the [OOUI documentation on MediaWiki] [1] for more information. * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Button_selects_and_option + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Selects_and_Options#Button_selects_and_option * * @class * @extends OO.ui.OptionWidget @@ -7941,7 +7958,7 @@ OO.ui.RadioOptionWidget.prototype.setDisabled = function ( disabled ) { * RadioSelectWidget is a {@link OO.ui.SelectWidget select widget} that contains radio * options and is used together with OO.ui.RadioOptionWidget. The RadioSelectWidget provides * an interface for adding, removing and selecting options. - * Please see the [OOjs UI documentation on MediaWiki][1] for more information. + * Please see the [OOUI documentation on MediaWiki][1] for more information. * * If you want to use this within an HTML form, such as a OO.ui.FormLayout, use * OO.ui.RadioSelectInputWidget instead. @@ -7967,7 +7984,7 @@ OO.ui.RadioOptionWidget.prototype.setDisabled = function ( disabled ) { * * $( 'body' ).append( radioSelect.$element ); * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Selects_and_Options * * @class @@ -8005,9 +8022,9 @@ OO.mixinClass( OO.ui.RadioSelectWidget, OO.ui.mixin.TabIndexedElement ); * MultioptionWidgets are special elements that can be selected and configured with data. The * data is often unique for each option, but it does not have to be. MultioptionWidgets are used * with OO.ui.SelectWidget to create a selection of mutually exclusive options. For more information - * and examples, please see the [OOjs UI documentation on MediaWiki][1]. + * and examples, please see the [OOUI documentation on MediaWiki][1]. * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Multioptions + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Selects_and_Multioptions * * @class * @extends OO.ui.Widget @@ -8087,9 +8104,9 @@ OO.ui.MultioptionWidget.prototype.setSelected = function ( state ) { /** * MultiselectWidget allows selecting multiple options from a list. * - * For more information about menus and options, please see the [OOjs UI documentation on MediaWiki][1]. + * For more information about menus and options, please see the [OOUI documentation on MediaWiki][1]. * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Selects_and_Options#Menu_selects_and_options * * @class * @abstract @@ -8147,27 +8164,49 @@ OO.mixinClass( OO.ui.MultiselectWidget, OO.ui.mixin.GroupWidget ); /* Methods */ /** - * Get options that are selected. + * Find options that are selected. * * @return {OO.ui.MultioptionWidget[]} Selected options */ -OO.ui.MultiselectWidget.prototype.getSelectedItems = function () { +OO.ui.MultiselectWidget.prototype.findSelectedItems = function () { return this.items.filter( function ( item ) { return item.isSelected(); } ); }; /** - * Get the data of options that are selected. + * Get options that are selected. + * + * @deprecated Since v0.25.0; use {@link #findSelectedItems} instead. + * @return {OO.ui.MultioptionWidget[]} Selected options + */ +OO.ui.MultiselectWidget.prototype.getSelectedItems = function () { + OO.ui.warnDeprecation( 'MultiselectWidget#getSelectedItems: Deprecated function. Use findSelectedItems instead. See T76630.' ); + return this.findSelectedItems(); +}; + +/** + * Find the data of options that are selected. * * @return {Object[]|string[]} Values of selected options */ -OO.ui.MultiselectWidget.prototype.getSelectedItemsData = function () { - return this.getSelectedItems().map( function ( item ) { +OO.ui.MultiselectWidget.prototype.findSelectedItemsData = function () { + return this.findSelectedItems().map( function ( item ) { return item.data; } ); }; +/** + * Get the data of options that are selected. + * + * @deprecated Since v0.25.0; use {@link #findSelectedItemsData} instead. + * @return {Object[]|string[]} Values of selected options + */ +OO.ui.MultiselectWidget.prototype.getSelectedItemsData = function () { + OO.ui.warnDeprecation( 'MultiselectWidget#getSelectedItemsData: Deprecated function. Use findSelectedItemsData instead. See T76630.' ); + return this.findSelectedItemsData(); +}; + /** * Select options by reference. Options not mentioned in the `items` array will be deselected. * @@ -8192,7 +8231,7 @@ OO.ui.MultiselectWidget.prototype.selectItemsByData = function ( datas ) { var items, widget = this; items = datas.map( function ( data ) { - return widget.getItemFromData( data ); + return widget.findItemFromData( data ); } ); this.selectItems( items ); return this; @@ -8201,9 +8240,9 @@ OO.ui.MultiselectWidget.prototype.selectItemsByData = function ( datas ) { /** * CheckboxMultioptionWidget is an option widget that looks like a checkbox. * The class is used with OO.ui.CheckboxMultiselectWidget to create a selection of checkbox options. - * Please see the [OOjs UI documentation on MediaWiki] [1] for more information. + * Please see the [OOUI documentation on MediaWiki] [1] for more information. * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Button_selects_and_option + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Selects_and_Options#Button_selects_and_option * * @class * @extends OO.ui.MultioptionWidget @@ -8306,7 +8345,7 @@ OO.ui.CheckboxMultioptionWidget.prototype.onKeyDown = function ( e ) { * CheckboxMultiselectWidget is a {@link OO.ui.MultiselectWidget multiselect widget} that contains * checkboxes and is used together with OO.ui.CheckboxMultioptionWidget. The * CheckboxMultiselectWidget provides an interface for adding, removing and selecting options. - * Please see the [OOjs UI documentation on MediaWiki][1] for more information. + * Please see the [OOUI documentation on MediaWiki][1] for more information. * * If you want to use this within an HTML form, such as a OO.ui.FormLayout, use * OO.ui.CheckboxMultiselectInputWidget instead. @@ -8330,7 +8369,7 @@ OO.ui.CheckboxMultioptionWidget.prototype.onKeyDown = function ( e ) { * * $( 'body' ).append( multiselect.$element ); * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Selects_and_Options * * @class * @extends OO.ui.MultiselectWidget @@ -8568,9 +8607,9 @@ OO.ui.ProgressBarWidget.prototype.setProgress = function ( progress ) { * InputWidget is the base class for all input widgets, which * include {@link OO.ui.TextInputWidget text inputs}, {@link OO.ui.CheckboxInputWidget checkbox inputs}, * {@link OO.ui.RadioInputWidget radio inputs}, and {@link OO.ui.ButtonInputWidget button inputs}. - * See the [OOjs UI documentation on MediaWiki] [1] for more information and examples. + * See the [OOUI documentation on MediaWiki] [1] for more information and examples. * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs + * [1]: https://www.mediawiki.org/wiki/OOUI/Widgets/Inputs * * @abstract * @class @@ -8747,6 +8786,13 @@ OO.ui.InputWidget.prototype.setValue = function ( value ) { this.value = value; this.emit( 'change', this.value ); } + // The first time that the value is set (probably while constructing the widget), + // remember it in defaultValue. This property can be later used to check whether + // the value of the input has been changed since it was created. + if ( this.defaultValue === undefined ) { + this.defaultValue = this.value; + this.$input[ 0 ].defaultValue = this.defaultValue; + } return this; }; @@ -8848,7 +8894,7 @@ OO.ui.HiddenInputWidget.static.tagName = 'input'; * a OO.ui.FormLayout. If you do not need the button to work with HTML forms, you probably * want to use OO.ui.ButtonWidget instead. Button input widgets can be rendered as either an * HTML `