filedialogbuttonview.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. * Fired when file dialog is closed with file selected.
  42. *
  43. * fileDialogButtonView.on( 'done', ( evt, files ) => {
  44. * for ( const file of files ) {
  45. * processFile( file );
  46. * }
  47. * }
  48. *
  49. * @event done
  50. * @param {Array.<File>} files Array of selected files.
  51. */
  52. this.fileInputView.delegate( 'done' ).to( this );
  53. this.on( 'execute', () => {
  54. this.fileInputView.open();
  55. } );
  56. document.body.appendChild( this.fileInputView.element );
  57. }
  58. /**
  59. * @inheritDoc
  60. */
  61. destroy() {
  62. document.body.removeChild( this.fileInputView.element );
  63. return super.destroy();
  64. }
  65. }
  66. /**
  67. * Hidden file input view class.
  68. *
  69. * @private
  70. * @extends {module:ui/view~View}
  71. */
  72. class FileInputView extends View {
  73. /**
  74. * @inheritDoc
  75. */
  76. constructor( locale ) {
  77. super( locale );
  78. /**
  79. * Accepted file types. Can be provided in form of file extensions, media type or one of:
  80. * * `audio/*`,
  81. * * `video/*`,
  82. * * `image/*`.
  83. *
  84. * @observable
  85. * @member {String} #acceptedType
  86. */
  87. this.set( 'acceptedType' );
  88. const bind = this.bindTemplate;
  89. this.template = new Template( {
  90. tag: 'input',
  91. attributes: {
  92. class: [
  93. 'ck-hidden'
  94. ],
  95. type: 'file',
  96. tabindex: '-1',
  97. accept: bind.to( 'acceptedType' )
  98. },
  99. on: {
  100. // Removing from code coverage since we cannot programmatically set input element files.
  101. change: bind.to( /* istanbul ignore next */ () => {
  102. if ( this.element && this.element.files && this.element.files.length ) {
  103. this.fire( 'done', this.element.files );
  104. }
  105. this.element.value = '';
  106. } )
  107. }
  108. } );
  109. }
  110. /**
  111. * Opens file dialog.
  112. */
  113. open() {
  114. this.element.click();
  115. }
  116. }