X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=resources%2Flib%2Foojs-ui%2Foojs-ui-core.js;h=fd4e033ab3c1edb13d3a31481215d4d5d35d013c;hb=9964ca1a390c446397dcd466916ffed356cdc3c9;hp=c982010abc0ec816f7b63cc25c6475ddd249198b;hpb=32628487e17c27f3437d44bd54edb8438e837b82;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 c982010abc..fd4e033ab3 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.17.9 + * OOjs UI v0.18.0 * https://www.mediawiki.org/wiki/OOjs_UI * * Copyright 2011–2016 OOjs UI Team and other contributors. * Released under the MIT license * http://oojs.mit-license.org * - * Date: 2016-09-13T18:30:02Z + * Date: 2016-11-09T00:52:37Z */ ( function ( OO ) { @@ -260,6 +260,18 @@ OO.ui.debounce = function ( func, wait, immediate ) { }; }; +/** + * Puts a console warning with provided message. + * + * @param {string} message + */ +OO.ui.warnDeprecation = function ( message ) { + if ( OO.getProp( window, 'console', 'warn' ) !== undefined ) { + // eslint-disable-next-line no-console + console.warn( message ); + } +}; + /** * Returns a function, that, when invoked, will only be triggered at most once * during a given window of time. If called again during that window, it will @@ -312,30 +324,6 @@ OO.ui.now = Date.now || function () { return new Date().getTime(); }; -/** - * Proxy for `node.addEventListener( eventName, handler, true )`. - * - * @param {HTMLElement} node - * @param {string} eventName - * @param {Function} handler - * @deprecated since 0.15.0 - */ -OO.ui.addCaptureEventListener = function ( node, eventName, handler ) { - node.addEventListener( eventName, handler, true ); -}; - -/** - * Proxy for `node.removeEventListener( eventName, handler, true )`. - * - * @param {HTMLElement} node - * @param {string} eventName - * @param {Function} handler - * @deprecated since 0.15.0 - */ -OO.ui.removeCaptureEventListener = function ( node, eventName, handler ) { - node.removeEventListener( eventName, handler, true ); -}; - /** * Reconstitute a JavaScript object corresponding to a widget created by * the PHP implementation. @@ -747,6 +735,7 @@ OO.ui.Element.static.unsafeInfuse = function ( idOrNode, domPromise ) { // pick up dynamic state, like focus, value of form inputs, scroll position, etc. state = cls.static.gatherPreInfuseState( $elem[ 0 ], data ); // rebuild widget + // eslint-disable-next-line new-cap obj = new cls( data ); // now replace old DOM with this new DOM. if ( top ) { @@ -1610,7 +1599,6 @@ OO.ui.Theme.prototype.getElementClasses = function () { * For elements with theme logic hooks, this should be called any time there's a state change. * * @param {OO.ui.Element} element Element for which to update classes - * @return {Object.} Categorized class names with `on` and `off` lists */ OO.ui.Theme.prototype.updateElementClasses = function ( element ) { var $elements = $( [] ), @@ -1871,13 +1859,18 @@ OO.ui.mixin.ButtonElement.prototype.setButtonElement = function ( $button ) { this.$button = $button .addClass( 'oo-ui-buttonElement-button' ) - .attr( { role: 'button' } ) .on( { mousedown: this.onMouseDownHandler, keydown: this.onKeyDownHandler, click: this.onClickHandler, keypress: this.onKeyPressHandler } ); + + // Add `role="button"` on `` elements, where it's needed + // `toUppercase()` is added for XHTML documents + if ( this.$button.prop( 'tagName' ).toUpperCase() === 'A' ) { + this.$button.attr( 'role', 'button' ); + } }; /** @@ -3393,31 +3386,14 @@ OO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.FlaggedElement ); OO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.TabIndexedElement ); OO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.AccessKeyedElement ); -/* Methods */ - -/** - * @inheritdoc - */ -OO.ui.ButtonWidget.prototype.onMouseDown = function ( e ) { - if ( !this.isDisabled() ) { - // Remove the tab-index while the button is down to prevent the button from stealing focus - this.$button.removeAttr( 'tabindex' ); - } - - return OO.ui.mixin.ButtonElement.prototype.onMouseDown.call( this, e ); -}; +/* Static Properties */ /** * @inheritdoc */ -OO.ui.ButtonWidget.prototype.onMouseUp = function ( e ) { - if ( !this.isDisabled() ) { - // Restore the tab-index after the button is up to restore the button's accessibility - this.$button.attr( 'tabindex', this.tabIndex ); - } +OO.ui.ButtonWidget.static.cancelButtonMouseDownEvents = false; - return OO.ui.mixin.ButtonElement.prototype.onMouseUp.call( this, e ); -}; +/* Methods */ /** * Get hyperlink location. @@ -7582,18 +7558,6 @@ OO.ui.InputWidget.prototype.getValue = function () { return this.value; }; -/** - * Set the directionality of the input, either RTL (right-to-left) or LTR (left-to-right). - * - * @deprecated since v0.13.1; use #setDir directly - * @param {boolean} isRTL Directionality is right-to-left - * @chainable - */ -OO.ui.InputWidget.prototype.setRTL = function ( isRTL ) { - this.setDir( isRTL ? 'rtl' : 'ltr' ); - return this; -}; - /** * Set the directionality of the input. * @@ -8612,7 +8576,7 @@ OO.ui.CheckboxMultiselectInputWidget.prototype.setOptions = function ( options ) * @constructor * @param {Object} [config] Configuration options * @cfg {string} [type='text'] The value of the HTML `type` attribute: 'text', 'password', 'search', - * 'email', 'url', 'date' or 'number'. Ignored if `multiline` is true. + * 'email', 'url', 'date', 'month' or 'number'. Ignored if `multiline` is true. * * Some values of `type` result in additional behaviors: * @@ -8646,17 +8610,14 @@ OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) { type: 'text', labelPosition: 'after' }, config ); + if ( config.type === 'search' ) { + OO.ui.warnDeprecation( 'TextInputWidget: config.type=\'search\' is deprecated. Use the SearchInputWidget instead. See T148471 for details.' ); if ( config.icon === undefined ) { config.icon = 'search'; } // indicator: 'clear' is set dynamically later, depending on value } - if ( config.required ) { - if ( config.indicator === undefined ) { - config.indicator = 'required'; - } - } // Parent constructor OO.ui.TextInputWidget.parent.call( this, config ); @@ -8670,6 +8631,7 @@ OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) { // Properties this.type = this.getSaneType( config ); this.readOnly = false; + this.required = false; this.multiline = !!config.multiline; this.autosize = !!config.autosize; this.minRows = config.rows !== undefined ? config.rows : ''; @@ -8713,6 +8675,7 @@ OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) { .addClass( 'oo-ui-textInputWidget oo-ui-textInputWidget-type-' + this.type ) .append( this.$icon, this.$indicator ); this.setReadOnly( !!config.readOnly ); + this.setRequired( !!config.required ); this.updateSearchIndicator(); if ( config.placeholder !== undefined ) { this.$input.attr( 'placeholder', config.placeholder ); @@ -8723,10 +8686,6 @@ OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) { if ( config.autofocus ) { this.$input.attr( 'autofocus', 'autofocus' ); } - if ( config.required ) { - this.$input.attr( 'required', 'required' ); - this.$input.attr( 'aria-required', 'true' ); - } if ( config.autocomplete === false ) { this.$input.attr( 'autocomplete', 'off' ); // Turning off autocompletion also disables "form caching" when the user navigates to a @@ -8925,6 +8884,42 @@ OO.ui.TextInputWidget.prototype.setReadOnly = function ( state ) { return this; }; +/** + * Check if the input is {@link #required required}. + * + * @return {boolean} + */ +OO.ui.TextInputWidget.prototype.isRequired = function () { + return this.required; +}; + +/** + * Set the {@link #required required} state of the input. + * + * @param {boolean} state Make input required + * @chainable + */ +OO.ui.TextInputWidget.prototype.setRequired = function ( state ) { + this.required = !!state; + if ( this.required ) { + this.$input + .attr( 'required', 'required' ) + .attr( 'aria-required', 'true' ); + if ( this.getIndicator() === null ) { + this.setIndicator( 'required' ); + } + } else { + this.$input + .removeAttr( 'required' ) + .removeAttr( 'aria-required' ); + if ( this.getIndicator() === 'required' ) { + this.setIndicator( null ); + } + } + this.updateSearchIndicator(); + return this; +}; + /** * Support function for making #onElementAttach work across browsers. * @@ -9100,6 +9095,7 @@ OO.ui.TextInputWidget.prototype.getSaneType = function ( config ) { 'email', 'url', 'date', + 'month', 'number' ]; return allowedTypes.indexOf( config.type ) !== -1 ? config.type : 'text'; @@ -9297,30 +9293,6 @@ OO.ui.TextInputWidget.prototype.setValidityFlag = function ( isValid ) { } }; -/** - * Check if a value is valid. - * - * This method returns a promise that resolves with a boolean `true` if the current value is - * considered valid according to the supplied {@link #validate validation pattern}. - * - * @deprecated since v0.12.3 - * @return {jQuery.Promise} A promise that resolves to a boolean `true` if the value is valid. - */ -OO.ui.TextInputWidget.prototype.isValid = function () { - var result; - - if ( this.validate instanceof Function ) { - result = this.validate( this.getValue() ); - if ( result && $.isFunction( result.promise ) ) { - return result.promise(); - } else { - return $.Deferred().resolve( !!result ).promise(); - } - } else { - return $.Deferred().resolve( !!this.getValue().match( this.validate ) ).promise(); - } -}; - /** * Get the validity of current value. * @@ -9449,6 +9421,99 @@ OO.ui.TextInputWidget.prototype.restorePreInfuseState = function ( state ) { } }; +/** + * @class + * @extends OO.ui.TextInputWidget + * + * @constructor + * @param {Object} [config] Configuration options + */ +OO.ui.SearchInputWidget = function OoUiSearchInputWidget( config ) { + config = $.extend( { + icon: 'search' + }, config ); + + // Set type to text so that TextInputWidget doesn't + // get stuck in an infinite loop. + config.type = 'text'; + + // Parent constructor + OO.ui.SearchInputWidget.parent.call( this, config ); + + // Initialization + this.$element.addClass( 'oo-ui-textInputWidget-type-search' ); + this.updateSearchIndicator(); + this.connect( this, { + disable: 'onDisable' + } ); +}; + +/* Setup */ + +OO.inheritClass( OO.ui.SearchInputWidget, OO.ui.TextInputWidget ); + +/* Methods */ + +/** + * @inheritdoc + * @protected + */ +OO.ui.SearchInputWidget.prototype.getInputElement = function () { + return $( '' ).attr( 'type', 'search' ); +}; + +/** + * @inheritdoc + */ +OO.ui.SearchInputWidget.prototype.onIndicatorMouseDown = function ( e ) { + if ( e.which === OO.ui.MouseButtons.LEFT ) { + // Clear the text field + this.setValue( '' ); + this.$input[ 0 ].focus(); + return false; + } +}; + +/** + * Update the 'clear' indicator displayed on type: 'search' text + * fields, hiding it when the field is already empty or when it's not + * editable. + */ +OO.ui.SearchInputWidget.prototype.updateSearchIndicator = function () { + if ( this.getValue() === '' || this.isDisabled() || this.isReadOnly() ) { + this.setIndicator( null ); + } else { + this.setIndicator( 'clear' ); + } +}; + +/** + * @inheritdoc + */ +OO.ui.SearchInputWidget.prototype.onChange = function () { + OO.ui.SearchInputWidget.parent.prototype.onChange.call( this ); + this.updateSearchIndicator(); +}; + +/** + * Handle disable events. + * + * @param {boolean} disabled Element is disabled + * @private + */ +OO.ui.SearchInputWidget.prototype.onDisable = function () { + this.updateSearchIndicator(); +}; + +/** + * @inheritdoc + */ +OO.ui.SearchInputWidget.prototype.setReadOnly = function ( state ) { + OO.ui.SearchInputWidget.parent.prototype.setReadOnly.call( this, state ); + this.updateSearchIndicator(); + return this; +}; + /** * ComboBoxInputWidgets combine a {@link OO.ui.TextInputWidget text input} (where a value * can be entered manually) and a {@link OO.ui.MenuSelectWidget menu of options} (from which @@ -9511,17 +9576,19 @@ OO.ui.TextInputWidget.prototype.restorePreInfuseState = function ( state ) { OO.ui.ComboBoxInputWidget = function OoUiComboBoxInputWidget( config ) { // Configuration initialization config = $.extend( { - indicator: 'down', autocomplete: false }, config ); - // For backwards-compatibility with ComboBoxWidget config - $.extend( config, config.input ); // Parent constructor OO.ui.ComboBoxInputWidget.parent.call( this, config ); // Properties this.$overlay = config.$overlay || this.$element; + this.dropdownButton = new OO.ui.ButtonWidget( { + classes: [ 'oo-ui-comboBoxInputWidget-dropdownButton' ], + indicator: 'down', + disabled: this.disabled + } ); this.menu = new OO.ui.FloatingMenuSelectWidget( $.extend( { widget: this, @@ -9531,18 +9598,15 @@ OO.ui.ComboBoxInputWidget = function OoUiComboBoxInputWidget( config ) { }, config.menu ) ); - // For backwards-compatibility with ComboBoxWidget - this.input = this; // Events - this.$indicator.on( { - click: this.onIndicatorClick.bind( this ), - keypress: this.onIndicatorKeyPress.bind( this ) - } ); this.connect( this, { change: 'onInputChange', enter: 'onInputEnter' } ); + this.dropdownButton.connect( this, { + click: 'onDropdownButtonClick' + } ); this.menu.connect( this, { choose: 'onMenuChoose', add: 'onMenuItemsChange', @@ -9558,8 +9622,12 @@ OO.ui.ComboBoxInputWidget = function OoUiComboBoxInputWidget( config ) { if ( config.options !== undefined ) { this.setOptions( config.options ); } - // Extra class for backwards-compatibility with ComboBoxWidget - this.$element.addClass( 'oo-ui-comboBoxInputWidget oo-ui-comboBoxWidget' ); + this.$field = $( '
' ) + .addClass( 'oo-ui-comboBoxInputWidget-field' ) + .append( this.$input, this.dropdownButton.$element ); + this.$element + .addClass( 'oo-ui-comboBoxInputWidget' ) + .append( this.$field ); this.$overlay.append( this.menu.$element ); this.onMenuItemsChange(); }; @@ -9608,42 +9676,24 @@ OO.ui.ComboBoxInputWidget.prototype.onInputChange = function ( value ) { }; /** - * Handle mouse click events. - * - * @private - * @param {jQuery.Event} e Mouse click event - */ -OO.ui.ComboBoxInputWidget.prototype.onIndicatorClick = function ( e ) { - if ( !this.isDisabled() && e.which === OO.ui.MouseButtons.LEFT ) { - this.menu.toggle(); - this.$input[ 0 ].focus(); - } - return false; -}; - -/** - * Handle key press events. + * Handle input enter events. * * @private - * @param {jQuery.Event} e Key press event */ -OO.ui.ComboBoxInputWidget.prototype.onIndicatorKeyPress = function ( e ) { - if ( !this.isDisabled() && ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER ) ) { - this.menu.toggle(); - this.$input[ 0 ].focus(); - return false; +OO.ui.ComboBoxInputWidget.prototype.onInputEnter = function () { + if ( !this.isDisabled() ) { + this.menu.toggle( false ); } }; /** - * Handle input enter events. + * Handle button click events. * * @private */ -OO.ui.ComboBoxInputWidget.prototype.onInputEnter = function () { - if ( !this.isDisabled() ) { - this.menu.toggle( false ); - } +OO.ui.ComboBoxInputWidget.prototype.onDropdownButtonClick = function () { + this.menu.toggle(); + this.$input[ 0 ].focus(); }; /** @@ -9677,6 +9727,9 @@ OO.ui.ComboBoxInputWidget.prototype.setDisabled = function ( disabled ) { // Parent method OO.ui.ComboBoxInputWidget.parent.prototype.setDisabled.call( this, disabled ); + if ( this.dropdownButton ) { + this.dropdownButton.setDisabled( this.isDisabled() ); + } if ( this.menu ) { this.menu.setDisabled( this.isDisabled() ); } @@ -9703,12 +9756,6 @@ OO.ui.ComboBoxInputWidget.prototype.setOptions = function ( options ) { return this; }; -/** - * @class - * @deprecated since 0.13.2; use OO.ui.ComboBoxInputWidget instead - */ -OO.ui.ComboBoxWidget = OO.ui.ComboBoxInputWidget; - /** * FieldLayouts are used with OO.ui.FieldsetLayout. Each FieldLayout requires a field-widget, * which is a widget that is specified by reference before any optional configuration settings. @@ -10015,6 +10062,7 @@ OO.ui.FieldLayout.prototype.updateMessages = function () { * @constructor * @param {OO.ui.Widget} fieldWidget Field widget * @param {OO.ui.ButtonWidget} buttonWidget Button widget + * @param {Object} config */ OO.ui.ActionFieldLayout = function OoUiActionFieldLayout( fieldWidget, buttonWidget, config ) { // Allow passing positional parameters inside the config object @@ -10121,6 +10169,7 @@ OO.ui.FieldsetLayout = function OoUiFieldsetLayout( config ) { } // Initialization + this.$group.addClass( 'oo-ui-fieldsetLayout-group' ); this.$element .addClass( 'oo-ui-fieldsetLayout' ) .prepend( this.$label, this.$help, this.$icon, this.$group );