filedialogbuttonview.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /**
  2. * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* globals document */
  6. /**
  7. * @module upload/ui/filedialogbuttonview
  8. */
  9. import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
  10. import View from '@ckeditor/ckeditor5-ui/src/view';
  11. import Template from '@ckeditor/ckeditor5-ui/src/template';
  12. /**
  13. * File Dialog button view.
  14. *
  15. * @extends module:ui/button/buttonview~ButtonView
  16. */
  17. export default class FileDialogButtonView extends ButtonView {
  18. /**
  19. * @inheritDoc
  20. */
  21. constructor( locale ) {
  22. super( locale );
  23. /**
  24. * Hidden input view used to execute file dialog. It will be hidden and added to the end of `document.body`.
  25. *
  26. * @protected
  27. * @member module:upload/ui/filedialogbuttonview~FileDialogButtonView #fileInputView
  28. */
  29. this.fileInputView = new FileInputView( locale );
  30. /**
  31. * Accepted file types. Can be provided in form of file extensions, media type or one of:
  32. * * `audio/*`,
  33. * * `video/*`,
  34. * * `image/*`.
  35. *
  36. * @observable
  37. * @member {String} #acceptedType
  38. */
  39. this.fileInputView.bind( 'acceptedType' ).to( this, 'acceptedType' );
  40. /**
  41. * Indicates if multiple files can be selected. Defaults to `true`.
  42. *
  43. * @observable
  44. * @member {Boolean} #allowMultipleFiles
  45. */
  46. this.set( 'allowMultipleFiles', false );
  47. this.fileInputView.bind( 'allowMultipleFiles' ).to( this, 'allowMultipleFiles' );
  48. /**
  49. * Fired when file dialog is closed with file selected.
  50. *
  51. * fileDialogButtonView.on( 'done', ( evt, files ) => {
  52. * for ( const file of files ) {
  53. * processFile( file );
  54. * }
  55. * }
  56. *
  57. * @event done
  58. * @param {Array.<File>} files Array of selected files.
  59. */
  60. this.fileInputView.delegate( 'done' ).to( this );
  61. this.on( 'execute', () => {
  62. this.fileInputView.open();
  63. } );
  64. document.body.appendChild( this.fileInputView.element );
  65. }
  66. /**
  67. * @inheritDoc
  68. */
  69. destroy() {
  70. document.body.removeChild( this.fileInputView.element );
  71. return super.destroy();
  72. }
  73. }
  74. /**
  75. * Hidden file input view class.
  76. *
  77. * @private
  78. * @extends {module:ui/view~View}
  79. */
  80. class FileInputView extends View {
  81. /**
  82. * @inheritDoc
  83. */
  84. constructor( locale ) {
  85. super( locale );
  86. /**
  87. * Accepted file types. Can be provided in form of file extensions, media type or one of:
  88. * * `audio/*`,
  89. * * `video/*`,
  90. * * `image/*`.
  91. *
  92. * @observable
  93. * @member {String} #acceptedType
  94. */
  95. this.set( 'acceptedType' );
  96. /**
  97. * Indicates if multiple files can be selected. Defaults to `false`.
  98. *
  99. * @observable
  100. * @member {Boolean} #allowMultipleFiles
  101. */
  102. this.set( 'allowMultipleFiles', false );
  103. const bind = this.bindTemplate;
  104. this.template = new Template( {
  105. tag: 'input',
  106. attributes: {
  107. class: [
  108. 'ck-hidden'
  109. ],
  110. type: 'file',
  111. tabindex: '-1',
  112. accept: bind.to( 'acceptedType' ),
  113. multiple: bind.to( 'allowMultipleFiles' )
  114. },
  115. on: {
  116. // Removing from code coverage since we cannot programmatically set input element files.
  117. change: bind.to( /* istanbul ignore next */ () => {
  118. if ( this.element && this.element.files && this.element.files.length ) {
  119. this.fire( 'done', this.element.files );
  120. }
  121. this.element.value = '';
  122. } )
  123. }
  124. } );
  125. }
  126. /**
  127. * Opens file dialog.
  128. */
  129. open() {
  130. this.element.click();
  131. }
  132. }