From c7d2d8cbffc0c014a7bb2ed9ee0d463c00dbe832 Mon Sep 17 00:00:00 2001
From: lore-w <metro-cpu@hotmail.com>
Date: Wed, 9 Dec 2015 15:07:37 +0800
Subject: [PATCH] uploadfive修改

---
 static/js/me/jquery.upload.js      | 874 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 static/js/me/jquery.uploadifive.js | 874 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 static/js/me/suggest.js            |   4 ++--
 3 files changed, 876 insertions(+), 876 deletions(-)
 create mode 100644 static/js/me/jquery.upload.js
 delete mode 100644 static/js/me/jquery.uploadifive.js

diff --git a/static/js/me/jquery.upload.js b/static/js/me/jquery.upload.js
new file mode 100644
index 0000000..89865f7
--- /dev/null
+++ b/static/js/me/jquery.upload.js
@@ -0,0 +1,874 @@
+/*
+UploadiFive 1.2.2
+Copyright (c) 2012 Reactive Apps, Ronnie Garcia
+Released under the UploadiFive Standard License <http://www.uploadify.com/uploadifive-standard-license>
+*/
+
+var jQuery = require('jquery');
+
+;(function($) {
+
+    var methods = {
+
+        init : function(options) {
+            
+            return this.each(function() {
+
+                // Create a reference to the jQuery DOM object
+                var $this = $(this);
+                    $this.data('uploadifive', {
+                        inputs     : {}, // The object that contains all the file inputs
+                        inputCount : 0,  // The total number of file inputs created
+                        fileID     : 0,
+                        queue      : {
+                                         count      : 0, // Total number of files in the queue
+                                         selected   : 0, // Number of files selected in the last select operation
+                                         replaced   : 0, // Number of files replaced in the last select operation
+                                         errors     : 0, // Number of files that returned an error in the last select operation
+                                         queued     : 0, // Number of files added to the queue in the last select operation
+                                         cancelled  : 0  // Total number of files that have been cancelled or removed from the queue
+                                     },
+                        uploads    : {
+                                         current    : 0, // Number of files currently being uploaded
+                                         attempts   : 0, // Number of file uploads attempted in the last upload operation
+                                         successful : 0, // Number of files successfully uploaded in the last upload operation
+                                         errors     : 0, // Number of files returning errors in the last upload operation
+                                         count      : 0  // Total number of files uploaded successfully
+                                     }
+                    });
+                var $data = $this.data('uploadifive');
+
+                // Set the default options
+                var settings = $data.settings = $.extend({
+                    'auto'            : true,               // Automatically upload a file when it's added to the queue
+                    'buttonClass'     : false,              // A class to add to the UploadiFive button
+                    'buttonText'      : 'Select Files',     // The text that appears on the UploadiFive button
+                    'checkScript'     : false,              // Path to the script that checks for existing file names 
+                    'dnd'             : true,               // Allow drag and drop into the queue
+                    'dropTarget'      : false,              // Selector for the drop target
+                    'fileObjName'     : 'Filedata',         // The name of the file object to use in your server-side script
+                    'fileSizeLimit'   : 0,                  // Maximum allowed size of files to upload
+                    'fileType'        : false,              // Type of files allowed (image, etc), separate with a pipe character |
+                    'formData'        : {},                 // Additional data to send to the upload script
+                    'height'          : 30,                 // The height of the button
+                    'itemTemplate'    : false,              // The HTML markup for the item in the queue
+                    'method'          : 'post',             // The method to use when submitting the upload
+                    'multi'           : true,               // Set to true to allow multiple file selections
+                    'overrideEvents'  : [],                 // An array of events to override
+                    'queueID'         : false,              // The ID of the file queue
+                    'queueSizeLimit'  : 0,                  // The maximum number of files that can be in the queue
+                    'removeCompleted' : false,              // Set to true to remove files that have completed uploading
+                    'simUploadLimit'  : 0,                  // The maximum number of files to upload at once
+                    'truncateLength'  : 0,                  // The length to truncate the file names to
+                    'uploadLimit'     : 0,                  // The maximum number of files you can upload
+                    'uploadScript'    : 'uploadifive.php',  // The path to the upload script
+                    'width'           : 100                 // The width of the button
+
+                    /*
+                    // Events
+                    'onAddQueueItem'   : function(file) {},                        // Triggered for each file that is added to the queue
+                    'onCancel'         : function(file) {},                        // Triggered when a file is cancelled or removed from the queue
+                    'onCheck'          : function(file, exists) {},                // Triggered when the server is checked for an existing file
+                    'onClearQueue'     : function(queue) {},                       // Triggered during the clearQueue function
+                    'onDestroy'        : function() {}                             // Triggered during the destroy function
+                    'onDrop'           : function(files, numberOfFilesDropped) {}, // Triggered when files are dropped into the file queue
+                    'onError'          : function(file, fileType, data) {},        // Triggered when an error occurs
+                    'onFallback'       : function() {},                            // Triggered if the HTML5 File API is not supported by the browser
+                    'onInit'           : function() {},                            // Triggered when UploadiFive if initialized
+                    'onQueueComplete'  : function() {},                            // Triggered once when an upload queue is done
+                    'onProgress'       : function(file, event) {},                 // Triggered during each progress update of an upload
+                    'onSelect'         : function() {},                            // Triggered once when files are selected from a dialog box
+                    'onUpload'         : function(file) {},                        // Triggered when an upload queue is started
+                    'onUploadComplete' : function(file, data) {},                  // Triggered when a file is successfully uploaded
+                    'onUploadFile'     : function(file) {},                        // Triggered for each file being uploaded
+                    */
+                }, options);
+
+                // Calculate the file size limit
+                if (isNaN(settings.fileSizeLimit)) {
+                    var fileSizeLimitBytes = parseInt(settings.fileSizeLimit) * 1.024
+                    if (settings.fileSizeLimit.indexOf('KB') > -1) {
+                        settings.fileSizeLimit = fileSizeLimitBytes * 1000;
+                    } else if (settings.fileSizeLimit.indexOf('MB') > -1) {
+                        settings.fileSizeLimit = fileSizeLimitBytes * 1000000;
+                    } else if (settings.fileSizeLimit.indexOf('GB') > -1) {
+                        settings.fileSizeLimit = fileSizeLimitBytes * 1000000000;
+                    }
+                } else {
+                    settings.fileSizeLimit = settings.fileSizeLimit * 1024;
+                }
+
+                // Create a template for a file input
+                $data.inputTemplate = $('<input type="file">')
+                .css({
+                    'font-size' : settings.height + 'px',
+                    'opacity'   : 0,
+                    'position'  : 'absolute',
+                    'right'     : '-3px',
+                    'top'       : '-3px',
+                    'z-index'   : 999 
+                });
+
+                // Create a new input
+                $data.createInput = function() {
+
+                    // Create a clone of the file input
+                    var input     = $data.inputTemplate.clone();
+                    // Create a unique name for the input item
+                    var inputName = input.name = 'input' + $data.inputCount++;
+                    // Set the multiple attribute
+                    if (settings.multi) {
+                        input.attr('multiple', true);
+                    }
+                    // Set the accept attribute on the input
+                    if (settings.fileType) {
+                        input.attr('accept', settings.fileType);
+                    }
+                    // Set the onchange event for the input
+                    input.bind('change', function() {
+                        $data.queue.selected = 0;
+                        $data.queue.replaced = 0;
+                        $data.queue.errors   = 0;
+                        $data.queue.queued   = 0;
+                        // Add a queue item to the queue for each file
+                        var limit = this.files.length;
+                        $data.queue.selected = limit;
+                        if (($data.queue.count + limit) > settings.queueSizeLimit && settings.queueSizeLimit !== 0) {
+                            if ($.inArray('onError', settings.overrideEvents) < 0) {
+                                alert('The maximum number of queue items has been reached (' + settings.queueSizeLimit + ').  Please select fewer files.');
+                            }
+                            // Trigger the error event
+                            if (typeof settings.onError === 'function') {
+                                settings.onError.call($this, 'QUEUE_LIMIT_EXCEEDED');
+                            }
+                        } else {
+                            for (var n = 0; n < limit; n++) {
+                                file = this.files[n];
+                                $data.addQueueItem(file);
+                            }
+                            $data.inputs[inputName] = this;
+                            $data.createInput();
+                        }
+                        // Upload the file if auto-uploads are enabled
+                        if (settings.auto) {
+                            methods.upload.call($this);
+                        }
+                        // Trigger the select event
+                        if (typeof settings.onSelect === 'function') {
+                            settings.onSelect.call($this, $data.queue);
+                        }
+                    });
+                    // Hide the existing current item and add the new one
+                    if ($data.currentInput) {
+                        $data.currentInput.hide();
+                    }
+                    $data.button.append(input);
+                    $data.currentInput = input;
+                }
+
+                // Remove an input
+                $data.destroyInput = function(key) {
+                    $($data.inputs[key]).remove();
+                    delete $data.inputs[key];
+                    $data.inputCount--;
+                }
+
+                // Drop a file into the queue
+                $data.drop = function(e) {
+                    $data.queue.selected = 0;
+                    $data.queue.replaced = 0;
+                    $data.queue.errors   = 0;
+                    $data.queue.queued   = 0;
+
+                    var fileData = e.dataTransfer;
+
+                    var inputName = fileData.name = 'input' + $data.inputCount++;
+                    // Add a queue item to the queue for each file
+                    var limit = fileData.files.length;
+                    $data.queue.selected = limit;
+                    if (($data.queue.count + limit) > settings.queueSizeLimit && settings.queueSizeLimit !== 0) {
+                        // Check if the queueSizeLimit was reached
+                        if ($.inArray('onError', settings.overrideEvents) < 0) {
+                            alert('The maximum number of queue items has been reached (' + settings.queueSizeLimit + ').  Please select fewer files.');
+                        }
+                        // Trigger the onError event
+                        if (typeof settings.onError === 'function') {
+                            settings.onError.call($this, 'QUEUE_LIMIT_EXCEEDED');
+                        }
+                    } else {
+                        // Add a queue item for each file
+                        for (var n = 0; n < limit; n++) {
+                            file = fileData.files[n];
+                            $data.addQueueItem(file);
+                        }
+                        // Save the data to the inputs object
+                        $data.inputs[inputName] = fileData;
+                    }
+
+                    // Upload the file if auto-uploads are enabled
+                    if (settings.auto) {
+                        methods.upload.call($this);
+                    }
+
+                    // Trigger the onDrop event
+                    if (typeof settings.onDrop === 'function') {
+                        settings.onDrop.call($this, fileData.files, fileData.files.length);
+                    }
+
+                    // Stop FireFox from opening the dropped file(s)
+                    e.preventDefault();
+                    e.stopPropagation();
+                }
+
+                // Check if a filename exists in the queue
+                $data.fileExistsInQueue = function(file) {
+                    for (var key in $data.inputs) {
+                        input = $data.inputs[key];
+                        limit = input.files.length;
+                        for (var n = 0; n < limit; n++) {
+                            existingFile = input.files[n];
+                            // Check if the filename matches
+                            if (existingFile.name == file.name && !existingFile.complete) {
+                                return true;
+                            }
+                        }
+                    }
+                    return false;
+                }
+
+                // Remove an existing file in the queue
+                $data.removeExistingFile = function(file) {
+                    for (var key in $data.inputs) {
+                        input = $data.inputs[key];
+                        limit = input.files.length;
+                        for (var n = 0; n < limit; n++) {
+                            existingFile = input.files[n];
+                            // Check if the filename matches
+                            if (existingFile.name == file.name && !existingFile.complete) {
+                                $data.queue.replaced++;
+                                methods.cancel.call($this, existingFile, true);
+                            }
+                        }
+                    }
+                }
+
+                // Create the file item template
+                if (settings.itemTemplate == false) {
+                    $data.queueItem = $('<div class="uploadifive-queue-item">\
+                        <a class="close" href="#">X</a>\
+                        <div><span class="filename"></span><span class="fileinfo"></span></div>\
+                        <div class="progress">\
+                            <div class="progress-bar"></div>\
+                        </div>\
+                    </div>');
+                } else {
+                    $data.queueItem = $(settings.itemTemplate);
+                }
+
+                // Add an item to the queue
+                $data.addQueueItem = function(file) {
+                    if ($.inArray('onAddQueueItem', settings.overrideEvents) < 0) {
+                        // Check if the filename already exists in the queue
+                        $data.removeExistingFile(file);
+                        // Create a clone of the queue item template
+                        file.queueItem = $data.queueItem.clone();
+                        // Add an ID to the queue item
+                        file.queueItem.attr('id', settings.id + '-file-' + $data.fileID++);
+                        // Bind the close event to the close button
+                        file.queueItem.find('.close').bind('click', function() {
+                           methods.cancel.call($this, file);
+                           return false;
+                        });
+                        var fileName = file.name;
+                        if (fileName.length > settings.truncateLength && settings.truncateLength != 0) {
+                            fileName = fileName.substring(0, settings.truncateLength) + '...';
+                        }
+                        file.queueItem.find('.filename').html(fileName);
+                        // Add a reference to the file
+                        file.queueItem.data('file', file);
+                        $data.queueEl.append(file.queueItem);
+                    }
+                    // Trigger the addQueueItem event
+                    if (typeof settings.onAddQueueItem === 'function') {
+                        settings.onAddQueueItem.call($this, file);
+                    }
+                    // Check the filesize
+                    if (file.size > settings.fileSizeLimit && settings.fileSizeLimit != 0) {
+                        $data.error('FILE_SIZE_LIMIT_EXCEEDED', file);
+                    } else {
+                        $data.queue.queued++;
+                        $data.queue.count++;
+                    }
+                }
+
+                // Remove an item from the queue
+                $data.removeQueueItem = function(file, instant, delay) {
+                    // Set the default delay
+                    if (!delay) delay = 0;
+                    var fadeTime = instant ? 0 : 500;
+                    if (file.queueItem) {
+                        if (file.queueItem.find('.fileinfo').html() != ' - Completed') {
+                            file.queueItem.find('.fileinfo').html(' - Cancelled');
+                        }
+                        file.queueItem.find('.progress-bar').width(0);
+                        file.queueItem.delay(delay).fadeOut(fadeTime, function() {
+                           $(this).remove();
+                        });
+                        delete file.queueItem;
+                        $data.queue.count--;
+                    }
+                }
+
+                // Count the number of files that need to be uploaded
+                $data.filesToUpload = function() {
+                    var filesToUpload = 0;
+                    for (var key in $data.inputs) {
+                        input = $data.inputs[key];
+                        limit = input.files.length;
+                        for (var n = 0; n < limit; n++) {
+                            file = input.files[n];
+                            if (!file.skip && !file.complete) {
+                                filesToUpload++;
+                            }
+                        }
+                    }
+                    return filesToUpload;
+                }
+
+                // Check if a file exists
+                $data.checkExists = function(file) {
+                    if ($.inArray('onCheck', settings.overrideEvents) < 0) {
+                        // This request needs to be synchronous
+                        $.ajaxSetup({
+                            'async' : false
+                        });
+                        // Send the filename to the check script
+                        var checkData = $.extend(settings.formData, {filename: file.name});
+                        $.post(settings.checkScript, checkData, function(fileExists) {
+                            file.exists = parseInt(fileExists);
+                        });
+                        if (file.exists) {
+                            if (!confirm('A file named ' + file.name + ' already exists in the upload folder.\nWould you like to replace it?')) {
+                                // If not replacing the file, cancel the upload
+                                methods.cancel.call($this, file);
+                                return true;
+                            }
+                        }
+                    }
+                    // Trigger the check event
+                    if (typeof settings.onCheck === 'function') {
+                        settings.onCheck.call($this, file, file.exists);
+                    }
+                    return false;
+                }
+
+                // Upload a single file
+                $data.uploadFile = function(file, uploadAll) {
+                    if (!file.skip && !file.complete && !file.uploading) {
+                        file.uploading = true;
+                        $data.uploads.current++;
+                        $data.uploads.attempted++;
+
+                        // Create a new AJAX request
+                        xhr = file.xhr = new XMLHttpRequest();
+
+                        // Start the upload
+                        // Use the faster FormData if it exists
+                        if (typeof FormData === 'function' || typeof FormData === 'object') {
+
+                            // Create a new FormData object
+                            var formData = new FormData();
+
+                            // Add the form data
+                            formData.append(settings.fileObjName, file);
+
+                            // Add the rest of the formData
+                            for (i in settings.formData) {
+                                formData.append(i, settings.formData[i]);
+                            }
+
+                            // Open the AJAX call
+                            xhr.open(settings.method, settings.uploadScript, true);
+
+                            // On progress function
+                            xhr.upload.addEventListener('progress', function(e) {
+                                if (e.lengthComputable) {
+                                    $data.progress(e, file);
+                                }
+                            }, false);
+
+                            // On complete function
+                            xhr.addEventListener('load', function(e) {
+                                if (this.readyState == 4) {
+                                    file.uploading = false;
+                                    if (this.status == 200) {
+                                        if (file.xhr.responseText !== 'Invalid file type.') {
+                                            $data.uploadComplete(e, file, uploadAll);
+                                        } else {
+                                            $data.error(file.xhr.responseText, file, uploadAll);
+                                        }
+                                    } else if (this.status == 404) {
+                                        $data.error('404_FILE_NOT_FOUND', file, uploadAll);
+                                    } else if (this.status == 403) {
+                                        $data.error('403_FORBIDDEN', file, uploadAll);
+                                    } else {
+                                        $data.error('Unknown Error', file, uploadAll);
+                                    }
+                                }
+                            });
+
+                            // Send the form data (multipart/form-data)
+                            xhr.send(formData);
+
+                        } else {
+
+                            // Send as binary
+                            var reader = new FileReader();
+                            reader.onload = function(e) {
+
+                                // Set some file builder variables
+                                var boundary = '-------------------------' + (new Date).getTime(),
+                                    dashes   = '--',
+                                    eol      = '\r\n',
+                                    binFile  = '';
+
+                                // Build an RFC2388 String 
+                                binFile += dashes + boundary + eol;
+                                // Generate the headers
+                                binFile += 'Content-Disposition: form-data; name="' + settings.fileObjName + '"';
+                                if (file.name) {
+                                    binFile += '; filename="' + file.name + '"';
+                                }
+                                binFile += eol;
+                                binFile += 'Content-Type: application/octet-stream' + eol + eol;
+                                binFile += e.target.result + eol;
+
+                                for (key in settings.formData) {
+                                    binFile += dashes + boundary + eol;
+                                    binFile += 'Content-Disposition: form-data; name="' + key + '"' + eol + eol;
+                                    binFile += settings.formData[key] + eol;
+                                }
+
+                                binFile += dashes + boundary + dashes + eol;
+
+                                // On progress function
+                                xhr.upload.addEventListener('progress', function(e) {
+                                    $data.progress(e, file);
+                                }, false);
+
+                                // On complete function
+                                xhr.addEventListener('load', function(e) {
+                                    file.uploading = false;
+                                    var status = this.status;
+                                    if (status == 404) {
+                                        $data.error('404_FILE_NOT_FOUND', file, uploadAll);
+                                    } else {
+                                        if (file.xhr.responseText != 'Invalid file type.') {    
+                                            $data.uploadComplete(e, file, uploadAll);
+                                        } else {
+                                            $data.error(file.xhr.responseText, file, uploadAll);
+                                        } 
+                                    }
+                                }, false);
+
+                                // Open the ajax request
+                                var url = settings.uploadScript;
+                                if (settings.method == 'get') {
+                                    var params = $(settings.formData).param();
+                                    url += params;
+                                }
+                                xhr.open(settings.method, settings.uploadScript, true);
+                                xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
+
+                                // Trigger the uploadFile event
+                                if (typeof settings.onUploadFile === 'function') {
+                                    settings.onUploadFile.call($this, file);
+                                }
+
+                                // Send the file for upload
+                                xhr.sendAsBinary(binFile);
+                            }
+                            reader.readAsBinaryString(file);
+
+                        }
+                    }
+                }
+
+                // Update a file upload's progress
+                $data.progress = function(e, file) {
+                    if ($.inArray('onProgress', settings.overrideEvents) < 0) {
+                        if (e.lengthComputable) {
+                            var percent = Math.round((e.loaded / e.total) * 100);
+                        }
+                        file.queueItem.find('.fileinfo').html(' - ' + percent + '%');
+                        file.queueItem.find('.progress-bar').css('width', percent + '%');
+                    }
+                    // Trigger the progress event
+                    if (typeof settings.onProgress === 'function') {
+                        settings.onProgress.call($this, file, e);
+                    }
+                }
+
+                // Trigger an error
+                $data.error = function(errorType, file, uploadAll) {
+                    if ($.inArray('onError', settings.overrideEvents) < 0) {
+                        // Get the error message
+                        switch(errorType) {
+                            case '404_FILE_NOT_FOUND':
+                                errorMsg = '404 Error';
+                                break;
+                            case '403_FORBIDDEN':
+                                errorMsg = '403 Forbidden';
+                                break;
+                            case 'FORBIDDEN_FILE_TYPE':
+                                errorMsg = 'Forbidden File Type';
+                                break;
+                            case 'FILE_SIZE_LIMIT_EXCEEDED':
+                                errorMsg = 'File Too Large';
+                                break;
+                            default:
+                                errorMsg = 'Unknown Error';
+                                break;
+                        }
+
+                        // Add the error class to the queue item
+                        file.queueItem.addClass('error')
+                        // Output the error in the queue item
+                        .find('.fileinfo').html(' - ' + errorMsg);
+                        // Hide the 
+                        file.queueItem.find('.progress').remove();
+                    }
+                    // Trigger the error event
+                    if (typeof settings.onError === 'function') {
+                        settings.onError.call($this, errorType, file);
+                    }
+                    file.skip = true;
+                    if (errorType == '404_FILE_NOT_FOUND') {
+                        $data.uploads.errors++;
+                    } else {
+                        $data.queue.errors++;
+                    }
+                    if (uploadAll) {
+                        methods.upload.call($this, null, true);
+                    }
+                }
+
+                // Trigger when a single file upload is complete
+                $data.uploadComplete = function(e, file, uploadAll) {
+                    if ($.inArray('onUploadComplete', settings.overrideEvents) < 0) {
+                        file.queueItem.find('.progress-bar').css('width', '100%');
+                        file.queueItem.find('.fileinfo').html(' - Completed');
+                        file.queueItem.find('.progress').slideUp(250);
+                        file.queueItem.addClass('complete');
+                    }
+                    // Trigger the complete event
+                    if (typeof settings.onUploadComplete === 'function') {
+                        settings.onUploadComplete.call($this, file, file.xhr.responseText);
+                    }
+                    if (settings.removeCompleted) {
+                        setTimeout(function() { methods.cancel.call($this, file); }, 3000);
+                    }
+                    file.complete = true;
+                    $data.uploads.successful++;
+                    $data.uploads.count++;
+                    $data.uploads.current--;
+                    delete file.xhr;
+                    if (uploadAll) {
+                        methods.upload.call($this, null, true);
+                    }
+                }
+
+                // Trigger when all the files are done uploading
+                $data.queueComplete = function() {
+                    // Trigger the queueComplete event
+                    if (typeof settings.onQueueComplete === 'function') {
+                        settings.onQueueComplete.call($this, $data.uploads);
+                    }
+                }
+
+                // ----------------------
+                // Initialize UploadiFive
+                // ----------------------
+
+                // Check if HTML5 is available
+                if (window.File && window.FileList && window.Blob && (window.FileReader || window.FormData)) {
+                    // Assign an ID to the object
+                    settings.id = 'uploadifive-' + $this.attr('id');
+
+                    // Wrap the file input in a div with overflow set to hidden
+                    $data.button = $('<div id="' + settings.id + '" class="uploadifive-button">' + settings.buttonText + '</div>');
+                    if (settings.buttonClass) $data.button.addClass(settings.buttonClass);
+
+                    // Style the button wrapper
+                    $data.button.css({
+                        'height'      : settings.height,
+                        'line-height' : settings.height + 'px', 
+                        'overflow'    : 'hidden',
+                        'position'    : 'relative',
+                        'text-align'  : 'center', 
+                        'width'       : settings.width
+                    });
+
+                    // Insert the button above the file input
+                    $this.before($data.button)
+                    // Add the file input to the button
+                    .appendTo($data.button)
+                    // Modify the styles of the file input
+                    .hide();
+
+                    // Create a new input
+                    $data.createInput.call($this);
+
+                    // Create the queue container
+                    if (!settings.queueID) {
+                        settings.queueID = settings.id + '-queue';
+                        $data.queueEl = $('<div id="' + settings.queueID + '" class="uploadifive-queue" />');
+                        $data.button.after($data.queueEl);
+                    } else {
+                        $data.queueEl = $('#' + settings.queueID);
+                    }
+
+                    // Add drag and drop functionality
+                    if (settings.dnd) {
+                        var $dropTarget = settings.dropTarget ? $(settings.dropTarget) : $data.queueEl.get(0);
+                        $dropTarget.addEventListener('dragleave', function(e) {
+                            // Stop FireFox from opening the dropped file(s)
+                            e.preventDefault();
+                            e.stopPropagation();
+                        }, false);
+                        $dropTarget.addEventListener('dragenter', function(e) {
+                            // Stop FireFox from opening the dropped file(s)
+                            e.preventDefault();
+                            e.stopPropagation();
+                        }, false);
+                        $dropTarget.addEventListener('dragover', function(e) {
+                            // Stop FireFox from opening the dropped file(s)
+                            e.preventDefault();
+                            e.stopPropagation();
+                        }, false);
+                        $dropTarget.addEventListener('drop', $data.drop, false);
+                    }
+
+                    // Send as binary workaround for Chrome
+                    if (!XMLHttpRequest.prototype.sendAsBinary) {
+                        XMLHttpRequest.prototype.sendAsBinary = function(datastr) {
+                            function byteValue(x) {
+                                return x.charCodeAt(0) & 0xff;
+                            }
+                            var ords = Array.prototype.map.call(datastr, byteValue);
+                            var ui8a = new Uint8Array(ords);
+                            this.send(ui8a.buffer);
+                        }
+                    }
+
+                    // Trigger the oninit event
+                    if (typeof settings.onInit === 'function') {
+                        settings.onInit.call($this);
+                    }
+
+                } else {
+
+                    // Trigger the fallback event
+                    if (typeof settings.onFallback === 'function') {
+                        settings.onFallback.call($this);
+                    }
+                    return false;
+
+                }
+
+            });
+
+        },
+
+
+        // Write some data to the console
+        debug : function() {
+
+            return this.each(function() {
+
+                console.log($(this).data('uploadifive'));
+
+            });
+
+        },
+
+        // Clear all the items from the queue
+        clearQueue : function() {
+
+            this.each(function() {
+
+                var $this    = $(this),
+                    $data    = $this.data('uploadifive'),
+                    settings = $data.settings;
+
+                for (var key in $data.inputs) {
+                    input = $data.inputs[key];
+                    limit = input.files.length;
+                    for (i = 0; i < limit; i++) {
+                        file = input.files[i];
+                        methods.cancel.call($this, file);
+                    }
+                }
+                // Trigger the onClearQueue event
+                if (typeof settings.onClearQueue === 'function') {
+                    settings.onClearQueue.call($this, $('#' + $data.settings.queueID));
+                }
+
+            });
+
+        },
+
+        // Cancel a file upload in progress or remove a file from the queue
+        cancel : function(file, fast) {
+
+            this.each(function() {
+
+                var $this    = $(this),
+                    $data    = $this.data('uploadifive'),
+                    settings = $data.settings;
+
+                // If user passed a queue item ID instead of file...
+                if (typeof file === 'string') {
+                    if (!isNaN(file)) {
+                        fileID = 'uploadifive-' + $(this).attr('id') + '-file-' + file;
+                    }
+                    file = $('#' + fileID).data('file');
+                }
+
+                file.skip = true;
+                $data.filesCancelled++;
+                if (file.uploading) {
+                    $data.uploads.current--;
+                    file.uploading = false;
+                    file.xhr.abort();
+                    delete file.xhr;
+                    methods.upload.call($this);
+                }
+                if ($.inArray('onCancel', settings.overrideEvents) < 0) {
+                    $data.removeQueueItem(file, fast);
+                }
+
+                // Trigger the cancel event
+                if (typeof settings.onCancel === 'function') {
+                    settings.onCancel.call($this, file);
+                }
+                
+            });
+            
+        },
+
+        // Upload the files in the queue
+        upload : function(file, keepVars) {
+
+            this.each(function() {
+
+                var $this    = $(this),
+                    $data    = $this.data('uploadifive'),
+                    settings = $data.settings;
+
+                if (file) {
+
+                    $data.uploadFile.call($this, file);
+
+                } else {
+
+                    // Check if the upload limit was reached
+                    if (($data.uploads.count + $data.uploads.current) < settings.uploadLimit || settings.uploadLimit == 0) {
+                        if (!keepVars) {
+                            $data.uploads.attempted   = 0;
+                            $data.uploads.successsful = 0;
+                            $data.uploads.errors      = 0;
+                            var filesToUpload = $data.filesToUpload();
+                            // Trigger the onUpload event
+                            if (typeof settings.onUpload === 'function') {
+                                settings.onUpload.call($this, filesToUpload);
+                            }
+                        }
+
+                        // Loop through the files
+                        $('#' + settings.queueID).find('.uploadifive-queue-item').not('.error, .complete').each(function() {
+                            _file = $(this).data('file');
+                            // Check if the simUpload limit was reached
+                            if (($data.uploads.current >= settings.simUploadLimit && settings.simUploadLimit !== 0) || ($data.uploads.current >= settings.uploadLimit && settings.uploadLimit !== 0) || ($data.uploads.count >= settings.uploadLimit && settings.uploadLimit !== 0)) {
+                                return false;
+                            }
+                            if (settings.checkScript) {
+                                // Let the loop know that we're already processing this file
+                                _file.checking = true;
+                                skipFile = $data.checkExists(_file);
+                                _file.checking = false;
+                                if (!skipFile) {
+                                    $data.uploadFile(_file, true);
+                                }
+                            } else {
+                                $data.uploadFile(_file, true);
+                            }
+                        });
+                        if ($('#' + settings.queueID).find('.uploadifive-queue-item').not('.error, .complete').size() == 0) {
+                            $data.queueComplete();
+                        }
+                    } else {
+                        if ($data.uploads.current == 0) {
+                            if ($.inArray('onError', settings.overrideEvents) < 0) {
+                                if ($data.filesToUpload() > 0 && settings.uploadLimit != 0) {
+                                    alert('The maximum upload limit has been reached.');
+                                }
+                            }
+                            // Trigger the onError event
+                            if (typeof settings.onError === 'function') {
+                                settings.onError.call($this, 'UPLOAD_LIMIT_EXCEEDED', $data.filesToUpload());
+                            }
+                        }
+                    }
+
+                }
+
+            });
+
+        },
+
+        // Destroy an instance of UploadiFive
+        destroy : function() {
+
+            this.each(function() {
+
+                var $this    = $(this),
+                    $data    = $this.data('uploadifive'),
+                    settings = $data.settings;
+            
+                // Clear the queue
+                methods.clearQueue.call($this);
+                // Destroy the queue if it was created
+                if (!settings.queueID) $('#' + settings.queueID).remove();
+                // Remove extra inputs
+                $this.siblings('input').remove();
+                // Show the original file input
+                $this.show()
+                // Move the file input out of the button
+                .insertBefore($data.button);
+                // Delete the button
+                $data.button.remove();
+                // Trigger the destroy event
+                if (typeof settings.onDestroy === 'function') {
+                    settings.onDestroy.call($this);
+                }
+
+            });
+
+        }
+
+    }
+
+    $.fn.upload = function(method) {
+
+        if (methods[method]) {
+            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
+        } else if (typeof method === 'object' || !method) {
+            return methods.init.apply(this, arguments);
+        } else {
+            $.error('The method ' + method + ' does not exist in $.uploadify');
+        }
+
+    }
+
+})(jQuery);
\ No newline at end of file
diff --git a/static/js/me/jquery.uploadifive.js b/static/js/me/jquery.uploadifive.js
deleted file mode 100644
index 9d8562c..0000000
--- a/static/js/me/jquery.uploadifive.js
+++ /dev/null
@@ -1,874 +0,0 @@
-/*
-UploadiFive 1.2.2
-Copyright (c) 2012 Reactive Apps, Ronnie Garcia
-Released under the UploadiFive Standard License <http://www.uploadify.com/uploadifive-standard-license>
-*/
-
-var jQuery = require('jquery');
-
-;(function($) {
-
-    var methods = {
-
-        init : function(options) {
-            
-            return this.each(function() {
-
-                // Create a reference to the jQuery DOM object
-                var $this = $(this);
-                    $this.data('uploadifive', {
-                        inputs     : {}, // The object that contains all the file inputs
-                        inputCount : 0,  // The total number of file inputs created
-                        fileID     : 0,
-                        queue      : {
-                                         count      : 0, // Total number of files in the queue
-                                         selected   : 0, // Number of files selected in the last select operation
-                                         replaced   : 0, // Number of files replaced in the last select operation
-                                         errors     : 0, // Number of files that returned an error in the last select operation
-                                         queued     : 0, // Number of files added to the queue in the last select operation
-                                         cancelled  : 0  // Total number of files that have been cancelled or removed from the queue
-                                     },
-                        uploads    : {
-                                         current    : 0, // Number of files currently being uploaded
-                                         attempts   : 0, // Number of file uploads attempted in the last upload operation
-                                         successful : 0, // Number of files successfully uploaded in the last upload operation
-                                         errors     : 0, // Number of files returning errors in the last upload operation
-                                         count      : 0  // Total number of files uploaded successfully
-                                     }
-                    });
-                var $data = $this.data('uploadifive');
-
-                // Set the default options
-                var settings = $data.settings = $.extend({
-                    'auto'            : true,               // Automatically upload a file when it's added to the queue
-                    'buttonClass'     : false,              // A class to add to the UploadiFive button
-                    'buttonText'      : 'Select Files',     // The text that appears on the UploadiFive button
-                    'checkScript'     : false,              // Path to the script that checks for existing file names 
-                    'dnd'             : true,               // Allow drag and drop into the queue
-                    'dropTarget'      : false,              // Selector for the drop target
-                    'fileObjName'     : 'Filedata',         // The name of the file object to use in your server-side script
-                    'fileSizeLimit'   : 0,                  // Maximum allowed size of files to upload
-                    'fileType'        : false,              // Type of files allowed (image, etc), separate with a pipe character |
-                    'formData'        : {},                 // Additional data to send to the upload script
-                    'height'          : 30,                 // The height of the button
-                    'itemTemplate'    : false,              // The HTML markup for the item in the queue
-                    'method'          : 'post',             // The method to use when submitting the upload
-                    'multi'           : true,               // Set to true to allow multiple file selections
-                    'overrideEvents'  : [],                 // An array of events to override
-                    'queueID'         : false,              // The ID of the file queue
-                    'queueSizeLimit'  : 0,                  // The maximum number of files that can be in the queue
-                    'removeCompleted' : false,              // Set to true to remove files that have completed uploading
-                    'simUploadLimit'  : 0,                  // The maximum number of files to upload at once
-                    'truncateLength'  : 0,                  // The length to truncate the file names to
-                    'uploadLimit'     : 0,                  // The maximum number of files you can upload
-                    'uploadScript'    : 'uploadifive.php',  // The path to the upload script
-                    'width'           : 100                 // The width of the button
-
-                    /*
-                    // Events
-                    'onAddQueueItem'   : function(file) {},                        // Triggered for each file that is added to the queue
-                    'onCancel'         : function(file) {},                        // Triggered when a file is cancelled or removed from the queue
-                    'onCheck'          : function(file, exists) {},                // Triggered when the server is checked for an existing file
-                    'onClearQueue'     : function(queue) {},                       // Triggered during the clearQueue function
-                    'onDestroy'        : function() {}                             // Triggered during the destroy function
-                    'onDrop'           : function(files, numberOfFilesDropped) {}, // Triggered when files are dropped into the file queue
-                    'onError'          : function(file, fileType, data) {},        // Triggered when an error occurs
-                    'onFallback'       : function() {},                            // Triggered if the HTML5 File API is not supported by the browser
-                    'onInit'           : function() {},                            // Triggered when UploadiFive if initialized
-                    'onQueueComplete'  : function() {},                            // Triggered once when an upload queue is done
-                    'onProgress'       : function(file, event) {},                 // Triggered during each progress update of an upload
-                    'onSelect'         : function() {},                            // Triggered once when files are selected from a dialog box
-                    'onUpload'         : function(file) {},                        // Triggered when an upload queue is started
-                    'onUploadComplete' : function(file, data) {},                  // Triggered when a file is successfully uploaded
-                    'onUploadFile'     : function(file) {},                        // Triggered for each file being uploaded
-                    */
-                }, options);
-
-                // Calculate the file size limit
-                if (isNaN(settings.fileSizeLimit)) {
-                    var fileSizeLimitBytes = parseInt(settings.fileSizeLimit) * 1.024
-                    if (settings.fileSizeLimit.indexOf('KB') > -1) {
-                        settings.fileSizeLimit = fileSizeLimitBytes * 1000;
-                    } else if (settings.fileSizeLimit.indexOf('MB') > -1) {
-                        settings.fileSizeLimit = fileSizeLimitBytes * 1000000;
-                    } else if (settings.fileSizeLimit.indexOf('GB') > -1) {
-                        settings.fileSizeLimit = fileSizeLimitBytes * 1000000000;
-                    }
-                } else {
-                    settings.fileSizeLimit = settings.fileSizeLimit * 1024;
-                }
-
-                // Create a template for a file input
-                $data.inputTemplate = $('<input type="file">')
-                .css({
-                    'font-size' : settings.height + 'px',
-                    'opacity'   : 0,
-                    'position'  : 'absolute',
-                    'right'     : '-3px',
-                    'top'       : '-3px',
-                    'z-index'   : 999 
-                });
-
-                // Create a new input
-                $data.createInput = function() {
-
-                    // Create a clone of the file input
-                    var input     = $data.inputTemplate.clone();
-                    // Create a unique name for the input item
-                    var inputName = input.name = 'input' + $data.inputCount++;
-                    // Set the multiple attribute
-                    if (settings.multi) {
-                        input.attr('multiple', true);
-                    }
-                    // Set the accept attribute on the input
-                    if (settings.fileType) {
-                        input.attr('accept', settings.fileType);
-                    }
-                    // Set the onchange event for the input
-                    input.bind('change', function() {
-                        $data.queue.selected = 0;
-                        $data.queue.replaced = 0;
-                        $data.queue.errors   = 0;
-                        $data.queue.queued   = 0;
-                        // Add a queue item to the queue for each file
-                        var limit = this.files.length;
-                        $data.queue.selected = limit;
-                        if (($data.queue.count + limit) > settings.queueSizeLimit && settings.queueSizeLimit !== 0) {
-                            if ($.inArray('onError', settings.overrideEvents) < 0) {
-                                alert('The maximum number of queue items has been reached (' + settings.queueSizeLimit + ').  Please select fewer files.');
-                            }
-                            // Trigger the error event
-                            if (typeof settings.onError === 'function') {
-                                settings.onError.call($this, 'QUEUE_LIMIT_EXCEEDED');
-                            }
-                        } else {
-                            for (var n = 0; n < limit; n++) {
-                                file = this.files[n];
-                                $data.addQueueItem(file);
-                            }
-                            $data.inputs[inputName] = this;
-                            $data.createInput();
-                        }
-                        // Upload the file if auto-uploads are enabled
-                        if (settings.auto) {
-                            methods.upload.call($this);
-                        }
-                        // Trigger the select event
-                        if (typeof settings.onSelect === 'function') {
-                            settings.onSelect.call($this, $data.queue);
-                        }
-                    });
-                    // Hide the existing current item and add the new one
-                    if ($data.currentInput) {
-                        $data.currentInput.hide();
-                    }
-                    $data.button.append(input);
-                    $data.currentInput = input;
-                }
-
-                // Remove an input
-                $data.destroyInput = function(key) {
-                    $($data.inputs[key]).remove();
-                    delete $data.inputs[key];
-                    $data.inputCount--;
-                }
-
-                // Drop a file into the queue
-                $data.drop = function(e) {
-                    $data.queue.selected = 0;
-                    $data.queue.replaced = 0;
-                    $data.queue.errors   = 0;
-                    $data.queue.queued   = 0;
-
-                    var fileData = e.dataTransfer;
-
-                    var inputName = fileData.name = 'input' + $data.inputCount++;
-                    // Add a queue item to the queue for each file
-                    var limit = fileData.files.length;
-                    $data.queue.selected = limit;
-                    if (($data.queue.count + limit) > settings.queueSizeLimit && settings.queueSizeLimit !== 0) {
-                        // Check if the queueSizeLimit was reached
-                        if ($.inArray('onError', settings.overrideEvents) < 0) {
-                            alert('The maximum number of queue items has been reached (' + settings.queueSizeLimit + ').  Please select fewer files.');
-                        }
-                        // Trigger the onError event
-                        if (typeof settings.onError === 'function') {
-                            settings.onError.call($this, 'QUEUE_LIMIT_EXCEEDED');
-                        }
-                    } else {
-                        // Add a queue item for each file
-                        for (var n = 0; n < limit; n++) {
-                            file = fileData.files[n];
-                            $data.addQueueItem(file);
-                        }
-                        // Save the data to the inputs object
-                        $data.inputs[inputName] = fileData;
-                    }
-
-                    // Upload the file if auto-uploads are enabled
-                    if (settings.auto) {
-                        methods.upload.call($this);
-                    }
-
-                    // Trigger the onDrop event
-                    if (typeof settings.onDrop === 'function') {
-                        settings.onDrop.call($this, fileData.files, fileData.files.length);
-                    }
-
-                    // Stop FireFox from opening the dropped file(s)
-                    e.preventDefault();
-                    e.stopPropagation();
-                }
-
-                // Check if a filename exists in the queue
-                $data.fileExistsInQueue = function(file) {
-                    for (var key in $data.inputs) {
-                        input = $data.inputs[key];
-                        limit = input.files.length;
-                        for (var n = 0; n < limit; n++) {
-                            existingFile = input.files[n];
-                            // Check if the filename matches
-                            if (existingFile.name == file.name && !existingFile.complete) {
-                                return true;
-                            }
-                        }
-                    }
-                    return false;
-                }
-
-                // Remove an existing file in the queue
-                $data.removeExistingFile = function(file) {
-                    for (var key in $data.inputs) {
-                        input = $data.inputs[key];
-                        limit = input.files.length;
-                        for (var n = 0; n < limit; n++) {
-                            existingFile = input.files[n];
-                            // Check if the filename matches
-                            if (existingFile.name == file.name && !existingFile.complete) {
-                                $data.queue.replaced++;
-                                methods.cancel.call($this, existingFile, true);
-                            }
-                        }
-                    }
-                }
-
-                // Create the file item template
-                if (settings.itemTemplate == false) {
-                    $data.queueItem = $('<div class="uploadifive-queue-item">\
-                        <a class="close" href="#">X</a>\
-                        <div><span class="filename"></span><span class="fileinfo"></span></div>\
-                        <div class="progress">\
-                            <div class="progress-bar"></div>\
-                        </div>\
-                    </div>');
-                } else {
-                    $data.queueItem = $(settings.itemTemplate);
-                }
-
-                // Add an item to the queue
-                $data.addQueueItem = function(file) {
-                    if ($.inArray('onAddQueueItem', settings.overrideEvents) < 0) {
-                        // Check if the filename already exists in the queue
-                        $data.removeExistingFile(file);
-                        // Create a clone of the queue item template
-                        file.queueItem = $data.queueItem.clone();
-                        // Add an ID to the queue item
-                        file.queueItem.attr('id', settings.id + '-file-' + $data.fileID++);
-                        // Bind the close event to the close button
-                        file.queueItem.find('.close').bind('click', function() {
-                           methods.cancel.call($this, file);
-                           return false;
-                        });
-                        var fileName = file.name;
-                        if (fileName.length > settings.truncateLength && settings.truncateLength != 0) {
-                            fileName = fileName.substring(0, settings.truncateLength) + '...';
-                        }
-                        file.queueItem.find('.filename').html(fileName);
-                        // Add a reference to the file
-                        file.queueItem.data('file', file);
-                        $data.queueEl.append(file.queueItem);
-                    }
-                    // Trigger the addQueueItem event
-                    if (typeof settings.onAddQueueItem === 'function') {
-                        settings.onAddQueueItem.call($this, file);
-                    }
-                    // Check the filesize
-                    if (file.size > settings.fileSizeLimit && settings.fileSizeLimit != 0) {
-                        $data.error('FILE_SIZE_LIMIT_EXCEEDED', file);
-                    } else {
-                        $data.queue.queued++;
-                        $data.queue.count++;
-                    }
-                }
-
-                // Remove an item from the queue
-                $data.removeQueueItem = function(file, instant, delay) {
-                    // Set the default delay
-                    if (!delay) delay = 0;
-                    var fadeTime = instant ? 0 : 500;
-                    if (file.queueItem) {
-                        if (file.queueItem.find('.fileinfo').html() != ' - Completed') {
-                            file.queueItem.find('.fileinfo').html(' - Cancelled');
-                        }
-                        file.queueItem.find('.progress-bar').width(0);
-                        file.queueItem.delay(delay).fadeOut(fadeTime, function() {
-                           $(this).remove();
-                        });
-                        delete file.queueItem;
-                        $data.queue.count--;
-                    }
-                }
-
-                // Count the number of files that need to be uploaded
-                $data.filesToUpload = function() {
-                    var filesToUpload = 0;
-                    for (var key in $data.inputs) {
-                        input = $data.inputs[key];
-                        limit = input.files.length;
-                        for (var n = 0; n < limit; n++) {
-                            file = input.files[n];
-                            if (!file.skip && !file.complete) {
-                                filesToUpload++;
-                            }
-                        }
-                    }
-                    return filesToUpload;
-                }
-
-                // Check if a file exists
-                $data.checkExists = function(file) {
-                    if ($.inArray('onCheck', settings.overrideEvents) < 0) {
-                        // This request needs to be synchronous
-                        $.ajaxSetup({
-                            'async' : false
-                        });
-                        // Send the filename to the check script
-                        var checkData = $.extend(settings.formData, {filename: file.name});
-                        $.post(settings.checkScript, checkData, function(fileExists) {
-                            file.exists = parseInt(fileExists);
-                        });
-                        if (file.exists) {
-                            if (!confirm('A file named ' + file.name + ' already exists in the upload folder.\nWould you like to replace it?')) {
-                                // If not replacing the file, cancel the upload
-                                methods.cancel.call($this, file);
-                                return true;
-                            }
-                        }
-                    }
-                    // Trigger the check event
-                    if (typeof settings.onCheck === 'function') {
-                        settings.onCheck.call($this, file, file.exists);
-                    }
-                    return false;
-                }
-
-                // Upload a single file
-                $data.uploadFile = function(file, uploadAll) {
-                    if (!file.skip && !file.complete && !file.uploading) {
-                        file.uploading = true;
-                        $data.uploads.current++;
-                        $data.uploads.attempted++;
-
-                        // Create a new AJAX request
-                        xhr = file.xhr = new XMLHttpRequest();
-
-                        // Start the upload
-                        // Use the faster FormData if it exists
-                        if (typeof FormData === 'function' || typeof FormData === 'object') {
-
-                            // Create a new FormData object
-                            var formData = new FormData();
-
-                            // Add the form data
-                            formData.append(settings.fileObjName, file);
-
-                            // Add the rest of the formData
-                            for (i in settings.formData) {
-                                formData.append(i, settings.formData[i]);
-                            }
-
-                            // Open the AJAX call
-                            xhr.open(settings.method, settings.uploadScript, true);
-
-                            // On progress function
-                            xhr.upload.addEventListener('progress', function(e) {
-                                if (e.lengthComputable) {
-                                    $data.progress(e, file);
-                                }
-                            }, false);
-
-                            // On complete function
-                            xhr.addEventListener('load', function(e) {
-                                if (this.readyState == 4) {
-                                    file.uploading = false;
-                                    if (this.status == 200) {
-                                        if (file.xhr.responseText !== 'Invalid file type.') {
-                                            $data.uploadComplete(e, file, uploadAll);
-                                        } else {
-                                            $data.error(file.xhr.responseText, file, uploadAll);
-                                        }
-                                    } else if (this.status == 404) {
-                                        $data.error('404_FILE_NOT_FOUND', file, uploadAll);
-                                    } else if (this.status == 403) {
-                                        $data.error('403_FORBIDDEN', file, uploadAll);
-                                    } else {
-                                        $data.error('Unknown Error', file, uploadAll);
-                                    }
-                                }
-                            });
-
-                            // Send the form data (multipart/form-data)
-                            xhr.send(formData);
-
-                        } else {
-
-                            // Send as binary
-                            var reader = new FileReader();
-                            reader.onload = function(e) {
-
-                                // Set some file builder variables
-                                var boundary = '-------------------------' + (new Date).getTime(),
-                                    dashes   = '--',
-                                    eol      = '\r\n',
-                                    binFile  = '';
-
-                                // Build an RFC2388 String 
-                                binFile += dashes + boundary + eol;
-                                // Generate the headers
-                                binFile += 'Content-Disposition: form-data; name="' + settings.fileObjName + '"';
-                                if (file.name) {
-                                    binFile += '; filename="' + file.name + '"';
-                                }
-                                binFile += eol;
-                                binFile += 'Content-Type: application/octet-stream' + eol + eol;
-                                binFile += e.target.result + eol;
-
-                                for (key in settings.formData) {
-                                    binFile += dashes + boundary + eol;
-                                    binFile += 'Content-Disposition: form-data; name="' + key + '"' + eol + eol;
-                                    binFile += settings.formData[key] + eol;
-                                }
-
-                                binFile += dashes + boundary + dashes + eol;
-
-                                // On progress function
-                                xhr.upload.addEventListener('progress', function(e) {
-                                    $data.progress(e, file);
-                                }, false);
-
-                                // On complete function
-                                xhr.addEventListener('load', function(e) {
-                                    file.uploading = false;
-                                    var status = this.status;
-                                    if (status == 404) {
-                                        $data.error('404_FILE_NOT_FOUND', file, uploadAll);
-                                    } else {
-                                        if (file.xhr.responseText != 'Invalid file type.') {    
-                                            $data.uploadComplete(e, file, uploadAll);
-                                        } else {
-                                            $data.error(file.xhr.responseText, file, uploadAll);
-                                        } 
-                                    }
-                                }, false);
-
-                                // Open the ajax request
-                                var url = settings.uploadScript;
-                                if (settings.method == 'get') {
-                                    var params = $(settings.formData).param();
-                                    url += params;
-                                }
-                                xhr.open(settings.method, settings.uploadScript, true);
-                                xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
-
-                                // Trigger the uploadFile event
-                                if (typeof settings.onUploadFile === 'function') {
-                                    settings.onUploadFile.call($this, file);
-                                }
-
-                                // Send the file for upload
-                                xhr.sendAsBinary(binFile);
-                            }
-                            reader.readAsBinaryString(file);
-
-                        }
-                    }
-                }
-
-                // Update a file upload's progress
-                $data.progress = function(e, file) {
-                    if ($.inArray('onProgress', settings.overrideEvents) < 0) {
-                        if (e.lengthComputable) {
-                            var percent = Math.round((e.loaded / e.total) * 100);
-                        }
-                        file.queueItem.find('.fileinfo').html(' - ' + percent + '%');
-                        file.queueItem.find('.progress-bar').css('width', percent + '%');
-                    }
-                    // Trigger the progress event
-                    if (typeof settings.onProgress === 'function') {
-                        settings.onProgress.call($this, file, e);
-                    }
-                }
-
-                // Trigger an error
-                $data.error = function(errorType, file, uploadAll) {
-                    if ($.inArray('onError', settings.overrideEvents) < 0) {
-                        // Get the error message
-                        switch(errorType) {
-                            case '404_FILE_NOT_FOUND':
-                                errorMsg = '404 Error';
-                                break;
-                            case '403_FORBIDDEN':
-                                errorMsg = '403 Forbidden';
-                                break;
-                            case 'FORBIDDEN_FILE_TYPE':
-                                errorMsg = 'Forbidden File Type';
-                                break;
-                            case 'FILE_SIZE_LIMIT_EXCEEDED':
-                                errorMsg = 'File Too Large';
-                                break;
-                            default:
-                                errorMsg = 'Unknown Error';
-                                break;
-                        }
-
-                        // Add the error class to the queue item
-                        file.queueItem.addClass('error')
-                        // Output the error in the queue item
-                        .find('.fileinfo').html(' - ' + errorMsg);
-                        // Hide the 
-                        file.queueItem.find('.progress').remove();
-                    }
-                    // Trigger the error event
-                    if (typeof settings.onError === 'function') {
-                        settings.onError.call($this, errorType, file);
-                    }
-                    file.skip = true;
-                    if (errorType == '404_FILE_NOT_FOUND') {
-                        $data.uploads.errors++;
-                    } else {
-                        $data.queue.errors++;
-                    }
-                    if (uploadAll) {
-                        methods.upload.call($this, null, true);
-                    }
-                }
-
-                // Trigger when a single file upload is complete
-                $data.uploadComplete = function(e, file, uploadAll) {
-                    if ($.inArray('onUploadComplete', settings.overrideEvents) < 0) {
-                        file.queueItem.find('.progress-bar').css('width', '100%');
-                        file.queueItem.find('.fileinfo').html(' - Completed');
-                        file.queueItem.find('.progress').slideUp(250);
-                        file.queueItem.addClass('complete');
-                    }
-                    // Trigger the complete event
-                    if (typeof settings.onUploadComplete === 'function') {
-                        settings.onUploadComplete.call($this, file, file.xhr.responseText);
-                    }
-                    if (settings.removeCompleted) {
-                        setTimeout(function() { methods.cancel.call($this, file); }, 3000);
-                    }
-                    file.complete = true;
-                    $data.uploads.successful++;
-                    $data.uploads.count++;
-                    $data.uploads.current--;
-                    delete file.xhr;
-                    if (uploadAll) {
-                        methods.upload.call($this, null, true);
-                    }
-                }
-
-                // Trigger when all the files are done uploading
-                $data.queueComplete = function() {
-                    // Trigger the queueComplete event
-                    if (typeof settings.onQueueComplete === 'function') {
-                        settings.onQueueComplete.call($this, $data.uploads);
-                    }
-                }
-
-                // ----------------------
-                // Initialize UploadiFive
-                // ----------------------
-
-                // Check if HTML5 is available
-                if (window.File && window.FileList && window.Blob && (window.FileReader || window.FormData)) {
-                    // Assign an ID to the object
-                    settings.id = 'uploadifive-' + $this.attr('id');
-
-                    // Wrap the file input in a div with overflow set to hidden
-                    $data.button = $('<div id="' + settings.id + '" class="uploadifive-button">' + settings.buttonText + '</div>');
-                    if (settings.buttonClass) $data.button.addClass(settings.buttonClass);
-
-                    // Style the button wrapper
-                    $data.button.css({
-                        'height'      : settings.height,
-                        'line-height' : settings.height + 'px', 
-                        'overflow'    : 'hidden',
-                        'position'    : 'relative',
-                        'text-align'  : 'center', 
-                        'width'       : settings.width
-                    });
-
-                    // Insert the button above the file input
-                    $this.before($data.button)
-                    // Add the file input to the button
-                    .appendTo($data.button)
-                    // Modify the styles of the file input
-                    .hide();
-
-                    // Create a new input
-                    $data.createInput.call($this);
-
-                    // Create the queue container
-                    if (!settings.queueID) {
-                        settings.queueID = settings.id + '-queue';
-                        $data.queueEl = $('<div id="' + settings.queueID + '" class="uploadifive-queue" />');
-                        $data.button.after($data.queueEl);
-                    } else {
-                        $data.queueEl = $('#' + settings.queueID);
-                    }
-
-                    // Add drag and drop functionality
-                    if (settings.dnd) {
-                        var $dropTarget = settings.dropTarget ? $(settings.dropTarget) : $data.queueEl.get(0);
-                        $dropTarget.addEventListener('dragleave', function(e) {
-                            // Stop FireFox from opening the dropped file(s)
-                            e.preventDefault();
-                            e.stopPropagation();
-                        }, false);
-                        $dropTarget.addEventListener('dragenter', function(e) {
-                            // Stop FireFox from opening the dropped file(s)
-                            e.preventDefault();
-                            e.stopPropagation();
-                        }, false);
-                        $dropTarget.addEventListener('dragover', function(e) {
-                            // Stop FireFox from opening the dropped file(s)
-                            e.preventDefault();
-                            e.stopPropagation();
-                        }, false);
-                        $dropTarget.addEventListener('drop', $data.drop, false);
-                    }
-
-                    // Send as binary workaround for Chrome
-                    if (!XMLHttpRequest.prototype.sendAsBinary) {
-                        XMLHttpRequest.prototype.sendAsBinary = function(datastr) {
-                            function byteValue(x) {
-                                return x.charCodeAt(0) & 0xff;
-                            }
-                            var ords = Array.prototype.map.call(datastr, byteValue);
-                            var ui8a = new Uint8Array(ords);
-                            this.send(ui8a.buffer);
-                        }
-                    }
-
-                    // Trigger the oninit event
-                    if (typeof settings.onInit === 'function') {
-                        settings.onInit.call($this);
-                    }
-
-                } else {
-
-                    // Trigger the fallback event
-                    if (typeof settings.onFallback === 'function') {
-                        settings.onFallback.call($this);
-                    }
-                    return false;
-
-                }
-
-            });
-
-        },
-
-
-        // Write some data to the console
-        debug : function() {
-
-            return this.each(function() {
-
-                console.log($(this).data('uploadifive'));
-
-            });
-
-        },
-
-        // Clear all the items from the queue
-        clearQueue : function() {
-
-            this.each(function() {
-
-                var $this    = $(this),
-                    $data    = $this.data('uploadifive'),
-                    settings = $data.settings;
-
-                for (var key in $data.inputs) {
-                    input = $data.inputs[key];
-                    limit = input.files.length;
-                    for (i = 0; i < limit; i++) {
-                        file = input.files[i];
-                        methods.cancel.call($this, file);
-                    }
-                }
-                // Trigger the onClearQueue event
-                if (typeof settings.onClearQueue === 'function') {
-                    settings.onClearQueue.call($this, $('#' + $data.settings.queueID));
-                }
-
-            });
-
-        },
-
-        // Cancel a file upload in progress or remove a file from the queue
-        cancel : function(file, fast) {
-
-            this.each(function() {
-
-                var $this    = $(this),
-                    $data    = $this.data('uploadifive'),
-                    settings = $data.settings;
-
-                // If user passed a queue item ID instead of file...
-                if (typeof file === 'string') {
-                    if (!isNaN(file)) {
-                        fileID = 'uploadifive-' + $(this).attr('id') + '-file-' + file;
-                    }
-                    file = $('#' + fileID).data('file');
-                }
-
-                file.skip = true;
-                $data.filesCancelled++;
-                if (file.uploading) {
-                    $data.uploads.current--;
-                    file.uploading = false;
-                    file.xhr.abort();
-                    delete file.xhr;
-                    methods.upload.call($this);
-                }
-                if ($.inArray('onCancel', settings.overrideEvents) < 0) {
-                    $data.removeQueueItem(file, fast);
-                }
-
-                // Trigger the cancel event
-                if (typeof settings.onCancel === 'function') {
-                    settings.onCancel.call($this, file);
-                }
-                
-            });
-            
-        },
-
-        // Upload the files in the queue
-        upload : function(file, keepVars) {
-
-            this.each(function() {
-
-                var $this    = $(this),
-                    $data    = $this.data('uploadifive'),
-                    settings = $data.settings;
-
-                if (file) {
-
-                    $data.uploadFile.call($this, file);
-
-                } else {
-
-                    // Check if the upload limit was reached
-                    if (($data.uploads.count + $data.uploads.current) < settings.uploadLimit || settings.uploadLimit == 0) {
-                        if (!keepVars) {
-                            $data.uploads.attempted   = 0;
-                            $data.uploads.successsful = 0;
-                            $data.uploads.errors      = 0;
-                            var filesToUpload = $data.filesToUpload();
-                            // Trigger the onUpload event
-                            if (typeof settings.onUpload === 'function') {
-                                settings.onUpload.call($this, filesToUpload);
-                            }
-                        }
-
-                        // Loop through the files
-                        $('#' + settings.queueID).find('.uploadifive-queue-item').not('.error, .complete').each(function() {
-                            _file = $(this).data('file');
-                            // Check if the simUpload limit was reached
-                            if (($data.uploads.current >= settings.simUploadLimit && settings.simUploadLimit !== 0) || ($data.uploads.current >= settings.uploadLimit && settings.uploadLimit !== 0) || ($data.uploads.count >= settings.uploadLimit && settings.uploadLimit !== 0)) {
-                                return false;
-                            }
-                            if (settings.checkScript) {
-                                // Let the loop know that we're already processing this file
-                                _file.checking = true;
-                                skipFile = $data.checkExists(_file);
-                                _file.checking = false;
-                                if (!skipFile) {
-                                    $data.uploadFile(_file, true);
-                                }
-                            } else {
-                                $data.uploadFile(_file, true);
-                            }
-                        });
-                        if ($('#' + settings.queueID).find('.uploadifive-queue-item').not('.error, .complete').size() == 0) {
-                            $data.queueComplete();
-                        }
-                    } else {
-                        if ($data.uploads.current == 0) {
-                            if ($.inArray('onError', settings.overrideEvents) < 0) {
-                                if ($data.filesToUpload() > 0 && settings.uploadLimit != 0) {
-                                    alert('The maximum upload limit has been reached.');
-                                }
-                            }
-                            // Trigger the onError event
-                            if (typeof settings.onError === 'function') {
-                                settings.onError.call($this, 'UPLOAD_LIMIT_EXCEEDED', $data.filesToUpload());
-                            }
-                        }
-                    }
-
-                }
-
-            });
-
-        },
-
-        // Destroy an instance of UploadiFive
-        destroy : function() {
-
-            this.each(function() {
-
-                var $this    = $(this),
-                    $data    = $this.data('uploadifive'),
-                    settings = $data.settings;
-            
-                // Clear the queue
-                methods.clearQueue.call($this);
-                // Destroy the queue if it was created
-                if (!settings.queueID) $('#' + settings.queueID).remove();
-                // Remove extra inputs
-                $this.siblings('input').remove();
-                // Show the original file input
-                $this.show()
-                // Move the file input out of the button
-                .insertBefore($data.button);
-                // Delete the button
-                $data.button.remove();
-                // Trigger the destroy event
-                if (typeof settings.onDestroy === 'function') {
-                    settings.onDestroy.call($this);
-                }
-
-            });
-
-        }
-
-    }
-
-    $.fn.uploadifive = function(method) {
-
-        if (methods[method]) {
-            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
-        } else if (typeof method === 'object' || !method) {
-            return methods.init.apply(this, arguments);
-        } else {
-            $.error('The method ' + method + ' does not exist in $.uploadify');
-        }
-
-    }
-
-})(jQuery);
\ No newline at end of file
diff --git a/static/js/me/suggest.js b/static/js/me/suggest.js
index d28f4ca..f3505e6 100644
--- a/static/js/me/suggest.js
+++ b/static/js/me/suggest.js
@@ -23,7 +23,7 @@ var $uploadImgList = $('.upload-img-list'),
     imgStr = '',
     uploadImgNum = 0;
 
-require('./jquery.uploadifive');
+require('./jquery.upload');
 
 imgTpl = '{{# imgList}}' +
     '<li>' +
@@ -34,7 +34,7 @@ imgTpl = '{{# imgList}}' +
 
 imgTemplate = Handlebars.compile(imgTpl);
 
-$('#upload-img').uploadifive({
+$('#upload-img').upload({
     auto: true,
     fileType: 'image/*',
     uploadScript: '/home/suggestimgUpload',
--
libgit2 0.24.0