diff --git a/packages/ckeditor5-widget/src/widgetresize.js b/packages/ckeditor5-widget/src/widgetresize.js index 41878ca9bce..43fa74ec04e 100644 --- a/packages/ckeditor5-widget/src/widgetresize.js +++ b/packages/ckeditor5-widget/src/widgetresize.js @@ -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'; @@ -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 = () => { @@ -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(); } } diff --git a/packages/ckeditor5-widget/tests/widgetresize-integration.js b/packages/ckeditor5-widget/tests/widgetresize-integration.js new file mode 100644 index 00000000000..6b52d006411 --- /dev/null +++ b/packages/ckeditor5-widget/tests/widgetresize-integration.js @@ -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, '[]' ); + + 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 ); + } ); +} ); diff --git a/packages/ckeditor5-widget/tests/widgetresize.js b/packages/ckeditor5-widget/tests/widgetresize.js index cf039a8bb12..899e272f6b8 100644 --- a/packages/ckeditor5-widget/tests/widgetresize.js +++ b/packages/ckeditor5-widget/tests/widgetresize.js @@ -72,7 +72,8 @@ describe( 'WidgetResize', () => { const unrelatedElement = document.createElement( 'div' ); editor.plugins.get( WidgetResize )._mouseDownListener( {}, { - target: unrelatedElement + domTarget: unrelatedElement, + preventDefault: sinon.spy() } ); } ); @@ -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', () => { diff --git a/packages/ckeditor5-widget/tests/widgetresize/_utils/utils.js b/packages/ckeditor5-widget/tests/widgetresize/_utils/utils.js index a3fce10a0c1..9b9d62248da 100644 --- a/packages/ckeditor5-widget/tests/widgetresize/_utils/utils.js +++ b/packages/ckeditor5-widget/tests/widgetresize/_utils/utils.js @@ -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 } ); }, /**