/*!
- * OOUI v0.26.4
+ * OOUI v0.27.2
* https://www.mediawiki.org/wiki/OOUI
*
* Copyright 2011–2018 OOUI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2018-04-17T22:23:58Z
+ * Date: 2018-06-06T16:16:10Z
*/
( function ( OO ) {
*
* @param {string|HTMLElement|jQuery} idOrNode
* A DOM id (if a string) or node for the widget to infuse.
+ * @param {Object} [config] Configuration options
* @return {OO.ui.Element}
* The `OO.ui.Element` corresponding to this (infusable) document node.
*/
-OO.ui.infuse = function ( idOrNode ) {
- return OO.ui.Element.static.infuse( idOrNode );
+OO.ui.infuse = function ( idOrNode, config ) {
+ return OO.ui.Element.static.infuse( idOrNode, config );
};
( function () {
*
* @param {string|HTMLElement|jQuery} idOrNode
* A DOM id (if a string) or node for the widget to infuse.
+ * @param {Object} [config] Configuration options
* @return {OO.ui.Element}
* The `OO.ui.Element` corresponding to this (infusable) document node.
* For `Tag` objects emitted on the HTML side (used occasionally for content)
* the value returned is a newly-created Element wrapping around the existing
* DOM node.
*/
-OO.ui.Element.static.infuse = function ( idOrNode ) {
- var obj = OO.ui.Element.static.unsafeInfuse( idOrNode, false );
+OO.ui.Element.static.infuse = function ( idOrNode, config ) {
+ var obj = OO.ui.Element.static.unsafeInfuse( idOrNode, config, false );
// Verify that the type matches up.
// FIXME: uncomment after T89721 is fixed, see T90929.
/*
*
* @private
* @param {string|HTMLElement|jQuery} idOrNode
- * @param {jQuery.Promise|boolean} domPromise A promise that will be resolved
+ * @param {Object} [config] Configuration options
+ * @param {jQuery.Promise} [domPromise] A promise that will be resolved
* when the top-level widget of this infusion is inserted into DOM,
- * replacing the original node; or false for top-level invocation.
+ * replacing the original node; only used internally.
* @return {OO.ui.Element}
*/
-OO.ui.Element.static.unsafeInfuse = function ( idOrNode, domPromise ) {
+OO.ui.Element.static.unsafeInfuse = function ( idOrNode, config, domPromise ) {
// look for a cached result of a previous infusion.
var id, $elem, error, data, cls, parts, parent, obj, top, state, infusedChildren;
if ( typeof idOrNode === 'string' ) {
}
if ( data._ === 'Tag' ) {
// Special case: this is a raw Tag; wrap existing node, don't rebuild.
- return new OO.ui.Element( { $element: $elem } );
+ return new OO.ui.Element( $.extend( {}, config, { $element: $elem } ) );
}
parts = data._.split( '.' );
cls = OO.getProp.apply( OO, [ window ].concat( parts ) );
throw new Error( 'Unknown widget type: id: ' + id + ', class: ' + data._ );
}
- if ( domPromise === false ) {
+ if ( !domPromise ) {
top = $.Deferred();
domPromise = top.promise();
}
var infused;
if ( OO.isPlainObject( value ) ) {
if ( value.tag ) {
- infused = OO.ui.Element.static.unsafeInfuse( value.tag, domPromise );
+ infused = OO.ui.Element.static.unsafeInfuse( value.tag, config, domPromise );
infusedChildren.push( infused );
// Flatten the structure
infusedChildren.push.apply( infusedChildren, infused.$element.data( 'ooui-infused-children' ) || [] );
state = cls.static.gatherPreInfuseState( $elem[ 0 ], data );
// rebuild widget
// eslint-disable-next-line new-cap
- obj = new cls( data );
+ obj = new cls( $.extend( {}, config, 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.
return null;
};
-/**
- * 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.
*
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.
*
*
* MessageDialog.prototype.initialize = function () {
* MessageDialog.parent.prototype.initialize.apply( this, arguments );
- * this.content = new OO.ui.PanelLayout( { $: this.$, padded: true } );
+ * this.content = new OO.ui.PanelLayout( { padded: true } );
* this.content.$element.append( '<p>Click the \'Done\' action widget to see its pending state. Note that action widgets can be marked pending in message dialogs but not process dialogs.</p>' );
* this.$body.append( this.content.$element );
* };
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.
*
OO.ui.mixin.ClippableElement.call( this, $.extend( {}, config, { $clippable: this.$group } ) );
OO.ui.mixin.FloatableElement.call( this, config );
+ // Initial vertical positions other than 'center' will result in
+ // the menu being flipped if there is not enough space in the container.
+ // Store the original position so we know what to reset to.
+ this.originalVerticalPosition = this.verticalPosition;
+
// Properties
this.autoHide = config.autoHide === undefined || !!config.autoHide;
this.hideOnChoose = config.hideOnChoose === undefined || !!config.hideOnChoose;
* The menu is ready: it is visible and has been positioned and clipped.
*/
+/* Static properties */
+
+/**
+ * Positions to flip to if there isn't room in the container for the
+ * menu in a specific direction.
+ *
+ * @property {Object.<string,string>}
+ */
+OO.ui.MenuSelectWidget.static.flippedPositions = {
+ below: 'above',
+ above: 'below',
+ top: 'bottom',
+ bottom: 'top'
+};
+
/* Methods */
/**
* @inheritdoc
*/
OO.ui.MenuSelectWidget.prototype.toggle = function ( visible ) {
- var change, belowHeight, aboveHeight;
+ var change, originalHeight, flippedHeight;
visible = ( visible === undefined ? !this.visible : !!visible ) && !!this.items.length;
change = visible !== this.isVisible();
this.warnedUnattached = true;
}
- if ( change ) {
- if ( visible && ( this.width || this.$floatableContainer ) ) {
- this.setIdealSize( this.width || this.$floatableContainer.width() );
- }
- if ( visible ) {
- // Reset position before showing the popup again. It's possible we no longer need to flip
- // (e.g. if the user scrolled).
- this.setVerticalPosition( 'below' );
- }
+ if ( change && visible ) {
+ // Reset position before showing the popup again. It's possible we no longer need to flip
+ // (e.g. if the user scrolled).
+ this.setVerticalPosition( this.originalVerticalPosition );
}
// Parent method
if ( change ) {
if ( visible ) {
- this.bindKeyDownListener();
- this.bindKeyPressListener();
+
+ if ( this.width ) {
+ this.setIdealSize( this.width );
+ } else if ( this.$floatableContainer ) {
+ this.$clippable.css( 'width', 'auto' );
+ this.setIdealSize(
+ this.$floatableContainer[ 0 ].offsetWidth > this.$clippable[ 0 ].offsetWidth ?
+ // Dropdown is smaller than handle so expand to width
+ this.$floatableContainer[ 0 ].offsetWidth :
+ // Dropdown is larger than handle so auto size
+ 'auto'
+ );
+ this.$clippable.css( 'width', '' );
+ }
this.togglePositioning( !!this.$floatableContainer );
this.toggleClipping( true );
- 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' );
+ this.bindKeyDownListener();
+ this.bindKeyPressListener();
+
+ if (
+ ( this.isClippedVertically() || this.isFloatableOutOfView() ) &&
+ this.originalVerticalPosition !== 'center'
+ ) {
+ // If opening the menu in one direction causes it to be clipped, flip it
+ originalHeight = this.$element.height();
+ this.setVerticalPosition(
+ this.constructor.static.flippedPositions[ this.originalVerticalPosition ]
+ );
if ( this.isClippedVertically() || this.isFloatableOutOfView() ) {
- // If opening upwards also causes it to be clipped, flip it to open in whichever direction
+ // If flipping also causes it to be clipped, open in whichever direction
// we have more space
- aboveHeight = this.$element.height();
- if ( aboveHeight < belowHeight ) {
- this.setVerticalPosition( 'below' );
+ flippedHeight = this.$element.height();
+ if ( originalHeight > flippedHeight ) {
+ this.setVerticalPosition( this.originalVerticalPosition );
}
}
}
} );
};
-/**
- * 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.
*
} );
};
-/**
- * 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.
*
* - **inline**: The label is placed after the field-widget and aligned to the left.
* An inline-alignment is best used with checkboxes or radio buttons.
*
- * Help text is accessed via a help icon that appears in the upper right corner of the rendered field layout.
+ * Help text can either be:
+ *
+ * - accessed via a help icon that appears in the upper right corner of the rendered field layout, or
+ * - shown as a subtle explanation below the label.
+ *
+ * If the help text is brief, or is essential to always espose it, set `helpInline` to `true`. If it
+ * is long or not essential, leave `helpInline` to its default, `false`.
+ *
* Please see the [OOUI documentation on MediaWiki] [1] for examples and more information.
*
* [1]: https://www.mediawiki.org/wiki/OOUI/Layouts/Fields_and_Fieldsets
* @constructor
* @param {OO.ui.Widget} fieldWidget Field widget
* @param {Object} [config] Configuration options
- * @cfg {string} [align='left'] Alignment of the label: 'left', 'right', 'top' or 'inline'
- * @cfg {Array} [errors] Error messages about the widget, which will be displayed below the widget.
+ * @cfg {string} [align='left'] Alignment of the label: 'left', 'right', 'top'
+ * or 'inline'
+ * @cfg {Array} [errors] Error messages about the widget, which will be
+ * displayed below the widget.
* The array may contain strings or OO.ui.HtmlSnippet instances.
- * @cfg {Array} [notices] Notices about the widget, which will be displayed below the widget.
+ * @cfg {Array} [notices] Notices about the widget, which will be displayed
+ * below the widget.
* The array may contain strings or OO.ui.HtmlSnippet instances.
- * @cfg {string|OO.ui.HtmlSnippet} [help] Help text. When help text is specified, a "help" icon will appear
- * in the upper-right corner of the rendered field; clicking it will display the text in a popup.
- * For important messages, you are advised to use `notices`, as they are always shown.
- * @cfg {jQuery} [$overlay] Passed to OO.ui.PopupButtonWidget for help popup, if `help` is given.
+ * These are more visible than `help` messages when `helpInline` is set, and so
+ * might be good for transient messages.
+ * @cfg {string|OO.ui.HtmlSnippet} [help] Help text. When help text is specified
+ * and `helpInline` is `false`, a "help" icon will appear in the upper-right
+ * corner of the rendered field; clicking it will display the text in a popup.
+ * If `helpInline` is `true`, then a subtle description will be shown after the
+ * label.
+ * @cfg {boolean} [helpInline=false] Whether or not the help should be inline,
+ * or shown when the "help" icon is clicked.
+ * @cfg {jQuery} [$overlay] Passed to OO.ui.PopupButtonWidget for help popup, if
+ * `help` is given.
* See <https://www.mediawiki.org/wiki/OOUI/Concepts#Overlays>.
*
* @throws {Error} An error is thrown if no widget is specified
}
// Configuration initialization
- config = $.extend( { align: 'left' }, config );
+ config = $.extend( { align: 'left', helpInline: false }, config );
// Parent constructor
OO.ui.FieldLayout.parent.call( this, config );
this.$header = $( '<span>' );
this.$body = $( '<div>' );
this.align = null;
+ this.helpInline = config.helpInline;
+
if ( config.help ) {
- this.popupButtonWidget = new OO.ui.PopupButtonWidget( {
- $overlay: config.$overlay,
- popup: {
- padded: true
- },
- classes: [ 'oo-ui-fieldLayout-help' ],
- framed: false,
- icon: 'info'
- } );
- if ( config.help instanceof OO.ui.HtmlSnippet ) {
- this.popupButtonWidget.getPopup().$body.html( config.help.toString() );
+ if ( this.helpInline ) {
+ this.$help = new OO.ui.LabelWidget( {
+ label: config.help,
+ classes: [ 'oo-ui-inline-help' ]
+ } ).$element;
} else {
- this.popupButtonWidget.getPopup().$body.text( config.help );
+ this.popupButtonWidget = new OO.ui.PopupButtonWidget( {
+ $overlay: config.$overlay,
+ popup: {
+ padded: true
+ },
+ classes: [ 'oo-ui-fieldLayout-help' ],
+ framed: false,
+ icon: 'info',
+ label: OO.ui.msg( 'ooui-field-help' )
+ } );
+ if ( config.help instanceof OO.ui.HtmlSnippet ) {
+ this.popupButtonWidget.getPopup().$body.html( config.help.toString() );
+ } else {
+ this.popupButtonWidget.getPopup().$body.text( config.help );
+ }
+ this.$help = this.popupButtonWidget.$element;
}
- this.$help = this.popupButtonWidget.$element;
} else {
this.$help = $( [] );
}
this.fieldWidget.connect( this, { disable: 'onFieldDisable' } );
// Initialization
- if ( config.help ) {
+ if ( config.help && !config.helpInline ) {
// Set the 'aria-describedby' attribute on the fieldWidget
// Preference given to an input or a button
(
value = 'top';
}
// Reorder elements
- if ( value === 'top' ) {
- this.$header.append( this.$help, this.$label );
- this.$body.append( this.$header, this.$field );
- } else if ( value === 'inline' ) {
- this.$header.append( this.$help, this.$label );
- this.$body.append( this.$field, this.$header );
+
+ if ( this.helpInline ) {
+ if ( value === 'inline' ) {
+ this.$header.append( this.$label, this.$help );
+ this.$body.append( this.$field, this.$header );
+ } else {
+ this.$header.append( this.$label, this.$help );
+ this.$body.append( this.$header, this.$field );
+ }
} else {
- this.$header.append( this.$label );
- this.$body.append( this.$header, this.$help, this.$field );
+ if ( value === 'top' ) {
+ this.$header.append( this.$help, this.$label );
+ this.$body.append( this.$header, this.$field );
+ } else if ( value === 'inline' ) {
+ this.$header.append( this.$help, this.$label );
+ this.$body.append( this.$field, this.$header );
+ } else {
+ this.$header.append( this.$label );
+ this.$body.append( this.$header, this.$help, this.$field );
+ }
}
// Set classes. The following classes can be used here:
// * oo-ui-fieldLayout-align-left
},
classes: [ 'oo-ui-fieldsetLayout-help' ],
framed: false,
- icon: 'info'
+ icon: 'info',
+ label: OO.ui.msg( 'ooui-field-help' )
} );
if ( config.help instanceof OO.ui.HtmlSnippet ) {
this.popupButtonWidget.getPopup().$body.html( config.help.toString() );
OO.inheritClass( OO.ui.HorizontalLayout, OO.ui.Layout );
OO.mixinClass( OO.ui.HorizontalLayout, OO.ui.mixin.GroupElement );
+/**
+ * NumberInputWidgets combine a {@link OO.ui.TextInputWidget text input} (where a value
+ * can be entered manually) and two {@link OO.ui.ButtonWidget button widgets}
+ * (to adjust the value in increments) to allow the user to enter a number.
+ *
+ * @example
+ * // Example: A NumberInputWidget.
+ * var numberInput = new OO.ui.NumberInputWidget( {
+ * label: 'NumberInputWidget',
+ * input: { value: 5 },
+ * min: 1,
+ * max: 10
+ * } );
+ * $( 'body' ).append( numberInput.$element );
+ *
+ * @class
+ * @extends OO.ui.TextInputWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object} [minusButton] Configuration options to pass to the {@link OO.ui.ButtonWidget decrementing button widget}.
+ * @cfg {Object} [plusButton] Configuration options to pass to the {@link OO.ui.ButtonWidget incrementing button widget}.
+ * @cfg {boolean} [allowInteger=false] Whether the field accepts only integer values.
+ * @cfg {number} [min=-Infinity] Minimum allowed value
+ * @cfg {number} [max=Infinity] Maximum allowed value
+ * @cfg {number} [step=1] Delta when using the buttons or up/down arrow keys
+ * @cfg {number|null} [pageStep] Delta when using the page-up/page-down keys. Defaults to 10 times #step.
+ * @cfg {boolean} [showButtons=true] Whether to show the plus and minus buttons.
+ */
+OO.ui.NumberInputWidget = function OoUiNumberInputWidget( config ) {
+ var $field = $( '<div>' )
+ .addClass( 'oo-ui-numberInputWidget-field' );
+
+ // Configuration initialization
+ config = $.extend( {
+ allowInteger: false,
+ min: -Infinity,
+ max: Infinity,
+ step: 1,
+ pageStep: null,
+ showButtons: true
+ }, config );
+
+ // For backward compatibility
+ $.extend( config, config.input );
+ this.input = this;
+
+ // Parent constructor
+ OO.ui.NumberInputWidget.parent.call( this, $.extend( config, {
+ type: 'number'
+ } ) );
+
+ if ( config.showButtons ) {
+ this.minusButton = new OO.ui.ButtonWidget( $.extend(
+ {
+ disabled: this.isDisabled(),
+ tabIndex: -1,
+ classes: [ 'oo-ui-numberInputWidget-minusButton' ],
+ icon: 'subtract'
+ },
+ config.minusButton
+ ) );
+ this.minusButton.$element.attr( 'aria-hidden', 'true' );
+ this.plusButton = new OO.ui.ButtonWidget( $.extend(
+ {
+ disabled: this.isDisabled(),
+ tabIndex: -1,
+ classes: [ 'oo-ui-numberInputWidget-plusButton' ],
+ icon: 'add'
+ },
+ config.plusButton
+ ) );
+ this.plusButton.$element.attr( 'aria-hidden', 'true' );
+ }
+
+ // Events
+ this.$input.on( {
+ keydown: this.onKeyDown.bind( this ),
+ 'wheel mousewheel DOMMouseScroll': this.onWheel.bind( this )
+ } );
+ if ( config.showButtons ) {
+ this.plusButton.connect( this, {
+ click: [ 'onButtonClick', +1 ]
+ } );
+ this.minusButton.connect( this, {
+ click: [ 'onButtonClick', -1 ]
+ } );
+ }
+
+ // Build the field
+ $field.append( this.$input );
+ if ( config.showButtons ) {
+ $field
+ .prepend( this.minusButton.$element )
+ .append( this.plusButton.$element );
+ }
+
+ // Initialization
+ this.setAllowInteger( config.allowInteger || config.isInteger );
+ this.setRange( config.min, config.max );
+ this.setStep( config.step, config.pageStep );
+ // Set the validation method after we set allowInteger and range
+ // so that it doesn't immediately call setValidityFlag
+ this.setValidation( this.validateNumber.bind( this ) );
+
+ this.$element
+ .addClass( 'oo-ui-numberInputWidget' )
+ .toggleClass( 'oo-ui-numberInputWidget-buttoned', config.showButtons )
+ .append( $field );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.NumberInputWidget, OO.ui.TextInputWidget );
+
+/* Methods */
+
+/**
+ * Set whether only integers are allowed
+ *
+ * @param {boolean} flag
+ */
+OO.ui.NumberInputWidget.prototype.setAllowInteger = function ( flag ) {
+ this.allowInteger = !!flag;
+ this.setValidityFlag();
+};
+// Backward compatibility
+OO.ui.NumberInputWidget.prototype.setIsInteger = OO.ui.NumberInputWidget.prototype.setAllowInteger;
+
+/**
+ * Get whether only integers are allowed
+ *
+ * @return {boolean} Flag value
+ */
+OO.ui.NumberInputWidget.prototype.getAllowInteger = function () {
+ return this.allowInteger;
+};
+// Backward compatibility
+OO.ui.NumberInputWidget.prototype.getIsInteger = OO.ui.NumberInputWidget.prototype.getAllowInteger;
+
+/**
+ * Set the range of allowed values
+ *
+ * @param {number} min Minimum allowed value
+ * @param {number} max Maximum allowed value
+ */
+OO.ui.NumberInputWidget.prototype.setRange = function ( min, max ) {
+ if ( min > max ) {
+ throw new Error( 'Minimum (' + min + ') must not be greater than maximum (' + max + ')' );
+ }
+ this.min = min;
+ this.max = max;
+ this.$input.attr( 'min', this.min );
+ this.$input.attr( 'max', this.max );
+ this.setValidityFlag();
+};
+
+/**
+ * Get the current range
+ *
+ * @return {number[]} Minimum and maximum values
+ */
+OO.ui.NumberInputWidget.prototype.getRange = function () {
+ return [ this.min, this.max ];
+};
+
+/**
+ * Set the stepping deltas
+ *
+ * @param {number} step Normal step
+ * @param {number|null} pageStep Page step. If null, 10 * step will be used.
+ */
+OO.ui.NumberInputWidget.prototype.setStep = function ( step, pageStep ) {
+ if ( step <= 0 ) {
+ throw new Error( 'Step value must be positive' );
+ }
+ if ( pageStep === null ) {
+ pageStep = step * 10;
+ } else if ( pageStep <= 0 ) {
+ throw new Error( 'Page step value must be positive' );
+ }
+ this.step = step;
+ this.pageStep = pageStep;
+ this.$input.attr( 'step', this.step );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.NumberInputWidget.prototype.setValue = function ( value ) {
+ if ( value === '' ) {
+ // Some browsers allow a value in the input even if there isn't one reported by $input.val()
+ // so here we make sure an 'empty' value is actually displayed as such.
+ this.$input.val( '' );
+ }
+ return OO.ui.NumberInputWidget.parent.prototype.setValue.call( this, value );
+};
+
+/**
+ * Get the current stepping values
+ *
+ * @return {number[]} Step and page step
+ */
+OO.ui.NumberInputWidget.prototype.getStep = function () {
+ return [ this.step, this.pageStep ];
+};
+
+/**
+ * Get the current value of the widget as a number
+ *
+ * @return {number} May be NaN, or an invalid number
+ */
+OO.ui.NumberInputWidget.prototype.getNumericValue = function () {
+ return +this.getValue();
+};
+
+/**
+ * Adjust the value of the widget
+ *
+ * @param {number} delta Adjustment amount
+ */
+OO.ui.NumberInputWidget.prototype.adjustValue = function ( delta ) {
+ var n, v = this.getNumericValue();
+
+ delta = +delta;
+ if ( isNaN( delta ) || !isFinite( delta ) ) {
+ throw new Error( 'Delta must be a finite number' );
+ }
+
+ if ( isNaN( v ) ) {
+ n = 0;
+ } else {
+ n = v + delta;
+ n = Math.max( Math.min( n, this.max ), this.min );
+ if ( this.allowInteger ) {
+ n = Math.round( n );
+ }
+ }
+
+ if ( n !== v ) {
+ this.setValue( n );
+ }
+};
+/**
+ * Validate input
+ *
+ * @private
+ * @param {string} value Field value
+ * @return {boolean}
+ */
+OO.ui.NumberInputWidget.prototype.validateNumber = function ( value ) {
+ var n = +value;
+ if ( value === '' ) {
+ return !this.isRequired();
+ }
+
+ if ( isNaN( n ) || !isFinite( n ) ) {
+ return false;
+ }
+
+ if ( this.allowInteger && Math.floor( n ) !== n ) {
+ return false;
+ }
+
+ if ( n < this.min || n > this.max ) {
+ return false;
+ }
+
+ return true;
+};
+
+/**
+ * Handle mouse click events.
+ *
+ * @private
+ * @param {number} dir +1 or -1
+ */
+OO.ui.NumberInputWidget.prototype.onButtonClick = function ( dir ) {
+ this.adjustValue( dir * this.step );
+};
+
+/**
+ * Handle mouse wheel events.
+ *
+ * @private
+ * @param {jQuery.Event} event
+ */
+OO.ui.NumberInputWidget.prototype.onWheel = function ( event ) {
+ var delta = 0;
+
+ if ( !this.isDisabled() && this.$input.is( ':focus' ) ) {
+ // Standard 'wheel' event
+ if ( event.originalEvent.deltaMode !== undefined ) {
+ this.sawWheelEvent = true;
+ }
+ if ( event.originalEvent.deltaY ) {
+ delta = -event.originalEvent.deltaY;
+ } else if ( event.originalEvent.deltaX ) {
+ delta = event.originalEvent.deltaX;
+ }
+
+ // Non-standard events
+ if ( !this.sawWheelEvent ) {
+ if ( event.originalEvent.wheelDeltaX ) {
+ delta = -event.originalEvent.wheelDeltaX;
+ } else if ( event.originalEvent.wheelDeltaY ) {
+ delta = event.originalEvent.wheelDeltaY;
+ } else if ( event.originalEvent.wheelDelta ) {
+ delta = event.originalEvent.wheelDelta;
+ } else if ( event.originalEvent.detail ) {
+ delta = -event.originalEvent.detail;
+ }
+ }
+
+ if ( delta ) {
+ delta = delta < 0 ? -1 : 1;
+ this.adjustValue( delta * this.step );
+ }
+
+ return false;
+ }
+};
+
+/**
+ * Handle key down events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.NumberInputWidget.prototype.onKeyDown = function ( e ) {
+ if ( !this.isDisabled() ) {
+ switch ( e.which ) {
+ case OO.ui.Keys.UP:
+ this.adjustValue( this.step );
+ return false;
+ case OO.ui.Keys.DOWN:
+ this.adjustValue( -this.step );
+ return false;
+ case OO.ui.Keys.PAGEUP:
+ this.adjustValue( this.pageStep );
+ return false;
+ case OO.ui.Keys.PAGEDOWN:
+ this.adjustValue( -this.pageStep );
+ return false;
+ }
+ }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.NumberInputWidget.prototype.setDisabled = function ( disabled ) {
+ // Parent method
+ OO.ui.NumberInputWidget.parent.prototype.setDisabled.call( this, disabled );
+
+ if ( this.minusButton ) {
+ this.minusButton.setDisabled( this.isDisabled() );
+ }
+ if ( this.plusButton ) {
+ this.plusButton.setDisabled( this.isDisabled() );
+ }
+
+ return this;
+};
+
}( OO ) );
-//# sourceMappingURL=oojs-ui-core.js.map
\ No newline at end of file
+//# sourceMappingURL=oojs-ui-core.js.map.json
\ No newline at end of file