Merge "Check for global blocks"
[lhc/web/wiklou.git] / resources / lib / oojs-ui / oojs-ui-core.js
index 1b90db5..64c6be6 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.16.3
+ * OOjs UI v0.16.6
  * 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-03-16T19:20:22Z
+ * Date: 2016-04-19T21:57:49Z
  */
 ( function ( OO ) {
 
@@ -2052,6 +2052,16 @@ OO.ui.mixin.GroupElement = function OoUiMixinGroupElement( config ) {
        this.setGroupElement( config.$group || $( '<div>' ) );
 };
 
+/* Events */
+
+/**
+ * @event change
+ *
+ * A change event is emitted when the set of selected items changes.
+ *
+ * @param {OO.ui.Element[]} items Items currently in the group
+ */
+
 /* Methods */
 
 /**
@@ -2243,6 +2253,7 @@ OO.ui.mixin.GroupElement.prototype.addItems = function ( items, index ) {
                this.items.splice.apply( this.items, [ index, 0 ].concat( items ) );
        }
 
+       this.emit( 'change', this.getItems() );
        return this;
 };
 
@@ -2279,6 +2290,7 @@ OO.ui.mixin.GroupElement.prototype.removeItems = function ( items ) {
                }
        }
 
+       this.emit( 'change', this.getItems() );
        return this;
 };
 
@@ -2310,6 +2322,7 @@ OO.ui.mixin.GroupElement.prototype.clearItems = function () {
                item.$element.detach();
        }
 
+       this.emit( 'change', this.getItems() );
        this.items = [];
        return this;
 };
@@ -2788,9 +2801,7 @@ OO.ui.mixin.LabelElement.prototype.setLabelElement = function ( $label ) {
  */
 OO.ui.mixin.LabelElement.prototype.setLabel = function ( label ) {
        label = typeof label === 'function' ? OO.ui.resolveMsg( label ) : label;
-       label = ( ( typeof label === 'string' && label.length ) || label instanceof jQuery || label instanceof OO.ui.HtmlSnippet ) ? label : null;
-
-       this.$element.toggleClass( 'oo-ui-labelElement', !!label );
+       label = ( ( typeof label === 'string' || label instanceof jQuery ) && label.length ) || ( label instanceof OO.ui.HtmlSnippet && label.toString().length ) ? label : null;
 
        if ( this.label !== label ) {
                if ( this.$label ) {
@@ -2800,6 +2811,8 @@ OO.ui.mixin.LabelElement.prototype.setLabel = function ( label ) {
                this.emit( 'labelChange' );
        }
 
+       this.$element.toggleClass( 'oo-ui-labelElement', !!this.label );
+
        return this;
 };
 
@@ -4066,12 +4079,16 @@ OO.ui.mixin.ClippableElement.prototype.setIdealSize = function ( width, height )
 };
 
 /**
- * Clip element to visible boundaries and allow scrolling when needed. Call this method when
- * the element's natural height changes.
+ * Clip element to visible boundaries and allow scrolling when needed. You should call this method
+ * when the element's natural height changes.
  *
  * Element will be clipped the bottom or right of the element is within 10px of the edge of, or
  * overlapped by, the visible area of the nearest scrollable container.
  *
+ * Because calling clip() when the natural height changes isn't always possible, we also set
+ * max-height when the element isn't being clipped. This means that if the element tries to grow
+ * beyond the edge, something reasonable will happen before clip() is called.
+ *
  * @chainable
  */
 OO.ui.mixin.ClippableElement.prototype.clip = function () {
@@ -4115,14 +4132,30 @@ OO.ui.mixin.ClippableElement.prototype.clip = function () {
        clipHeight = allotedHeight < naturalHeight;
 
        if ( clipWidth ) {
-               this.$clippable.css( { overflowX: 'scroll', width: Math.max( 0, allotedWidth ) } );
+               this.$clippable.css( {
+                       overflowX: 'scroll',
+                       width: Math.max( 0, allotedWidth ),
+                       maxWidth: ''
+               } );
        } else {
-               this.$clippable.css( { width: this.idealWidth ? this.idealWidth - extraWidth : '', overflowX: '' } );
+               this.$clippable.css( {
+                       overflowX: '',
+                       width: this.idealWidth ? this.idealWidth - extraWidth : '',
+                       maxWidth: Math.max( 0, allotedWidth )
+               } );
        }
        if ( clipHeight ) {
-               this.$clippable.css( { overflowY: 'scroll', height: Math.max( 0, allotedHeight ) } );
+               this.$clippable.css( {
+                       overflowY: 'scroll',
+                       height: Math.max( 0, allotedHeight ),
+                       maxHeight: ''
+               } );
        } else {
-               this.$clippable.css( { height: this.idealHeight ? this.idealHeight - extraHeight : '', overflowY: '' } );
+               this.$clippable.css( {
+                       overflowY: '',
+                       height: this.idealHeight ? this.idealHeight - extraHeight : '',
+                       maxHeight: Math.max( 0, allotedHeight )
+               } );
        }
 
        // If we stopped clipping in at least one of the dimensions
@@ -6909,9 +6942,11 @@ OO.ui.InputWidget.static.reusePreInfuseDOM = function ( node, config ) {
  */
 OO.ui.InputWidget.static.gatherPreInfuseState = function ( node, config ) {
        var state = OO.ui.InputWidget.parent.static.gatherPreInfuseState( node, config );
-       state.value = config.$input.val();
-       // Might be better in TabIndexedElement, but it's awkward to do there because mixins are awkward
-       state.focus = config.$input.is( ':focus' );
+       if ( config.$input && config.$input.length ) {
+               state.value = config.$input.val();
+               // Might be better in TabIndexedElement, but it's awkward to do there because mixins are awkward
+               state.focus = config.$input.is( ':focus' );
+       }
        return state;
 };
 
@@ -7708,6 +7743,16 @@ OO.ui.RadioSelectInputWidget.static.gatherPreInfuseState = function ( node, conf
        return state;
 };
 
+/**
+ * @inheritdoc
+ */
+OO.ui.RadioSelectInputWidget.static.reusePreInfuseDOM = function ( node, config ) {
+       config = OO.ui.RadioSelectInputWidget.parent.static.reusePreInfuseDOM( node, config );
+       // Cannot reuse the `<input type=radio>` set
+       delete config.$input;
+       return config;
+};
+
 /* Methods */
 
 /**
@@ -7812,7 +7857,7 @@ OO.ui.RadioSelectInputWidget.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' or 'date'. Ignored if `multiline` is true.
+ *  'email', 'url', 'date' or 'number'. Ignored if `multiline` is true.
  *
  *  Some values of `type` result in additional behaviors:
  *
@@ -7999,7 +8044,6 @@ OO.ui.TextInputWidget.static.gatherPreInfuseState = function ( node, config ) {
  *
  * @private
  * @param {jQuery.Event} e Mouse down event
- * @fires icon
  */
 OO.ui.TextInputWidget.prototype.onIconMouseDown = function ( e ) {
        if ( e.which === OO.ui.MouseButtons.LEFT ) {
@@ -8013,7 +8057,6 @@ OO.ui.TextInputWidget.prototype.onIconMouseDown = function ( e ) {
  *
  * @private
  * @param {jQuery.Event} e Mouse down event
- * @fires indicator
  */
 OO.ui.TextInputWidget.prototype.onIndicatorMouseDown = function ( e ) {
        if ( e.which === OO.ui.MouseButtons.LEFT ) {
@@ -8255,9 +8298,15 @@ OO.ui.TextInputWidget.prototype.adjustSize = function () {
  * @protected
  */
 OO.ui.TextInputWidget.prototype.getInputElement = function ( config ) {
-       return config.multiline ?
-               $( '<textarea>' ) :
-               $( '<input>' ).attr( 'type', this.getSaneType( config ) );
+       if ( config.multiline ) {
+               return $( '<textarea>' );
+       } else if ( this.getSaneType( config ) === 'number' ) {
+               return $( '<input>' )
+                       .attr( 'step', 'any' )
+                       .attr( 'type', 'number' );
+       } else {
+               return $( '<input>' ).attr( 'type', this.getSaneType( config ) );
+       }
 };
 
 /**
@@ -8268,9 +8317,16 @@ OO.ui.TextInputWidget.prototype.getInputElement = function ( config ) {
  * @private
  */
 OO.ui.TextInputWidget.prototype.getSaneType = function ( config ) {
-       var type = [ 'text', 'password', 'search', 'email', 'url', 'date' ].indexOf( config.type ) !== -1 ?
-               config.type :
-               'text';
+       var allowedTypes = [
+                       'text',
+                       'password',
+                       'search',
+                       'email',
+                       'url',
+                       'date',
+                       'number'
+               ],
+               type = allowedTypes.indexOf( config.type ) !== -1 ? config.type : 'text';
        return config.multiline ? 'multiline' : type;
 };
 
@@ -8680,7 +8736,8 @@ OO.ui.TextInputWidget.prototype.restorePreInfuseState = function ( state ) {
 OO.ui.ComboBoxInputWidget = function OoUiComboBoxInputWidget( config ) {
        // Configuration initialization
        config = $.extend( {
-               indicator: 'down'
+               indicator: 'down',
+               autocomplete: false
        }, config );
        // For backwards-compatibility with ComboBoxWidget config
        $.extend( config, config.input );