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

Change subject: Support for generic file drop handlers
......................................................................


Support for generic file drop handlers

Includes PlainTextFileDropHandler as an example implementation.

Change-Id: I1de3363a959d8297f73e650f2cc7fb6feb981d00
---
M .docs/categories.json
M .docs/config.json
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
A src/ui/ve.ui.FileDropHandler.js
A src/ui/ve.ui.FileDropHandlerFactory.js
A src/ui/ve.ui.PlainTextFileDropHandler.js
M src/ui/ve.ui.js
M tests/index.html
12 files changed, 257 insertions(+), 3 deletions(-)

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



diff --git a/.docs/categories.json b/.docs/categories.json
index d7b835f..b9764a1 100644
--- a/.docs/categories.json
+++ b/.docs/categories.json
@@ -124,7 +124,8 @@
                                        "ve.ui.DebugBar",
                                        "ve.ui.Action",
                                        "ve.ui.Trigger",
-                                       "ve.ui.Command"
+                                       "ve.ui.Command",
+                                       "ve.ui.*FileDropHandler"
                                ]
                        },
                        {
diff --git a/.docs/config.json b/.docs/config.json
index dbcc1ea..335c1af 100644
--- a/.docs/config.json
+++ b/.docs/config.json
@@ -6,7 +6,7 @@
        "--warnings": ["-nodoc(class,public)"],
        "--builtin-classes": true,
        "--warnings-exit-nonzero": true,
-       "--external": "HTMLDocument,Window,Node,Set,Range,Selection,ClientRect",
+       "--external": 
"HTMLDocument,Window,Node,Set,Range,Selection,ClientRect,File",
        "--output": "../docs",
        "--": [
                "./external.js",
diff --git a/.docs/eg-iframe.html b/.docs/eg-iframe.html
index 9551cf5..6d489de 100644
--- a/.docs/eg-iframe.html
+++ b/.docs/eg-iframe.html
@@ -282,6 +282,9 @@
                <script src="../src/ui/ve.ui.Action.js"></script>
                <script src="../src/ui/ve.ui.ActionFactory.js"></script>
                <script src="../src/ui/ve.ui.WindowManager.js"></script>
+               <script 
src="../src/ui/ve.ui.FileDropHandlerFactory.js"></script>
+               <script src="../src/ui/ve.ui.FileDropHandler.js"></script>
+               <script 
src="../src/ui/ve.ui.PlainTextFileDropHandler.js"></script>
                <script 
src="../src/ui/actions/ve.ui.AnnotationAction.js"></script>
                <script src="../src/ui/actions/ve.ui.ContentAction.js"></script>
                <script src="../src/ui/actions/ve.ui.FormatAction.js"></script>
diff --git a/build/modules.json b/build/modules.json
index ac78df2..4aeffb9 100644
--- a/build/modules.json
+++ b/build/modules.json
@@ -306,6 +306,9 @@
                        "src/ui/ve.ui.Action.js",
                        "src/ui/ve.ui.ActionFactory.js",
                        "src/ui/ve.ui.WindowManager.js",
+                       "src/ui/ve.ui.FileDropHandlerFactory.js",
+                       "src/ui/ve.ui.FileDropHandler.js",
+                       "src/ui/ve.ui.PlainTextFileDropHandler.js",
                        "src/ui/actions/ve.ui.AnnotationAction.js",
                        "src/ui/actions/ve.ui.ContentAction.js",
                        "src/ui/actions/ve.ui.FormatAction.js",
diff --git a/demos/ve/desktop.html b/demos/ve/desktop.html
index 341a701..8d38ad2 100644
--- a/demos/ve/desktop.html
+++ b/demos/ve/desktop.html
@@ -295,6 +295,9 @@
                <script src="../../src/ui/ve.ui.Action.js"></script>
                <script src="../../src/ui/ve.ui.ActionFactory.js"></script>
                <script src="../../src/ui/ve.ui.WindowManager.js"></script>
+               <script 
src="../../src/ui/ve.ui.FileDropHandlerFactory.js"></script>
+               <script src="../../src/ui/ve.ui.FileDropHandler.js"></script>
+               <script 
src="../../src/ui/ve.ui.PlainTextFileDropHandler.js"></script>
                <script 
src="../../src/ui/actions/ve.ui.AnnotationAction.js"></script>
                <script 
src="../../src/ui/actions/ve.ui.ContentAction.js"></script>
                <script 
src="../../src/ui/actions/ve.ui.FormatAction.js"></script>
diff --git a/demos/ve/mobile.html b/demos/ve/mobile.html
index a829446..d8cedce 100644
--- a/demos/ve/mobile.html
+++ b/demos/ve/mobile.html
@@ -296,6 +296,9 @@
                <script src="../../src/ui/ve.ui.Action.js"></script>
                <script src="../../src/ui/ve.ui.ActionFactory.js"></script>
                <script src="../../src/ui/ve.ui.WindowManager.js"></script>
+               <script 
src="../../src/ui/ve.ui.FileDropHandlerFactory.js"></script>
+               <script src="../../src/ui/ve.ui.FileDropHandler.js"></script>
+               <script 
src="../../src/ui/ve.ui.PlainTextFileDropHandler.js"></script>
                <script 
src="../../src/ui/actions/ve.ui.AnnotationAction.js"></script>
                <script 
src="../../src/ui/actions/ve.ui.ContentAction.js"></script>
                <script 
src="../../src/ui/actions/ve.ui.FormatAction.js"></script>
diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js
index dfd7b40..0e346cb 100644
--- a/src/ce/ve.ce.Surface.js
+++ b/src/ce/ve.ce.Surface.js
@@ -888,6 +888,8 @@
        var selectionJSON, dragSelection, dragRange, originFragment, originData,
                targetRange, targetOffset, targetFragment, dragHtml, dragText,
                htmlDoc, doc, data, pasteRules,
+               i, l, name, insert,
+               fileHandlers = [],
                dataTransfer = e.originalEvent.dataTransfer,
                $dropTarget = this.$lastDropTarget,
                dropPosition = this.lastDropPosition;
@@ -913,6 +915,15 @@
                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.fileDropHandlerFactory.getHandlerNameForType( dataTransfer.files[i].type 
);
+                       if ( name ) {
+                               fileHandlers.push(
+                                       ve.ui.fileDropHandlerFactory.create( 
name, this.surface, dataTransfer.files[i] )
+                               );
+                       }
+               }
        } else {
                try {
                        dragHtml = dataTransfer.getData( 'text/html' );
@@ -924,7 +935,7 @@
                }
        }
 
-       if ( ( dragRange && !dragRange.isCollapsed() ) || dragHtml || dragText 
) {
+       if ( ( dragRange && !dragRange.isCollapsed() ) || fileHandlers.length 
|| dragHtml || dragText  ) {
                if ( this.relocatingNode && 
!this.relocatingNode.getModel().isContent() ) {
                        // Block level drag and drop: use the lastDropTarget to 
get the targetOffset
                        if ( $dropTarget ) {
@@ -959,6 +970,13 @@
 
                        // Re-insert data at new location
                        targetFragment.insertContent( originData );
+               } else if ( fileHandlers.length ) {
+                       insert = function ( data ) {
+                               targetFragment.collapseToEnd().insertContent( 
data );
+                       };
+                       for ( i = 0, l = fileHandlers.length; i < l; i++ ) {
+                               fileHandlers[i].getInsertableData().done( 
insert );
+                       }
                } else if ( dragHtml ) {
                        pasteRules = this.getSurface().getPasteRules();
                        htmlDoc = ve.createDocumentFromHtml( dragHtml );
diff --git a/src/ui/ve.ui.FileDropHandler.js b/src/ui/ve.ui.FileDropHandler.js
new file mode 100644
index 0000000..4da35cf
--- /dev/null
+++ b/src/ui/ve.ui.FileDropHandler.js
@@ -0,0 +1,97 @@
+/*!
+ * VisualEditor UserInterface file drop handler class.
+ *
+ * @copyright 2011-2014 VisualEditor Team and others; see 
http://ve.mit-license.org
+ */
+
+/**
+ * File drop handler.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {ve.ui.Surface} surface Surface
+ * @param {File} file File to handle
+ */
+ve.ui.FileDropHandler = function VeUiFileDropHandler( surface, file ) {
+       // Properties
+       this.surface = surface;
+       this.file = file;
+
+       this.insertableDataDeferred = $.Deferred();
+
+       this.reader = new FileReader();
+
+       // 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.initClass( ve.ui.FileDropHandler );
+
+/* Static properties */
+
+/**
+ * Symbolic name for this handler. Must be unique.
+ *
+ * @static
+ * @property {string}
+ * @inheritable
+ */
+ve.ui.FileDropHandler.static.name = null;
+
+/**
+ * List of mime types supported by this handler
+ *
+ * @static
+ * @property {string[]}
+ * @inheritable
+ */
+ve.ui.FileDropHandler.static.types = [];
+
+/* Methods */
+
+/**
+ * Process the file
+ *
+ * Implementations should aim to resolve this.insertableDataDeferred.
+ */
+ve.ui.FileDropHandler.prototype.process = function () {
+       throw new Error( 've.ui.FileDropHandler subclass must implement 
process' );
+};
+
+/**
+ * Insert the file at a specified fragment
+ *
+ * @return {jQuery.Promise} Promise which resolves with data to insert
+ */
+ve.ui.FileDropHandler.prototype.getInsertableData = function () {
+       this.process();
+
+       return this.insertableDataDeferred.promise();
+};
+
+/**
+ * Handle progress events from the file reader
+ *
+ * @param {Event} e Progress event
+ */
+ve.ui.FileDropHandler.prototype.onFileProgress = function () {};
+
+/**
+ * Handle load events from the file reader
+ *
+ * @param {Event} e Load event
+ */
+ve.ui.FileDropHandler.prototype.onFileLoad = function () {};
+
+/**
+ * Handle load end events from the file reader
+ *
+ * @param {Event} e Load end event
+ */
+ve.ui.FileDropHandler.prototype.onFileLoadEnd = function () {};
diff --git a/src/ui/ve.ui.FileDropHandlerFactory.js 
b/src/ui/ve.ui.FileDropHandlerFactory.js
new file mode 100644
index 0000000..2005505
--- /dev/null
+++ b/src/ui/ve.ui.FileDropHandlerFactory.js
@@ -0,0 +1,52 @@
+/*!
+ * VisualEditor FileDropHandlerFactory class.
+ *
+ * @copyright 2011-2014 VisualEditor Team and others; see 
http://ve.mit-license.org
+ */
+
+/**
+ * Drop handler Factory.
+ *
+ * @class
+ * @extends OO.Factory
+ * @constructor
+ */
+ve.ui.FileDropHandlerFactory = function VeUiFileDropHandlerFactory() {
+       // Parent constructor
+       ve.ui.FileDropHandlerFactory.super.apply( this, arguments );
+
+       this.handlerNamesByType = {};
+};
+
+/* Inheritance */
+
+OO.inheritClass( ve.ui.FileDropHandlerFactory, OO.Factory );
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+ve.ui.FileDropHandlerFactory.prototype.register = function ( constructor ) {
+       // Parent method
+       ve.ui.FileDropHandlerFactory.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;
+       }
+};
+
+/**
+ * Returns the primary command for for node.
+ *
+ * @param {string} type File type
+ * @returns {string|undefined} Handler name, or undefined if not found
+ */
+ve.ui.FileDropHandlerFactory.prototype.getHandlerNameForType = function ( type 
) {
+       return this.handlerNamesByType[type];
+};
+
+/* Initialization */
+
+ve.ui.fileDropHandlerFactory = new ve.ui.FileDropHandlerFactory();
diff --git a/src/ui/ve.ui.PlainTextFileDropHandler.js 
b/src/ui/ve.ui.PlainTextFileDropHandler.js
new file mode 100644
index 0000000..64f298b
--- /dev/null
+++ b/src/ui/ve.ui.PlainTextFileDropHandler.js
@@ -0,0 +1,70 @@
+/*!
+ * VisualEditor UserInterface plain text file drop handler class.
+ *
+ * @copyright 2011-2014 VisualEditor Team and others; see 
http://ve.mit-license.org
+ */
+
+/**
+ * Plain text file drop handler.
+ *
+ * @class
+ * @extends ve.ui.FileDropHandler
+ *
+ * @constructor
+ * @param {ve.ui.Surface} surface
+ * @param {File} file
+ */
+ve.ui.PlainTextFileDropHandler = function VeUiPlainTextFileDropHandler() {
+       // Parent constructor
+       ve.ui.PlainTextFileDropHandler.super.apply( this, arguments );
+};
+
+/* Inheritance */
+
+OO.inheritClass( ve.ui.PlainTextFileDropHandler, ve.ui.FileDropHandler );
+
+/* Static properties */
+
+ve.ui.PlainTextFileDropHandler.static.name = 'plainText';
+
+ve.ui.PlainTextFileDropHandler.static.types = ['text/plain'];
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+ve.ui.PlainTextFileDropHandler.prototype.process = function () {
+       this.reader.readAsText( this.file );
+};
+
+/**
+ * @inheritdoc
+ */
+ve.ui.PlainTextFileDropHandler.prototype.onFileLoad = function () {
+       var i, l,
+               data = [],
+               lines = this.reader.result.split( /[\r\n]+/ );
+
+       for ( i = 0, l = lines.length; i < l; i++ ) {
+               if ( lines[i].length ) {
+                       data.push( { type: 'paragraph' } );
+                       data = data.concat( lines[i].split( '' ) );
+                       data.push( { type: '/paragraph' } );
+               }
+       }
+       this.insertableDataDeferred.resolve( data );
+};
+
+/**
+ * @inheritdoc
+ */
+ve.ui.PlainTextFileDropHandler.prototype.onFileLoadEnd = function () {
+       // 'loadend' fires after 'load'/'abort'/'error'.
+       // Reject the deferred if it hasn't already resolved.
+       this.insertableDataDeferred.reject();
+};
+
+/* Registration */
+
+ve.ui.fileDropHandlerFactory.register( ve.ui.PlainTextFileDropHandler );
diff --git a/src/ui/ve.ui.js b/src/ui/ve.ui.js
index 9e79453..f89b6b2 100644
--- a/src/ui/ve.ui.js
+++ b/src/ui/ve.ui.js
@@ -15,6 +15,7 @@
        //'commandRegistry' instantiated in ve.ui.CommandRegistry.js
        //'triggerRegistry' instantiated in ve.ui.TriggerRegistry.js
        //'toolFactory' instantiated in ve.ui.ToolFactory.js
+       //'fileDropHandlerFactory' instantiated in 
ve.ui.FileDropHandlerFactory.js
        windowFactory: new OO.Factory()
 };
 
diff --git a/tests/index.html b/tests/index.html
index 6491934..23e4d74 100644
--- a/tests/index.html
+++ b/tests/index.html
@@ -246,6 +246,9 @@
                <script src="../src/ui/ve.ui.Action.js"></script>
                <script src="../src/ui/ve.ui.ActionFactory.js"></script>
                <script src="../src/ui/ve.ui.WindowManager.js"></script>
+               <script 
src="../src/ui/ve.ui.FileDropHandlerFactory.js"></script>
+               <script src="../src/ui/ve.ui.FileDropHandler.js"></script>
+               <script 
src="../src/ui/ve.ui.PlainTextFileDropHandler.js"></script>
                <script 
src="../src/ui/actions/ve.ui.AnnotationAction.js"></script>
                <script src="../src/ui/actions/ve.ui.ContentAction.js"></script>
                <script src="../src/ui/actions/ve.ui.FormatAction.js"></script>

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I1de3363a959d8297f73e650f2cc7fb6feb981d00
Gerrit-PatchSet: 9
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Esanders <[email protected]>
Gerrit-Reviewer: Esanders <[email protected]>
Gerrit-Reviewer: Trevor Parscal <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

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

Reply via email to