Guest User

Untitled

a guest
Jul 18th, 2018
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.45 KB | None | 0 0
  1. /* global Blob, Uint8Array */
  2. import Component from '@ember/component';
  3.  
  4. import { inject as service } from '@ember/service';
  5. import { bind } from '@ember/runloop';
  6. import { computed, set, get } from '@ember/object';
  7. import DataTransfer from 'ember-file-upload/system/data-transfer';
  8. import uuid from 'ember-file-upload/system/uuid';
  9. import parseHTML from 'ember-file-upload/system/parse-html';
  10.  
  11. const DATA_TRANSFER = 'DATA_TRANSFER' + uuid.short();
  12.  
  13. let supported = (function () {
  14. return typeof window !== 'undefined' && window.document &&
  15. 'draggable' in document.createElement('span');
  16. }());
  17.  
  18. /**
  19. `{{file-dropzone-ex}}` is an element that will allow users to upload files by
  20. drag and drop.
  21.  
  22. ```hbs
  23. {{{#file-dropzone-ex name="photos" as |dropzone queue|}}
  24. {{#if dropzone.active}}
  25. {{#if dropzone.valid}}
  26. Drop to upload
  27. {{else}}
  28. Invalid
  29. {{/if}}
  30. {{else if queue.files.length}}
  31. Uploading {{queue.files.length}} files. ({{queue.progress}}%)
  32. {{else}}
  33. <h4>Upload Images</h4>
  34. <p>
  35. {{#if dropzone.supported}}
  36. Drag and drop images onto this area to upload them or
  37. {{/if}}
  38. {{#file-upload name="photos"
  39. accept="image/*"
  40. multiple=true
  41. onfileadd=(action "uploadImage")}}
  42. <a id="upload-image" tabindex=0>Add an Image.</a>
  43. {{/file-upload}}
  44. </p>
  45. {{/if}}
  46. {{/file-dropzone-ex}}
  47. ```
  48.  
  49. ```js
  50. import Controller from '@ember/controller';
  51.  
  52. export default Ember.Route.extend({
  53. actions: {
  54. uploadImage(file) {
  55. file.upload(URL, options).then((response) => {
  56. ...
  57. });
  58. }
  59. }
  60. });
  61. ```
  62.  
  63. @class FileDropzone
  64. @type Ember.Component
  65. @yield {Hash} dropzone
  66. @yield {boolean} dropzone.supported
  67. @yield {boolean} dropzone.active
  68. @yield {valid} dropzone.valid
  69. @yield {Queue} queue
  70. */
  71. export default Component.extend({
  72.  
  73. /**
  74. The name of the queue that files should be
  75. added to when they get dropped.
  76.  
  77. @argument name
  78. @type {string}
  79. */
  80. name: null,
  81.  
  82. supported,
  83.  
  84. /**
  85. `ondragenter` is called when a file has entered
  86. the dropzone.
  87.  
  88. @argument ondragenter
  89. @type {function}
  90. */
  91. ondragenter: null,
  92.  
  93. /**
  94. `ondragleave` is called when a file has left
  95. the dropzone.
  96.  
  97. @argument ondragleave
  98. @type {function}
  99. */
  100. ondragleave: null,
  101.  
  102. /**
  103. `ondrop` is called when a file has been dropped.
  104.  
  105. @argument ondrop
  106. @type {function}
  107. */
  108. ondrop: null,
  109.  
  110. fileQueue: service(),
  111.  
  112. /**
  113. Whether users can upload content
  114. from websites by dragging images from
  115. another webpage and dropping it into
  116. your app. The default is `false` to
  117. prevent cross-site scripting issues.
  118.  
  119. @argument allowUploadsFromWebsites
  120. @type {boolean}
  121. @default false
  122. */
  123. allowUploadsFromWebsites: false,
  124.  
  125. /**
  126. This is the type of cursor that should
  127. be shown when a drag event happens.
  128.  
  129. Corresponds to `dropEffect`.
  130.  
  131. This is one of the following:
  132.  
  133. - `copy`
  134. - `move`
  135. - `link`
  136.  
  137. @argument cursor
  138. @type {string}
  139. @default null
  140. */
  141. cursor: null,
  142.  
  143. queue: computed('name', {
  144. get() {
  145. let queueName = get(this, 'name');
  146. let queues = get(this, 'fileQueue');
  147. return queues.find(queueName) ||
  148. queues.create(queueName);
  149. }
  150. }),
  151.  
  152. isAllowed() {
  153. return get(this[DATA_TRANSFER], 'source') === 'os' ||
  154. get(this, 'allowUploadsFromWebsites');
  155. },
  156.  
  157. getEventSource(evt) {
  158. let types = evt.dataTransfer.types || [];
  159. let areSomeTypesFiles = false;
  160. for (let i = 0, len = types.length; i < len; i++) {
  161. if (types[i] === 'Files' ||
  162. types[i] === 'application/x-moz-file') {
  163. areSomeTypesFiles = true;
  164. break;
  165. }
  166. }
  167. return areSomeTypesFiles ? 'os' : 'web';
  168. },
  169.  
  170. getDataTransferItemDetails(evt) {
  171. let itemDetails = [];
  172.  
  173. if (evt.dataTransfer.items){
  174. for (let i = 0; i < evt.dataTransfer.items.length; i++) {
  175. let item = evt.dataTransfer.items[i];
  176. itemDetails.push({
  177. kind: item.kind,
  178. type: item.type
  179. });
  180. }
  181. }
  182.  
  183. return itemDetails;
  184. },
  185.  
  186. dragEnter(evt) {
  187. evt.preventDefault();
  188.  
  189. let dataTransfer = DataTransfer.create({
  190. queue: get(this, 'queue'),
  191. source: this.getEventSource(evt),
  192. dataTransfer: evt.dataTransfer,
  193. itemDetails: this.getDataTransferItemDetails(evt)
  194. });
  195. this[DATA_TRANSFER] = dataTransfer;
  196.  
  197. if (this.isAllowed()) {
  198. evt.dataTransfer.dropEffect = get(this, 'cursor');
  199. set(this, 'active', true);
  200. set(this, 'valid', get(dataTransfer, 'valid'));
  201.  
  202. if (this.ondragenter) {
  203. this.ondragenter(dataTransfer);
  204. }
  205. }
  206. },
  207.  
  208. dragLeave(evt) {
  209. evt.preventDefault();
  210.  
  211. set(this[DATA_TRANSFER], 'dataTransfer', evt.dataTransfer);
  212. if (this.isAllowed()) {
  213. if (evt.dataTransfer) {
  214. evt.dataTransfer.dropEffect = get(this, 'cursor');
  215. }
  216. if (this.ondragleave) {
  217. this.ondragleave(this[DATA_TRANSFER]);
  218. this[DATA_TRANSFER] = null;
  219. }
  220.  
  221. set(this, 'active', false);
  222. }
  223. },
  224.  
  225. dragOver(evt) {
  226. evt.preventDefault();
  227. evt.stopPropagation();
  228.  
  229. set(this[DATA_TRANSFER], 'dataTransfer', evt.dataTransfer);
  230. if (this.isAllowed()) {
  231. evt.dataTransfer.dropEffect = get(this, 'cursor');
  232. }
  233. },
  234.  
  235. drop(evt) {
  236. evt.preventDefault();
  237. evt.stopPropagation();
  238.  
  239. set(this[DATA_TRANSFER], 'dataTransfer', evt.dataTransfer);
  240.  
  241. if (!this.isAllowed()) {
  242. evt.dataTransfer.dropEffect = get(this, 'cursor');
  243. this[DATA_TRANSFER] = null;
  244. return;
  245. }
  246.  
  247. // Testing support for dragging and dropping images
  248. // from other browser windows
  249. let url;
  250.  
  251. let html = this[DATA_TRANSFER].getData('text/html');
  252. if (html) {
  253. let parsedHtml = parseHTML(html);
  254. let img = parsedHtml.getElementsByTagName('img')[0];
  255. if (img) {
  256. url = img.src;
  257. }
  258. }
  259.  
  260. if (url == null) {
  261. url = this[DATA_TRANSFER].getData('text/uri-list');
  262. }
  263.  
  264. if (url) {
  265. var image = new Image();
  266. var [filename] = url.split('/').slice(-1);
  267. image.crossOrigin = 'anonymous';
  268. image.onload = () => {
  269. var canvas = document.createElement('canvas');
  270. canvas.width = image.width;
  271. canvas.height = image.height;
  272.  
  273. var ctx = canvas.getContext('2d');
  274. ctx.drawImage(image, 0, 0);
  275.  
  276. if (canvas.toBlob) {
  277. canvas.toBlob((blob) => {
  278. let [file] = get(this, 'queue')._addFiles([blob], 'web');
  279. set(file, 'name', filename);
  280. });
  281. } else {
  282. let binStr = atob(canvas.toDataURL().split(',')[1]);
  283. let len = binStr.length;
  284. let arr = new Uint8Array(len);
  285.  
  286. for (var i=0; i<len; i++ ) {
  287. arr[i] = binStr.charCodeAt(i);
  288. }
  289. let blob = new Blob([arr], { type: 'image/png' });
  290. blob.name = filename;
  291. let [file] = get(this, 'queue')._addFiles([blob], 'web');
  292. set(file, 'name', filename);
  293. }
  294. };
  295. /* eslint-disable no-console */
  296. image.onerror = function (e) {
  297. console.log(e);
  298. };
  299. /* eslint-enable no-console */
  300. image.src = url;
  301. }
  302.  
  303. if (this.ondrop) {
  304. this.ondrop(this[DATA_TRANSFER]);
  305. }
  306.  
  307. // Add file(s) to upload queue.
  308. set(this, 'active', false);
  309. get(this, 'queue')._addFiles(get(this[DATA_TRANSFER], 'files'), 'drag-and-drop');
  310. this[DATA_TRANSFER] = null;
  311. }
  312. });
Add Comment
Please, Sign In to add comment