Esanders has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/187951

Change subject: Support generic data transfer handlers
......................................................................

Support generic data transfer handlers

Move file transfer handlers into subclass which only
run when item.kind === 'file'.

Change-Id: Ie9892950163d6c8b8fb1f8c3e19de86e704a2209
---
M .docs/eg-iframe.html
M build/modules.json
M demos/ve/desktop.html
M demos/ve/mobile.html
M src/ce/ve.ce.Surface.js
M src/ui/datatransferhandlers/ve.ui.DSVFileTransferHandler.js
M src/ui/datatransferhandlers/ve.ui.HTMLFileTransferHandler.js
M src/ui/datatransferhandlers/ve.ui.PlainTextFileTransferHandler.js
M src/ui/ve.ui.DataTransferHandler.js
M src/ui/ve.ui.DataTransferHandlerFactory.js
A src/ui/ve.ui.FileTransferHandler.js
M tests/index.html
12 files changed, 175 insertions(+), 82 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor 
refs/changes/51/187951/1

diff --git a/.docs/eg-iframe.html b/.docs/eg-iframe.html
index 4d1ce0d..73dc5d7 100644
--- a/.docs/eg-iframe.html
+++ b/.docs/eg-iframe.html
@@ -305,6 +305,7 @@
                <script src="../src/ui/ve.ui.Action.js"></script>
                <script src="../src/ui/ve.ui.ActionFactory.js"></script>
                <script src="../src/ui/ve.ui.DataTransferHandler.js"></script>
+               <script src="../src/ui/ve.ui.FileTransferHandler.js"></script>
                <script 
src="../src/ui/ve.ui.DataTransferHandlerFactory.js"></script>
                <script src="../src/ui/ve.ui.WindowManager.js"></script>
                <script 
src="../src/ui/actions/ve.ui.AnnotationAction.js"></script>
diff --git a/build/modules.json b/build/modules.json
index 981741b..9bb8bc3 100644
--- a/build/modules.json
+++ b/build/modules.json
@@ -329,6 +329,7 @@
                        "src/ui/ve.ui.Action.js",
                        "src/ui/ve.ui.ActionFactory.js",
                        "src/ui/ve.ui.DataTransferHandler.js",
+                       "src/ui/ve.ui.FileTransferHandler.js",
                        "src/ui/ve.ui.DataTransferHandlerFactory.js",
                        "src/ui/ve.ui.WindowManager.js",
                        "src/ui/actions/ve.ui.AnnotationAction.js",
diff --git a/demos/ve/desktop.html b/demos/ve/desktop.html
index cf2c404..2ba1eb4 100644
--- a/demos/ve/desktop.html
+++ b/demos/ve/desktop.html
@@ -318,6 +318,7 @@
                <script src="../../src/ui/ve.ui.Action.js"></script>
                <script src="../../src/ui/ve.ui.ActionFactory.js"></script>
                <script 
src="../../src/ui/ve.ui.DataTransferHandler.js"></script>
+               <script 
src="../../src/ui/ve.ui.FileTransferHandler.js"></script>
                <script 
src="../../src/ui/ve.ui.DataTransferHandlerFactory.js"></script>
                <script src="../../src/ui/ve.ui.WindowManager.js"></script>
                <script 
src="../../src/ui/actions/ve.ui.AnnotationAction.js"></script>
diff --git a/demos/ve/mobile.html b/demos/ve/mobile.html
index 545566c..5d2f311 100644
--- a/demos/ve/mobile.html
+++ b/demos/ve/mobile.html
@@ -319,6 +319,7 @@
                <script src="../../src/ui/ve.ui.Action.js"></script>
                <script src="../../src/ui/ve.ui.ActionFactory.js"></script>
                <script 
src="../../src/ui/ve.ui.DataTransferHandler.js"></script>
+               <script 
src="../../src/ui/ve.ui.FileTransferHandler.js"></script>
                <script 
src="../../src/ui/ve.ui.DataTransferHandlerFactory.js"></script>
                <script src="../../src/ui/ve.ui.WindowManager.js"></script>
                <script 
src="../../src/ui/actions/ve.ui.AnnotationAction.js"></script>
diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js
index 725b6d9..4671e02 100644
--- a/src/ce/ve.ce.Surface.js
+++ b/src/ce/ve.ce.Surface.js
@@ -994,9 +994,10 @@
        // Properties may be nullified by other events, so cache before 
setTimeout
        var selectionJSON, dragSelection, dragRange, originFragment, originData,
                targetRange, targetOffset, targetFragment, dragHtml, dragText,
-               i, l, name, insert,
+               i, l, name, insert, item,
                fileHandlers = [],
                dataTransfer = e.originalEvent.dataTransfer,
+               items = dataTransfer && ( dataTransfer.items || 
dataTransfer.files ),
                $dropTarget = this.$lastDropTarget,
                dropPosition = this.lastDropPosition;
 
@@ -1021,12 +1022,18 @@
                if ( dragSelection instanceof ve.dm.LinearSelection ) {
                        dragRange = dragSelection.getRange();
                }
-       } else if ( dataTransfer.files.length ) {
-               for ( i = 0, l = dataTransfer.files.length; i < l; i++ ) {
-                       name = 
ve.ui.dataTransferHandlerFactory.getHandlerNameForType( 
dataTransfer.files[i].type );
+       } else if ( items && items.length ) {
+               for ( i = 0, l = items.length; i < l; i++ ) {
+                       if ( items[i].kind ) {
+                               item = items[i];
+                       } else {
+                               // Create fake DataTransferItem from file
+                               item = new ve.ui.DataTransferItem( items[i] );
+                       }
+                       name = 
ve.ui.dataTransferHandlerFactory.getHandlerNameForItem( item );
                        if ( name ) {
                                fileHandlers.push(
-                                       
ve.ui.dataTransferHandlerFactory.create( name, this.surface, 
dataTransfer.files[i] )
+                                       
ve.ui.dataTransferHandlerFactory.create( name, this.surface, item )
                                );
                        }
                }
diff --git a/src/ui/datatransferhandlers/ve.ui.DSVFileTransferHandler.js 
b/src/ui/datatransferhandlers/ve.ui.DSVFileTransferHandler.js
index 5dba350..78f3fcc 100644
--- a/src/ui/datatransferhandlers/ve.ui.DSVFileTransferHandler.js
+++ b/src/ui/datatransferhandlers/ve.ui.DSVFileTransferHandler.js
@@ -8,7 +8,7 @@
  * Delimiter-separated values data transfer handler.
  *
  * @class
- * @extends ve.ui.DataTransferHandler
+ * @extends ve.ui.FileTransferHandler
  *
  * @constructor
  * @param {ve.ui.Surface} surface
@@ -21,7 +21,7 @@
 
 /* Inheritance */
 
-OO.inheritClass( ve.ui.DSVFileTransferHandler, ve.ui.DataTransferHandler );
+OO.inheritClass( ve.ui.DSVFileTransferHandler, ve.ui.FileTransferHandler );
 
 /* Static properties */
 
diff --git a/src/ui/datatransferhandlers/ve.ui.HTMLFileTransferHandler.js 
b/src/ui/datatransferhandlers/ve.ui.HTMLFileTransferHandler.js
index e5ae986..712757e 100644
--- a/src/ui/datatransferhandlers/ve.ui.HTMLFileTransferHandler.js
+++ b/src/ui/datatransferhandlers/ve.ui.HTMLFileTransferHandler.js
@@ -8,7 +8,7 @@
  * HTML file data transfer handler.
  *
  * @class
- * @extends ve.ui.DataTransferHandler
+ * @extends ve.ui.FileTransferHandler
  *
  * @constructor
  * @param {ve.ui.Surface} surface
@@ -21,7 +21,7 @@
 
 /* Inheritance */
 
-OO.inheritClass( ve.ui.HTMLFileTransferHandler, ve.ui.DataTransferHandler );
+OO.inheritClass( ve.ui.HTMLFileTransferHandler, ve.ui.FileTransferHandler );
 
 /* Static properties */
 
diff --git a/src/ui/datatransferhandlers/ve.ui.PlainTextFileTransferHandler.js 
b/src/ui/datatransferhandlers/ve.ui.PlainTextFileTransferHandler.js
index fe78634..32afb0a 100644
--- a/src/ui/datatransferhandlers/ve.ui.PlainTextFileTransferHandler.js
+++ b/src/ui/datatransferhandlers/ve.ui.PlainTextFileTransferHandler.js
@@ -8,7 +8,7 @@
  * Plain text data transfer filetransfer handler.
  *
  * @class
- * @extends ve.ui.DataTransferHandler
+ * @extends ve.ui.FileTransferHandler
  *
  * @constructor
  * @param {ve.ui.Surface} surface
@@ -21,7 +21,7 @@
 
 /* Inheritance */
 
-OO.inheritClass( ve.ui.PlainTextFileTransferHandler, ve.ui.DataTransferHandler 
);
+OO.inheritClass( ve.ui.PlainTextFileTransferHandler, ve.ui.FileTransferHandler 
);
 
 /* Static properties */
 
diff --git a/src/ui/ve.ui.DataTransferHandler.js 
b/src/ui/ve.ui.DataTransferHandler.js
index b44dcc7..a40c336 100644
--- a/src/ui/ve.ui.DataTransferHandler.js
+++ b/src/ui/ve.ui.DataTransferHandler.js
@@ -12,24 +12,14 @@
  *
  * @constructor
  * @param {ve.ui.Surface} surface Surface
- * @param {File} file File to handle
+ * @param {DataTransferItem} item Data transfer item to handle
  */
-ve.ui.DataTransferHandler = function VeUiDataTransferHandler( surface, file ) {
+ve.ui.DataTransferHandler = function VeUiDataTransferHandler( surface, item ) {
        // Properties
        this.surface = surface;
-       this.file = file;
+       this.item = item;
 
        this.insertableDataDeferred = $.Deferred();
-
-       this.reader = new FileReader();
-
-       this.progress = false;
-       this.progressBar = null;
-
-       // Events
-       this.reader.addEventListener( 'progress', this.onFileProgress.bind( 
this ) );
-       this.reader.addEventListener( 'load', this.onFileLoad.bind( this ) );
-       this.reader.addEventListener( 'loadend', this.onFileLoadEnd.bind( this 
) );
 };
 
 /* Inheritance */
@@ -46,6 +36,17 @@
  * @inheritable
  */
 ve.ui.DataTransferHandler.static.name = null;
+
+/**
+ * List of transfer kinds supported by this handler
+ *
+ * Null means all kinds are supported.
+ *
+ * @static
+ * @property {string[]|null}
+ * @inheritable
+ */
+ve.ui.DataTransferHandler.static.kinds = null;
 
 /**
  * List of mime types supported by this handler
@@ -79,60 +80,8 @@
 };
 
 /**
- * Handle progress events from the file reader
- *
- * @param {Event} e Progress event
- */
-ve.ui.DataTransferHandler.prototype.onFileProgress = function () {};
-
-/**
- * Handle load events from the file reader
- *
- * @param {Event} e Load event
- */
-ve.ui.DataTransferHandler.prototype.onFileLoad = function () {};
-
-/**
- * Handle load end events from the file reader
- *
- * @param {Event} e Load end event
- */
-ve.ui.DataTransferHandler.prototype.onFileLoadEnd = function () {};
-
-/**
  * Abort the data transfer handler
  */
 ve.ui.DataTransferHandler.prototype.abort = function () {
        this.insertableDataDeferred.reject();
-};
-
-/**
- * Create a progress bar with a specified label
- *
- * @param {jQuery.Promise} progressCompletePromise Promise which resolves when 
the progress action is complete
- * @param {jQuery|string|Function} [label] Progress bar label, defaults to 
file name
- */
-ve.ui.DataTransferHandler.prototype.createProgress = function ( 
progressCompletePromise, label ) {
-       var handler = this;
-
-       this.surface.createProgress( progressCompletePromise, label || 
this.file.name ).done( function ( progressBar, cancelPromise ) {
-               // Set any progress that was achieved before this resolved
-               progressBar.setProgress( handler.progress );
-               handler.progressBar = progressBar;
-               cancelPromise.fail( handler.abort.bind( handler ) );
-       } );
-};
-
-/**
- * Set progress bar progress
- *
- * Progress is stored in a property in case the progress bar doesn't exist yet.
- *
- * @param {number} progress Progress percent
- */
-ve.ui.DataTransferHandler.prototype.setProgress = function ( progress ) {
-       this.progress = progress;
-       if ( this.progressBar ) {
-               this.progressBar.setProgress( this.progress );
-       }
 };
diff --git a/src/ui/ve.ui.DataTransferHandlerFactory.js 
b/src/ui/ve.ui.DataTransferHandlerFactory.js
index 4997c80..935aacd 100644
--- a/src/ui/ve.ui.DataTransferHandlerFactory.js
+++ b/src/ui/ve.ui.DataTransferHandlerFactory.js
@@ -15,7 +15,10 @@
        // Parent constructor
        ve.ui.DataTransferHandlerFactory.super.apply( this, arguments );
 
+       // Handlers which match all kinds and a specific type
        this.handlerNamesByType = {};
+       // Handlers which match a specific kind and type
+       this.handlerNamesByKindAndType = {};
 };
 
 /* Inheritance */
@@ -31,22 +34,56 @@
        // Parent method
        ve.ui.DataTransferHandlerFactory.super.prototype.register.call( this, 
constructor );
 
-       var i, l, types = constructor.static.types;
-       for ( i = 0, l = types.length; i < l; i++ ) {
-               this.handlerNamesByType[types[i]] = constructor.static.name;
+       var i, j, ilen, jlen,
+               kinds = constructor.static.kinds,
+               types = constructor.static.types;
+
+       if ( !kinds ) {
+               for ( j = 0, jlen = types.length; j < jlen; j++ ) {
+                       this.handlerNamesByType[types[j]] = 
constructor.static.name;
+               }
+       } else {
+               for ( i = 0, ilen = kinds.length; i < ilen; i++ ) {
+                       for ( j = 0, jlen = types.length; j < jlen; j++ ) {
+                               this.handlerNamesByKindAndType[kinds[i]] = 
this.handlerNamesByKindAndType[kinds[i]] || {};
+                               
this.handlerNamesByKindAndType[kinds[i]][types[j]] = constructor.static.name;
+                       }
+               }
        }
 };
 
 /**
  * Returns the primary command for for node.
  *
- * @param {string} type File type
+ * @param {DataTransferItem} item Data transfer item
  * @returns {string|undefined} Handler name, or undefined if not found
  */
-ve.ui.DataTransferHandlerFactory.prototype.getHandlerNameForType = function ( 
type ) {
-       return this.handlerNamesByType[type];
+ve.ui.DataTransferHandlerFactory.prototype.getHandlerNameForItem = function ( 
item ) {
+       return this.handlerNamesByKindAndType[item.kind][item.type] || 
this.handlerNamesByType[item.type];
 };
 
 /* Initialization */
 
 ve.ui.dataTransferHandlerFactory = new ve.ui.DataTransferHandlerFactory();
+
+/**
+ * Fake data transfer item from a file
+ *
+ * @class
+ * @constructor
+ * @param {File} file Data transfer file
+ */
+ve.ui.DataTransferItem = function VeUiDataTransferItem( file ) {
+       this.kind = 'file';
+       this.type = file.type;
+       this.file = file;
+};
+
+/**
+ * Get file object
+ *
+ * @return {File} File object
+ */
+ve.ui.DataTransferItem.prototype.getAsFile = function () {
+       return this.file;
+};
diff --git a/src/ui/ve.ui.FileTransferHandler.js 
b/src/ui/ve.ui.FileTransferHandler.js
new file mode 100644
index 0000000..1d27677
--- /dev/null
+++ b/src/ui/ve.ui.FileTransferHandler.js
@@ -0,0 +1,95 @@
+/*!
+ * VisualEditor UserInterface data transfer handler class.
+ *
+ * @copyright 2011-2015 VisualEditor Team and others; see 
http://ve.mit-license.org
+ */
+
+/**
+ * Data transfer handler.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {ve.ui.Surface} surface
+ * @param {DataTransferItem} item
+ */
+ve.ui.FileTransferHandler = function VeUiFileTransferHandler() {
+       // Parent constructor
+       ve.ui.FileTransferHandler.super.apply( this, arguments );
+
+       // Properties
+       this.file = this.item.getAsFile();
+
+       this.reader = new FileReader();
+
+       this.progress = false;
+       this.progressBar = null;
+
+       // Events
+       this.reader.addEventListener( 'progress', this.onFileProgress.bind( 
this ) );
+       this.reader.addEventListener( 'load', this.onFileLoad.bind( this ) );
+       this.reader.addEventListener( 'loadend', this.onFileLoadEnd.bind( this 
) );
+};
+
+/* Inheritance */
+
+OO.inheritClass( ve.ui.FileTransferHandler, ve.ui.DataTransferHandler );
+
+/* Static properties */
+
+ve.ui.FileTransferHandler.static.kinds = [ 'file' ];
+
+/* Methods */
+
+/**
+ * Handle progress events from the file reader
+ *
+ * @param {Event} e Progress event
+ */
+ve.ui.FileTransferHandler.prototype.onFileProgress = function () {};
+
+/**
+ * Handle load events from the file reader
+ *
+ * @param {Event} e Load event
+ */
+ve.ui.FileTransferHandler.prototype.onFileLoad = function () {};
+
+/**
+ * Handle load end events from the file reader
+ *
+ * @param {Event} e Load end event
+ */
+ve.ui.FileTransferHandler.prototype.onFileLoadEnd = function () {};
+
+/**
+ * Create a progress bar with a specified label
+ *
+ * @param {jQuery.Promise} progressCompletePromise Promise which resolves when 
the progress action is complete
+ * @param {jQuery|string|Function} [label] Progress bar label, defaults to 
file name
+ */
+ve.ui.FileTransferHandler.prototype.createProgress = function ( 
progressCompletePromise, label ) {
+       var handler = this;
+
+       this.surface.createProgress( progressCompletePromise, label || 
this.file.name ).done( function ( progressBar, cancelPromise ) {
+               // Set any progress that was achieved before this resolved
+               progressBar.setProgress( handler.progress );
+               handler.progressBar = progressBar;
+               cancelPromise.fail( handler.abort.bind( handler ) );
+       } );
+};
+
+/**
+ * Set progress bar progress
+ *
+ * Progress is stored in a property in case the progress bar doesn't exist yet.
+ *
+ * @param {number} progress Progress percent
+ */
+ve.ui.FileTransferHandler.prototype.setProgress = function ( progress ) {
+       this.progress = progress;
+       if ( this.progressBar ) {
+               this.progressBar.setProgress( this.progress );
+       }
+};
diff --git a/tests/index.html b/tests/index.html
index 43bd38c..8a19c45 100644
--- a/tests/index.html
+++ b/tests/index.html
@@ -260,6 +260,7 @@
                <script src="../src/ui/ve.ui.Action.js"></script>
                <script src="../src/ui/ve.ui.ActionFactory.js"></script>
                <script src="../src/ui/ve.ui.DataTransferHandler.js"></script>
+               <script src="../src/ui/ve.ui.FileTransferHandler.js"></script>
                <script 
src="../src/ui/ve.ui.DataTransferHandlerFactory.js"></script>
                <script src="../src/ui/ve.ui.WindowManager.js"></script>
                <script 
src="../src/ui/actions/ve.ui.AnnotationAction.js"></script>

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie9892950163d6c8b8fb1f8c3e19de86e704a2209
Gerrit-PatchSet: 1
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Esanders <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to