diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ec1475b..e8116377 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # CKEditor 4 Angular Integration Changelog +## ckeditor4-angular 1.2.0 + +New Features: + +* [#7](/~https://github.com/ckeditor/ckeditor4-angular/issues/7): CKEditor 4 component now exposes more CKEditor 4 native events. Thanks to [Eduard Zintz](/~https://github.com/ezintz)! New exposed events are: + * [paste](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-paste) + * [afterPaste](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-afterPaste) + * [dragStat](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-dragstart) + * [dragEnd](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-dragend) + * [drop](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-drop) + * [fileUploadRequest](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-fileUploadRequest) + * [fileUploadResponse](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-fileUploadResponse) + ## ckeditor4-angular 1.1.0 Other Changes: diff --git a/src/app/simple-usage/simple-usage.component.html b/src/app/simple-usage/simple-usage.component.html index 5d451c18..fb67689a 100644 --- a/src/app/simple-usage/simple-usage.component.html +++ b/src/app/simple-usage/simple-usage.component.html @@ -14,8 +14,15 @@
Note: editors have it's data synchronized, so every change in one of editors propagates to another.
diff --git a/src/app/simple-usage/simple-usage.component.ts b/src/app/simple-usage/simple-usage.component.ts index 9394ca5c..da67d3c1 100644 --- a/src/app/simple-usage/simple-usage.component.ts +++ b/src/app/simple-usage/simple-usage.component.ts @@ -46,4 +46,32 @@ You learn to appreciate each and every single one of the differences while you b onBlur( event: CKEditor4.EventInfo, editorName: string ): void { console.log( `Blurred ${editorName.toLowerCase()} editing view.` ); } + + onPaste( event: CKEditor4.EventInfo, editorName: string ): void { + console.log( `Pasted into ${editorName.toLowerCase()} editing view.` ); + } + + onAfterPaste( event: CKEditor4.EventInfo, editorName: string ): void { + console.log( `After pasted fired in ${editorName.toLowerCase()} editing view.` ); + } + + onDragStart( event: CKEditor4.EventInfo, editorName: string ): void { + console.log( `Drag started in ${editorName.toLowerCase()} editing view.` ); + } + + onDragEnd( event: CKEditor4.EventInfo, editorName: string ): void { + console.log( `Drag ended in ${editorName.toLowerCase()} editing view.` ); + } + + onDrop( event: CKEditor4.EventInfo, editorName: string ): void { + console.log( `Dropped in ${editorName.toLowerCase()} editing view.` ); + } + + onFileUploadRequest( event: CKEditor4.EventInfo, editorName: string ): void { + console.log( `File upload requested in ${editorName.toLowerCase()} editor.` ); + } + + onFileUploadResponse( event: CKEditor4.EventInfo, editorName: string ): void { + console.log( `File upload responded in ${editorName.toLowerCase()} editor.` ); + } } diff --git a/src/ckeditor/ckeditor.component.spec.ts b/src/ckeditor/ckeditor.component.spec.ts index 1997c966..fbfe6182 100644 --- a/src/ckeditor/ckeditor.component.spec.ts +++ b/src/ckeditor/ckeditor.component.spec.ts @@ -5,7 +5,14 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { CKEditorComponent } from './ckeditor.component'; -import { whenEvent, whenDataReady, setDataMultipleTimes } from '../test.tools'; +import { + fireDragEvent, + mockDropEvent, + mockPasteEvent, + setDataMultipleTimes, + whenDataReady, + whenEvent +} from '../test.tools'; import { CKEditor4 } from './ckeditor'; import EditorType = CKEditor4.EditorType; @@ -345,6 +352,123 @@ describe( 'CKEditorComponent', () => { expect( spy ).toHaveBeenCalledTimes( 1 ); } ); + + it( 'paste should emit component paste', () => { + const pasteEventMock = mockPasteEvent(); + pasteEventMock.$.clipboardData.setData( 'text/html', 'bam
' ); + + fixture.detectChanges(); + + const spy = jasmine.createSpy(); + component.paste.subscribe( spy ); + + const editable = component.instance.editable(); + editable.fire( 'paste', pasteEventMock ); + + return whenEvent( 'paste', component ).then( () => { + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( component.instance.getData() ).toEqual( 'bam
\n' ); + } ); + } ); + + it( 'afterPaste should emit component afterPaste', () => { + const pasteEventMock = mockPasteEvent(); + pasteEventMock.$.clipboardData.setData( 'text/html', 'bam
' ); + + fixture.detectChanges(); + + const spy = jasmine.createSpy(); + component.afterPaste.subscribe( spy ); + + const editable = component.instance.editable(); + editable.fire( 'paste', pasteEventMock ); + + return whenEvent( 'afterPaste', component ).then( () => { + expect( spy ).toHaveBeenCalledTimes( 1 ); + expect( component.instance.getData() ).toEqual( 'bam
\n' ); + } ); + } ); + + it( 'drag/drop events should emit component dragStart, dragEnd and drop', async done => { + fixture.detectChanges(); + + const spyDragStart = jasmine.createSpy( 'dragstart' ); + component.dragStart.subscribe( spyDragStart ); + + const spyDragEnd = jasmine.createSpy( 'dragend' ); + component.dragEnd.subscribe( spyDragEnd ); + + const spyDrop = jasmine.createSpy( 'drop' ); + component.drop.subscribe( spyDrop ); + + whenDataReady( component.instance, () => { + const dropEvent = mockDropEvent(); + const paragraph = component.instance.editable().findOne( 'p' ); + + component.instance.getSelection().selectElement( paragraph ); + + fireDragEvent( 'dragstart', component.instance, dropEvent ); + + expect( spyDragStart ).toHaveBeenCalledTimes( 1 ); + + fireDragEvent( 'dragend', component.instance, dropEvent ); + + expect( spyDragEnd ).toHaveBeenCalledTimes( 1 ); + + // There is some issue in Firefox with simulating drag-drop flow. The drop event + // is not fired making this assertion fail. Let's skip it for now. + if ( !CKEDITOR.env.gecko ) { + fireDragEvent( 'drop', component.instance, dropEvent ); + + expect( spyDrop ).toHaveBeenCalledTimes( 1 ); + } + + done(); + } ); + } ); + + it( 'fileUploadRequest should emit component fileUploadRequest', () => { + fixture.detectChanges(); + + const spy = jasmine.createSpy(); + component.fileUploadRequest.subscribe( spy ); + + const fileLoaderMock = { + fileLoader: { + file: Blob ? new Blob() : '', + fileName: 'fileName', + xhr: { + open: function() {}, + send: function() {} + } + }, + requestData: {} + }; + + component.instance.fire( 'fileUploadRequest', fileLoaderMock ); + + expect( spy ).toHaveBeenCalledTimes( 1 ); + } ); + + it( 'fileUploadResponse should emit component fileUploadResponse', () => { + fixture.detectChanges(); + + const spy = jasmine.createSpy(); + component.fileUploadResponse.subscribe( spy ); + + const data = { + fileLoader: { + xhr: { responseText: 'Not a JSON.' }, + lang: { + filetools: { responseError: 'Error' } + } + } + }; + + component.instance.fire( 'fileUploadResponse', data ); + + expect( spy ).toHaveBeenCalledTimes( 1 ); + } ); } ); describe( 'when control value accessor callbacks are set', () => { diff --git a/src/ckeditor/ckeditor.component.ts b/src/ckeditor/ckeditor.component.ts index 3b07fd36..e35ed86f 100644 --- a/src/ckeditor/ckeditor.component.ts +++ b/src/ckeditor/ckeditor.component.ts @@ -146,6 +146,41 @@ export class CKEditorComponent implements AfterViewInit, OnDestroy, ControlValue */ @Output() dataChange = new EventEmitter