Przeglądaj źródła

Merge pull request #7550 from ckeditor/i/6755

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.
Maciej 5 lat temu
rodzic
commit
27fce4e3c3

+ 13 - 4
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();
 		}
 	}
 

+ 55 - 0
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, '[<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 );
+	} );
+} );

+ 22 - 1
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', () => {

+ 5 - 4
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 } );
 	},
 
 	/**