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