I'm using jQuery 1.11.1 and jQuery validation plugin
I have added the following script to my contact form to validate it and send via AJAX ({{hash_tag}} in code is Twig variable):
<script>
$("#contactform").validate({
rules: {
content_{{ hash_tag }}: {
required: true,
minlength: 20
},
name_{{ hash_tag }}: {
required: true,
minlength: 2
},
subject_{{ hash_tag }}: {
required: true,
minlength: 10
},
email_{{ hash_tag }}: {
required: true,
email: true
}
},
submitHandler: function(form) {
var postData = $(form).serializeArray();
var formURL = $(form).attr("action");
$.ajax(
{
url : formURL,
type: "POST",
data : postData,
success:function(data, textStatus, jqXHR)
{
$('#articlecontent').html(data.content);
$("html, body").animate({ scrollTop: 0 });
},
error: function(jqXHR, exception)
{
$(form).submit();
}
});
}
});
</script>
The script (after small testing) seems to work. But the problem is - when user have filled in form correctly and when PHP is sending email it may take a few seconds. User after clicking submit button of course doesn't have to know that form is send via AJAX and may think that something is not working ok and may for example click again or do something else.
The question is - how to show user that after clicking something is happening and email will be send in a few seconds? I don't know what's the best practice to do that. Please give me some nice solution. Progress bar is not necessary I think (it's probably hard to determine how long it would take) but maybe some other effect would be fine.
EDIT
After changing submitHandler I have now:
submitHandler: function(form) {
var postData = $(form).serializeArray();
var formURL = $(form).attr("action");
$.ajax(
{
url : formURL,
type: "POST",
data : postData,
beforeSend: function (){
$(form).hide();
$("#formsending").show();
},
success:function(data, textStatus, jqXHR)
{
$('#articlecontent').html(data.content);
$("html, body").animate({ scrollTop: 0 });
},
error: function(jqXHR, exception)
{
$(form).submit();
},
complete: function (){
$("#formsending").hide();
$(form).show();
}
});
}
It works somehow but still not exactly 100% I wanted. When I click send, form is being hidden and info that email is sending is being displayed but on server-site I have also data validation. Let's assume some complex validation cannot be done by jQuery/HTML5 and it must be done in PHP. When user clicks submit even form is invalid for a small time info that email is being sent is displayed. Is it possible somehow to launch beforeSend (or maybe some similar action) for example after second or 0.5 second to make sure that email is in fact being sent?
There is a nice plug in to show a progress wheel whenever an ajax request is in progress.
jQuery BlockUI
This is especially nice since it will automatically show a progress wheel for any ajax request, so you don't have to specifically set it up everywhere you make ajax calls.
Using this plug in the only code you need to write is
$(document).ajaxStart($.blockUI).ajaxStop($.unblockUI);
EDIT (from question update)
If you want to only show the progress spinner when the validation is successful and the email is actually being sent then you could have a separate ajax call that just performs validation and doesn't show any kind of progress (it should not take too long just to validate) and then if that call is successful make a separate ajax call that actually sends the email and does show the spinner.
Example:
submitHandler: function(form) {
var postData = $(form).serializeArray();
var formURL = $(form).attr("action");
var validateURL = "something else";
$.ajax({
url : validateURL,
type: "POST",
data : postData,
success:function(data, textStatus, jqXHR)
{
if(data.MyFieldThatIndicatesSuccess) {
$.ajax({
url : formURL,
type: "POST",
data : postData,
beforeSend: function (){
$(form).hide();
$("#formsending").show();
},
success: function(data, textStatus, jqXHR) {
$('#articlecontent').html(data.content);
$("html, body").animate({ scrollTop: 0 });
},
error: function(jqXHR, exception) {
//handle error
}
complete: function (){
$("#formsending").hide();
$(form).show();
}
});
}
},
error: function(jqXHR, exception)
{
//handle error
}
});
}
If I understand your problem correctly, what you would like is some message or animation to show when the user presses submit and it to go away again once the php has done its thing?
If so you would just have to add some code at the commented areas to show/hide an element that shows a message or a spinner.
submitHandler: function(form) {
var postData = $(form).serializeArray();
var formURL = $(form).attr("action");
//Some code to make a div appear e.g.
//$("#contactform").append("<div class='loading'><img src='spinner.gif'></div>");
$.ajax(
{
url : formURL,
type: "POST",
data : postData,
success:function(data, textStatus, jqXHR)
{
//some code to make the div disapear e.g.
//$(".loading").remove();
$('#articlecontent').html(data.content);
$("html, body").animate({ scrollTop: 0 });
},
error: function(jqXHR, exception)
{
$(form).submit();
}
});
}
Related
I have an app that allows users at the same company on the same login to vote on specific items, therefore I'm unable to use IP to control how many times the user votes. How can I use jQuery to allow the user to only vote once?
jQuery:
$("#xmlDiv").on("click", ".upvote", function(e) {
var id = $(this).attr("id");
var main = $(this);
$.ajax({
type: 'post',
url: 'includes/upvote.php',
data: { "id":id },
success(data) {
main.parent().find("div.votenum").html(data);
},
error: function (xhr, textStatus, error) {
alert("Sorry!");
}
});
});
$("#xmlDiv").on("click", ".downvote", function(e) {
var main = $(this);
var id = $(this).attr("id");
$.ajax({
type: 'post',
url: 'includes/downvote.php',
data: { "id":id },
success(data) {
main.parent().find("div.votenum").html(data);
},
error: function (xhr, textStatus, error) {
alert("Sorry!");
}
});
});
HTML:
<img src="arrow-up-01-20.png" style="float:right;" class="upvote" id="5">
<img src="arrow-down-01-20.png" id="5" class="downvote" style="float:right;">
<div class="votenum" style="float:right;" id="5">12</div>
When the user click on upvote, you can add a class to the div voted
main.addClass("voted");
and you can check with hasClass("voted")
$("#xmlDiv").on("click", ".upvote", function(e) {
var id = $(this).attr("id");
var main = $(this);
if(main.hasClass("voted"))
return;
main.addClass("voted");
$.ajax({
type: 'post',
url: 'includes/upvote.php',
data: { "id":id },
success(data) {
main.parent().find("div.votenum").html(data);
},
error: function (xhr, textStatus, error) {
alert("Sorry!");
}
});
});
I suggest to control again at server side
jQuery can't retain memory across page loads. Refreshing the page makes any logic start from the start. You're solution is going to have to involve server logic.
As far as how to actually do this, if you can't use separate accounts or IPs, perhaps you could identify user by device, browser, and other identifying digital fingerprints. There are a lot and you can make a relatively secure vote, however, anyone with know how would be able to cheat on a vote that doesn't involve secure separate accounts.
I'm trying to load different templates through $.ajax based on what buttons a user clicks. I know how to do it with one template file, but can't seem to find a way to adjust the code to load different template based on click (without repeating the code).
Here's the relevant part of the ajax call:
var $this = $('#my-data');
$('#button-foo').click(function() {
$.ajax({
url: myAjax.ajax_url,
data: {
action: 'my_ajax_action'
},
cache: true,
beforeSend: function(){
$this.empty();
$this.addClass('loading');
},
complete: function(){
$this.removeClass('loading');
},
success: function(data) {
$this.append(data);
},
error: function(MLHttpRequest, textStatus, errorThrown){
alert(errorThrown);
}
});
});
And here's my Wordpress function:
function my_ajax_action() {
include(locate_template( 'part-template-foo.php' ));
die();
}
add_action('wp_ajax_nopriv_my_ajax_action', 'my_ajax_action');
add_action('wp_ajax_my_ajax_action', 'my_ajax_action');
Now what I need would be to include 4 different templates (part-template-bar.php, part-template-foobar.php, etc) based on user click. Something like:
function my_ajax_action() {
if ($_REQUEST['template'] == 'foo') {
include(locate_template( 'part-foo.php' ));
die();
}
if ($_REQUEST['template'] == 'bar') {
include(locate_template( 'part-bar.php' ));
die();
}
...
}
Any hint on how could I do this without having to repeat the js code and wp function four times? Thank you.
i am getting a form with user parameters when i make an AJAX call to a page which later on is submiited to a url so that i can create a session for the same user in advance and when
that person goes to that site he sees his name there.
i created one div tag with id "abc_session", assign that form (whose id is fm1) to it,and submitted the form.
now as per the requirement session is created but page automatically gets redirected to that site url to which form is submitted.i just don't wan't that to happen.
can anyone please suggest something..or some workaround
the form that AJAX returns looks something like this:
<html>
<body onload="document.fm1.submit();return false">
<form name = "fm1" method="post" action = "https://abcd.com/abc ">
<input type=hidden name ="name" value="xyz">
<input type=hidden name ="login_parameters" value="CDF5D71C5BDB942EE2FB6C285B8DEBFE4C5675137B615CD2276571813AAC872AC8942E26B71026414BED1FEA09427D0B20A50FE2F70032D2E5B382598EC3C71D73EAB4ECBF7273A73BEB98ACEA4A0B775E7772BDC7C6746C355">
</form></body>
</html>
and the script goes like this
$(document).ready(function() {
function callwebsite()
{
$.ajax({
url: "/NASApp/benemain/website",
data: {},
type:"POST",
dataType: 'text',
cache: false,
success: function (data) {
alert("Call made to website.. ");
console.log(data);
document.getElementById("abc_session").innerHTML=data;
document.fm1.submit();
},
error : function(response){
console.log('ERROR');
},
statusCode : {
500 : function() {
console.log('500 error');
window.location.reload(true);
},
401 : function() {
console.log('401 error');
window.location.reload(true);
},
404 : function(){
console.log('400 error');
}
}
});
}
callwebsite();
tried extracting the data and maiking another ajax call as suggested by quentin but getting this error "Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource.This can be fixed by moving the resource to the same domain or enabling CORS."
$.ajax({
url: lcAction,
data: {partner_id:lcPartner,login_parameters:lcLP },
type:"POST",
headers:{'Access-Control-Allow-Origin': '*'},
dataType: 'text',
//crossDomain: true,
//cache: false,
success: function(data)
{
alert("success");
},
error:function(response)
{
//alert("error");
console.log(response);
}
});
You are submitting the form:
document.getElementById("abc_session").innerHTML=data;
document.fm1.submit(); // Here
Don't do that.
Extract the data from it and make another Ajax request.
You should use e.preventDefault() as soon as you submit the form.
Note: I personally prefer jQuery instead of $; it's more typing but I find it more readable.
I have a simple form that lets the user enter their first/last names and email address. It has a "Save" button, that, when clicked, executes:
jQuery('#saveButton').click(function() {
alert('About to Save to server');
var validated = validateContact();
if(!validated) {
alert('Did not validate!');
return;
} else {
alert('Validated!');
}
jQuery().ajax({
url: "saveContact",
type:"post",
dataType: 'json',
data: {
contact: {
firstName: jQuery('#firstName').val(),
lastName: jQuery('#lastName').val(),
emailAddress: jQuery('#emailAddress').val()
}
},
success: function(result) {
jQuery('#firstName').val("");
jQuery('#lastName').val("");
jQuery('#emailAddress').val("");
},
error: function(xhr){
alert(xhr.responseText);
}
});
alert('Saved to server');
});
When I click the "Save" button, I get several alert popups, including the "Validated!" message, however the script seems to die shortly after that, and I never see the "Saved to server" alert. This tells me my jQuery/AJAX call is bad. Furthermore, when I open my browser's Developer Tools, I don't see the browser actually making a network POST to my backend. In the console I don't see any errors. Any ideas as to where I'm going wrong and why I'm not even seeing any network activity?
Replace jQuery().ajax with jQuery.ajax({...})
Following Errors in your code:
Used jquery instead of jQuery.
Used jQuery() instead of jQuery in calling ajax method.
JS:
jQuery('#saveButton').click(function () {
alert('About to Save to server');
var validated = true; //Changed to temporary value.
if (!validated) {
alert('Did not validate!');
return;
} else {
alert('Validated!');
}
jQuery.ajax({ //Replaced jQuery() with jQuery
url: "/saveContact", //Sample URL
type: "post",
dataType: 'json',
data: {
contact: {
firstName: jQuery('#firstName').val(), //Replaced jquery with jQuery
lastName: jQuery('#lastName').val(), //Replaced jquery with jQuery
emailAddress: jQuery('#emailAddress').val() //Replaced jquery with jQuery
}
},
success: function (result) {
jQuery('#firstName').val(""); //Replaced jquery with jQuery
jQuery('#lastName').val(""); //Replaced jquery with jQuery
jQuery('#emailAddress').val(""); //Replaced jquery with jQuery
},
error: function (xhr) {
alert(xhr.responseText);
}
});
alert('Saved to server');
});
Demo: http://jsfiddle.net/lotusgodkk/x2mv94vm/6/
I want to reuse a javascript function using a scala template so I would only have to pass a different success/failure function, but I don't seem to be able to able to pass a javascript function to a scala template.
Please note I'm veeeeerry new to this and don't even know if what I am doing is possible.
This is kind of what I'm trying to achieve:
#(formId: String, success: JavaScript, fail: JavaScript)
<script type="text/javascript">
$("#formId").submit(function(e)
{
var data = $(this).serializeArray();
var action = $(this).attr("action");
$.ajax(
{
url : action,
type: "POST",
data : data,
success:function(data, textStatus, jqXHR) // Change contents to dynamic parameter for scala??? perhaps a javascript function to execute???
{
#success()
/*console.log("save succesfull, progress!")
alert('Save successfull, now move on!');*/
},
error: function(jqXHR, textStatus, errorThrown) // Change contents to dynamic parameter for scala??? perhaps a javascript function to execute???
{
//if fails
#fail()
/*console.log(jqXHR.responseText);
var errors = JSON.parse(jqXHR.responseText);
console.log(errors);
alert('Woops, something went wrong: ' + jqXHR.responseText);*/
}
});
e.preventDefault();
});
</script>
How it would be used:
#snippets.ajaxFormSubmit("#form",
function()
{
alert("Save successfull, now move on!");
},
function()
{
alert("Save failed!");
}
)
You can pass any content to a template via Html type.
#(formId: String, success: Html, fail: Html)
<script type="text/javascript">
$("#formId").submit(function(e)
{
var data = $(this).serializeArray();
var action = $(this).attr("action");
$.ajax(
{
url : action,
type: "POST",
data : data,
success:function(data, textStatus, jqXHR) // Change contents to dynamic parameter for scala??? perhaps a javascript function to execute???
{
#success
},
error: function(jqXHR, textStatus, errorThrown) // Change contents to dynamic parameter for scala??? perhaps a javascript function to execute???
{
#fail
}
});
e.preventDefault();
});
</script>
In a client view you can user it as follows:
#successFunc = {
alert("Save successfull, now move on!");
}
#failureFunc = {
alert("Save failed!");
}
#snippets.ajaxFormSubmit("#form", successFunc, failureFunc)