Skip to content

Commit

Permalink
Merge pull request #7550 from ckeditor/i/6755
Browse files Browse the repository at this point in the history
Fix (widget): The resizing mechanism will not trigger other `view.Document#mousedown` events. Thanks to that while resizing an image inside a cell, the mouse will not trigger the table's actions. Closes #6755.
  • Loading branch information
jodator authored Jul 6, 2020
2 parents 7eb8c6f + df70766 commit 27fce4e
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 9 deletions.
17 changes: 13 additions & 4 deletions packages/ckeditor5-widget/src/widgetresize.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Resizer from './widgetresize/resizer';
import DomEmitterMixin from '@ckeditor/ckeditor5-utils/src/dom/emittermixin';
import global from '@ckeditor/ckeditor5-utils/src/dom/global';
import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
import MouseObserver from '@ckeditor/ckeditor5-engine/src/view/observer/mouseobserver';
import mix from '@ckeditor/ckeditor5-utils/src/mix';
import { throttle } from 'lodash-es';

Expand Down Expand Up @@ -71,12 +72,13 @@ export default class WidgetResize extends Plugin {
isFormatting: true
} );

this.editor.editing.view.addObserver( MouseObserver );

this._observer = Object.create( DomEmitterMixin );

this._observer.listenTo( domDocument, 'mousedown', this._mouseDownListener.bind( this ) );
this.listenTo( this.editor.editing.view.document, 'mousedown', this._mouseDownListener.bind( this ), { priority: 'high' } );

this._observer.listenTo( domDocument, 'mousemove', this._mouseMoveListener.bind( this ) );

this._observer.listenTo( domDocument, 'mouseup', this._mouseUpListener.bind( this ) );

const redrawFocusedResizer = () => {
Expand Down Expand Up @@ -182,13 +184,20 @@ export default class WidgetResize extends Plugin {
* @param {Event} domEventData Native DOM event.
*/
_mouseDownListener( event, domEventData ) {
if ( !Resizer.isResizeHandle( domEventData.target ) ) {
const resizeHandle = domEventData.domTarget;

if ( !Resizer.isResizeHandle( resizeHandle ) ) {
return;
}
const resizeHandle = domEventData.target;

this._activeResizer = this._getResizerByHandle( resizeHandle );

if ( this._activeResizer ) {
this._activeResizer.begin( resizeHandle );

// Do not call other events when resizing. See: #6755.
event.stop();
domEventData.preventDefault();
}
}

Expand Down
55 changes: 55 additions & 0 deletions packages/ckeditor5-widget/tests/widgetresize-integration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

/* global document, Event */

import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';

import { setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
import Image from '@ckeditor/ckeditor5-image/src/image';
import ImageResize from '@ckeditor/ckeditor5-image/src/imageresize';

describe( 'WidgetResize - integration', () => {
let editor, model, view, viewDocument, editorElement;

testUtils.createSinonSandbox();

beforeEach( () => {
editorElement = document.createElement( 'div' );
document.body.appendChild( editorElement );

return ClassicEditor.create( editorElement, { plugins: [ Image, ImageResize ] } )
.then( newEditor => {
editor = newEditor;
model = editor.model;
view = editor.editing.view;
viewDocument = view.document;
} );
} );

afterEach( () => {
editorElement.remove();

return editor.destroy();
} );

it( 'should not fire viewDocument#mousedown events after starting resizing', () => {
const eventSpy = sinon.spy().named( 'ViewDocument#mousedown' );

setModelData( model, '[<image src="/assets/sample.png"></image>]' );

const resizeSquareUI = [ ...viewDocument.getRoot().getChild( 0 ).getChildren() ]
.find( element => element.hasClass( 'ck-widget__resizer' ) );

const squareDomElement = view.domConverter.mapViewToDom( resizeSquareUI ).querySelector( '.ck-widget__resizer__handle-top-left' );

viewDocument.on( 'mousedown', eventSpy );

squareDomElement.dispatchEvent( new Event( 'mousedown' ) );

expect( eventSpy.called ).to.equal( false );
} );
} );
23 changes: 22 additions & 1 deletion packages/ckeditor5-widget/tests/widgetresize.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ describe( 'WidgetResize', () => {
const unrelatedElement = document.createElement( 'div' );

editor.plugins.get( WidgetResize )._mouseDownListener( {}, {
target: unrelatedElement
domTarget: unrelatedElement,
preventDefault: sinon.spy()
} );
} );

Expand Down Expand Up @@ -114,6 +115,26 @@ describe( 'WidgetResize', () => {
resizerMouseSimulator.dragTo( editor, domParts.resizeHandle, initialPointerPosition );
// No exception should be thrown.
} );

it( 'stops the event after starting resizing', () => {
const stopSpy = sinon.spy().named( 'stop' );

const domParts = getWidgetDomParts( editor, widget, 'top-right' );

resizerMouseSimulator.down( editor, domParts.resizeHandle, { stop: stopSpy } );

expect( stopSpy.called ).to.be.equal( true );
} );

it( 'prevents default action after starting resizing', () => {
const preventDefaultSpy = sinon.spy().named( 'preventDefault' );

const domParts = getWidgetDomParts( editor, widget, 'top-right' );

resizerMouseSimulator.down( editor, domParts.resizeHandle, { preventDefault: preventDefaultSpy } );

expect( preventDefaultSpy.called ).to.be.equal( true );
} );
} );

describe( 'visibility', () => {
Expand Down
9 changes: 5 additions & 4 deletions packages/ckeditor5-widget/tests/widgetresize/_utils/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import WidgetResize from '../../../src/widgetresize';
import Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';

export const resizerMouseSimulator = {
down( editor, domTarget ) {
this._getPlugin( editor )._mouseDownListener( {}, {
target: domTarget
} );
down( editor, domTarget, options = {} ) {
const preventDefault = options.preventDefault || sinon.spy().named( 'preventDefault' );
const stop = options.stop || sinon.spy().named( 'stop' );

this._getPlugin( editor )._mouseDownListener( { stop }, { domTarget, preventDefault } );
},

/**
Expand Down

0 comments on commit 27fce4e

Please sign in to comment.