diff --git a/htdocs/includes/jquery/plugins/fileupload/README.txt b/htdocs/includes/jquery/plugins/fileupload/README.txt new file mode 100644 index 00000000000..64eeeed84f2 --- /dev/null +++ b/htdocs/includes/jquery/plugins/fileupload/README.txt @@ -0,0 +1,61 @@ +jQuery File Upload Plugin +========================= + +Demo +---- +http://aquantum-demo.appspot.com/file-upload + +Features +-------- + - Multiple file upload: + Allows to select multiple files at once and upload them simultaneously. + - Drag & Drop support: + Allows to upload files by dragging them from your desktop or filemanager and dropping them on your browser window. + - Upload progress bar: + Shows a progress bar indicating the upload progress for individual files. + - Cancelable uploads: + Individual file uploads can be canceled to stop the upload progress. + - No browser plugins (e.g. Adobe Flash) required: + The implementation is based on open standards like HTML5 and JavaScript and requires no additional browser plugins. + - Graceful fallback for legacy browsers: + Uploads files via XMLHttpRequests if supported and uses iframes as fallback for legacy browsers. + - HTML file upload form fallback: + Shows a standard HTML file upload form if JavaScript is disabled. + - Cross-site file uploads: + Supports uploading files to a different domain with Cross-site XMLHttpRequests. + - Multiple plugin instances: + Allows to use multiple plugin instances on the same webpage. + - Customizable and extensible: + Provides an API to set individual options and define callBack methods for various upload events. + - Multipart and file contents stream uploads: + Files can be uploaded as standard "multipart/form-data" or file contents stream (HTTP PUT file upload). + - Compatible with any server-side application platform: + Works with Google App Engine (Python, Java), Ruby on Rails, PHP and any other platform that supports HTTP file uploads. + +Requirements +------------ + - jQuery v. 1.4+ + - jQuery UI v. 1.8+ (optional) + +Browser Support (tested versions) +--------------------------------- + - Google Chrome - 7.0, 8.0, 9.0 + - Apple Safari - 5.0 ¹ + - Mozilla Firefox - 3.6 + - Opera - 10.60 ², 11.00 ² + - Microsoft Internet Explorer 6.0 ², 7.0 ², 8.0 ², 9.0 ² +¹ Drag & Drop is not supported on the Windows version of Safari. +² MSIE and Opera have no support for Drag & Drop, multiple file selection or upload progress indication. + +License +------- +Released under the MIT license: +http://creativecommons.org/licenses/MIT/ + +Source Code & Download +---------------------- +https://github.com/blueimp/jQuery-File-Upload + +Documentation +------------- +https://github.com/blueimp/jQuery-File-Upload/wiki diff --git a/htdocs/includes/jquery/plugins/fileupload/jquery.fileupload-ui.css b/htdocs/includes/jquery/plugins/fileupload/jquery.fileupload-ui.css new file mode 100644 index 00000000000..7e31abcf20a --- /dev/null +++ b/htdocs/includes/jquery/plugins/fileupload/jquery.fileupload-ui.css @@ -0,0 +1,70 @@ +.file_upload { + position: relative; + overflow: hidden; + direction: ltr; + cursor: pointer; + text-align: center; + color: #333; + font-weight: bold; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + border-radius: 10px; + width: 200px; + height: 30px; + line-height: 30px; + background: palegreen; + border: 1px solid limegreen; +} + +.file_upload_small { + width: 200px; + height: 30px; + line-height: 30px; + font-size: auto; + background: palegreen; + border: 1px solid limegreen; +} + +.file_upload_large { + width: 100%; + height: 150px; + line-height: 150px; + font-size: 20px; + background: palegreen; + border: 1px solid limegreen; +} + +.file_upload_highlight { + background: lawngreen; +} + +.file_upload input { + position: absolute; + top: 0; + right: 0; + margin: 0; + border: 300px solid transparent; + opacity: 0; + -ms-filter: 'alpha(opacity=0)'; + filter: alpha(opacity=0); + -o-transform: translate(-300px, -300px) scale(10); + -moz-transform: translate(-800px, 0) scale(10); + cursor: pointer; +} + +.file_upload iframe, .file_upload button { + display: none; +} + +.file_upload_progress .ui-progressbar-value { + background: url(pbar-ani.gif); +} + +.file_upload_progress div { + width: 150px; + height: 15px; +} + +.file_upload_cancel div { + cursor: pointer; +} \ No newline at end of file diff --git a/htdocs/includes/jquery/plugins/fileupload/jquery.fileupload-ui.js b/htdocs/includes/jquery/plugins/fileupload/jquery.fileupload-ui.js new file mode 100644 index 00000000000..abdb793fa75 --- /dev/null +++ b/htdocs/includes/jquery/plugins/fileupload/jquery.fileupload-ui.js @@ -0,0 +1,259 @@ +/* + * jQuery File Upload User Interface Plugin 3.2.2 + * + * Copyright 2010, Sebastian Tschan, AQUANTUM + * Licensed under the MIT license: + * http://creativecommons.org/licenses/MIT/ + * + * https://blueimp.net + * http://www.aquantum.de + */ + +/*jslint browser: true */ +/*global jQuery */ + +(function ($) { + + var UploadHandler, + methods; + + UploadHandler = function (container, options) { + var uploadHandler = this, + undef = 'undefined', + func = 'function', + dragOverTimeout, + isDropZoneEnlarged; + + this.dropZone = container; + this.progressSelector = '.file_upload_progress div'; + this.cancelSelector = '.file_upload_cancel div'; + this.cssClassSmall = 'file_upload_small'; + this.cssClassLarge = 'file_upload_large'; + this.cssClassHighlight = 'file_upload_highlight'; + this.dropEffect = 'highlight'; + this.uploadTable = this.downloadTable = $(); + + this.buildUploadRow = this.buildDownloadRow = function () { + return null; + }; + + this.addNode = function (parentNode, node, callBack) { + if (node) { + node.css('display', 'none').appendTo(parentNode).fadeIn(function () { + if (typeof callBack === func) { + try { + callBack(); + } catch (e) { + // Fix endless exception loop: + $(this).stop(); + throw e; + } + } + }); + } else if (typeof callBack === func) { + callBack(); + } + }; + + this.removeNode = function (node, callBack) { + if (node) { + node.fadeOut(function () { + $(this).remove(); + if (typeof callBack === func) { + try { + callBack(); + } catch (e) { + // Fix endless exception loop: + $(this).stop(); + throw e; + } + } + }); + } else if (typeof callBack === func) { + callBack(); + } + }; + + this.onAbort = function (event, files, index, xhr, handler) { + uploadHandler.removeNode(handler.uploadRow); + }; + + this.cancelUpload = function (event, files, index, xhr, handler) { + var readyState = xhr.readyState; + xhr.abort(); + // If readyState is below 2, abort() has no effect: + if (isNaN(readyState) || readyState < 2) { + handler.onAbort(event, files, index, xhr, handler); + } + }; + + this.initProgressBar = function (node, value) { + if (typeof node.progressbar === func) { + return node.progressbar({ + value: value + }); + } else { + var progressbar = $('').appendTo(node); + progressbar.progressbar = function (key, value) { + progressbar.attr('value', value); + }; + return progressbar; + } + }; + + this.initUploadRow = function (event, files, index, xhr, handler, callBack) { + var uploadRow = handler.uploadRow = uploadHandler.buildUploadRow(files, index); + if (uploadRow) { + handler.progressbar = uploadHandler.initProgressBar( + uploadRow.find(uploadHandler.progressSelector), + (xhr.upload ? 0 : 100) + ); + uploadRow.find(uploadHandler.cancelSelector).click(function (e) { + uploadHandler.cancelUpload(e, files, index, xhr, handler); + }); + } + uploadHandler.addNode(uploadHandler.uploadTable, uploadRow, callBack); + }; + + this.initUpload = function (event, files, index, xhr, handler, callBack) { + uploadHandler.initUploadRow(event, files, index, xhr, handler, function () { + if (typeof uploadHandler.beforeSend === func) { + uploadHandler.beforeSend(event, files, index, xhr, handler, callBack); + } else { + callBack(); + } + }); + }; + + this.onProgress = function (event, files, index, xhr, handler) { + if (handler.progressbar) { + handler.progressbar.progressbar( + 'value', + parseInt(event.loaded / event.total * 100, 10) + ); + } + }; + + this.parseResponse = function (xhr) { + if (typeof xhr.responseText !== undef) { + return $.parseJSON(xhr.responseText); + } else { + // Instead of an XHR object, an iframe is used for legacy browsers: + return $.parseJSON(xhr.contents().text()); + } + }; + + this.initDownloadRow = function (event, files, index, xhr, handler, callBack) { + var json, downloadRow; + try { + json = handler.response = uploadHandler.parseResponse(xhr); + downloadRow = handler.downloadRow = uploadHandler.buildDownloadRow(json); + uploadHandler.addNode(uploadHandler.downloadTable, downloadRow, callBack); + } catch (e) { + if (typeof uploadHandler.onError === func) { + handler.originalEvent = event; + uploadHandler.onError(e, files, index, xhr, handler); + } else { + throw e; + } + } + }; + + this.onLoad = function (event, files, index, xhr, handler) { + uploadHandler.removeNode(handler.uploadRow, function () { + uploadHandler.initDownloadRow(event, files, index, xhr, handler, function () { + if (typeof uploadHandler.onComplete === func) { + uploadHandler.onComplete(event, files, index, xhr, handler); + } + }); + }); + }; + + this.dropZoneEnlarge = function () { + if (!isDropZoneEnlarged) { + if (typeof uploadHandler.dropZone.switchClass === func) { + uploadHandler.dropZone.switchClass( + uploadHandler.cssClassSmall, + uploadHandler.cssClassLarge + ); + } else { + uploadHandler.dropZone.addClass(uploadHandler.cssClassLarge); + uploadHandler.dropZone.removeClass(uploadHandler.cssClassSmall); + } + isDropZoneEnlarged = true; + } + }; + + this.dropZoneReduce = function () { + if (typeof uploadHandler.dropZone.switchClass === func) { + uploadHandler.dropZone.switchClass( + uploadHandler.cssClassLarge, + uploadHandler.cssClassSmall + ); + } else { + uploadHandler.dropZone.addClass(uploadHandler.cssClassSmall); + uploadHandler.dropZone.removeClass(uploadHandler.cssClassLarge); + } + isDropZoneEnlarged = false; + }; + + this.onDocumentDragEnter = function (event) { + uploadHandler.dropZoneEnlarge(); + }; + + this.onDocumentDragOver = function (event) { + if (dragOverTimeout) { + clearTimeout(dragOverTimeout); + } + dragOverTimeout = setTimeout(function () { + uploadHandler.dropZoneReduce(); + }, 200); + }; + + this.onDragEnter = this.onDragLeave = function (event) { + uploadHandler.dropZone.toggleClass(uploadHandler.cssClassHighlight); + }; + + this.onDrop = function (event) { + if (dragOverTimeout) { + clearTimeout(dragOverTimeout); + } + if (uploadHandler.dropEffect && typeof uploadHandler.dropZone.effect === func) { + uploadHandler.dropZone.effect(uploadHandler.dropEffect, function () { + uploadHandler.dropZone.removeClass(uploadHandler.cssClassHighlight); + uploadHandler.dropZoneReduce(); + }); + } else { + uploadHandler.dropZone.removeClass(uploadHandler.cssClassHighlight); + uploadHandler.dropZoneReduce(); + } + }; + + $.extend(this, options); + }; + + methods = { + init : function (options) { + return this.each(function () { + $(this).fileUpload(new UploadHandler($(this), options)); + }); + }, + + destroy : function (namespace) { + return this.each(function () { + $(this).fileUpload('destroy', namespace); + }); + } + }; + + $.fn.fileUploadUI = 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('Method ' + method + ' does not exist on jQuery.fileUploadUI'); + } + }; + +}(jQuery)); \ No newline at end of file diff --git a/htdocs/includes/jquery/plugins/fileupload/jquery.fileupload.js b/htdocs/includes/jquery/plugins/fileupload/jquery.fileupload.js new file mode 100644 index 00000000000..4fc5f9e8fd9 --- /dev/null +++ b/htdocs/includes/jquery/plugins/fileupload/jquery.fileupload.js @@ -0,0 +1,475 @@ +/* + * jQuery File Upload Plugin 3.4 + * + * Copyright 2010, Sebastian Tschan, AQUANTUM + * Licensed under the MIT license: + * http://creativecommons.org/licenses/MIT/ + * + * https://blueimp.net + * http://www.aquantum.de + */ + +/*jslint browser: true */ +/*global File, FileReader, FormData, unescape, jQuery */ + +(function ($) { + + var FileUpload, + methods; + + FileUpload = function (container) { + var fileUpload = this, + uploadForm = (container.is('form') ? container : container.find('form').first()), + fileInput = uploadForm.find('input:file').first(), + settings = { + namespace: 'file_upload', + cssClass: 'file_upload', + dragDropSupport: true, + dropZone: container, + url: uploadForm.attr('action'), + method: uploadForm.attr('method'), + fieldName: fileInput.attr('name'), + multipart: true, + multiFileRequest: false, + formData: function () { + return uploadForm.serializeArray(); + }, + withCredentials: false, + forceIframeUpload: false + }, + documentListeners = {}, + dropZoneListeners = {}, + fileInputListeners = {}, + undef = 'undefined', + func = 'function', + num = 'number', + protocolRegExp = /^http(s)?:\/\//, + + MultiLoader = function (callBack, numberComplete) { + var loaded = 0; + this.complete = function () { + loaded += 1; + if (loaded === numberComplete) { + callBack(); + } + }; + }, + + isXHRUploadCapable = function () { + return typeof XMLHttpRequest !== undef && typeof File !== undef && ( + !settings.multipart || typeof FormData !== undef || typeof FileReader !== undef + ); + }, + + initEventHandlers = function () { + if (settings.dragDropSupport) { + if (typeof settings.onDocumentDragEnter === func) { + documentListeners['dragenter.' + settings.namespace] = settings.onDocumentDragEnter; + } + if (typeof settings.onDocumentDragLeave === func) { + documentListeners['dragleave.' + settings.namespace] = settings.onDocumentDragLeave; + } + documentListeners['dragover.' + settings.namespace] = fileUpload.onDocumentDragOver; + documentListeners['drop.' + settings.namespace] = fileUpload.onDocumentDrop; + $(document).bind(documentListeners); + if (typeof settings.onDragEnter === func) { + dropZoneListeners['dragenter.' + settings.namespace] = settings.onDragEnter; + } + if (typeof settings.onDragLeave === func) { + dropZoneListeners['dragleave.' + settings.namespace] = settings.onDragLeave; + } + dropZoneListeners['dragover.' + settings.namespace] = fileUpload.onDragOver; + dropZoneListeners['drop.' + settings.namespace] = fileUpload.onDrop; + settings.dropZone.bind(dropZoneListeners); + } + fileInputListeners['change.' + settings.namespace] = fileUpload.onChange; + fileInput.bind(fileInputListeners); + }, + + removeEventHandlers = function () { + $.each(documentListeners, function (key, value) { + $(document).unbind(key, value); + }); + $.each(dropZoneListeners, function (key, value) { + settings.dropZone.unbind(key, value); + }); + $.each(fileInputListeners, function (key, value) { + fileInput.unbind(key, value); + }); + }, + + initUploadEventHandlers = function (files, index, xhr, settings) { + if (typeof settings.onProgress === func) { + xhr.upload.onprogress = function (e) { + settings.onProgress(e, files, index, xhr, settings); + }; + } + if (typeof settings.onLoad === func) { + xhr.onload = function (e) { + settings.onLoad(e, files, index, xhr, settings); + }; + } + if (typeof settings.onAbort === func) { + xhr.onabort = function (e) { + settings.onAbort(e, files, index, xhr, settings); + }; + } + if (typeof settings.onError === func) { + xhr.onerror = function (e) { + settings.onError(e, files, index, xhr, settings); + }; + } + }, + + getFormData = function (settings) { + if (typeof settings.formData === func) { + return settings.formData(); + } else if ($.isArray(settings.formData)) { + return settings.formData; + } else if (settings.formData) { + var formData = []; + $.each(settings.formData, function (name, value) { + formData.push({name: name, value: value}); + }); + return formData; + } + return []; + }, + + isSameDomain = function (url) { + if (protocolRegExp.test(url)) { + var host = location.host, + indexStart = location.protocol.length + 2, + index = url.indexOf(host, indexStart), + pathIndex = index + host.length; + if ((index === indexStart || index === url.indexOf('@', indexStart) + 1) && + (url.length === pathIndex || $.inArray(url.charAt(pathIndex), ['/', '?', '#']) !== -1)) { + return true; + } + return false; + } + return true; + }, + + nonMultipartUpload = function (file, xhr, sameDomain) { + if (sameDomain) { + xhr.setRequestHeader('X-File-Name', unescape(encodeURIComponent(file.name))); + } + xhr.setRequestHeader('Content-Type', file.type); + xhr.send(file); + }, + + formDataUpload = function (files, xhr, settings) { + var formData = new FormData(), + i; + $.each(getFormData(settings), function (index, field) { + formData.append(field.name, field.value); + }); + for (i = 0; i < files.length; i += 1) { + formData.append(settings.fieldName, files[i]); + } + xhr.send(formData); + }, + + loadFileContent = function (file, callBack) { + var fileReader = new FileReader(); + fileReader.onload = function (e) { + file.content = e.target.result; + callBack(); + }; + fileReader.readAsBinaryString(file); + }, + + buildMultiPartFormData = function (boundary, files, fields) { + var doubleDash = '--', + crlf = '\r\n', + formData = ''; + $.each(fields, function (index, field) { + formData += doubleDash + boundary + crlf + + 'Content-Disposition: form-data; name="' + + unescape(encodeURIComponent(field.name)) + + '"' + crlf + crlf + + unescape(encodeURIComponent(field.value)) + crlf; + }); + $.each(files, function (index, file) { + formData += doubleDash + boundary + crlf + + 'Content-Disposition: form-data; name="' + + unescape(encodeURIComponent(settings.fieldName)) + + '"; filename="' + unescape(encodeURIComponent(file.name)) + '"' + crlf + + 'Content-Type: ' + file.type + crlf + crlf + + file.content + crlf; + }); + formData += doubleDash + boundary + doubleDash + crlf; + return formData; + }, + + fileReaderUpload = function (files, xhr, settings) { + var boundary = '----MultiPartFormBoundary' + (new Date()).getTime(), + loader, + i; + xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary); + loader = new MultiLoader(function () { + xhr.sendAsBinary(buildMultiPartFormData( + boundary, + files, + getFormData(settings) + )); + }, files.length); + for (i = 0; i < files.length; i += 1) { + loadFileContent(files[i], loader.complete); + } + }, + + upload = function (files, index, xhr, settings) { + var sameDomain = isSameDomain(settings.url), + filesToUpload; + initUploadEventHandlers(files, index, xhr, settings); + xhr.open(settings.method, settings.url, true); + if (sameDomain) { + xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + } else if (settings.withCredentials) { + xhr.withCredentials = true; + } + if (!settings.multipart) { + nonMultipartUpload(files[index], xhr, sameDomain); + } else { + if (typeof index === num) { + filesToUpload = [files[index]]; + } else { + filesToUpload = files; + } + if (typeof FormData !== undef) { + formDataUpload(filesToUpload, xhr, settings); + } else if (typeof FileReader !== undef) { + fileReaderUpload(filesToUpload, xhr, settings); + } else { + $.error('Browser does neither support FormData nor FileReader interface'); + } + } + }, + + handleUpload = function (event, files, index) { + var xhr = new XMLHttpRequest(), + uploadSettings = $.extend({}, settings); + if (typeof settings.initUpload === func) { + settings.initUpload( + event, + files, + index, + xhr, + uploadSettings, + function () { + upload(files, index, xhr, uploadSettings); + } + ); + } else { + upload(files, index, xhr, uploadSettings); + } + }, + + handleFiles = function (event, files) { + var i; + if (settings.multiFileRequest) { + handleUpload(event, files); + } else { + for (i = 0; i < files.length; i += 1) { + handleUpload(event, files, i); + } + } + }, + + legacyUploadFormDataInit = function (input, settings) { + var formData = getFormData(settings); + uploadForm.find(':input').not(':disabled') + .attr('disabled', true) + .addClass(settings.namespace + '_disabled'); + $.each(formData, function (index, field) { + $('') + .attr('name', field.name) + .val(field.value) + .addClass(settings.namespace + '_form_data') + .insertBefore(fileInput); + }); + input.insertAfter(fileInput); + }, + + legacyUploadFormDataReset = function (input, settings) { + input.remove(); + uploadForm.find('.' + settings.namespace + '_disabled') + .removeAttr('disabled') + .removeClass(settings.namespace + '_disabled'); + uploadForm.find('.' + settings.namespace + '_form_data').remove(); + }, + + legacyUpload = function (input, iframe, settings) { + iframe + .unbind('abort') + .bind('abort', function (e) { + iframe.readyState = 0; + // javascript:false as iframe src prevents warning popups on HTTPS in IE6 + // concat is used here to prevent the "Script URL" JSLint error: + iframe.unbind('load').attr('src', 'javascript'.concat(':false;')); + if (typeof settings.onAbort === func) { + settings.onAbort(e, [{name: input.val(), type: null, size: null}], 0, iframe, settings); + } + }) + .unbind('load') + .bind('load', function (e) { + iframe.readyState = 4; + if (typeof settings.onLoad === func) { + settings.onLoad(e, [{name: input.val(), type: null, size: null}], 0, iframe, settings); + } + }); + uploadForm + .attr('action', settings.url) + .attr('target', iframe.attr('name')); + legacyUploadFormDataInit(input, settings); + iframe.readyState = 2; + uploadForm.get(0).submit(); + legacyUploadFormDataReset(input, settings); + }, + + handleLegacyUpload = function (event, input) { + // javascript:false as iframe src prevents warning popups on HTTPS in IE6: + var iframe = $(''), + uploadSettings = $.extend({}, settings); + iframe.readyState = 0; + iframe.abort = function () { + iframe.trigger('abort'); + }; + iframe.bind('load', function () { + iframe.unbind('load'); + if (typeof settings.initUpload === func) { + settings.initUpload( + event, + [{name: input.val(), type: null, size: null}], + 0, + iframe, + uploadSettings, + function () { + legacyUpload(input, iframe, uploadSettings); + } + ); + } else { + legacyUpload(input, iframe, uploadSettings); + } + }).appendTo(uploadForm); + }, + + resetFileInput = function () { + var inputClone = fileInput.clone(true); + $('
').append(inputClone).get(0).reset(); + fileInput.replaceWith(inputClone); + fileInput = inputClone; + }; + + this.onDocumentDragOver = function (e) { + if (typeof settings.onDocumentDragOver === func && + settings.onDocumentDragOver(e) === false) { + return false; + } + e.preventDefault(); + }; + + this.onDocumentDrop = function (e) { + if (typeof settings.onDocumentDrop === func && + settings.onDocumentDrop(e) === false) { + return false; + } + e.preventDefault(); + }; + + this.onDragOver = function (e) { + if (typeof settings.onDragOver === func && + settings.onDragOver(e) === false) { + return false; + } + var dataTransfer = e.originalEvent.dataTransfer; + if (dataTransfer) { + dataTransfer.dropEffect = dataTransfer.effectAllowed = 'copy'; + } + e.preventDefault(); + }; + + this.onDrop = function (e) { + if (typeof settings.onDrop === func && + settings.onDrop(e) === false) { + return false; + } + var dataTransfer = e.originalEvent.dataTransfer; + if (dataTransfer && dataTransfer.files && isXHRUploadCapable()) { + handleFiles(e, dataTransfer.files); + } + e.preventDefault(); + }; + + this.onChange = function (e) { + if (typeof settings.onChange === func && + settings.onChange(e) === false) { + return false; + } + if (!settings.forceIframeUpload && e.target.files && isXHRUploadCapable()) { + handleFiles(e, e.target.files); + } else { + handleLegacyUpload(e, $(e.target)); + } + resetFileInput(); + }; + + this.init = function (options) { + if (options) { + $.extend(settings, options); + } + if (container.data(settings.namespace)) { + $.error('FileUpload with namespace "' + settings.namespace + '" already assigned to this element'); + return; + } + container + .data(settings.namespace, fileUpload) + .addClass(settings.cssClass); + settings.dropZone.addClass(settings.cssClass); + initEventHandlers(); + }; + + this.destroy = function () { + removeEventHandlers(); + container + .removeData(settings.namespace) + .removeClass(settings.cssClass); + settings.dropZone.removeClass(settings.cssClass); + }; + }; + + methods = { + init : function (options) { + return this.each(function () { + (new FileUpload($(this))).init(options); + }); + }, + + destroy : function (namespace) { + return this.each(function () { + namespace = namespace ? namespace : 'file_upload'; + var fileUpload = $(this).data(namespace); + if (fileUpload) { + fileUpload.destroy(); + } else { + $.error('No FileUpload with namespace "' + namespace + '" assigned to this element'); + } + }); + + } + }; + + $.fn.fileUpload = 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('Method ' + method + ' does not exist on jQuery.fileUpload'); + } + }; + +}(jQuery)); \ No newline at end of file diff --git a/htdocs/includes/jquery/plugins/fileupload/pbar-ani.gif b/htdocs/includes/jquery/plugins/fileupload/pbar-ani.gif new file mode 100644 index 00000000000..0dfd45b885a Binary files /dev/null and b/htdocs/includes/jquery/plugins/fileupload/pbar-ani.gif differ