Created
July 27, 2018 07:23
-
-
Save KamiKillertO/14f4242ac8f5d65a18b22d7993411598 to your computer and use it in GitHub Desktop.
New Twiddle
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const ua = navigator.userAgent; | |
| function isIE() { | |
| return ua.indexOf('MSIE')!=-1 || ua.indexOf('Trident/') !== -1; | |
| } | |
| function getIEVersion() { | |
| const msie = ua.indexOf('MSIE '); | |
| if (msie > 0) { | |
| return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10); | |
| } | |
| const trident = ua.indexOf('Trident/'); | |
| if (trident > 0) { | |
| const rv = ua.indexOf('rv:'); | |
| return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10); | |
| } | |
| return null; | |
| } | |
| function isEdge() { | |
| return ua.indexOf('Edge/') !== -1; | |
| } | |
| function getEdgeVersion() { | |
| const edge = ua.indexOf('Edge/'); | |
| return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10); | |
| } | |
| function isChrome() { | |
| return ua.indexOf('Chrome') !== -1; | |
| } | |
| function getChromeVersion() { | |
| const version = /Chrome\/(\d+)./.exec(ua); | |
| return version !== null? parseInt(version[1], 10) : null; | |
| } | |
| function isFirefox() { | |
| return ua.indexOf('Firefox') !== -1; | |
| } | |
| function getFirefoxVersion() { | |
| const version = /Firefox\/(\d+)./.exec(ua); | |
| return version !== null? parseInt(version[1], 10) : null; | |
| } | |
| function isOpera() { | |
| return ua.indexOf('Opera') !== -1 || ua.indexOf('OPR'); | |
| } | |
| function isSafari() { | |
| return ua.indexOf('Safari') !== -1 && ua.indexOf('Chrome') === -1; | |
| } | |
| function getSafariVersion() { | |
| const version = /Version\/(\d+)./.exec(ua); | |
| return version !== null? parseInt(version[1], 10) : null; | |
| } | |
| export { isIE, getIEVersion, isEdge, getEdgeVersion, isChrome, getChromeVersion, isFirefox, getFirefoxVersion, isOpera, isSafari, getSafariVersion } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Ember from 'ember'; | |
| export default Ember.Component.extend({ | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Ember from 'ember'; | |
| export default Ember.Controller.extend({ | |
| appName: 'Ember Twiddle' | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Mixin from '@ember/object/mixin'; | |
| import $ from 'jquery'; | |
| import { get, set } from '@ember/object'; | |
| import { inject as service } from '@ember/service'; | |
| import { run } from '@ember/runloop'; | |
| import { isIE, isEdge, isSafari, getSafariVersion } from 'appaloosa-components/browser-detect'; | |
| // find a way to namespace variables | |
| // variables namespace using an object => issue (share between all mixin instance ><) | |
| // see https://dockyard.com/blog/2015/09/18/ember-best-practices-avoid-leaking-state-into-factories | |
| // maybe a mixin is not the good solution | |
| export default Mixin.create({ | |
| assetsUploader: service(), | |
| classNameBindings: ['isDragOver:drag'], | |
| /** | |
| * @property {boolean} disableDragAndDrop - Disable component dragAndDrop | |
| * @default false | |
| * @public | |
| */ | |
| disableDragAndDrop: false, | |
| /** | |
| * @property {boolean} isDragOver - Will be set to true if something is dragOver the component | |
| * @readonly // disable update in didUpdateAttrs | |
| * @default false | |
| * @public | |
| */ | |
| isDragOver: false, | |
| /** | |
| * @property {boolean} uploadDone - Will be set to true when upload is done. | |
| * @readonly // disable update in didUpdateAttrs | |
| * @default false | |
| * @public | |
| */ | |
| uploadDone: false, | |
| /** | |
| * @property {boolean} uploadStart - Will be set to true when uploadStart. | |
| * @readonly // disable update in didUpdateAttrs | |
| * @default false | |
| * @public | |
| */ | |
| // behavior when multiple files?? | |
| uploadStart: false, | |
| /** | |
| * @property {string} dropZoneSelector - You can optionally pass in a jQuery style selector string for the dragAnDrop zone | |
| * @default null | |
| * @public | |
| */ | |
| dropZoneSelector: null, | |
| /** | |
| * @property {string} acceptedMime - The mime types accepted by the input and the drag-and-drop. Use a comma between types | |
| * @default '*' | |
| * @public | |
| */ | |
| // prevent update | |
| acceptedMime: "*", | |
| __R_A_MIME: null, | |
| /** | |
| * @property {string} acceptedFileExtensions - The files extensions accepted by the input and the drag-and-drop. Use a comma between types. No need to add the dot before; | |
| * @default '' | |
| * @public | |
| */ | |
| // prevent update | |
| acceptedExtensions: '', | |
| __R_A_EXTENSIONS: null, | |
| /** | |
| * @property {boolean} inputMultiple - Input `multiple` attribute | |
| * @default true | |
| * @public | |
| */ | |
| inputMultiple: true, | |
| /** | |
| * @property {boolean} invalidFileDropped - Will be set to true if an invalid file is dropped | |
| * @default false | |
| * @public | |
| */ | |
| invalidFileDropped: false, | |
| /** | |
| * @property {File[]} processingFiles - Contain all files dropped. File contained new properties `uploadStart`, `uploadPercentage` and `uploadDone` | |
| * @default true | |
| * @public | |
| */ | |
| processingFiles: [], | |
| /** | |
| * @property {boolean} directUpload - By default files are uploaded after drop.Set it to false to disable this behavior | |
| * @default true | |
| * @public | |
| */ | |
| directUpload: true, | |
| /** | |
| * @property {function} uploadDoneAction - An ember action to trigger when the file is uploaded | |
| * @default A noop function | |
| * @public | |
| */ | |
| uploadDoneAction: () => {}, | |
| __input: null, | |
| __resetDefaultValue() { | |
| set(this, 'uploadDone', false); | |
| set(this, 'uploadStart', false); | |
| set(this, 'invalidFileDropped', false); | |
| this.__clearProcessingFiles(); | |
| }, | |
| init() { | |
| this._super(...arguments); | |
| const acceptedMime = get(this, 'acceptedMime'); | |
| const R_A_MIME = new RegExp(acceptedMime.replace(/\//g, '\\/').replace(/,/g, '|')); | |
| set(this, '__R_A_MIME', R_A_MIME); | |
| const acceptedExtensions = get(this, 'acceptedExtensions'); | |
| const R_A_EXTENSIONS = new RegExp(`\\.(${acceptedExtensions.replace(/\./g,'').replace(/,/g, '|')})$`); | |
| set(this, '__R_A_EXTENSIONS', R_A_EXTENSIONS); | |
| }, | |
| drop(event) { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| set(this, 'isDragOver', false); | |
| if (get(this, 'disableDragAndDrop') === true) { | |
| return; | |
| } | |
| const files = event.dataTransfer.files; // Array of all files | |
| if (this.canDropFiles(files) === true) { | |
| set(this, 'invalidFileDropped', true); | |
| return false; | |
| } | |
| this.__clearProcessingFiles(); | |
| // clear uploadQueue ? before? | |
| set(this, "disableDragAndDrop", true); // temporary | |
| this.__resetDefaultValue(); | |
| this.__populateUploadQueue(files); | |
| if (get(this, "directUpload")) { | |
| this.__startUpload(); | |
| } | |
| }, | |
| dragOver: function (e) { | |
| if (get(this, 'disableDragAndDrop') === true) { //find a better way to disable drag and Drop | |
| return false; | |
| } | |
| let container = this.$(get(this, 'dropZoneSelector')); | |
| if (container.is(this.$(e.target)) || container.has(this.$(e.target)).length) { | |
| e.preventDefault(e); | |
| e.stopPropagation(); | |
| // Makes it possible to drag files from chrome's download bar | |
| // http://stackoverflow.com/questions/19526430/drag-and-drop-file-uploads-from-chrome-downloads-bar | |
| // Try is required to prevent bug in Internet Explorer 11 (SCRIPT65535 exception) | |
| var efct = void 0; | |
| try { | |
| efct = e.dataTransfer.effectAllowed; | |
| } catch (error) { | |
| // | |
| } | |
| e.dataTransfer.dropEffect = ('move' === efct || 'linkMove' === efct) ? 'move' : 'copy'; | |
| set(this, 'isDragOver', true); | |
| } | |
| return false; | |
| }, | |
| dragLeave: function (event) { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| if (get(this, 'disableDragAndDrop') === true) { | |
| return; | |
| } | |
| set(this, 'isDragOver', false); | |
| }, | |
| canDropFiles(files) { | |
| if (files.length === 0) { | |
| return true; | |
| } | |
| if ( files.length > 1 && get(this, 'inputMultiple') === false) { | |
| return true; | |
| } | |
| if (this.__isAcceptedFiles(files) === false) { | |
| return true; | |
| } | |
| return false; | |
| }, | |
| /** | |
| * Check files extensions | |
| */ | |
| __isAcceptedFiles(files){ | |
| for (let i = 0; i < files.length; i++) { | |
| if (this.isMimeAccepted(files[i]) === false && this.isExtensionAccepted(files[i]) === false) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| }, | |
| isMimeAccepted(file) { | |
| return get(this, '__R_A_MIME').test(file.type); | |
| }, | |
| // in timeInit // @see didInsertElement | |
| isExtensionAccepted(file) { | |
| return get(this, '__R_A_EXTENSIONS').test(file.name); | |
| }, | |
| __populateUploadQueue(files) { | |
| const processingFiles = get(this, 'processingFiles'); | |
| for (let i = 0; i < files.length; i++) { | |
| let file = files[i]; | |
| file.localFileUri = URL.createObjectURL(file); // add a method to generate thumbnails? | |
| file.uploadStart = false; | |
| file.uploadDone = false; | |
| file.uploadPercentage = 0; | |
| processingFiles.pushObject(file); | |
| } | |
| }, | |
| __filePercentageUpdate(file, percentage) { | |
| set(file, 'uploadStart', true); | |
| set(file, 'uploadPercentage', percentage); | |
| }, | |
| __startUpload() { | |
| const processingFiles = get(this, 'processingFiles'); | |
| processingFiles.forEach(file => this.__uploadFile(file)); | |
| }, | |
| async __uploadFile(file) { | |
| set(this, 'uploadStart', true); | |
| const key = await get(this, 'assetsUploader').upload(file, this.__filePercentageUpdate.bind(this)); | |
| get(this, 'uploadDoneAction')(key, file); | |
| set(file, 'uploadDone', true); | |
| set(file, 'uploadStart', false); | |
| if (get(this, 'inputMultiple') && this.__allFilesUploaded() === true) { | |
| set(this, 'uploadDone', true); // not updating here >< | |
| set(this, 'disableDragAndDrop', false); // temporary | |
| set(this, 'uploadStart', false); | |
| } else { | |
| set(this, 'uploadDone', true); | |
| set(this, 'uploadStart', false); | |
| } | |
| }, | |
| __allFilesUploaded() { | |
| return get(this, 'processingFiles').find(file => file.uploadDone === false) === undefined; | |
| }, | |
| __clearProcessingFiles() { // should stop upload too | |
| get(this, 'processingFiles').clear(); | |
| }, | |
| __setupInput() { | |
| const input = document.createElement('input'); | |
| input.type = "file"; | |
| if (isIE() || isEdge() || (isSafari() && getSafariVersion() < 12)) { | |
| // Edge an safari does not support files extension in accept | |
| // https://caniuse.com/#feat=input-file-accept | |
| // files check will be done in the change event handler | |
| input.accept = `*`; | |
| } else { | |
| input.accept = `${get(this, 'acceptedExtensions')},${get(this, 'acceptedMime')}`; | |
| } | |
| input.multiple = get(this, 'inputMultiple'); | |
| return input; | |
| }, | |
| __inputChangeHandler({ target }) { | |
| const files = target.files; | |
| run(() => { | |
| if (this.__isAcceptedFiles(files) ===false) { | |
| set(this, 'invalidFileDropped', true); | |
| return false; | |
| } | |
| this.__clearProcessingFiles(); | |
| this.__populateUploadQueue(files); | |
| if (get(this, "directUpload")) { | |
| this.__startUpload(); | |
| } | |
| $(target).remove(); | |
| }); | |
| }, | |
| actions: { | |
| openFilePicker() { | |
| this.__resetDefaultValue(); | |
| const input = this.__setupInput(); | |
| $(input).on('change', this.__inputChangeHandler.bind(this)); | |
| $(input).trigger('click'); | |
| }, | |
| uploadFiles() { | |
| this.__startUpload(); | |
| } | |
| } | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "version": "0.15.0", | |
| "EmberENV": { | |
| "FEATURES": {} | |
| }, | |
| "options": { | |
| "use_pods": false, | |
| "enable-testing": false | |
| }, | |
| "dependencies": { | |
| "jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js", | |
| "ember": "3.2.2", | |
| "ember-template-compiler": "3.2.2", | |
| "ember-testing": "3.2.2" | |
| }, | |
| "addons": { | |
| "ember-data": "3.2.0" | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment