jenkins-bot has submitted this change and it was merged.

Change subject: Add OO.ui.SelectFileWidget
......................................................................


Add OO.ui.SelectFileWidget

Bug: T91146
Change-Id: Ic4db04daf11f3ab461a16ed3a1e9561e82351bc5
---
M build/modules.json
M demos/pages/widgets.js
M i18n/en.json
M i18n/qqq.json
M jsduck.json
M src/core.js
M src/styles/core.less
M src/styles/theme.less
A src/styles/widgets/SelectFileWidget.less
M src/themes/apex/widgets.less
M src/themes/blank/widgets.less
M src/themes/mediawiki/widgets.less
A src/widgets/SelectFileWidget.js
13 files changed, 732 insertions(+), 4 deletions(-)

Approvals:
  Trevor Parscal: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/build/modules.json b/build/modules.json
index 5aa773f..c83dc3d 100644
--- a/build/modules.json
+++ b/build/modules.json
@@ -72,6 +72,7 @@
                                "src/widgets/PopupButtonWidget.js",
                                "src/widgets/ToggleButtonWidget.js",
                        "src/widgets/DropdownWidget.js",
+                       "src/widgets/SelectFileWidget.js",
                        "src/widgets/IconWidget.js",
                        "src/widgets/IndicatorWidget.js",
                        "src/widgets/InputWidget.js",
diff --git a/demos/pages/widgets.js b/demos/pages/widgets.js
index 52c6ee8..93f4cf1 100644
--- a/demos/pages/widgets.js
+++ b/demos/pages/widgets.js
@@ -817,6 +817,41 @@
                                        }
                                ),
                                new OO.ui.FieldLayout(
+                                       new OO.ui.SelectFileWidget( {} ),
+                                       {
+                                               label: 'SelectFileWidget\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.SelectFileWidget( { accept: [ 
'image/png', 'image/jpeg' ] } ),
+                                       {
+                                               label: 'SelectFileWidget 
(accept PNG and JPEG)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.SelectFileWidget( {
+                                               icon: 'tag',
+                                               indicator: 'required'
+                                       } ),
+                                       {
+                                               label: 'SelectFileWidget (icon, 
indicator)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.SelectFileWidget( {
+                                               icon: 'tag',
+                                               indicator: 'required',
+                                               disabled: true
+                                       } ),
+                                       {
+                                               label: 'SelectFileWidget 
(disabled)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
                                        new OO.ui.DropdownWidget( {
                                                label: 'Select one',
                                                menu: {
diff --git a/i18n/en.json b/i18n/en.json
index 1db3fd8..9812ec6 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -27,5 +27,8 @@
        "ooui-dialog-process-error": "Something went wrong",
        "ooui-dialog-process-dismiss": "Dismiss",
        "ooui-dialog-process-retry": "Try again",
-       "ooui-dialog-process-continue": "Continue"
+       "ooui-dialog-process-continue": "Continue",
+       "ooui-selectfile-not-supported": "File selection is not supported",
+       "ooui-selectfile-placeholder": "No file is selected",
+       "ooui-semicolon-separator": "; "
 }
diff --git a/i18n/qqq.json b/i18n/qqq.json
index c1b794a..bef65ed 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -31,5 +31,8 @@
        "ooui-dialog-process-error": "Title for process dialog error 
description",
        "ooui-dialog-process-dismiss": "Label for process dialog dismiss error 
button, visible when describing errors\n{{Identical|Dismiss}}",
        "ooui-dialog-process-retry": "Label for process dialog retry action 
button, visible when describing recoverable errors\n{{Identical|Try again}}",
-       "ooui-dialog-process-continue": "Label for process dialog retry action 
button, visible when describing only warnings\n{{Identical|Continue}}"
+       "ooui-dialog-process-continue": "Label for process dialog retry action 
button, visible when describing only warnings\n{{Identical|Continue}}",
+       "ooui-selectfile-not-supported": "Label for the file selection dialog 
if file selection is not supported",
+       "ooui-selectfile-placeholder": "Label for the file selection dialog 
when no file is currently selected",
+       "ooui-semicolon-separator": "{{optional}} Semicolon used as a separator"
 }
diff --git a/jsduck.json b/jsduck.json
index 918b570..2eae6e6 100644
--- a/jsduck.json
+++ b/jsduck.json
@@ -6,7 +6,7 @@
        "--processes": "0",
        "--warnings-exit-nonzero": true,
        "--builtin-classes": true,
-       "--external": "HTMLDocument,Window,MouseEvent,KeyboardEvent",
+       "--external": "HTMLDocument,Window,MouseEvent,KeyboardEvent,File",
        "--warnings": ["-nodoc(class,public)"],
        "--": [
                "jsduck.external.js",
diff --git a/src/core.js b/src/core.js
index 1331f5c..6aad59e 100644
--- a/src/core.js
+++ b/src/core.js
@@ -216,7 +216,13 @@
                // Label for process dialog retry action button, visible when 
describing only recoverable errors
                'ooui-dialog-process-retry': 'Try again',
                // Label for process dialog retry action button, visible when 
describing only warnings
-               'ooui-dialog-process-continue': 'Continue'
+               'ooui-dialog-process-continue': 'Continue',
+               // Default placeholder for file selection widgets
+               'ooui-selectfile-not-supported': 'File selection is not 
supported',
+               // Default placeholder for file selection widgets
+               'ooui-selectfile-placeholder': 'No file is selected',
+               // Semicolon separator
+               'ooui-semicolon-separator': '; '
        };
 
        /**
diff --git a/src/styles/core.less b/src/styles/core.less
index fc1c91f..6c65853 100644
--- a/src/styles/core.less
+++ b/src/styles/core.less
@@ -95,6 +95,7 @@
 @import 'widgets/MenuSectionOptionWidget.less';
 @import 'widgets/TextInputMenuSelectWidget.less';
 @import 'widgets/DropdownWidget.less';
+@import 'widgets/SelectFileWidget.less';
 
 @import 'widgets/OutlineSelectWidget.less';
 @import 'widgets/OutlineOptionWidget.less';
diff --git a/src/styles/theme.less b/src/styles/theme.less
index 2cd4c0e..92d3252 100644
--- a/src/styles/theme.less
+++ b/src/styles/theme.less
@@ -63,6 +63,7 @@
 .theme-oo-ui-iconWidget () {}
 .theme-oo-ui-indicatorWidget () {}
 .theme-oo-ui-dropdownWidget () {}
+.theme-oo-ui-selectFileWidget () {}
 .theme-oo-ui-inputWidget () {}
 .theme-oo-ui-buttonInputWidget () {}
 .theme-oo-ui-checkboxInputWidget () {}
diff --git a/src/styles/widgets/SelectFileWidget.less 
b/src/styles/widgets/SelectFileWidget.less
new file mode 100644
index 0000000..c912cdf
--- /dev/null
+++ b/src/styles/widgets/SelectFileWidget.less
@@ -0,0 +1,63 @@
+@import '../common';
+
+.oo-ui-selectFileWidget {
+       display: inline-block;
+       position: relative;
+       vertical-align: middle;
+
+       &-handle {
+               width: 100%;
+               display: inline-block;
+               cursor: pointer;
+               overflow: hidden;
+
+               .oo-ui-unselectable();
+               .oo-ui-box-sizing(border-box);
+
+               > .oo-ui-indicatorElement-indicator,
+               > .oo-ui-iconElement-icon,
+               > .oo-ui-selectFileWidget-clearButton {
+                       position: absolute;
+                       background-position: center center;
+                       background-repeat: no-repeat;
+               }
+
+               > input[type="file"] {
+                       position: absolute;
+                       margin: 0;
+                       top: 0;
+                       bottom: 0;
+                       left: 0;
+                       right: 0;
+                       width: 100%;
+                       height: 100%;
+                       opacity: 0;
+                       z-index: 1;
+                       cursor: pointer;
+               }
+
+               > .oo-ui-selectFileWidget-clearButton {
+                       z-index: 2;
+               }
+       }
+
+       &.oo-ui-widget-disabled,
+       &-notsupported {
+               .oo-ui-selectFileWidget-handle {
+                       cursor: default;
+
+                       > input[type="file"] {
+                               display: none;
+                       }
+               }
+       }
+
+       &-empty,
+       &-notsupported {
+               .oo-ui-selectFileWidget-clearButton {
+                       display: none;
+               }
+       }
+
+       .theme-oo-ui-selectFileWidget();
+}
diff --git a/src/themes/apex/widgets.less b/src/themes/apex/widgets.less
index f415b6d..21c64fa 100644
--- a/src/themes/apex/widgets.less
+++ b/src/themes/apex/widgets.less
@@ -166,6 +166,121 @@
        }
 }
 
+.theme-oo-ui-selectFileWidget () {
+       margin: 0.25em 0;
+       width: 100%;
+       max-width: 50em;
+
+       .oo-ui-inline-spacing(0.5em);
+
+       &-handle {
+               height: 2.5em;
+               border: 1px solid rgba(0,0,0,0.1);
+               border-radius: 0.25em;
+               padding: 0 0.5em;
+
+               > .oo-ui-indicatorElement-indicator {
+                       right: 0;
+               }
+
+               > .oo-ui-iconElement-icon {
+                       left: 0.25em;
+               }
+
+               .oo-ui-selectFileWidget-label {
+                       line-height: 2.5em;
+                       margin: 0;
+                       display: inline-block;
+                       overflow: hidden;
+                       width: 100%;
+                       white-space: nowrap;
+                       .oo-ui-box-sizing( border-box );
+                       text-overflow: ellipsis;
+               }
+
+               .oo-ui-selectFileWidget-clearButton {
+                       top: 0;
+                       width: @icon-size;
+                       height: @icon-size;
+                       margin: 0.3em;
+               }
+
+               > .oo-ui-indicatorElement-indicator {
+                       top: 0;
+                       width: @indicator-size;
+                       height: @indicator-size;
+                       margin: 0.775em;
+               }
+
+               > .oo-ui-iconElement-icon {
+                       top: 0;
+                       width: @icon-size;
+                       height: @icon-size;
+                       margin: 0.3em;
+               }
+       }
+
+       &:hover .oo-ui-selectFileWidget-handle {
+               border-color: #aaa;
+       }
+
+       &.oo-ui-widget-disabled {
+               .oo-ui-selectFileWidget-handle {
+                       color: #ccc;
+                       text-shadow: 0 1px 1px #fff;
+                       border-color: #ddd;
+                       background-color: #f3f3f3;
+
+                       > .oo-ui-iconElement-icon,
+                       > .oo-ui-indicatorElement-indicator {
+                               opacity: 0.2;
+                       }
+               }
+       }
+
+       &-empty {
+               .oo-ui-selectFileWidget-label {
+                       color: #ccc;
+               }
+       }
+
+       &.oo-ui-iconElement .oo-ui-selectFileWidget-handle {
+               padding-left: 3em;
+       }
+
+       // With close, no indicator:
+       & .oo-ui-selectFileWidget-handle {
+               padding-right: 3em;
+
+               .oo-ui-selectFileWidget-clearButton {
+                       right: 0;
+               }
+       }
+
+       // With close, with indicator:
+       &.oo-ui-indicatorElement .oo-ui-selectFileWidget-handle {
+               padding-right: 5em;
+
+               .oo-ui-selectFileWidget-clearButton {
+                       right: 2em;
+               }
+       }
+
+       // No close, no indicator:
+       &-empty, &-notsupported {
+               .oo-ui-selectFileWidget-handle {
+                       padding-right: 1em;
+               }
+       }
+
+       // No close, with indicator:
+       &-empty.oo-ui-indicatorElement, &-notsupported.oo-ui-indicatorElement {
+               .oo-ui-selectFileWidget-handle {
+                       padding-right: 2em;
+               }
+       }
+}
+
 .theme-oo-ui-inputWidget () {
        .oo-ui-inline-spacing(0.5em);
 }
diff --git a/src/themes/blank/widgets.less b/src/themes/blank/widgets.less
index 68c64cd..a23ea99 100644
--- a/src/themes/blank/widgets.less
+++ b/src/themes/blank/widgets.less
@@ -22,6 +22,8 @@
 
 .theme-oo-ui-dropdownWidget () {}
 
+.theme-oo-ui-selectFileWidget () {}
+
 .theme-oo-ui-inputWidget () {}
 
 .theme-oo-ui-buttonInputWidget () {}
diff --git a/src/themes/mediawiki/widgets.less 
b/src/themes/mediawiki/widgets.less
index 2f07287..1ce4cdc 100644
--- a/src/themes/mediawiki/widgets.less
+++ b/src/themes/mediawiki/widgets.less
@@ -170,6 +170,121 @@
        }
 }
 
+.theme-oo-ui-selectFileWidget () {
+       margin: 0.25em 0;
+       width: 100%;
+       max-width: 50em;
+
+       .oo-ui-inline-spacing(0.5em);
+
+       &-handle {
+               height: 2.5em;
+               border: 1px solid #ccc;
+               border-radius: 0.1em;
+               padding: 0 1em;
+
+               > .oo-ui-indicatorElement-indicator {
+                       right: 0;
+               }
+
+               > .oo-ui-iconElement-icon {
+                       left: 0.25em;
+               }
+
+               .oo-ui-selectFileWidget-label {
+                       line-height: 2.5em;
+                       margin: 0;
+                       display: inline-block;
+                       overflow: hidden;
+                       width: 100%;
+                       white-space: nowrap;
+                       .oo-ui-box-sizing( border-box );
+                       text-overflow: ellipsis;
+               }
+
+               .oo-ui-selectFileWidget-clearButton {
+                       top: 0;
+                       width: @icon-size;
+                       height: @icon-size;
+                       margin: 0.3em;
+               }
+
+               > .oo-ui-indicatorElement-indicator {
+                       top: 0;
+                       width: @indicator-size;
+                       height: @indicator-size;
+                       margin: 0.775em;
+               }
+
+               > .oo-ui-iconElement-icon {
+                       top: 0;
+                       width: @icon-size;
+                       height: @icon-size;
+                       margin: 0.3em;
+               }
+       }
+
+       &:hover .oo-ui-selectFileWidget-handle {
+               border-color: #aaa;
+       }
+
+       &.oo-ui-widget-disabled {
+               .oo-ui-selectFileWidget-handle {
+                       color: #ccc;
+                       text-shadow: 0 1px 1px #fff;
+                       border-color: #ddd;
+                       background-color: #f3f3f3;
+
+                       > .oo-ui-iconElement-icon,
+                       > .oo-ui-indicatorElement-indicator {
+                               opacity: 0.2;
+                       }
+               }
+       }
+
+       &-empty {
+               .oo-ui-selectFileWidget-label {
+                       color: #ccc;
+               }
+       }
+
+       &.oo-ui-iconElement .oo-ui-selectFileWidget-handle {
+               padding-left: 3em;
+       }
+
+       // With close, no indicator:
+       & .oo-ui-selectFileWidget-handle {
+               padding-right: 3em;
+
+               .oo-ui-selectFileWidget-clearButton {
+                       right: 0;
+               }
+       }
+
+       // With close, with indicator:
+       &.oo-ui-indicatorElement .oo-ui-selectFileWidget-handle {
+               padding-right: 5em;
+
+               .oo-ui-selectFileWidget-clearButton {
+                       right: 2em;
+               }
+       }
+
+       // No close, no indicator:
+       &-empty, &-notsupported {
+               .oo-ui-selectFileWidget-handle {
+                       padding-right: 1em;
+               }
+       }
+
+       // No close, with indicator:
+       &-empty.oo-ui-indicatorElement, &-notsupported.oo-ui-indicatorElement {
+               .oo-ui-selectFileWidget-handle {
+                       padding-right: 2em;
+               }
+       }
+}
+
 .theme-oo-ui-inputWidget () {
        .oo-ui-inline-spacing(0.5em);
 }
diff --git a/src/widgets/SelectFileWidget.js b/src/widgets/SelectFileWidget.js
new file mode 100644
index 0000000..afe822a
--- /dev/null
+++ b/src/widgets/SelectFileWidget.js
@@ -0,0 +1,383 @@
+/**
+ * SelectFileWidgets allow for selecting files, using the HTML5 File API. These
+ * widgets can be configured with {@link OO.ui.IconElement icons} and {@link
+ * OO.ui.IndicatorElement indicators}.
+ * Please see the [OOjs UI documentation on MediaWiki] [1] for more 
information and examples.
+ *
+ *     @example
+ *     // Example of a file select widget
+ *     var selectFile = new OO.ui.SelectFileWidget();
+ *     $( 'body' ).append( selectFile.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.IconElement
+ * @mixins OO.ui.IndicatorElement
+ * @mixins OO.ui.PendingElement
+ * @mixins OO.ui.LabelElement
+ * @mixins OO.ui.TabIndexedElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string[]|null} [accept=null] MIME types to accept. null accepts all 
types.
+ * @cfg {string} [placeholder] Text to display when no file is selected.
+ * @cfg {string} [notsupported] Text to display when file support is missing 
in the browser.
+ * @cfg {boolean} [droppable=true] Whether to accept files by drag and drop.
+ */
+OO.ui.SelectFileWidget = function OoUiSelectFileWidget( config ) {
+       var dragHandler;
+
+       // Configuration initialization
+       config = $.extend( {
+               accept: null,
+               placeholder: OO.ui.msg( 'ooui-selectfile-placeholder' ),
+               notsupported: OO.ui.msg( 'ooui-selectfile-not-supported' ),
+               droppable: true
+       }, config );
+
+       // Parent constructor
+       OO.ui.SelectFileWidget.super.call( this, config );
+
+       // Properties (must be set before TabIndexedElement constructor call)
+       this.$handle = $( '<span>' );
+
+       // Mixin constructors
+       OO.ui.IconElement.call( this, config );
+       OO.ui.IndicatorElement.call( this, config );
+       OO.ui.PendingElement.call( this, config );
+       OO.ui.LabelElement.call( this, $.extend( config, { autoFitLabel: true } 
) );
+       OO.ui.TabIndexedElement.call( this, $.extend( {}, config, { 
$tabIndexed: this.$handle } ) );
+
+       // Properties
+       this.isSupported = this.constructor.static.isSupported();
+       this.currentFile = null;
+       if ( Array.isArray( config.accept ) ) {
+               this.accept = config.accept;
+       } else {
+               this.accept = null;
+       }
+       this.placeholder = config.placeholder;
+       this.notsupported = config.notsupported;
+       this.onFileSelectedHandler = this.onFileSelected.bind( this );
+
+       this.clearButton = new OO.ui.ButtonWidget( {
+               classes: [ 'oo-ui-selectFileWidget-clearButton' ],
+               framed: false,
+               icon: 'remove',
+               disabled: this.disabled
+       } );
+
+       // Events
+       this.$handle.on( {
+               keypress: this.onKeyPress.bind( this )
+       } );
+       this.clearButton.connect( this, {
+               click: 'onClearClick'
+       } );
+       if ( config.droppable ) {
+               dragHandler = this.onDragEnterOrOver.bind( this );
+               this.$handle.on( {
+                       dragenter: dragHandler,
+                       dragover: dragHandler,
+                       dragleave: this.onDragLeave.bind( this ),
+                       drop: this.onDrop.bind( this )
+               } );
+       }
+
+       // Initialization
+       this.addInput();
+       this.updateUI();
+       this.$label.addClass( 'oo-ui-selectFileWidget-label' );
+       this.$handle
+               .addClass( 'oo-ui-selectFileWidget-handle' )
+               .append( this.$icon, this.$label, this.clearButton.$element, 
this.$indicator );
+       this.$element
+               .addClass( 'oo-ui-selectFileWidget' )
+               .append( this.$handle );
+       if ( config.droppable ) {
+               this.$element.addClass( 'oo-ui-selectFileWidget-droppable' );
+       }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.SelectFileWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.SelectFileWidget, OO.ui.IconElement );
+OO.mixinClass( OO.ui.SelectFileWidget, OO.ui.IndicatorElement );
+OO.mixinClass( OO.ui.SelectFileWidget, OO.ui.PendingElement );
+OO.mixinClass( OO.ui.SelectFileWidget, OO.ui.LabelElement );
+OO.mixinClass( OO.ui.SelectFileWidget, OO.ui.TabIndexedElement );
+
+/* Static properties */
+
+/**
+ * Check if this widget is supported
+ *
+ * @static
+ * @return {boolean}
+ */
+OO.ui.SelectFileWidget.static.isSupported = function () {
+       var $input;
+       if ( OO.ui.SelectFileWidget.static.isSupportedCache === null ) {
+               $input = $( '<input type="file">' );
+               OO.ui.SelectFileWidget.static.isSupportedCache = 
$input[0].files !== undefined;
+       }
+       return OO.ui.SelectFileWidget.static.isSupportedCache;
+};
+
+OO.ui.SelectFileWidget.static.isSupportedCache = null;
+
+/* Events */
+
+/**
+ * @event change
+ *
+ * A change event is emitted when the on/off state of the toggle changes.
+ *
+ * @param {File|null} value New value
+ */
+
+/* Methods */
+
+/**
+ * Get the current value of the field
+ *
+ * @return {File|null}
+ */
+OO.ui.SelectFileWidget.prototype.getValue = function () {
+       return this.currentFile;
+};
+
+/**
+ * Set the current value of the field
+ *
+ * @param {File|null} file File to select
+ */
+OO.ui.SelectFileWidget.prototype.setValue = function ( file ) {
+       if ( this.currentFile !== file ) {
+               this.currentFile = file;
+               this.updateUI();
+               this.emit( 'change', this.currentFile );
+       }
+};
+
+/**
+ * Update the user interface when a file is selected or unselected
+ *
+ * @protected
+ */
+OO.ui.SelectFileWidget.prototype.updateUI = function () {
+       if ( !this.isSupported ) {
+               this.$element.addClass( 'oo-ui-selectFileWidget-notsupported' );
+               this.$element.removeClass( 'oo-ui-selectFileWidget-empty' );
+               this.setLabel( this.notsupported );
+       } else if ( this.currentFile ) {
+               this.$element.removeClass( 'oo-ui-selectFileWidget-empty' );
+               this.setLabel( this.currentFile.name +
+                       ( this.currentFile.type !== '' ? OO.ui.msg( 
'ooui-semicolon-separator' ) + this.currentFile.type : '' )
+               );
+       } else {
+               this.$element.addClass( 'oo-ui-selectFileWidget-empty' );
+               this.setLabel( this.placeholder );
+       }
+
+       if ( this.$input ) {
+               this.$input.attr( 'title', this.getLabel() );
+       }
+};
+
+/**
+ * Add the input to the handle
+ *
+ * @private
+ */
+OO.ui.SelectFileWidget.prototype.addInput = function () {
+       if ( this.$input ) {
+               this.$input.remove();
+       }
+
+       if ( !this.isSupported ) {
+               this.$input = null;
+               return;
+       }
+
+       this.$input = $( '<input type="file">' );
+       this.$input.on( 'change', this.onFileSelectedHandler );
+       this.$input.attr( {
+               tabindex: -1,
+               title: this.getLabel()
+       } );
+       if ( this.accept ) {
+               this.$input.attr( 'accept', this.accept.join( ', ' ) );
+       }
+       this.$handle.append( this.$input );
+};
+
+/**
+ * Determine if we should accept this file
+ *
+ * @private
+ * @param {File} file
+ * @return {boolean}
+ */
+OO.ui.SelectFileWidget.prototype.isFileAcceptable = function ( file ) {
+       var i, mime, mimeTest;
+
+       if ( !this.accept || file.type === '' ) {
+               return true;
+       }
+
+       mime = file.type;
+       for ( i = 0; i < this.accept.length; i++ ) {
+               mimeTest = this.accept[i];
+               if ( mimeTest === mime ) {
+                       return true;
+               } else if ( mimeTest.substr( -2 ) === '/*' ) {
+                       mimeTest = mimeTest.substr( 0, mimeTest.length - 1 );
+                       if ( mime.substr( 0, mimeTest.length ) === mimeTest ) {
+                               return true;
+                       }
+               }
+       }
+
+       return false;
+};
+
+/**
+ * Handle file selection from the input
+ *
+ * @private
+ * @param {jQuery.Event} e
+ */
+OO.ui.SelectFileWidget.prototype.onFileSelected = function ( e ) {
+       var file = null;
+
+       if ( e.target.files && e.target.files[0] ) {
+               file = e.target.files[0];
+               if ( !this.isFileAcceptable( file ) ) {
+                       file = null;
+               }
+       }
+
+       this.setValue( file );
+       this.addInput();
+};
+
+/**
+ * Handle clear button click events.
+ *
+ * @private
+ */
+OO.ui.SelectFileWidget.prototype.onClearClick = function () {
+       this.setValue( null );
+       return false;
+};
+
+/**
+ * Handle key press events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key press event
+ */
+OO.ui.SelectFileWidget.prototype.onKeyPress = function ( e ) {
+       if ( this.isSupported && !this.isDisabled() && this.$input &&
+               ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )
+       ) {
+               this.$input.click();
+               return false;
+       }
+};
+
+/**
+ * Handle drag enter and over events
+ *
+ * @private
+ * @param {jQuery.Event} e Drag event
+ */
+OO.ui.SelectFileWidget.prototype.onDragEnterOrOver = function ( e ) {
+       var file = null,
+               dt = e.originalEvent.dataTransfer;
+
+       e.preventDefault();
+       e.stopPropagation();
+
+       if ( this.isDisabled() || !this.isSupported ) {
+               this.$element.removeClass( 'oo-ui-selectFileWidget-canDrop' );
+               dt.dropEffect = 'none';
+               return false;
+       }
+
+       if ( dt && dt.files && dt.files[0] ) {
+               file = dt.files[0];
+               if ( !this.isFileAcceptable( file ) ) {
+                       file = null;
+               }
+       } else if ( dt && dt.types && $.inArray( 'Files', dt.types ) ) {
+               // We know we have files so set 'file' to something truthy, we 
just
+               // can't know any details about them.
+               // * https://bugzilla.mozilla.org/show_bug.cgi?id=640534
+               file = 'Files exist, but details are unknown';
+       }
+       if ( file ) {
+               this.$element.addClass( 'oo-ui-selectFileWidget-canDrop' );
+       } else {
+               this.$element.removeClass( 'oo-ui-selectFileWidget-canDrop' );
+               dt.dropEffect = 'none';
+       }
+
+       return false;
+};
+
+/**
+ * Handle drag leave events
+ *
+ * @private
+ * @param {jQuery.Event} e Drag event
+ */
+OO.ui.SelectFileWidget.prototype.onDragLeave = function () {
+       this.$element.removeClass( 'oo-ui-selectFileWidget-canDrop' );
+};
+
+/**
+ * Handle drop events
+ *
+ * @private
+ * @param {jQuery.Event} e Drop event
+ */
+OO.ui.SelectFileWidget.prototype.onDrop = function ( e ) {
+       var file = null,
+               dt = e.originalEvent.dataTransfer;
+
+       e.preventDefault();
+       e.stopPropagation();
+       this.$element.removeClass( 'oo-ui-selectFileWidget-canDrop' );
+
+       if ( this.isDisabled() || !this.isSupported ) {
+               return false;
+       }
+
+       if ( dt && dt.files && dt.files[0] ) {
+               file = dt.files[0];
+               if ( !this.isFileAcceptable( file ) ) {
+                       file = null;
+               }
+       }
+       if ( file ) {
+               this.setValue( file );
+       }
+
+       return false;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.SelectFileWidget.prototype.setDisabled = function ( state ) {
+       OO.ui.SelectFileWidget.super.prototype.setDisabled.call( this, state );
+       if ( this.clearButton ) {
+               this.clearButton.setDisabled( state );
+       }
+       return this;
+};

-- 
To view, visit https://gerrit.wikimedia.org/r/213588
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ic4db04daf11f3ab461a16ed3a1e9561e82351bc5
Gerrit-PatchSet: 4
Gerrit-Project: oojs/ui
Gerrit-Branch: master
Gerrit-Owner: Anomie <bjor...@wikimedia.org>
Gerrit-Reviewer: Bartosz DziewoƄski <matma....@gmail.com>
Gerrit-Reviewer: Esanders <esand...@wikimedia.org>
Gerrit-Reviewer: Trevor Parscal <tpars...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to