/*!
- * OOjs UI v0.17.7
+ * OOjs UI v0.17.10
* 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-08-03T16:38:22Z
+ * Date: 2016-10-03T18:59:01Z
*/
( function ( OO ) {
// pick up dynamic state, like focus, value of form inputs, scroll position, etc.
state = cls.static.gatherPreInfuseState( $elem[ 0 ], data );
// rebuild widget
- // jscs:disable requireCapitalizedConstructors
obj = new cls( data );
- // jscs:enable requireCapitalizedConstructors
// 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,
* @class
*
* @constructor
- * @param {Object} [config] Configuration options
*/
-OO.ui.Theme = function OoUiTheme( config ) {
- // Configuration initialization
- config = config || {};
-};
+OO.ui.Theme = function OoUiTheme() {};
/* Setup */
// Properties
this.$button = null;
this.framed = null;
- this.active = false;
+ this.active = config.active !== undefined && config.active;
this.onMouseUpHandler = this.onMouseUp.bind( this );
this.onMouseDownHandler = this.onMouseDown.bind( this );
this.onKeyDownHandler = this.onKeyDown.bind( this );
OO.ui.mixin.ButtonElement.prototype.setActive = function ( value ) {
this.active = !!value;
this.$element.toggleClass( 'oo-ui-buttonElement-active', this.active );
+ this.updateThemeClasses();
return this;
};
keypress: this.menu.onKeyPressHandler,
blur: this.menu.clearKeyPressBuffer.bind( this.menu )
} );
- this.menu.connect( this, { select: 'onMenuSelect' } );
+ this.menu.connect( this, {
+ select: 'onMenuSelect',
+ toggle: 'onMenuToggle'
+ } );
// Initialization
this.$handle
this.setLabel( selectedLabel );
};
+/**
+ * Handle menu toggle events.
+ *
+ * @private
+ * @param {boolean} isVisible Menu toggle event
+ */
+OO.ui.DropdownWidget.prototype.onMenuToggle = function ( isVisible ) {
+ this.$element.toggleClass( 'oo-ui-dropdownWidget-open', isVisible );
+};
+
/**
* Handle mouse click events.
*
*/
OO.ui.mixin.FloatableElement.prototype.isElementInViewport = function ( $element, $container ) {
var elemRect, contRect,
- topEdgeInBounds = false,
leftEdgeInBounds = false,
bottomEdgeInBounds = false,
rightEdgeInBounds = false;
contRect = $container[ 0 ].getBoundingClientRect();
}
- if ( elemRect.top >= contRect.top && elemRect.top <= contRect.bottom ) {
- topEdgeInBounds = true;
- }
+ // For completeness, if we still cared about topEdgeInBounds, that'd be:
+ // elemRect.top >= contRect.top && elemRect.top <= contRect.bottom
if ( elemRect.left >= contRect.left && elemRect.left <= contRect.right ) {
leftEdgeInBounds = true;
}
return this;
};
+/**
+ * Progress bars visually display the status of an operation, such as a download,
+ * and can be either determinate or indeterminate:
+ *
+ * - **determinate** process bars show the percent of an operation that is complete.
+ *
+ * - **indeterminate** process bars use a visual display of motion to indicate that an operation
+ * is taking place. Because the extent of an indeterminate operation is unknown, the bar does
+ * not use percentages.
+ *
+ * The value of the `progress` configuration determines whether the bar is determinate or indeterminate.
+ *
+ * @example
+ * // Examples of determinate and indeterminate progress bars.
+ * var progressBar1 = new OO.ui.ProgressBarWidget( {
+ * progress: 33
+ * } );
+ * var progressBar2 = new OO.ui.ProgressBarWidget();
+ *
+ * // Create a FieldsetLayout to layout progress bars
+ * var fieldset = new OO.ui.FieldsetLayout;
+ * fieldset.addItems( [
+ * new OO.ui.FieldLayout( progressBar1, {label: 'Determinate', align: 'top'}),
+ * new OO.ui.FieldLayout( progressBar2, {label: 'Indeterminate', align: 'top'})
+ * ] );
+ * $( 'body' ).append( fieldset.$element );
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {number|boolean} [progress=false] The type of progress bar (determinate or indeterminate).
+ * To create a determinate progress bar, specify a number that reflects the initial percent complete.
+ * By default, the progress bar is indeterminate.
+ */
+OO.ui.ProgressBarWidget = function OoUiProgressBarWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.ProgressBarWidget.parent.call( this, config );
+
+ // Properties
+ this.$bar = $( '<div>' );
+ this.progress = null;
+
+ // Initialization
+ this.setProgress( config.progress !== undefined ? config.progress : false );
+ this.$bar.addClass( 'oo-ui-progressBarWidget-bar' );
+ this.$element
+ .attr( {
+ role: 'progressbar',
+ 'aria-valuemin': 0,
+ 'aria-valuemax': 100
+ } )
+ .addClass( 'oo-ui-progressBarWidget' )
+ .append( this.$bar );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ProgressBarWidget, OO.ui.Widget );
+
+/* Static Properties */
+
+OO.ui.ProgressBarWidget.static.tagName = 'div';
+
+/* Methods */
+
+/**
+ * Get the percent of the progress that has been completed. Indeterminate progresses will return `false`.
+ *
+ * @return {number|boolean} Progress percent
+ */
+OO.ui.ProgressBarWidget.prototype.getProgress = function () {
+ return this.progress;
+};
+
+/**
+ * Set the percent of the process completed or `false` for an indeterminate process.
+ *
+ * @param {number|boolean} progress Progress percent or `false` for indeterminate
+ */
+OO.ui.ProgressBarWidget.prototype.setProgress = function ( progress ) {
+ this.progress = progress;
+
+ if ( progress !== false ) {
+ this.$bar.css( 'width', this.progress + '%' );
+ this.$element.attr( 'aria-valuenow', this.progress );
+ } else {
+ this.$bar.css( 'width', '' );
+ this.$element.removeAttr( 'aria-valuenow' );
+ }
+ this.$element.toggleClass( 'oo-ui-progressBarWidget-indeterminate', progress === false );
+};
+
/**
* InputWidget is the base class for all input widgets, which
* include {@link OO.ui.TextInputWidget text inputs}, {@link OO.ui.CheckboxInputWidget checkbox inputs},
// Events
this.$input.on( {
keypress: this.onKeyPress.bind( this ),
- blur: this.onBlur.bind( this )
+ blur: this.onBlur.bind( this ),
+ focus: this.onFocus.bind( this )
} );
this.$input.one( {
focus: this.onElementAttach.bind( this )
change: 'onChange',
disable: 'onDisable'
} );
+ this.on( 'change', OO.ui.debounce( this.onDebouncedChange.bind( this ), 250 ) );
// Initialization
this.$element
this.setValidityFlag();
};
+/**
+ * Handle focus events.
+ *
+ * @private
+ * @param {jQuery.Event} e Focus event
+ */
+OO.ui.TextInputWidget.prototype.onFocus = function () {
+ this.setValidityFlag( true );
+};
+
/**
* Handle element attach events.
*
*/
OO.ui.TextInputWidget.prototype.onChange = function () {
this.updateSearchIndicator();
- this.setValidityFlag();
this.adjustSize();
};
+/**
+ * Handle debounced change events.
+ *
+ * @param {string} value
+ * @private
+ */
+OO.ui.TextInputWidget.prototype.onDebouncedChange = function () {
+ this.setValidityFlag();
+};
+
/**
* Handle disable events.
*
// Initialization
this.$element
.addClass( 'oo-ui-fieldLayout' )
+ .toggleClass( 'oo-ui-fieldLayout-disabled', this.fieldWidget.isDisabled() )
.append( this.$help, this.$body );
this.$body.addClass( 'oo-ui-fieldLayout-body' );
this.$messages.addClass( 'oo-ui-fieldLayout-messages' );
this.$field
.addClass( 'oo-ui-fieldLayout-field' )
- .toggleClass( 'oo-ui-fieldLayout-disable', this.fieldWidget.isDisabled() )
.append( this.fieldWidget.$element );
this.setErrors( config.errors || [] );
// Mixin constructors
OO.ui.mixin.IconElement.call( this, config );
- OO.ui.mixin.LabelElement.call( this, config );
+ OO.ui.mixin.LabelElement.call( this, $.extend( {}, config, { $label: $( '<legend>' ) } ) );
OO.ui.mixin.GroupElement.call( this, config );
if ( config.help ) {
}
// Initialization
+ this.$group.addClass( 'oo-ui-fieldsetLayout-group' );
this.$element
.addClass( 'oo-ui-fieldsetLayout' )
- .prepend( this.$help, this.$icon, this.$label, this.$group );
+ .prepend( this.$label, this.$help, this.$icon, this.$group );
if ( Array.isArray( config.items ) ) {
this.addItems( config.items );
}
OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.mixin.LabelElement );
OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.mixin.GroupElement );
+/* Static Properties */
+
+OO.ui.FieldsetLayout.static.tagName = 'fieldset';
+
/**
* FormLayouts are used to wrap {@link OO.ui.FieldsetLayout FieldsetLayouts} when you intend to use browser-based
* form submission for the fields instead of handling them in JavaScript. Form layouts can be configured with an