/*!
- * OOUI v0.26.5
+ * OOUI v0.27.0
* 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-24T23:29:01Z
+ * Date: 2018-05-09T00:44:45Z
*/
( function ( OO ) {
* @constructor
* @param {Object} [config] Configuration object
* @cfg {boolean} [valid=true] Item is valid
+ * @cfg {boolean} [fixed] Item is fixed. This means the item is
+ * always included in the values and cannot be removed.
*/
OO.ui.TagItemWidget = function OoUiTagItemWidget( config ) {
config = config || {};
OO.ui.mixin.DraggableElement.call( this, config );
this.valid = config.valid === undefined ? true : !!config.valid;
+ this.fixed = !!config.fixed;
this.closeButton = new OO.ui.ButtonWidget( {
framed: false,
*/
/**
- * @event disabled
- * @param {boolean} isDisabled Item is disabled
+ * @event fixed
+ * @param {boolean} isFixed Item is fixed
*
- * Item disabled state has changed
+ * Item fixed state has changed
*/
/* Methods */
+/**
+ * Set this item as fixed, meaning it cannot be removed
+ *
+ * @param {string} [state] Item is fixed
+ * @fires fixed
+ */
+OO.ui.TagItemWidget.prototype.setFixed = function ( state ) {
+ state = state === undefined ? !this.fixed : !!state;
+
+ if ( this.fixed !== state ) {
+ this.fixed = state;
+ if ( this.closeButton ) {
+ this.closeButton.toggle( !this.fixed );
+ }
+
+ if ( !this.fixed && this.elementGroup && !this.elementGroup.isDraggable() ) {
+ // Only enable the state of the item if the
+ // entire group is draggable
+ this.toggleDraggable( !this.fixed );
+ }
+ this.$element.toggleClass( 'oo-ui-tagItemWidget-fixed', this.fixed );
+
+ this.emit( 'fixed', this.isFixed() );
+ }
+ return this;
+};
+
+/**
+ * Check whether the item is fixed
+ */
+OO.ui.TagItemWidget.prototype.isFixed = function () {
+ return this.fixed;
+};
+
/**
* @inheritdoc
- * @fires disabled
*/
OO.ui.TagItemWidget.prototype.setDisabled = function ( state ) {
+ if ( state && this.elementGroup && !this.elementGroup.isDisabled() ) {
+ OO.ui.warnDeprecation( 'TagItemWidget#setDisabled: Disabling individual items is deprecated and will result in inconsistent behavior. Use #setFixed instead. See T193571.' );
+ }
// Parent method
OO.ui.TagItemWidget.parent.prototype.setDisabled.call( this, state );
+ if (
+ !state &&
+ // Verify we have a group, and that the widget is ready
+ this.toggleDraggable && this.elementGroup &&
+ !this.isFixed() &&
+ !this.elementGroup.isDraggable()
+ ) {
+ // Only enable the draggable state of the item if the
+ // entire group is draggable to begin with, and if the
+ // item is not fixed
+ this.toggleDraggable( !state );
+ }
if ( this.closeButton ) {
this.closeButton.setDisabled( state );
}
- this.emit( 'disabled', this.isDisabled() );
return this;
};
OO.ui.TagItemWidget.prototype.onKeyDown = function ( e ) {
var movement;
- if ( !this.isDisabled() && 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 ) {
remove: 'itemRemove',
navigate: 'itemNavigate',
select: 'itemSelect',
- disabled: 'itemDisabled'
+ fixed: 'itemFixed'
} );
this.connect( this, {
itemRemove: 'onTagRemove',
itemSelect: 'onTagSelect',
- itemDisabled: 'onTagDisabled',
+ itemFixed: 'onTagFixed',
itemNavigate: 'onTagNavigate',
change: 'onChangeTags'
} );
* @param {OO.ui.TagItemWidget} item Selected item
*/
OO.ui.TagMultiselectWidget.prototype.onTagSelect = function ( item ) {
- if ( this.hasInput && this.allowEditTags ) {
+ if ( this.hasInput && this.allowEditTags && !item.isFixed() ) {
if ( this.input.getValue() ) {
this.addTagFromInput();
}
};
/**
- * Respond to item disabled state change
+ * Respond to item fixed state change
*
* @param {OO.ui.TagItemWidget} item Selected item
- * @param {boolean} isDisabled Item is disabled
*/
-OO.ui.TagMultiselectWidget.prototype.onTagDisabled = function ( item, isDisabled ) {
- if ( isDisabled ) {
- // Move item to start if it is disabled
- this.addItems( item, 0 );
+OO.ui.TagMultiselectWidget.prototype.onTagFixed = function ( item ) {
+ var i,
+ items = this.getItems();
+
+ // Move item to the end of the static items
+ for ( i = 0; i < items.length; i++ ) {
+ if ( items[ i ] !== item && !items[ i ].isFixed() ) {
+ break;
+ }
}
+ this.addItems( item, i );
};
/**
* Respond to change event, where items were added, removed, or cleared.
*/
OO.ui.MenuTagMultiselectWidget.prototype.onTagSelect = function ( tagItem ) {
var menuItem = this.menu.findItemFromData( tagItem.getData() );
- // Override the base behavior from TagMultiselectWidget; the base behavior
- // in TagMultiselectWidget is to remove the tag to edit it in the input,
- // but in our case, we want to utilize the menu selection behavior, and
- // definitely not remove the item.
-
- // If there is an input that is used for filtering, erase the value so we don't filter
- if ( this.hasInput && this.menu.filterFromInput ) {
- this.input.setValue( '' );
- }
+ if ( !this.allowArbitrary ) {
+ // Override the base behavior from TagMultiselectWidget; the base behavior
+ // in TagMultiselectWidget is to remove the tag to edit it in the input,
+ // but in our case, we want to utilize the menu selection behavior, and
+ // definitely not remove the item.
+
+ // If there is an input that is used for filtering, erase the value so we don't filter
+ if ( this.hasInput && this.menu.filterFromInput ) {
+ this.input.setValue( '' );
+ }
- // Select the menu item
- this.menu.selectItem( menuItem );
+ // Select the menu item
+ this.menu.selectItem( menuItem );
- this.focus();
+ this.focus();
+ } else {
+ // Use the default
+ OO.ui.MenuTagMultiselectWidget.parent.prototype.onTagSelect.call( this, tagItem );
+ }
};
/**
this.onFileSelectedHandler = this.onFileSelected.bind( this );
this.selectButton = new OO.ui.ButtonWidget( {
+ $element: $( '<label>' ),
classes: [ 'oo-ui-selectFileWidget-selectButton' ],
label: OO.ui.msg( 'ooui-selectfile-button-select' ),
disabled: this.disabled || !this.isSupported
return this.results;
};
-/**
- * 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.plusButton = new OO.ui.ButtonWidget( $.extend(
- {
- disabled: this.isDisabled(),
- tabIndex: -1,
- classes: [ 'oo-ui-numberInputWidget-plusButton' ],
- icon: 'add'
- },
- config.plusButton
- ) );
- }
-
- // 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.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;
-};
-
-/**
- * @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-widgets.js.map
\ No newline at end of file