Skip to content

Commit

Permalink
Add support for JSON-P cross domain updates, like in the case where t…
Browse files Browse the repository at this point in the history
…he upload server is not the same as the web server

Signed-off-by: Piotr Sarnacki <drogus@gmail.com>
  • Loading branch information
deadprogram authored and drogus committed Feb 10, 2009
1 parent 54a24b6 commit a518b05
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 113 deletions.
23 changes: 21 additions & 2 deletions README
Expand Up @@ -37,17 +37,35 @@ $(function() {
/* scripts locations for safari */
jqueryPath: "../lib/jquery.js",
uploadProgressPath: "../jquery.uploadProgress.js",
/* function called each time bar is updated */
/* function called each time bar is updated */
uploading: function(upload) {$('#percents').html(upload.percents+'%');},
/* selector or element that will be updated */
progressBar: "#progressbar",
/* progress reports url */
progressUrl: "/progress",
/* how often will bar be updated */
/* how often will bar be updated */
interval: 2000
});
});

If you need to update the progress bar from a different domain or subdomain, liek if your upload server is different from your normal web server, you can try the JSON-P protocol, like this:
$(function() {
$('form').uploadProgress({
/* scripts locations for safari */
jqueryPath: "../lib/jquery.js",
uploadProgressPath: "../jquery.uploadProgress.js",
/* function called each time bar is updated */
uploading: function(upload) {$('#percents').html(upload.percents+'%');},
/* selector or element that will be updated */
progressBar: "#progressbar",
/* progress reports url in a different domain or subdomain from caller */
progressUrl: "uploads.somewhere.com/progress",
/* how often will bar be updated */
interval: 2000,
/* use json-p for cross-domain call */
dataType: 'jsonp'
});
});

defaults:

Expand All @@ -61,3 +79,4 @@ success: function() {}
error: function() {}
uploadProgressPath: '/javascripts/jquery.js'
jqueryPath: '/javascripts/jquery.uploadProgress.js'
dataType: 'json'
219 changes: 108 additions & 111 deletions jquery.uploadProgress.js
@@ -1,119 +1,116 @@
/*
* jquery.uploadProgress
*
* Copyright (c) 2008 Piotr Sarnacki (drogomir.com)
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
*/
* jquery.uploadProgress
*
* Copyright (c) 2008 Piotr Sarnacki (drogomir.com)
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
*/
(function($) {
$.fn.uploadProgress = function(options) {
options = $.extend({
interval: 2000,
progressBar: "#progressbar",
progressUrl: "/progress",
start: function() {},
uploading: function() {},
complete: function() {},
success: function() {},
error: function() {},
preloadImages: [],
uploadProgressPath: '/javascripts/jquery.uploadProgress.js',
jqueryPath: '/javascripts/jquery.js',
timer: ""
}, options);

$(function() {
//preload images
for(var i = 0; i<options.preloadImages.length; i++)
{
options.preloadImages[i] = $("<img>").attr("src", options.preloadImages[i]);
}
/* tried to add iframe after submit (to not always load it) but it won't work.
safari can't get scripts properly while submitting files */
if($.browser.safari && top.document == document) {
/* iframe to send ajax requests in safari
thanks to Michele Finotto for idea */
iframe = document.createElement('iframe');
iframe.name = "progressFrame";
$(iframe).css({width: '0', height: '0', position: 'absolute', top: '-3000px'});
document.body.appendChild(iframe);

var d = iframe.contentWindow.document;
d.open();
/* weird - safari won't load scripts without this lines... */
d.write('<html><head></head><body></body></html>');
d.close();

var b = d.body;
var s = d.createElement('script');
s.src = options.jqueryPath;
/* must be sure that jquery is loaded */
s.onload = function() {
var s1 = d.createElement('script');
s1.src = options.uploadProgressPath;
b.appendChild(s1);
}
b.appendChild(s);
}
});
options = $.extend({
dataType: "json",
interval: 2000,
progressBar: "#progressbar",
progressUrl: "/progress",
start: function() {},
uploading: function() {},
complete: function() {},
success: function() {},
error: function() {},
preloadImages: [],
uploadProgressPath: '/javascripts/jquery.uploadProgress.js',
jqueryPath: '/javascripts/jquery.js',
timer: ""
}, options);

return this.each(function(){
$(this).bind('submit', function() {
var uuid = "";
for (i = 0; i < 32; i++) { uuid += Math.floor(Math.random() * 16).toString(16); }

/* update uuid */
options.uuid = uuid;
/* start callback */
options.start();

/* patch the form-action tag to include the progress-id
if X-Progress-ID has been already added just replace it */
if(old_id = /X-Progress-ID=([^&]+)/.exec($(this).attr("action"))) {
var action = $(this).attr("action").replace(old_id[1], uuid);
$(this).attr("action", action);
} else {
$(this).attr("action", jQuery(this).attr("action") + "?X-Progress-ID=" + uuid);
}
var uploadProgress = $.browser.safari ? progressFrame.jQuery.uploadProgress : jQuery.uploadProgress;
options.timer = window.setInterval(function() { uploadProgress(this, options) }, options.interval);
});
});
$(function() {
//preload images
for(var i = 0; i<options.preloadImages.length; i++)
{
options.preloadImages[i] = $("<img>").attr("src", options.preloadImages[i]);
}
/* tried to add iframe after submit (to not always load it) but it won't work.
safari can't get scripts properly while submitting files */
if($.browser.safari && top.document == document) {
/* iframe to send ajax requests in safari
thanks to Michele Finotto for idea */
iframe = document.createElement('iframe');
iframe.name = "progressFrame";
$(iframe).css({width: '0', height: '0', position: 'absolute', top: '-3000px'});
document.body.appendChild(iframe);

var d = iframe.contentWindow.document;
d.open();
/* weird - safari won't load scripts without this lines... */
d.write('<html><head></head><body></body></html>');
d.close();

var b = d.body;
var s = d.createElement('script');
s.src = options.jqueryPath;
/* must be sure that jquery is loaded */
s.onload = function() {
var s1 = d.createElement('script');
s1.src = options.uploadProgressPath;
b.appendChild(s1);
}
b.appendChild(s);
}
});

return this.each(function(){
$(this).bind('submit', function() {
var uuid = "";
for (i = 0; i < 32; i++) { uuid += Math.floor(Math.random() * 16).toString(16); }

/* update uuid */
options.uuid = uuid;
/* start callback */
options.start();

/* patch the form-action tag to include the progress-id if X-Progress-ID has been already added just replace it */
if(old_id = /X-Progress-ID=([^&]+)/.exec($(this).attr("action"))) {
var action = $(this).attr("action").replace(old_id[1], uuid);
$(this).attr("action", action);
} else {
$(this).attr("action", jQuery(this).attr("action") + "?X-Progress-ID=" + uuid);
}
var uploadProgress = $.browser.safari ? progressFrame.jQuery.uploadProgress : jQuery.uploadProgress;
options.timer = window.setInterval(function() { uploadProgress(this, options) }, options.interval);
});
});
};

jQuery.uploadProgress = function(e, options) {
jQuery.ajax({
type: "GET",
url: options.progressUrl,
dataType: "json",
beforeSend: function(xhr) {
xhr.setRequestHeader("X-Progress-ID", options.uuid);
},
success: function(upload) {
if (upload.state == 'uploading') {
upload.percents = Math.floor((upload.received / upload.size)*1000)/10;

var bar = $.browser.safari ? $(options.progressBar, parent.document) : $(options.progressBar);
bar.css({width: upload.percents+'%'});
options.uploading(upload);
}

if (upload.state == 'done' || upload.state == 'error') {
window.clearTimeout(options.timer);
options.complete(upload);
}

if (upload.state == 'done') {
options.success(upload);
}

if (upload.state == 'error') {
options.error(upload);
}
}
});
jQuery.ajax({
type: "GET",
url: options.progressUrl + "?X-Progress-ID=" + options.uuid,
dataType: options.dataType,
success: function(upload) {
if (upload.state == 'uploading') {
upload.percents = Math.floor((upload.received / upload.size)*1000)/10;

var bar = $.browser.safari ? $(options.progressBar, parent.document) : $(options.progressBar);
bar.css({width: upload.percents+'%'});
options.uploading(upload);
}

if (upload.state == 'done' || upload.state == 'error') {
window.clearTimeout(options.timer);
options.complete(upload);
}

if (upload.state == 'done') {
options.success(upload);
}

if (upload.state == 'error') {
options.error(upload);
}
}
});
};

})(jQuery);

0 comments on commit a518b05

Please sign in to comment.