static/js/common/upload-base.js (89 lines of code) (raw):

import $ from 'jquery'; import { _pd } from '../lib/prevent-default'; import { formatFileSize } from '../zamboni/global'; import { format } from '../lib/format'; import { CustomFormData } from '../zamboni/form-data'; /* This abstracts the uploading of all files. Currently, it's only * extended by addonUploader(). Eventually imageUploader() should as well */ function getErrors(results) { return results.errors; } let settings = { filetypes: [], getErrors: getErrors, cancel: $(), maxSize: null, }; $.fn.fileUploader = function (options) { return $(this).each(function () { let $upload_field = $(this), formData = false, errors = false, aborted = false; if (options) { $.extend(settings, options); } $upload_field.on('change', uploaderStart); $(settings.cancel).click( _pd(function () { $upload_field.trigger('upload_action_abort'); }), ); function uploaderStart() { if ($upload_field[0].files.length === 0) { return; } let domfile = $upload_field[0].files[0], url = $upload_field.attr('data-upload-url'), csrf = $('input[name=csrfmiddlewaretoken]').val(), file = { name: domfile.name || domfile.fileName, size: domfile.size, type: domfile.type, }; formData = new CustomFormData(); aborted = false; $upload_field.trigger('upload_start', [file]); /* Disable uploading while something is uploading */ $upload_field.prop('disabled', true); $upload_field.parent().find('a').addClass('disabled'); $upload_field.on('reenable_uploader', function () { $upload_field.prop('disabled', false); $upload_field.parent().find('a').removeClass('disabled'); }); let exts = new RegExp('\\.(' + settings.filetypes.join('|') + ')$', 'i'); if (!file.name.match(exts)) { errors = [gettext("The filetype you uploaded isn't recognized.")]; $upload_field.trigger('upload_errors', [file, errors]); $upload_field.trigger('upload_finished', [file]); return; } if (settings.maxSize && domfile.size > settings.maxSize) { errors = [ format(gettext('Your file exceeds the maximum size of {0}.'), [ formatFileSize(settings.maxSize), ]), ]; $upload_field.trigger('upload_errors', [file, errors]); $upload_field.trigger('upload_finished', [file]); return; } // We should be good to go! formData.open('POST', url, true); formData.append('csrfmiddlewaretoken', csrf); if (options.appendFormData) { options.appendFormData(formData); } if (domfile instanceof File) { // Needed b/c of tests. formData.append('upload', domfile); } $upload_field .off('upload_action_abort') .on('upload_action_abort', function () { aborted = true; formData.xhr.abort(); errors = [gettext('You cancelled the upload.')]; $upload_field.trigger('upload_errors', [file, errors]); $upload_field.trigger('upload_finished', [file]); }); formData.xhr.upload.addEventListener( 'progress', function (e) { if (e.lengthComputable) { let pct = Math.round((e.loaded * 100) / e.total); $upload_field.trigger('upload_progress', [file, pct]); } }, false, ); formData.xhr.onreadystatechange = function () { $upload_field.trigger('upload_onreadystatechange', [ file, formData.xhr, aborted, ]); }; formData.send(); } }); };