Chamilo is a learning management system focused on ease of use and accessibility
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
chamilo-lms/main/inc/lib/javascript/jquery-upload/jquery.fileupload.js

629 lines
25 KiB

/*
* jQuery File Upload Plugin 3.7.1
*
* 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 defaultNamespace = 'file_upload',
undef = 'undefined',
func = 'function',
num = 'number',
FileUpload,
methods,
MultiLoader = function (callBack, numberComplete) {
var loaded = 0;
this.complete = function () {
loaded += 1;
if (loaded === numberComplete) {
callBack();
}
};
};
FileUpload = function (container) {
var fileUpload = this,
uploadForm,
fileInput,
settings = {
namespace: defaultNamespace,
uploadFormFilter: function (index) {
return true;
},
fileInputFilter: function (index) {
return true;
},
cssClass: defaultNamespace,
dragDropSupport: true,
dropZone: container,
url: function (form) {
return form.attr('action');
},
method: function (form) {
return form.attr('method');
},
fieldName: function (input) {
return input.attr('name');
},
formData: function (form) {
return form.serializeArray();
},
multipart: true,
multiFileRequest: false,
withCredentials: false,
forceIframeUpload: false
},
documentListeners = {},
dropZoneListeners = {},
protocolRegExp = /^http(s)?:\/\//,
optionsReference,
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] = function (e) {
settings.onDocumentDragEnter(e);
};
}
if (typeof settings.onDocumentDragLeave === func) {
documentListeners['dragleave.' + settings.namespace] = function (e) {
settings.onDocumentDragLeave(e);
};
}
documentListeners['dragover.' + settings.namespace] = fileUpload.onDocumentDragOver;
documentListeners['drop.' + settings.namespace] = fileUpload.onDocumentDrop;
$(document).bind(documentListeners);
if (typeof settings.onDragEnter === func) {
dropZoneListeners['dragenter.' + settings.namespace] = function (e) {
settings.onDragEnter(e);
};
}
if (typeof settings.onDragLeave === func) {
dropZoneListeners['dragleave.' + settings.namespace] = function (e) {
settings.onDragLeave(e);
};
}
dropZoneListeners['dragover.' + settings.namespace] = fileUpload.onDragOver;
dropZoneListeners['drop.' + settings.namespace] = fileUpload.onDrop;
settings.dropZone.bind(dropZoneListeners);
}
fileInput.bind('change.' + settings.namespace, fileUpload.onChange);
},
removeEventHandlers = function () {
$.each(documentListeners, function (key, value) {
$(document).unbind(key, value);
});
$.each(dropZoneListeners, function (key, value) {
settings.dropZone.unbind(key, value);
});
fileInput.unbind('change.' + settings.namespace);
},
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);
};
}
},
getUrl = function (settings) {
if (typeof settings.url === func) {
return settings.url(settings.uploadForm || uploadForm);
}
return settings.url;
},
getMethod = function (settings) {
if (typeof settings.method === func) {
return settings.method(settings.uploadForm || uploadForm);
}
return settings.method;
},
getFieldName = function (settings) {
if (typeof settings.fieldName === func) {
return settings.fieldName(settings.fileInput || fileInput);
}
return settings.fieldName;
},
getFormData = function (settings) {
var formData;
if (typeof settings.formData === func) {
return settings.formData(settings.uploadForm || uploadForm);
} else if ($.isArray(settings.formData)) {
return settings.formData;
} else if (settings.formData) {
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(getFieldName(settings), 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, filesFieldName, 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(filesFieldName)) +
'"; 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,
getFieldName(settings),
getFormData(settings)
));
}, files.length);
for (i = 0; i < files.length; i += 1) {
loadFileContent(files[i], loader.complete);
}
},
upload = function (files, index, xhr, settings) {
var url = getUrl(settings),
sameDomain = isSameDomain(url),
filesToUpload;
initUploadEventHandlers(files, index, xhr, settings);
xhr.open(getMethod(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, input, form, index) {
var xhr = new XMLHttpRequest(),
uploadSettings = $.extend({}, settings);
uploadSettings.fileInput = input;
uploadSettings.uploadForm = form;
if (typeof uploadSettings.initUpload === func) {
uploadSettings.initUpload(
event,
files,
index,
xhr,
uploadSettings,
function () {
upload(files, index, xhr, uploadSettings);
}
);
} else {
upload(files, index, xhr, uploadSettings);
}
},
handleFiles = function (event, files, input, form) {
var i;
if (settings.multiFileRequest) {
handleUpload(event, files, input, form);
} else {
for (i = 0; i < files.length; i += 1) {
handleUpload(event, files, input, form, i);
}
}
},
legacyUploadFormDataInit = function (input, form, settings) {
var formData = getFormData(settings);
form.find(':input').not(':disabled')
.attr('disabled', true)
.addClass(settings.namespace + '_disabled');
$.each(formData, function (index, field) {
$('<input type="hidden"/>')
.attr('name', field.name)
.val(field.value)
.addClass(settings.namespace + '_form_data')
.appendTo(form);
});
input
.attr('name', getFieldName(settings))
.appendTo(form);
},
legacyUploadFormDataReset = function (input, form, settings) {
input.detach();
form.find('.' + settings.namespace + '_disabled')
.removeAttr('disabled')
.removeClass(settings.namespace + '_disabled');
form.find('.' + settings.namespace + '_form_data').remove();
},
legacyUpload = function (input, form, iframe, settings) {
var originalAction = form.attr('action'),
originalMethod = form.attr('method'),
originalTarget = form.attr('target');
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);
}
// Fix for IE endless progress bar activity bug (happens on form submits to iframe targets):
$('<iframe src="javascript:false;" style="display:none"></iframe>').appendTo(form).remove();
});
form
.attr('action', getUrl(settings))
.attr('method', getMethod(settings))
.attr('target', iframe.attr('name'));
legacyUploadFormDataInit(input, form, settings);
iframe.readyState = 2;
form.get(0).submit();
legacyUploadFormDataReset(input, form, settings);
form
.attr('action', originalAction)
.attr('method', originalMethod)
.attr('target', originalTarget);
},
handleLegacyUpload = function (event, input, form) {
// javascript:false as iframe src prevents warning popups on HTTPS in IE6:
var iframe = $('<iframe src="javascript:false;" style="display:none" name="iframe_' +
settings.namespace + '_' + (new Date()).getTime() + '"></iframe>'),
uploadSettings = $.extend({}, settings);
uploadSettings.fileInput = input;
uploadSettings.uploadForm = form;
iframe.readyState = 0;
iframe.abort = function () {
iframe.trigger('abort');
};
iframe.bind('load', function () {
iframe.unbind('load');
if (typeof uploadSettings.initUpload === func) {
uploadSettings.initUpload(
event,
[{name: input.val(), type: null, size: null}],
0,
iframe,
uploadSettings,
function () {
legacyUpload(input, form, iframe, uploadSettings);
}
);
} else {
legacyUpload(input, form, iframe, uploadSettings);
}
}).appendTo(form);
},
initUploadForm = function () {
uploadForm = (container.is('form') ? container : container.find('form'))
.filter(settings.uploadFormFilter);
},
initFileInput = function () {
fileInput = uploadForm.find('input:file')
.filter(settings.fileInputFilter);
},
replaceFileInput = function (input) {
var inputClone = input.clone(true);
$('<form/>').append(inputClone).get(0).reset();
input.after(inputClone).detach();
initFileInput();
};
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;
}
var input = $(e.target),
form = $(e.target.form);
if (form.length === 1) {
input.data(defaultNamespace + '_form', form);
replaceFileInput(input);
} else {
form = input.data(defaultNamespace + '_form');
}
if (!settings.forceIframeUpload && e.target.files && isXHRUploadCapable()) {
handleFiles(e, e.target.files, input, form);
} else {
handleLegacyUpload(e, input, form);
}
};
this.init = function (options) {
if (options) {
$.extend(settings, options);
optionsReference = options;
}
initUploadForm();
initFileInput();
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.not(container).addClass(settings.cssClass);
initEventHandlers();
};
this.options = function (options) {
var oldCssClass,
oldDropZone,
uploadFormFilterUpdate,
fileInputFilterUpdate;
if (typeof options === undef) {
return $.extend({}, settings);
}
if (optionsReference) {
$.extend(optionsReference, options);
}
removeEventHandlers();
$.each(options, function (name, value) {
switch (name) {
case 'namespace':
$.error('The FileUpload namespace cannot be updated.');
return;
case 'uploadFormFilter':
uploadFormFilterUpdate = true;
fileInputFilterUpdate = true;
break;
case 'fileInputFilter':
fileInputFilterUpdate = true;
break;
case 'cssClass':
oldCssClass = settings.cssClass;
break;
case 'dropZone':
oldDropZone = settings.dropZone;
break;
}
settings[name] = value;
});
if (uploadFormFilterUpdate) {
initUploadForm();
}
if (fileInputFilterUpdate) {
initFileInput();
}
if (typeof oldCssClass !== undef) {
container
.removeClass(oldCssClass)
.addClass(settings.cssClass);
(oldDropZone ? oldDropZone : settings.dropZone).not(container)
.removeClass(oldCssClass);
settings.dropZone.not(container).addClass(settings.cssClass);
} else if (oldDropZone) {
oldDropZone.not(container).removeClass(settings.cssClass);
settings.dropZone.not(container).addClass(settings.cssClass);
}
initEventHandlers();
};
this.option = function (name, value) {
var options;
if (typeof value === undef) {
return settings[name];
}
options = {};
options[name] = value;
fileUpload.options(options);
};
this.destroy = function () {
removeEventHandlers();
container
.removeData(settings.namespace)
.removeClass(settings.cssClass);
settings.dropZone.not(container).removeClass(settings.cssClass);
};
};
methods = {
init : function (options) {
return this.each(function () {
(new FileUpload($(this))).init(options);
});
},
option: function (option, value, namespace) {
namespace = namespace ? namespace : defaultNamespace;
var fileUpload = $(this).data(namespace);
if (fileUpload) {
if (typeof option === 'string') {
return fileUpload.option(option, value);
}
return fileUpload.options(option);
} else {
$.error('No FileUpload with namespace "' + namespace + '" assigned to this element');
}
},
destroy : function (namespace) {
namespace = namespace ? namespace : defaultNamespace;
return this.each(function () {
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));