JQuery plugins : Use jquery-upload-progress and jquery validation together
I would like to use these two JQuery plugins on the same form :
- JQuery validation plugin : http://bassistance.de/jquery-plugins/jquery-plugin-validation/
- JQuery-upload-progress : http://github.com/drogus/jquery-upload-progress
The behavior that I would like to have:
- Validate the form with the validation plugin
- If no error start the upload and the uploadProgress plugin. If errors, show them and don't start the uploadProgress plugin.
The two plugins work well separately. When I apply both on the same form, it works well if all is correct. When there are errors in the form, the uploadProgress starts (the start and uploading functions run) but the actual upload doesn't. It shows an upload bar that will never change because the form is not submitted.
I think that the problem comes from the fact that the two plugins register something to execute when the submit button is pressed.
Here is my JavaScript (updated after the first answer, but the problem is still here):
/* ---------------------------------
* Parameters for the form validator
* --------------------------------- */
$.validator.setDefaults({
highlight: function(input) {
$(input).addClass("highlight");
},
unhighlight: function(input) {
$(input).removeClass("highlight");
}
});
$(document).ready(function(){
/* ----------------------
* Validator registration
* ---------------------- */
$("#upload_form").validate({
rules: {
title: {
required: true,
minlength: 5,
maxlength: 100
},
file: {
required: true,
accept: 'ogg|ogv|avi|mpe?g|mov|wmv|flv|mp4'
}
},
messages: {
title: {
required: "Please enter a title for the video",
minlength: jQuery.format("The title must be at least {0} characters long"),
maxlength: jQuery.format("The title must be shorter than {0} characters")
},
file: {
required: "Please choose a video file to upload",
accept: "Please choose a valid video file (ogg, ogv, avi, mpg, mpeg, mov, flv, mp4)"
}
}
});
/* ---------------
* Upload progress
* --------------- */
$('#upload_form').uploadProgress({
/* scripts locations for safari */
jqueryPath: "{{MEDIA_URL|default:'/media/'}}js/jquery.uploadProgress.js",
uploadProgressPath: "{{MEDIA_URL|default:'/media/'}}js/jquery.uploadProgress.js",
/* selector or element that will be updated */
progressBar: "#progress_indicator",
/* progress reports url */
progressUrl: '/upload/progress/',
/* function called just before starting the upload */
start: function() {
$("#upload_form").hide();
filename = $("#id_file").val().split(/[\/\\]/).pop();
fmts = gettext("Uploading %(filename)s...");
dat = {
filename: filename
};
s = interpolate(fmts,dat,true);
$("#progress_filename").html(s);
$("#progress_container").show();
},
/* function called each time bar is updated */
uploading: function(upload) {
if (upload.percents >= 100) {
window.clearTimeout(this.timer);
fmts = gettext("Saving %(filename)s...");
dat = {
filename: filename
开发者_如何学运维 };
s = interpolate(fmts,dat,true);
$("#progress_filename").html(s);
} else {
fmts = gettext("Uploading %(filename)s : %(percents)s%...");
dat = {
filename: filename,
percents: upload.percents
};
s = interpolate(fmts,dat,true);
$("#progress_filename").html(s);
}
},
/* how often will bar be updated */
interval: 1000
});
});
And the related HTML:
<form id="upload_form" action="/upload/" method="post" enctype="multipart/form-data">
<label for="id_title">Title</label>: <input id="id_title" type="text" name="title"/>
<br/>
<label for="id_description">Description</label>: <input id="id_description" type="text" name="description" />
<br/>
<label for="id_file">File</label>: <input type="file" name="file" id="id_file" />
</div>
<div>
<!-- <button type="submit" class="accept" >Submit</button> -->
<input type="submit" value="Submit" />
</div>
</form>
<div id="progress_container">
<div id="progress_filename"></div>
<div id="progress_bar">
<div id="progress_indicator"></div>
</div>
</div>
Note : the progress_container div is hidden via CSS at page load.
My temporary fix for the problem was to deactivate the validation on submit and only use the other events, but I would like to validate on submit too.
Problem is that jquery-plugin-validation submits form before JQuery-upload-progress modify form param "action" with "X-Progress-ID" identifier.
To fix this problem you need following workaround: set "X-Progress-ID" identifier to form before initializing plugin-validation and pass this identifier to JQuery-upload-progress.
Code example:
var UUID="";
for (i = 0; i < 32; i++) { UUID += Math.floor(Math.random() * 16).toString(16); }
$("#myform").validate({
rules:{....},
submitHandler: function(form) {
/* 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($("#myform").attr("action"))) {
var action = $("#myform").attr("action").replace(old_id[1], UUID);
$("#myform").attr("action", action);
} else {
var action = $("#myform").attr("action");
var action_sep = (action.lastIndexOf("?") != -1) ? "&": "?";
$("#myform").attr("action", action + action_sep + "X-Progress-ID=" + UUID);
}
form.submit();
}
});
Than initialize JQuery-upload-progress and pass generated UUID
$(" $("#myform").uploadProgress({
uuid: UUID,
jqueryPath:....,
uploadProgressPath:...,
and finally fix at jquery.uploadProgress.js 1) add uuid at constructor
options = $.extend({
uuid: false,
dataType: "json",
interval: 2000,
progressBar: "#progressbar",
2) change binding functionality:
return this.each(function(){
$(this).bind('submit', function() {
var uuid = options.uuid;
if(!options.uuid ){
uuid = "";
for (i = 0; i < 32; i++) { uuid += Math.floor(Math.random() * 16).toString(16); }
}
/* update uuid */
options.uuid = uuid;
/* start callback */
options.start(uuid);
Thats all.
The upload progress connectes to the submit event. And thus yiour form is "submitting" first and then stopped by the validation. If you first register the validation and then the upload it might work.
You could/should also check wether to to start the upload at the "start" callback.
By the way:
$(document).ready(function() {
$(function() {
seens a bit to much, it's 2 times the same function.
$(function() {
should work fine.
This "should" work:
$.validator.setDefaults({
highlight: function(input) {
$(input).addClass("highlight");
},
unhighlight: function(input) {
$(input).removeClass("highlight");
} });
$(function() {
/* ----------------------
* Init form validation
* ---------------------- */
$("#upload_form").validate({
rules: {
title: {
required: true,
minlength: 5,
maxlength: 100
},
file: {
required: true,
accept: 'ogg|ogv|avi|mpe?g|mov|wmv|flv|mp4'
}
},
messages: {
title: {
required: "Please enter a title for the video",
minlength: "The title must be at least 5 characters long",
maxlength: "The title must be shorter than 100 characters"
},
file: {
required: "Please choose a video file to upload",
accept: "Please choose a valid video file (ogg, ogv, avi, mpg, mpeg, mov, flv, mp4)"
}
}
});
/* ---------------
* Upload progress
* --------------- */
$('#upload_form').uploadProgress({
/* selector or element that will be updated */
progressBar: "#progress_indicator",
/* progress reports url */
progressUrl: '/upload/progress/',
/* function called just before starting the upload */
start: function() {
if (!$("#upload_form").valid()) {
return false;
}
$("#upload_form").hide();
$("#progress_filename").html("Uploading file...");
$("#progress_container").show();
},
/* function called each time bar is updated */
uploading: function(upload) {
if (upload.percents >= 100) {
window.clearTimeout(this.timer);
$("#progress_filename").html(Saving file...);
} else {
$("#progress_filename").html("Uploading file : " + upload.percents + "%...");
}
},
/* how often will bar be updated */
interval: 1000
});
});
精彩评论