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

Change subject: Surface drop: Show branch node drop markers for file drop
......................................................................


Surface drop: Show branch node drop markers for file drop

We can tell when the user is about to drop a file. As FF doesn't
let us know anything about the file, just assume it results in
generating a branch node, and use the branch node drop markers
to avoid splitting a paragraph with your drop.

Bug: T115859
Change-Id: I1aae7f2e68241da98f64f943f449f3b97efd21f8
---
M src/ce/ve.ce.Surface.js
M src/ui/ve.ui.DataTransferItem.js
2 files changed, 65 insertions(+), 13 deletions(-)

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



diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js
index 360b792..919e63a 100644
--- a/src/ce/ve.ce.Surface.js
+++ b/src/ce/ve.ce.Surface.js
@@ -45,6 +45,7 @@
        this.renderLocks = 0;
        this.dragging = false;
        this.relocatingNode = false;
+       this.allowedFile = null;
        this.resizing = false;
        this.focused = false;
        this.deactivated = false;
@@ -137,6 +138,7 @@
        this.$element.on( {
                dragstart: this.onDocumentDragStart.bind( this ),
                dragover: this.onDocumentDragOver.bind( this ),
+               dragleave: this.onDocumentDragLeave.bind( this ),
                drop: this.onDocumentDrop.bind( this )
        } );
 
@@ -969,18 +971,56 @@
  * @param {jQuery.Event} e Drag over event
  */
 ve.ce.Surface.prototype.onDocumentDragOver = function ( e ) {
-       var $target, $dropTarget, node, dropPosition, targetPosition, top, left,
-               nodeType, inIgnoreChildren;
-       if ( !this.relocatingNode ) {
-               return;
+       var i, l, $target, $dropTarget, node, dropPosition, targetPosition, 
top, left,
+               nodeType, inIgnoreChildren, item, fakeItem,
+               isContent = true,
+               dataTransfer = e.originalEvent.dataTransfer;
+
+       if ( this.relocatingNode ) {
+               isContent = this.relocatingNode.isContent();
+               nodeType = this.relocatingNode.getType();
+       } else {
+               if ( this.allowedFile === null ) {
+                       this.allowedFile = false;
+                       // If we can get file metadata, check if there is a 
DataTransferHandler registered
+                       // to handle it.
+                       if ( dataTransfer.items ) {
+                               for ( i = 0, l = dataTransfer.items.length; i < 
l; i++ ) {
+                                       item = dataTransfer.items[ i ];
+                                       if ( item.kind !== 'string' ) {
+                                               fakeItem = new 
ve.ui.DataTransferItem( item.kind, item.type );
+                                               if ( 
ve.init.target.dataTransferHandlerFactory.getHandlerNameForItem( fakeItem ) ) {
+                                                       this.allowedFile = true;
+                                                       break;
+                                               }
+                                       }
+                               }
+                       } else if ( dataTransfer.files ) {
+                               for ( i = 0, l = dataTransfer.files.length; i < 
l; i++ ) {
+                                       item = dataTransfer.items[ i ];
+                                       fakeItem = new ve.ui.DataTransferItem( 
item.kind, item.type );
+                                       if ( 
ve.init.target.dataTransferHandlerFactory.getHandlerNameForItem( fakeItem ) ) {
+                                               this.allowedFile = true;
+                                               break;
+                                       }
+                               }
+                       // If we have no metadata (e.g. in Firefox) assume it 
is droppable
+                       } else if ( Array.prototype.indexOf.call( 
dataTransfer.types || [], 'Files' ) !== -1 ) {
+                               this.allowedFile = true;
+                       }
+               }
+               // this.allowedFile is cached until the next dragleave event
+               if ( this.allowedFile ) {
+                       isContent = false;
+                       nodeType = 'alienBlock';
+               }
        }
 
-       if ( !this.relocatingNode.isContent() ) {
+       if ( !isContent ) {
                e.preventDefault();
                $target = $( e.target ).closest( '.ve-ce-branchNode, 
.ve-ce-leafNode' );
                if ( $target.length ) {
                        // Find the nearest node which will accept this node 
type
-                       nodeType = this.relocatingNode.getType();
                        node = $target.data( 'view' );
                        while ( node.parent && 
!node.parent.isAllowedChildNodeType( nodeType ) ) {
                                node = node.parent;
@@ -1034,6 +1074,21 @@
 };
 
 /**
+ * Handle document drag leave events.
+ *
+ * @method
+ * @param {jQuery.Event} e Drag leave event
+ */
+ve.ce.Surface.prototype.onDocumentDragLeave = function () {
+       this.allowedFile = null;
+       if ( this.$lastDropTarget ) {
+               this.$dropMarker.addClass( 'oo-ui-element-hidden' );
+               this.$lastDropTarget = null;
+               this.lastDropPosition = null;
+       }
+};
+
+/**
  * Handle document drop events.
  *
  * Limits native drag and drop behaviour.
@@ -1054,7 +1109,7 @@
        e.preventDefault();
 
        // Determine drop position
-       if ( this.relocatingNode && !this.relocatingNode.getModel().isContent() 
) {
+       if ( $dropTarget ) {
                // Block level drag and drop: use the lastDropTarget to get the 
targetOffset
                if ( $dropTarget ) {
                        targetRange = $dropTarget.data( 'view' 
).getModel().getOuterRange();
@@ -2707,12 +2762,9 @@
        if ( this.relocatingNode ) {
                this.emit( 'relocationEnd', this.relocatingNode );
                this.relocatingNode = null;
-               if ( this.$lastDropTarget ) {
-                       this.$dropMarker.addClass( 'oo-ui-element-hidden' );
-                       this.$lastDropTarget = null;
-                       this.lastDropPosition = null;
-               }
        }
+       // Trigger a drag leave event to clear markers
+       this.onDocumentDragLeave();
 };
 
 /**
diff --git a/src/ui/ve.ui.DataTransferItem.js b/src/ui/ve.ui.DataTransferItem.js
index 175ed1e..0608231 100644
--- a/src/ui/ve.ui.DataTransferItem.js
+++ b/src/ui/ve.ui.DataTransferItem.js
@@ -16,7 +16,7 @@
 ve.ui.DataTransferItem = function VeUiDataTransferItem( kind, type, data, name 
) {
        this.kind = kind;
        this.type = type;
-       this.data = data;
+       this.data = data || {};
        this.blob = this.data.blob || null;
        this.stringData = this.data.stringData || ve.getProp( this.blob, 'name' 
) || null;
        this.name = name;

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I1aae7f2e68241da98f64f943f449f3b97efd21f8
Gerrit-PatchSet: 5
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Esanders <[email protected]>
Gerrit-Reviewer: Alex Monk <[email protected]>
Gerrit-Reviewer: Bartosz DziewoƄski <[email protected]>
Gerrit-Reviewer: DLynch <[email protected]>
Gerrit-Reviewer: Esanders <[email protected]>
Gerrit-Reviewer: Jforrester <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

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

Reply via email to