8
0
Просмотр исходного кода

Refactored FileDialogButtonView component.

Oskar Wróbel 8 лет назад
Родитель
Сommit
740504f7d5

+ 6 - 3
packages/ckeditor5-upload/src/imageuploadbutton.js

@@ -40,13 +40,16 @@ export default class ImageUploadButton extends Plugin {
 			const command = editor.commands.get( 'imageUpload' );
 
 			view.set( {
-				label: t( 'Insert image' ),
-				icon: imageIcon,
-				tooltip: true,
 				acceptedType: 'image/*',
 				allowMultipleFiles: true
 			} );
 
+			view.buttonView.set( {
+				label: t( 'Insert image' ),
+				icon: imageIcon,
+				tooltip: true
+			} );
+
 			view.bind( 'isEnabled' ).to( command );
 
 			view.on( 'done', ( evt, files ) => {

+ 29 - 27
packages/ckeditor5-upload/src/ui/filedialogbuttonview.js

@@ -3,8 +3,6 @@
  * For licensing, see LICENSE.md.
  */
 
-/* globals document */
-
 /**
  * @module upload/ui/filedialogbuttonview
  */
@@ -16,9 +14,12 @@ import Template from '@ckeditor/ckeditor5-ui/src/template';
 /**
  * File Dialog button view.
  *
- * @extends module:ui/button/buttonview~ButtonView
+ * This component implements wrapper element with {@link module:ui/button/buttonview~ButtonView ButtonView}
+ * and and hidden `input[type="file"]` inside.
+ *
+ * @extends module:ui/view~View
  */
-export default class FileDialogButtonView extends ButtonView {
+export default class FileDialogButtonView extends View {
 	/**
 	 * @inheritDoc
 	 */
@@ -26,13 +27,19 @@ export default class FileDialogButtonView extends ButtonView {
 		super( locale );
 
 		/**
-		 * Hidden input view used to execute file dialog. It will be hidden and added to the end of `document.body`.
+		 * Button View.
+		 *
+		 * @member {module:ui/button/buttonview~ButtonView}
+		 */
+		this.buttonView = new ButtonView( locale );
+
+		/**
+		 * Hidden input view used to execute file dialog.
 		 *
 		 * @protected
 		 * @member {module:upload/ui/filedialogbuttonview~FileInputView}
 		 */
-		this.fileInputView = new FileInputView( locale );
-		this.addChildren( this.fileInputView );
+		this._fileInputView = new FileInputView( locale );
 
 		/**
 		 * Accepted file types. Can be provided in form of file extensions, media type or one of:
@@ -43,7 +50,7 @@ export default class FileDialogButtonView extends ButtonView {
 		 * @observable
 		 * @member {String} #acceptedType
 		 */
-		this.fileInputView.bind( 'acceptedType' ).to( this );
+		this._fileInputView.bind( 'acceptedType' ).to( this );
 
 		/**
 		 * Indicates if multiple files can be selected. Defaults to `true`.
@@ -51,7 +58,7 @@ export default class FileDialogButtonView extends ButtonView {
 		 * @observable
 		 * @member {Boolean} #allowMultipleFiles
 		 */
-		this.fileInputView.bind( 'allowMultipleFiles' ).to( this );
+		this._fileInputView.bind( 'allowMultipleFiles' ).to( this );
 
 		/**
 		 * Fired when file dialog is closed with file selected.
@@ -65,27 +72,22 @@ export default class FileDialogButtonView extends ButtonView {
 		 * @event done
 		 * @param {Array.<File>} files Array of selected files.
 		 */
-		this.fileInputView.delegate( 'done' ).to( this );
+		this._fileInputView.delegate( 'done' ).to( this );
 
-		this.on( 'execute', () => {
-			this.fileInputView.open();
+		this.template = new Template( {
+			tag: 'span',
+			attributes: {
+				class: 'ck-file-dialog-button',
+			},
+			children: [
+				this.buttonView,
+				this._fileInputView
+			]
 		} );
-	}
 
-	/**
-	 * @inheritDoc
-	 */
-	init() {
-		super.init();
-		document.body.appendChild( this.fileInputView.element );
-	}
-
-	/**
-	 * @inheritDoc
-	 */
-	destroy() {
-		super.destroy();
-		this.fileInputView.element.remove();
+		this.buttonView.on( 'execute', () => {
+			this._fileInputView.open();
+		} );
 	}
 }
 

+ 38 - 28
packages/ckeditor5-upload/tests/ui/filedialogbuttonview.js

@@ -3,9 +3,9 @@
  * For licensing, see LICENSE.md.
  */
 
-/* globals document */
-
 import FileDialogButtonView from '../../src/ui/filedialogbuttonview';
+import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
+import View from '@ckeditor/ckeditor5-ui/src/view';
 
 describe( 'FileDialogButtonView', () => {
 	let view, localeMock;
@@ -17,43 +17,53 @@ describe( 'FileDialogButtonView', () => {
 		return view.init();
 	} );
 
-	it( 'should append input view to document body', () => {
-		expect( document.body.contains( view.fileInputView.element ) ).to.true;
+	it( 'should be rendered from a template', () => {
+		expect( view.element.classList.contains( 'ck-file-dialog-button' ) ).to.true;
 	} );
 
-	it( 'should remove input view from body after destroy', () => {
-		view.destroy();
+	describe( 'child views', () => {
+		describe( 'button view', () => {
+			it( 'should be rendered', () => {
+				expect( view.buttonView ).to.instanceof( ButtonView );
+				expect( view.buttonView ).to.equal( view.template.children.get( 0 ) );
+			} );
 
-		expect( document.body.contains( view.fileInputView.element ) ).to.false;
-	} );
+			it( 'should open file dialog on execute', () => {
+				const spy = sinon.spy( view._fileInputView, 'open' );
+				view.buttonView.fire( 'execute' );
 
-	it( 'should open file dialog on execute', () => {
-		const spy = sinon.spy( view.fileInputView, 'open' );
-		view.fire( 'execute' );
+				sinon.assert.calledOnce( spy );
+			} );
+		} );
 
-		sinon.assert.calledOnce( spy );
-	} );
+		describe( 'file dialog', () => {
+			it( 'should be rendered', () => {
+				expect( view._fileInputView ).to.instanceof( View );
+				expect( view._fileInputView ).to.equal( view.template.children.get( 1 ) );
+			} );
 
-	it( 'should pass acceptedType to input view', () => {
-		view.set( { acceptedType: 'audio/*' } );
+			it( 'should be bound to view#acceptedType', () => {
+				view.set( { acceptedType: 'audio/*' } );
 
-		expect( view.fileInputView.acceptedType ).to.equal( 'audio/*' );
-	} );
+				expect( view._fileInputView.acceptedType ).to.equal( 'audio/*' );
+			} );
 
-	it( 'should pass allowMultipleFiles to input view', () => {
-		view.set( { allowMultipleFiles: true } );
+			it( 'should be bound to view#allowMultipleFiles', () => {
+				view.set( { allowMultipleFiles: true } );
 
-		expect( view.fileInputView.allowMultipleFiles ).to.be.true;
-	} );
+				expect( view._fileInputView.allowMultipleFiles ).to.be.true;
+			} );
 
-	it( 'should delegate input view done event', done => {
-		const files = [];
+			it( 'should delegate done event to view', () => {
+				const spy = sinon.spy();
+				const files = [];
 
-		view.on( 'done', ( evt, data ) => {
-			expect( data ).to.equal( files );
-			done();
-		} );
+				view.on( 'done', spy );
+				view._fileInputView.fire( 'done', files );
 
-		view.fileInputView.fire( 'done', files );
+				sinon.assert.calledOnce( spy );
+				expect( spy.lastCall.args[ 1 ] ).to.equal( files );
+			} );
+		} );
 	} );
 } );