Last active
December 15, 2015 21:09
-
-
Save maca/5323739 to your computer and use it in GitHub Desktop.
jQuery xhr uploads plugin.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* jQuery XHR upload plugin | |
* http://github.com/maca | |
* | |
* Copyright 2011, Macario Ortega | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* | |
*/ | |
(function($){ | |
$.fn.ajaxyUpload = function(opts) { | |
var settings = { | |
error : $.noop, | |
success : $.noop, | |
start : $.noop, | |
complete : $.noop, | |
cancelText : 'cancel', | |
spinner : {color : '#555', lines : 6, length : 2, width : 9, radius : 6} | |
}; | |
return $(this).each(function(){ | |
var fileInput = $(this); | |
if (opts) { $.extend(settings, opts); } | |
fileInput.attr("multiple", "multiple"); | |
// xhrUpload callback, this is triggered below only if the browser has hxr upload | |
// capabilities | |
fileInput.bind('xhrUpload', function(){ | |
var self = this; | |
$.each(this.files, function(index, file){ | |
var advance = $('<div>').addClass('inline-upload-advance'); | |
var pBar = $('<div>').addClass('inline-upload-progress-bar').append(advance); | |
var cancelLink = $('<a href="#">').addClass('inline-upload-cancel-link').text(settings.cancelText); | |
var uploadStatus = $('<div>').addClass('inline-upload-upload-status').append(pBar).append(cancelLink).click(function(){ | |
$(self).trigger('cancelUpload'); | |
return false; | |
}); | |
advance.css('height','10px'); | |
advance.css('background-color', '#33a'); | |
advance.css('width', '0px'); | |
pBar.css('width','200px'); | |
pBar.css('background-color','#fff'); | |
pBar.css('border','1px solid #BBB'); | |
fileInput.after(uploadStatus); | |
var xhrUpload = $.ajax({ | |
type : "POST", | |
url : settings.url, | |
xhr : function(){ | |
var xhr = $.ajaxSettings.xhr(); | |
xhr.upload.onprogress = function(rpe) { | |
var progress = (rpe.loaded / rpe.total * 100 >> 0) + '%'; | |
advance.css('width', progress); | |
}; | |
xhr.onloadstart = function(){ | |
fileInput.val(''); | |
settings.start.apply(self); | |
}; | |
return xhr; | |
}, | |
beforeSend : function(xhr){ | |
// here we set custom headers for the rack middleware, first one tells the Rack app we are doing | |
// an xhr upload, the two others are self explanatory | |
xhr.setRequestHeader("X-XHR-Upload", "1"); | |
xhr.setRequestHeader("X-File-Name", file.name || file.fileName); | |
xhr.setRequestHeader("X-File-Size", file.fileSize); | |
}, | |
success : function(data, status, xhr) { | |
settings.success.apply(self, [data, status, xhr]); | |
}, | |
error : function(xhr, text, error) { | |
if (xhr.status == 422) { | |
settings.error.apply(self, [$.parseJSON(xhr.responseText)]); | |
} else if (text != 'abort') { | |
settings.error.apply(self); | |
}; | |
}, | |
complete : function(xhr, status) { | |
settings.complete.apply(self); | |
uploadStatus.remove(); | |
}, | |
contentType : file.type || "application/octet-stream", | |
dataType : "json", | |
processData : false, | |
data : file | |
}); | |
$(self).bind('cancelUpload', function(){ | |
xhrUpload.abort(); | |
uploadStatus.remove(); | |
if($.browser.msie){ | |
correctInput($('#main_uploader')).show(); | |
correctInput($('#project_uploader')).show(); | |
}else{ | |
$('#main_uploader').find('a.upload_image').show(); | |
$('#project_uploader').find('a.upload_image').show(); | |
} | |
return true; | |
}) | |
}); | |
}); | |
// set an iframeUpload callback as fallback for older browsers | |
fileInput.bind('iframeUpload', function(){ | |
var input = $("<input type='file' class='inline-upload-input'>").attr('name', 'file'); | |
var iframe = $("<iframe class='inline-upload-catcher' name='inline-upload-catcher-" + new Date().getTime() + "'></iframe>").hide(); | |
var spinner = $('<div>').addClass('spinner').hide(); | |
var auth = $("<input type='hidden' name='authenticity_token'>").val( $('input[name=authenticity_token]').val() ); // Rails authenticity token | |
var form = $("<form enctype='multipart/form-data' method='post' action=" + settings.url + "></form>").addClass('inline-upload-form').append(input).append(auth); | |
form.attr('target', iframe.attr('name')); | |
new Spinner(settings.spinner).spin(spinner[0]); | |
spinner.css('height', spinner.css('height') || '10px'); | |
spinner.css('height', spinner.css('height') || '10px'); | |
spinner.css('z-index', spinner.css('z-index') || '3000'); | |
$(this).after(form).after(iframe).hide(); | |
input.after(spinner); | |
input.bind('complete', function(event, data){ | |
if (data.errors != undefined && data.errors != null) { | |
settings.error.apply(this, [data]); | |
} else { | |
settings.success.apply(this, [data]); | |
}; | |
spinner.hide(); | |
settings.complete.apply(this); | |
}); | |
input.change(function(){ | |
settings.start.apply(this); | |
spinner.show(); | |
form.submit(); | |
$(this).val(''); | |
}); | |
iframe.load(function(){ | |
var script = $(this).contents().find('script'); | |
if (script.size() > 0) { | |
var data = script.html() | |
input.trigger('complete', [$.parseJSON(data)]); | |
} | |
}); | |
}); | |
// Not used just to check browser capabilities | |
var xhr = $.ajaxSettings.xhr(); | |
// If the browser has xhr upload capabilities trigger xhrUpload otherwise fallback to iframe upload | |
if (this.files && xhr && xhr.upload && (xhr.upload.onprogress !== undefined) && window.FileReader) { | |
fileInput.change(function(){ $(this).trigger('xhrUpload') }); | |
} else { | |
fileInput.trigger('iframeUpload'); | |
}; | |
}) | |
}; | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment