Source: FileUpload.js

/**
                * @author Rafael Ostertag <rafael.ostertag@math.uzh.ch>
                */

                /* global $ */
                /* global EventEmitter */

                /* @depend QfqEvents.js */

                /**
                * Qfq Namespace
                *
                * @namespace QfqNS
                */
                var QfqNS = QfqNS || {};

                (function (n) {
                'use strict';

                /**
                *
                * @param formSelector
                * @param targetUrl
                * @constructor
                * @name QfqNS.FileUpload
                */
                n.FileUpload = function (formSelector, targetUrl) {
                this.formSelector = formSelector;
                this.targetUrl = targetUrl;
                this.eventEmitter = new EventEmitter();

                this.setupOnChangeHandler();
                };

                n.FileUpload.prototype.on = n.EventEmitter.onMixin;

                /**
                *
                * @private
                */
                n.FileUpload.prototype.setupOnChangeHandler = function () {
                $(this.formSelector + " :file").on('change', this.performFileUpload.bind(this));
                };

                /**
                * @private
                * @param event
                */
                n.FileUpload.prototype.performFileUpload = function (event) {
                this.eventEmitter.emitEvent('fileupload.started', n.EventEmitter.makePayload(event.target, null));

                var data = this.prepareData(event.target);

                $.ajax({
                url: this.targetUrl,
                type: 'POST',
                data: data,
                cache: false,
                processData: false,
                contentType: false
                })
                .done(this.ajaxSuccessHandler.bind(this, event.target))
                .fail(this.ajaxErrorHandler.bind(this, event.target));
                };

                n.FileUpload.prototype.prepareData = function (htmlFileInput) {
                if (!htmlFileInput.hasAttribute("name")) {
                throw new Error("File input element requires 'name' attribute");
                }

                var fileInputName = htmlFileInput.getAttribute('name');

                var data = new FormData();
                $.each(htmlFileInput.files, function (key, value) {
                data.append(fileInputName + '_' + key, value);
                });

                data.append('s', $(htmlFileInput).data('sip'));
                data.append('name', fileInputName);

                return data;
                };

                /**
                * @private
                * @param data
                * @param textStatus
                * @param jqXHR
                */

                n.FileUpload.prototype.ajaxSuccessHandler = function (uploadTriggeredBy, data, textStatus, jqXHR) {
                var eventData = n.EventEmitter.makePayload(uploadTriggeredBy, data, {
                textStatus: textStatus,
                jqXHR: jqXHR
                });
                this.eventEmitter.emitEvent('fileupload.upload.successful', eventData);
                this.eventEmitter.emitEvent('fileupload.ended', eventData);
                };

                /**
                * @private
                * @param jqXHR
                * @param textStatus
                * @param errorThrown
                */
                n.FileUpload.prototype.ajaxErrorHandler = function (uploadTriggeredBy, jqXHR, textStatus, errorThrown) {
                var eventData = n.EventEmitter.makePayload(uploadTriggeredBy, null, {
                textStatus: textStatus,
                errorThrown: errorThrown,
                jqXHR: jqXHR
                });
                this.eventEmitter.emitEvent('fileupload.upload.failed', eventData);
                this.eventEmitter.emitEvent('fileupload.ended', eventData);
                };


                })(QfqNS);