From 6ffd34897d1b18144946397ac7aa62d9e973fcd6 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 19 Oct 2017 07:45:52 +0000 Subject: [PATCH] Remove dropzoneInput from global namespace --- .../javascripts/blob/blob_file_dropzone.js | 3 +- app/assets/javascripts/dropzone_input.js | 536 ++++++++---------- app/assets/javascripts/gl_form.js | 4 +- app/assets/javascripts/notes.js | 3 - app/assets/javascripts/zen_mode.js | 2 - .../blob/blob_file_dropzone_spec.js | 1 - spec/javascripts/zen_mode_spec.js | 3 +- 7 files changed, 256 insertions(+), 296 deletions(-) diff --git a/app/assets/javascripts/blob/blob_file_dropzone.js b/app/assets/javascripts/blob/blob_file_dropzone.js index ddd1fea3aca..0d590a9dbc4 100644 --- a/app/assets/javascripts/blob/blob_file_dropzone.js +++ b/app/assets/javascripts/blob/blob_file_dropzone.js @@ -1,6 +1,5 @@ /* eslint-disable func-names, object-shorthand, prefer-arrow-callback */ -/* global Dropzone */ - +import Dropzone from 'dropzone'; import '../lib/utils/url_utility'; import { HIDDEN_CLASS } from '../lib/utils/constants'; import csrf from '../lib/utils/csrf'; diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js index bd45da8c422..7a17adcd44e 100644 --- a/app/assets/javascripts/dropzone_input.js +++ b/app/assets/javascripts/dropzone_input.js @@ -1,308 +1,276 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, max-len, one-var, no-var, one-var-declaration-per-line, no-unused-vars, camelcase, quotes, no-useless-concat, prefer-template, quote-props, comma-dangle, object-shorthand, consistent-return, prefer-arrow-callback */ -/* global Dropzone */ +import Dropzone from 'dropzone'; import _ from 'underscore'; import './preview_markdown'; import csrf from './lib/utils/csrf'; -window.DropzoneInput = (function() { - function DropzoneInput(form) { - const divHover = '
'; - const iconPaperclip = ''; - const $attachButton = form.find('.button-attach-file'); - const $attachingFileMessage = form.find('.attaching-file-message'); - const $cancelButton = form.find('.button-cancel-uploading-files'); - const $retryLink = form.find('.retry-uploading-link'); - const $uploadProgress = form.find('.uploading-progress'); - const $uploadingErrorContainer = form.find('.uploading-error-container'); - const $uploadingErrorMessage = form.find('.uploading-error-message'); - const $uploadingProgressContainer = form.find('.uploading-progress-container'); - const uploadsPath = window.uploads_path || null; - const maxFileSize = gon.max_file_size || 10; - const formTextarea = form.find('.js-gfm-input'); - let handlePaste; - let pasteText; - let addFileToForm; - let updateAttachingMessage; - let isImage; - let getFilename; - let uploadFile; +export default function dropzoneInput(form) { + const divHover = '
'; + const iconPaperclip = ''; + const $attachButton = form.find('.button-attach-file'); + const $attachingFileMessage = form.find('.attaching-file-message'); + const $cancelButton = form.find('.button-cancel-uploading-files'); + const $retryLink = form.find('.retry-uploading-link'); + const $uploadProgress = form.find('.uploading-progress'); + const $uploadingErrorContainer = form.find('.uploading-error-container'); + const $uploadingErrorMessage = form.find('.uploading-error-message'); + const $uploadingProgressContainer = form.find('.uploading-progress-container'); + const uploadsPath = window.uploads_path || null; + const maxFileSize = gon.max_file_size || 10; + const formTextarea = form.find('.js-gfm-input'); + let handlePaste; + let pasteText; + let addFileToForm; + let updateAttachingMessage; + let isImage; + let getFilename; + let uploadFile; - formTextarea.wrap('
'); - formTextarea.on('paste', (function(_this) { - return function(event) { - return handlePaste(event); - }; - })(this)); + formTextarea.wrap('
'); + formTextarea.on('paste', event => handlePaste(event)); - // Add dropzone area to the form. - const $mdArea = formTextarea.closest('.md-area'); - form.setupMarkdownPreview(); - const $formDropzone = form.find('.div-dropzone'); - $formDropzone.parent().addClass('div-dropzone-wrapper'); - $formDropzone.append(divHover); - $formDropzone.find('.div-dropzone-hover').append(iconPaperclip); + // Add dropzone area to the form. + const $mdArea = formTextarea.closest('.md-area'); + form.setupMarkdownPreview(); + const $formDropzone = form.find('.div-dropzone'); + $formDropzone.parent().addClass('div-dropzone-wrapper'); + $formDropzone.append(divHover); + $formDropzone.find('.div-dropzone-hover').append(iconPaperclip); - if (!uploadsPath) return; + if (!uploadsPath) return; - const dropzone = $formDropzone.dropzone({ - url: uploadsPath, - dictDefaultMessage: '', - clickable: true, - paramName: 'file', - maxFilesize: maxFileSize, - uploadMultiple: false, - headers: csrf.headers, - previewContainer: false, - processing: function() { - return $('.div-dropzone-alert').alert('close'); - }, - dragover: function() { - $mdArea.addClass('is-dropzone-hover'); - form.find('.div-dropzone-hover').css('opacity', 0.7); - }, - dragleave: function() { - $mdArea.removeClass('is-dropzone-hover'); - form.find('.div-dropzone-hover').css('opacity', 0); - }, - drop: function() { - $mdArea.removeClass('is-dropzone-hover'); - form.find('.div-dropzone-hover').css('opacity', 0); - formTextarea.focus(); - }, - success: function(header, response) { - const processingFileCount = this.getQueuedFiles().length + this.getUploadingFiles().length; - const shouldPad = processingFileCount >= 1; + const dropzone = $formDropzone.dropzone({ + url: uploadsPath, + dictDefaultMessage: '', + clickable: true, + paramName: 'file', + maxFilesize: maxFileSize, + uploadMultiple: false, + headers: csrf.headers, + previewContainer: false, + processing: () => $('.div-dropzone-alert').alert('close'), + dragover: () => { + $mdArea.addClass('is-dropzone-hover'); + form.find('.div-dropzone-hover').css('opacity', 0.7); + }, + dragleave: () => { + $mdArea.removeClass('is-dropzone-hover'); + form.find('.div-dropzone-hover').css('opacity', 0); + }, + drop: () => { + $mdArea.removeClass('is-dropzone-hover'); + form.find('.div-dropzone-hover').css('opacity', 0); + formTextarea.focus(); + }, + success(header, response) { + const processingFileCount = this.getQueuedFiles().length + this.getUploadingFiles().length; + const shouldPad = processingFileCount >= 1; - pasteText(response.link.markdown, shouldPad); - // Show 'Attach a file' link only when all files have been uploaded. - if (!processingFileCount) $attachButton.removeClass('hide'); - addFileToForm(response.link.url); - }, - error: function(file, errorMessage = 'Attaching the file failed.', xhr) { - // If 'error' event is fired by dropzone, the second parameter is error message. - // If the 'errorMessage' parameter is empty, the default error message is set. - // If the 'error' event is fired by backend (xhr) error response, the third parameter is - // xhr object (xhr.responseText is error message). - // On error we hide the 'Attach' and 'Cancel' buttons - // and show an error. + pasteText(response.link.markdown, shouldPad); + // Show 'Attach a file' link only when all files have been uploaded. + if (!processingFileCount) $attachButton.removeClass('hide'); + addFileToForm(response.link.url); + }, + error: (file, errorMessage = 'Attaching the file failed.', xhr) => { + // If 'error' event is fired by dropzone, the second parameter is error message. + // If the 'errorMessage' parameter is empty, the default error message is set. + // If the 'error' event is fired by backend (xhr) error response, the third parameter is + // xhr object (xhr.responseText is error message). + // On error we hide the 'Attach' and 'Cancel' buttons + // and show an error. - // If there's xhr error message, let's show it instead of dropzone's one. - const message = xhr ? xhr.responseText : errorMessage; + // If there's xhr error message, let's show it instead of dropzone's one. + const message = xhr ? xhr.responseText : errorMessage; - $uploadingErrorContainer.removeClass('hide'); - $uploadingErrorMessage.html(message); - $attachButton.addClass('hide'); - $cancelButton.addClass('hide'); - }, - totaluploadprogress: function(totalUploadProgress) { - updateAttachingMessage(this.files, $attachingFileMessage); - $uploadProgress.text(Math.round(totalUploadProgress) + '%'); - }, - sending: function(file) { - // DOM elements already exist. - // Instead of dynamically generating them, - // we just either hide or show them. - $attachButton.addClass('hide'); - $uploadingErrorContainer.addClass('hide'); - $uploadingProgressContainer.removeClass('hide'); - $cancelButton.removeClass('hide'); - }, - removedfile: function() { - $attachButton.removeClass('hide'); - $cancelButton.addClass('hide'); - $uploadingProgressContainer.addClass('hide'); - $uploadingErrorContainer.addClass('hide'); - }, - queuecomplete: function() { - $('.dz-preview').remove(); - $('.markdown-area').trigger('input'); - - $uploadingProgressContainer.addClass('hide'); - $cancelButton.addClass('hide'); - } - }); - - const child = $(dropzone[0]).children('textarea'); - - // removeAllFiles(true) stops uploading files (if any) - // and remove them from dropzone files queue. - $cancelButton.on('click', (e) => { - const target = e.target.closest('.js-main-target-form').querySelector('.div-dropzone'); - - e.preventDefault(); - e.stopPropagation(); - Dropzone.forElement(target).removeAllFiles(true); - }); - - // If 'error' event is fired, we store a failed files, - // clear dropzone files queue, change status of failed files to undefined, - // and add that files to the dropzone files queue again. - // addFile() adds file to dropzone files queue and upload it. - $retryLink.on('click', (e) => { - const dropzoneInstance = Dropzone.forElement(e.target.closest('.js-main-target-form').querySelector('.div-dropzone')); - const failedFiles = dropzoneInstance.files; - - e.preventDefault(); - - // 'true' parameter of removeAllFiles() cancels uploading of files that are being uploaded at the moment. - dropzoneInstance.removeAllFiles(true); - - failedFiles.map((failedFile, i) => { - const file = failedFile; - - if (file.status === Dropzone.ERROR) { - file.status = undefined; - file.accepted = undefined; - } - - return dropzoneInstance.addFile(file); - }); - }); - - handlePaste = function(event) { - var filename, image, pasteEvent, text; - pasteEvent = event.originalEvent; - if (pasteEvent.clipboardData && pasteEvent.clipboardData.items) { - image = isImage(pasteEvent); - if (image) { - event.preventDefault(); - filename = getFilename(pasteEvent) || 'image.png'; - text = `{{${filename}}}`; - pasteText(text); - return uploadFile(image.getAsFile(), filename); - } - } - }; - - isImage = function(data) { - var i, item; - i = 0; - while (i < data.clipboardData.items.length) { - item = data.clipboardData.items[i]; - if (item.type.indexOf('image') !== -1) { - return item; - } - i += 1; - } - return false; - }; - - pasteText = function(text, shouldPad) { - var afterSelection, beforeSelection, caretEnd, caretStart, textEnd; - var formattedText = text; - if (shouldPad) formattedText += "\n\n"; - const textarea = child.get(0); - caretStart = textarea.selectionStart; - caretEnd = textarea.selectionEnd; - textEnd = $(child).val().length; - beforeSelection = $(child).val().substring(0, caretStart); - afterSelection = $(child).val().substring(caretEnd, textEnd); - $(child).val(beforeSelection + formattedText + afterSelection); - textarea.setSelectionRange(caretStart + formattedText.length, caretEnd + formattedText.length); - textarea.style.height = `${textarea.scrollHeight}px`; - formTextarea.get(0).dispatchEvent(new Event('input')); - return formTextarea.trigger('input'); - }; - - addFileToForm = function(path) { - $(form).append(''); - }; - - getFilename = function(e) { - var value; - if (window.clipboardData && window.clipboardData.getData) { - value = window.clipboardData.getData('Text'); - } else if (e.clipboardData && e.clipboardData.getData) { - value = e.clipboardData.getData('text/plain'); - } - value = value.split("\r"); - return value[0]; - }; - - const showSpinner = function(e) { - return $uploadingProgressContainer.removeClass('hide'); - }; - - const closeSpinner = function() { - return $uploadingProgressContainer.addClass('hide'); - }; - - const showError = function(message) { $uploadingErrorContainer.removeClass('hide'); $uploadingErrorMessage.html(message); - }; + $attachButton.addClass('hide'); + $cancelButton.addClass('hide'); + }, + totaluploadprogress(totalUploadProgress) { + updateAttachingMessage(this.files, $attachingFileMessage); + $uploadProgress.text(`${Math.round(totalUploadProgress)}%`); + }, + sending: () => { + // DOM elements already exist. + // Instead of dynamically generating them, + // we just either hide or show them. + $attachButton.addClass('hide'); + $uploadingErrorContainer.addClass('hide'); + $uploadingProgressContainer.removeClass('hide'); + $cancelButton.removeClass('hide'); + }, + removedfile: () => { + $attachButton.removeClass('hide'); + $cancelButton.addClass('hide'); + $uploadingProgressContainer.addClass('hide'); + $uploadingErrorContainer.addClass('hide'); + }, + queuecomplete: () => { + $('.dz-preview').remove(); + $('.markdown-area').trigger('input'); - const closeAlertMessage = function() { - return form.find('.div-dropzone-alert').alert('close'); - }; + $uploadingProgressContainer.addClass('hide'); + $cancelButton.addClass('hide'); + }, + }); - const insertToTextArea = function(filename, url) { - const $child = $(child); - $child.val(function(index, val) { - return val.replace(`{{${filename}}}`, url); - }); + const child = $(dropzone[0]).children('textarea'); - $child.trigger('change'); - }; + // removeAllFiles(true) stops uploading files (if any) + // and remove them from dropzone files queue. + $cancelButton.on('click', (e) => { + const target = e.target.closest('.js-main-target-form').querySelector('.div-dropzone'); - const appendToTextArea = function(url) { - return $(child).val(function(index, val) { - return val + url + "\n"; - }); - }; + e.preventDefault(); + e.stopPropagation(); + Dropzone.forElement(target).removeAllFiles(true); + }); - uploadFile = function(item, filename) { - var formData; - formData = new FormData(); - formData.append('file', item, filename); - return $.ajax({ - url: uploadsPath, - type: 'POST', - data: formData, - dataType: 'json', - processData: false, - contentType: false, - headers: csrf.headers, - beforeSend: function() { - showSpinner(); - return closeAlertMessage(); - }, - success: function(e, textStatus, response) { - return insertToTextArea(filename, response.responseJSON.link.markdown); - }, - error: function(response) { - return showError(response.responseJSON.message); - }, - complete: function() { - return closeSpinner(); - } - }); - }; + // If 'error' event is fired, we store a failed files, + // clear dropzone files queue, change status of failed files to undefined, + // and add that files to the dropzone files queue again. + // addFile() adds file to dropzone files queue and upload it. + $retryLink.on('click', (e) => { + const dropzoneInstance = Dropzone.forElement(e.target.closest('.js-main-target-form').querySelector('.div-dropzone')); + const failedFiles = dropzoneInstance.files; - updateAttachingMessage = (files, messageContainer) => { - let attachingMessage; - const filesCount = files.filter(function(file) { - return file.status === 'uploading' || - file.status === 'queued'; - }).length; + e.preventDefault(); - // Dinamycally change uploading files text depending on files number in - // dropzone files queue. - if (filesCount > 1) { - attachingMessage = 'Attaching ' + filesCount + ' files -'; - } else { - attachingMessage = 'Attaching a file -'; + // 'true' parameter of removeAllFiles() cancels + // uploading of files that are being uploaded at the moment. + dropzoneInstance.removeAllFiles(true); + + failedFiles.map((failedFile) => { + const file = failedFile; + + if (file.status === Dropzone.ERROR) { + file.status = undefined; + file.accepted = undefined; } - messageContainer.text(attachingMessage); - }; - - form.find('.markdown-selector').click(function(e) { - e.preventDefault(); - $(this).closest('.gfm-form').find('.div-dropzone').click(); - formTextarea.focus(); + return dropzoneInstance.addFile(file); }); - } + }); + // eslint-disable-next-line consistent-return + handlePaste = (event) => { + const pasteEvent = event.originalEvent; + if (pasteEvent.clipboardData && pasteEvent.clipboardData.items) { + const image = isImage(pasteEvent); + if (image) { + event.preventDefault(); + const filename = getFilename(pasteEvent) || 'image.png'; + const text = `{{${filename}}}`; + pasteText(text); + return uploadFile(image.getAsFile(), filename); + } + } + }; - return DropzoneInput; -})(); + isImage = (data) => { + let i = 0; + while (i < data.clipboardData.items.length) { + const item = data.clipboardData.items[i]; + if (item.type.indexOf('image') !== -1) { + return item; + } + i += 1; + } + return false; + }; + + pasteText = (text, shouldPad) => { + let formattedText = text; + if (shouldPad) { + formattedText += '\n\n'; + } + const textarea = child.get(0); + const caretStart = textarea.selectionStart; + const caretEnd = textarea.selectionEnd; + const textEnd = $(child).val().length; + const beforeSelection = $(child).val().substring(0, caretStart); + const afterSelection = $(child).val().substring(caretEnd, textEnd); + $(child).val(beforeSelection + formattedText + afterSelection); + textarea.setSelectionRange(caretStart + formattedText.length, caretEnd + formattedText.length); + textarea.style.height = `${textarea.scrollHeight}px`; + formTextarea.get(0).dispatchEvent(new Event('input')); + return formTextarea.trigger('input'); + }; + + addFileToForm = (path) => { + $(form).append(``); + }; + + getFilename = (e) => { + let value; + if (window.clipboardData && window.clipboardData.getData) { + value = window.clipboardData.getData('Text'); + } else if (e.clipboardData && e.clipboardData.getData) { + value = e.clipboardData.getData('text/plain'); + } + value = value.split('\r'); + return value[0]; + }; + + const showSpinner = () => $uploadingProgressContainer.removeClass('hide'); + + const closeSpinner = () => $uploadingProgressContainer.addClass('hide'); + + const showError = (message) => { + $uploadingErrorContainer.removeClass('hide'); + $uploadingErrorMessage.html(message); + }; + + const closeAlertMessage = () => form.find('.div-dropzone-alert').alert('close'); + + const insertToTextArea = (filename, url) => { + const $child = $(child); + $child.val((index, val) => val.replace(`{{${filename}}}`, url)); + + $child.trigger('change'); + }; + + uploadFile = (item, filename) => { + const formData = new FormData(); + formData.append('file', item, filename); + return $.ajax({ + url: uploadsPath, + type: 'POST', + data: formData, + dataType: 'json', + processData: false, + contentType: false, + headers: csrf.headers, + beforeSend: () => { + showSpinner(); + return closeAlertMessage(); + }, + success: (e, text, response) => { + const md = response.responseJSON.link.markdown; + insertToTextArea(filename, md); + }, + error: response => showError(response.responseJSON.message), + complete: () => closeSpinner(), + }); + }; + + updateAttachingMessage = (files, messageContainer) => { + let attachingMessage; + const filesCount = files.filter(file => file.status === 'uploading' || file.status === 'queued').length; + + // Dinamycally change uploading files text depending on files number in + // dropzone files queue. + if (filesCount > 1) { + attachingMessage = `Attaching ${filesCount} files -`; + } else { + attachingMessage = 'Attaching a file -'; + } + + messageContainer.text(attachingMessage); + }; + + form.find('.markdown-selector').click(function onMarkdownClick(e) { + e.preventDefault(); + $(this).closest('.gfm-form').find('.div-dropzone').click(); + formTextarea.focus(); + }); +} diff --git a/app/assets/javascripts/gl_form.js b/app/assets/javascripts/gl_form.js index 48d0c12143a..48cd43d3348 100644 --- a/app/assets/javascripts/gl_form.js +++ b/app/assets/javascripts/gl_form.js @@ -1,7 +1,7 @@ -/* global DropzoneInput */ /* global autosize */ import GfmAutoComplete from './gfm_auto_complete'; +import dropzoneInput from './dropzone_input'; export default class GLForm { constructor(form, enableGFM = false) { @@ -41,7 +41,7 @@ export default class GLForm { mergeRequests: this.enableGFM, labels: this.enableGFM, }); - new DropzoneInput(this.form); // eslint-disable-line no-new + dropzoneInput(this.form); autosize(this.textarea); } // form and textarea event listeners diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 790f78d2e11..9c008da1a5d 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -13,7 +13,6 @@ import $ from 'jquery'; import _ from 'underscore'; import Cookies from 'js-cookie'; import autosize from 'vendor/autosize'; -import Dropzone from 'dropzone'; import 'vendor/jquery.caret'; // required by jquery.atwho import 'vendor/jquery.atwho'; import AjaxCache from '~/lib/utils/ajax_cache'; @@ -22,13 +21,11 @@ import CommentTypeToggle from './comment_type_toggle'; import GLForm from './gl_form'; import loadAwardsHandler from './awards_handler'; import './autosave'; -import './dropzone_input'; import TaskList from './task_list'; import { ajaxPost, isInViewport, getPagePath, scrollToElement, isMetaKey } from './lib/utils/common_utils'; import imageDiffHelper from './image_diff/helpers/index'; window.autosize = autosize; -window.Dropzone = Dropzone; function normalizeNewlines(str) { return str.replace(/\r\n/g, '\n'); diff --git a/app/assets/javascripts/zen_mode.js b/app/assets/javascripts/zen_mode.js index 99c7644e4d9..cba7b9227cd 100644 --- a/app/assets/javascripts/zen_mode.js +++ b/app/assets/javascripts/zen_mode.js @@ -11,8 +11,6 @@ import Dropzone from 'dropzone'; import 'mousetrap'; import 'mousetrap/plugins/pause/mousetrap-pause'; -window.Dropzone = Dropzone; - // // ### Events // diff --git a/spec/javascripts/blob/blob_file_dropzone_spec.js b/spec/javascripts/blob/blob_file_dropzone_spec.js index 2c8183ff77b..47de63e6690 100644 --- a/spec/javascripts/blob/blob_file_dropzone_spec.js +++ b/spec/javascripts/blob/blob_file_dropzone_spec.js @@ -1,4 +1,3 @@ -import 'dropzone'; import BlobFileDropzone from '~/blob/blob_file_dropzone'; describe('BlobFileDropzone', () => { diff --git a/spec/javascripts/zen_mode_spec.js b/spec/javascripts/zen_mode_spec.js index bd18f79cea7..7047053d131 100644 --- a/spec/javascripts/zen_mode_spec.js +++ b/spec/javascripts/zen_mode_spec.js @@ -1,7 +1,6 @@ /* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, object-shorthand, comma-dangle, no-return-assign, new-cap, max-len */ -/* global Dropzone */ /* global Mousetrap */ - +import Dropzone from 'dropzone'; import ZenMode from '~/zen_mode'; (function() {