Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove chrome fix for dragging over iframes #15665

Merged
merged 1 commit into from
May 20, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 16 additions & 42 deletions packages/components/src/draggable/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,14 @@ const cloneWrapperClass = 'components-draggable__clone';
const cloneHeightTransformationBreakpoint = 700;
const clonePadding = 20;

const isChromeUA = ( ) => /Chrome/i.test( window.navigator.userAgent );
const documentHasIframes = ( ) => [ ...document.getElementById( 'editor' ).querySelectorAll( 'iframe' ) ].length > 0;

class Draggable extends Component {
constructor() {
super( ...arguments );

this.onDragStart = this.onDragStart.bind( this );
this.onDragOver = this.onDragOver.bind( this );
this.onDrop = this.onDrop.bind( this );
this.onDragEnd = this.onDragEnd.bind( this );
this.resetDragState = this.resetDragState.bind( this );

this.isChromeAndHasIframes = false;
}

componentWillUnmount() {
Expand All @@ -36,21 +30,21 @@ class Draggable extends Component {

/**
* Removes the element clone, resets cursor, and removes drag listener.
* @param {Object} event The non-custom DragEvent.
*
* @param {Object} event The non-custom DragEvent.
*/
onDragEnd( event ) {
const { onDragEnd = noop } = this.props;
if ( event ) {
event.preventDefault();
}
event.preventDefault();

this.resetDragState();
this.props.setTimeout( onDragEnd );
}

/*
/**
* Updates positioning of element clone based on mouse movement during dragging.
* @param {Object} event The non-custom DragEvent.
*
* @param {Object} event The non-custom DragEvent.
*/
onDragOver( event ) {
this.cloneWrapper.style.top =
Expand All @@ -63,21 +57,17 @@ class Draggable extends Component {
this.cursorTop = event.clientY;
}

onDrop( ) {
// As per https://html.spec.whatwg.org/multipage/dnd.html#dndevents
// the target node for the dragend is the source node that started the drag operation,
// while drop event's target is the current target element.
this.onDragEnd( null );
}

/**
* - Clones the current element and spawns clone over original element.
* - Adds a fake temporary drag image to avoid browser defaults.
* - Sets transfer data.
* - Adds dragover listener.
* @param {Object} event The non-custom DragEvent.
* @param {string} elementId The HTML id of the element to be dragged.
* @param {Object} transferData The data to be set to the event's dataTransfer - to be accessible in any later drop logic.
* This method does a couple of things:
*
* - Clones the current element and spawns clone over original element.
* - Adds a fake temporary drag image to avoid browser defaults.
* - Sets transfer data.
* - Adds dragover listener.
*
* @param {Object} event The non-custom DragEvent.
* @param {string} elementId The HTML id of the element to be dragged.
* @param {Object} transferData The data to be set to the event's dataTransfer - to be accessible in any later drop logic.
*/
onDragStart( event ) {
const { elementId, transferData, onDragStart = noop } = this.props;
Expand Down Expand Up @@ -140,17 +130,6 @@ class Draggable extends Component {
document.body.classList.add( 'is-dragging-components-draggable' );
document.addEventListener( 'dragover', this.onDragOver );

// Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=737691#c8
// dragend event won't be dispatched in the chrome browser
// when iframes are affected by the drag operation. So, in that case,
// we use the drop event to wrap up the dragging operation.
// This way the hack is contained to a specific use case and the external API
// still relies mostly on the dragend event.
if ( isChromeUA() && documentHasIframes() ) {
this.isChromeAndHasIframes = true;
document.addEventListener( 'drop', this.onDrop );
}

this.props.setTimeout( onDragStart );
}

Expand All @@ -166,11 +145,6 @@ class Draggable extends Component {
this.cloneWrapper = null;
}

if ( this.isChromeAndHasIframes ) {
this.isChromeAndHasIframes = false;
document.removeEventListener( 'drop', this.onDrop );
}

// Reset cursor.
document.body.classList.remove( 'is-dragging-components-draggable' );
}
Expand Down