From 427a44e887f4d961ff13903dd4cacb65b926d010 Mon Sep 17 00:00:00 2001 From: Kuba Niegowski Date: Fri, 20 Mar 2020 19:44:45 +0100 Subject: [PATCH] Handled paste and drop events no longer propagate up DOM tree. --- src/clipboard.js | 12 ++++++++- tests/clipboard.js | 49 ++++++++++++++++++++++++++++++++++++ tests/pasting-integration.js | 1 + 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/clipboard.js b/src/clipboard.js index 1240d05..5d612ff 100644 --- a/src/clipboard.js +++ b/src/clipboard.js @@ -16,6 +16,7 @@ import normalizeClipboardHtml from './utils/normalizeclipboarddata'; import viewToPlainText from './utils/viewtoplaintext.js'; import HtmlDataProcessor from '@ckeditor/ckeditor5-engine/src/dataprocessor/htmldataprocessor'; +import EventInfo from '@ckeditor/ckeditor5-utils/src/eventinfo'; /** * The clipboard feature. It is responsible for intercepting the `paste` and `drop` events and @@ -75,7 +76,15 @@ export default class Clipboard extends Plugin { content = this._htmlDataProcessor.toView( content ); - this.fire( 'inputTransformation', { content, dataTransfer } ); + const eventInfo = new EventInfo( this, 'inputTransformation' ); + this.fire( eventInfo, { content, dataTransfer } ); + + // If CKEditor handled the input, do not bubble the original event any further. + // This helps external integrations recognize that fact and act accordingly. + // https://github.com/ckeditor/ckeditor5-upload/issues/92 + if ( eventInfo.stop.called ) { + evt.stop(); + } view.scrollToTheSelection(); }, { priority: 'low' } ); @@ -95,6 +104,7 @@ export default class Clipboard extends Plugin { } model.insertContent( modelFragment ); + evt.stop(); } }, { priority: 'low' } ); diff --git a/tests/clipboard.js b/tests/clipboard.js index 0db36ef..84f4fde 100644 --- a/tests/clipboard.js +++ b/tests/clipboard.js @@ -8,6 +8,7 @@ import Clipboard from '../src/clipboard'; import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph'; import ClipboardObserver from '../src/clipboardobserver'; +import DataTransfer from '../src/datatransfer'; import { stringify as stringifyView, @@ -176,6 +177,7 @@ describe( 'Clipboard feature', () => { viewDocument.fire( 'paste', { dataTransfer: dataTransferMock, + stopPropagation() {}, preventDefault() {} } ); @@ -243,6 +245,7 @@ describe( 'Clipboard feature', () => { viewDocument.fire( 'paste', { dataTransfer: dataTransferMock, + stopPropagation() {}, preventDefault() {} } ); @@ -294,6 +297,52 @@ describe( 'Clipboard feature', () => { expect( spy.callCount ).to.equal( 0 ); } ); + // https://github.com/ckeditor/ckeditor5-upload/issues/92 + // https://github.com/ckeditor/ckeditor5/issues/6464 + it( 'should stop propagation of the original event if CKEditor handled the input', () => { + const dataTransferMock = createDataTransfer( { 'text/html': 'x' } ); + const spy = sinon.spy(); + + viewDocument.fire( 'paste', { + dataTransfer: dataTransferMock, + stopPropagation: spy, + preventDefault() {} + } ); + + expect( spy.callCount ).to.equal( 1 ); + } ); + + // https://github.com/ckeditor/ckeditor5-upload/issues/92 + // https://github.com/ckeditor/ckeditor5/issues/6464 + it( 'should stop propagation of the original event if inputTransformation listener called stop (for file drop)', () => { + const fileMock = { + type: 'application/zip', + size: 1024 + }; + const dataTransferMock = new DataTransfer( { files: [ fileMock ], types: [ 'Files' ], getData: () => {} } ); + const spy = sinon.spy(); + + viewDocument.fire( 'drop', { + dataTransfer: dataTransferMock, + stopPropagation: spy, + preventDefault() {} + } ); + + expect( spy.callCount ).to.equal( 0 ); + + clipboardPlugin.on( 'inputTransformation', evt => { + evt.stop(); + } ); + + viewDocument.fire( 'paste', { + dataTransfer: dataTransferMock, + stopPropagation: spy, + preventDefault() {} + } ); + + expect( spy.callCount ).to.equal( 1 ); + } ); + function createDataTransfer( data ) { return { getData( type ) { diff --git a/tests/pasting-integration.js b/tests/pasting-integration.js index 3dc09f1..931f8a3 100644 --- a/tests/pasting-integration.js +++ b/tests/pasting-integration.js @@ -196,6 +196,7 @@ describe( 'Pasting – integration', () => { function pasteHtml( editor, html ) { editor.editing.view.document.fire( 'paste', { dataTransfer: createDataTransfer( { 'text/html': html } ), + stopPropagation() {}, preventDefault() {} } ); }