API Docs for: 0.25.0
Show:

File: addon/components/file-chooser/component.js

  1. import Ember from 'ember';
  2. import layout from './template';
  3.  
  4. /**
  5. * @module ember-osf
  6. * @submodule components
  7. */
  8.  
  9. /**
  10. * This component lets the user choose a list of files from their computer, by
  11. * drag-and-drop, a file browser, or whatever method the developer wants.
  12. *
  13. * Exposed to parent context (bindable attributes)
  14. * - `files`: mutable list of chosen File objects
  15. * - `multiple`: boolean (default `true`), when `false`, only keeps the most
  16. * recently chosen File in the list
  17. * - `onChoose`: callback function called each time a file is added, with the
  18. * new File object as the only argument
  19. *
  20. * Exposed to block context
  21. * - `this`: the component object itself, so the block can invoke actions
  22. * example:
  23. * ```handlebars
  24. * {{#file-chooser files=fileList as |component|}}
  25. * {{input type='file'
  26. * change=(action 'onFileInputChange' target=component)}}
  27. * {{/file-chooser}}
  28. * ```
  29. *
  30. * Actions
  31. * - `onFileInputChange`: handle the `change` event on a file input
  32. * - `onChooseFile`: add a file to the chosen list
  33. *
  34. * Styling
  35. * - This component's element has the `drop-zone` class
  36. * - While the user is holding dragged files over this component, it
  37. * has the `drop-zone-ready` class
  38. *
  39. * @class file-chooser component
  40. */
  41. export default Ember.Component.extend({
  42. layout,
  43. i18n: Ember.inject.service(),
  44. classNames: ['drop-zone'],
  45. classNameBindings: ['dropZoneReady'],
  46. dropZoneReady: false,
  47. multiple: true,
  48.  
  49. dragOver(event) {
  50. if (event.dataTransfer.types.indexOf('Files') > -1) {
  51. this.set('dropZoneReady', true);
  52. event.dataTransfer.dropEffect = 'move';
  53. return false;
  54. } else {
  55. event.dataTransfer.dropEffect = 'none';
  56. }
  57. },
  58.  
  59. dragLeave(event) {
  60. this.set('dropZoneReady', false);
  61. event.dataTransfer.dropEffect = '';
  62. },
  63.  
  64. drop(event) {
  65. event.preventDefault();
  66. this.set('dropZoneReady', false);
  67. for (let i = 0; i < event.dataTransfer.files.length; i++) {
  68. let file = event.dataTransfer.files[i];
  69. this._chooseIfFile(file);
  70. }
  71. },
  72.  
  73. actions: {
  74. onFileInputChange(event) {
  75. for (let i = 0; i < event.target.files.length; i++) {
  76. let file = event.target.files[i];
  77. this.send('onChooseFile', file);
  78. }
  79. },
  80.  
  81. onChooseFile(file) {
  82. let files = this.get('files');
  83. if (typeof files === 'undefined') {
  84. this.set('files', Ember.A());
  85. files = this.get('files');
  86. }
  87. if (this.get('multiple')) {
  88. files.pushObject(file);
  89. } else {
  90. this.set('files', Ember.A([file]));
  91. }
  92.  
  93. let callback = this.get('onChoose');
  94. if (callback) {
  95. callback(file);
  96. }
  97. }
  98. },
  99.  
  100. _chooseIfFile(file) {
  101. // HACK: There's not a cross-browser way to see the contents of
  102. // dragged-and-dropped directories, but there's also not a good way to
  103. // tell whether a given File object is a directory. Hence, this:
  104. let p = new Ember.RSVP.Promise(function(resolve, reject) {
  105. let reader = new FileReader();
  106. reader.onload = () => resolve(); // it's a file
  107. reader.onerror = () => reject(); // it's a directory or something
  108. reader.readAsText(file.slice(0, 5));
  109. });
  110. p.then(() => this.send('onChooseFile', file));
  111. p.catch(() => this.set('errorMessage',
  112. `Cannot upload directories (${file.name})`));
  113. }
  114. });
  115.