How to stop compiler while ajax request not complete? - javascript

I have a form and in this a field is parent keywords as secret key. When i validate this form using javascript it working very well. i also check secret key that i associated with any parent or not. if not then galg set 0.
Ajax working ver well and it check also that secret key found or not. if found then it is correct or not, but compiler not wait to ajax complete. it submit the form and don't wait the ajax response. I want while ajax request not complete then it resume for some time and then next check other filed.
function PiggyBankValidation()
{
var flag = 1;
var Namepattern = /^[a-zA-Z0-9 ]{1,40}$/;
var account_name = $("#account_name");
var holding_terms = $("#holding_terms");
var goal = $("#goal");
var parent_keywords = $("#parent_keywords");
var terms = $("#terms");
//terms.attr("checked",false)
if(account_name.val().trim() == ""){
account_name.next('.JErrorMsg').text("Please Enter Account Name !");
flag = 0;
}else if(Namepattern.test(account_name.val().trim()) == false){
account_name.next('.JErrorMsg').text("Please Enter Correct Account Name !");
flag = 0;
}else{
account_name.next('.JErrorMsg').text("");
}
if(holding_terms.val().trim() == ""){
holding_terms.next('.JErrorMsg').text("Please Select Holding Terms !");
flag = 0;
}else if(Namepattern.test(holding_terms.val().trim()) == false){
holding_terms.next('.JErrorMsg').text("Please Select Holding Terms !");
flag = 0;
}else{
holding_terms.next('.JErrorMsg').text("");
}
if(goal.val().trim() == ""){
goal.next('.JErrorMsg').text("Please Enter Goal !");
flag = 0;
}else if(Namepattern.test(goal.val().trim()) == false){
goal.next('.JErrorMsg').text("Please Enter Correct Goal !");
flag = 0;
}else{
goal.next('.JErrorMsg').text("");
}
if(parent_keywords.val().trim() == ""){
parent_keywords.next('.JErrorMsg').text("Please Enter Parent Keywords !");
flag = 0;
}else if(Namepattern.test(parent_keywords.val().trim()) == false){
parent_keywords.next('.JErrorMsg').text("Please Enter Correct Parent Keywords !");
flag = 0;
}else{
parent_keywords.next('.JErrorMsg').text("Please wait...");
$.ajax({
url:siteurl+"ChildControlPanel/CheckSecretKey",
type: "POST",
data:{key:parent_keywords.val().trim()},
beforesend : function(){flag = 0;},
success : function(data){
if(data){
response = JSON.parse(data);
if(response.success){
parent_keywords.next('.JErrorMsg').text("");
}
if(response.error){
parent_keywords.next('.JErrorMsg').text(response.error);
flag = 0;
}
}else{
parent_keywords.next('.JErrorMsg').text("Please try again !");
flag = 0;
}
},
});
}
if(terms.prop("checked") == false){
terms.next('.JErrorMsg').text("Please Accept terms !");
flag = 0;
}
else
{
terms.next('.JErrorMsg').text("");
}
///alert(flag);
if(flag == 1)
{
alert("submit");
//return true;
return false;
}
else
{
return false;
}
}
i calling this function here
$(document).ready(function(){
$("#piggyBankSetup input").keypress(function(e){
if(e.keyCode == 13){
if(PiggyBankValidation()){
document.piggyBankSetup.submit();
}
}
});
$("#AddAccount").click(function(){
if(PiggyBankValidation()){
document.piggyBankSetup.submit();
}
});
});
When this function call and all fields have correct value only parent keywords (secret key) is wrong then it submit the form.

Try
Inside $.ajax request set 'async':false , this will make wait till request completed , otherwise you can set ajax request outside validation function and check for valid with adding some classes (check with jQuery.hasClass('class name')) to control or setting a global variable

Ajax is asynchronous. That's what the "A" in Ajax stands for. It's also asynchronous for a reason because that keeps the browser responsive during the network request which can take many seconds. You may want to read this reference:
How do I return the response from an asynchronous call?
As such, you need to prevent the default submission of your form (probably using event.preventDefault() but you don't show us the code that that would go in). And, then when the validation passes, you can then programmatically submit your form.
You will also need to correct your code to work with an asynchronous response. ALL code that uses the Ajax response needs to be in the success handler or called from the success handler. You can't set a flag there and then use that flag outside the success handler. The timing will not work properly .
If you need to somehow do multiple operations as part of the validation, then you will have to write async code that can handle multiple operations. This is all part of learning how to write proper async code and is required for good javascript development. You cannot return an async result from your PiggyBankValidation() function because the asynchronous results will not yet be available when PiggyBankValidation returns.
If you have multiple async operations, you can use callbacks or promises to help structure your async code. If you have only the one async operation, then just put all the other code in the success handler (or in a callback called from the success handler).

Related

jQuery - Checking val isn't empty and contains a specific piece of text

So I've got a .js file that checks that the values of my form. I'm trying to check that the form values aren't empty, and that one of the values contains a specific piece of text (in this case, my name). If the form does hold my name, then run the rest of the script.
Where I have commented //etc etc, an AJAX script is ran that posts to a PHP file.
This is all functioning as expected, until I run the additional if statement checking the input value for my name.
$('#submit').click(function(e){
this.enabled=true;
if ($.trim($("#name").val()) === "" || $.trim($("#topic_title").val()) === ""){
$('#message').html('you did not fill out one of the fields').css("color", "#be4343")
return false;
if($('#name').val().indexOf("Rich") != -1){ // without this if statement, the code runs fine.
$('#message').html("You have entered the wrong name.");
return false;
}
} else {
if($('#name, #topic_title').length && $('#name, #topic_title').val().length){
var name = $("#name").val();
var topic_title = $("#topic_title").val();
}}
// etc etc
});
Question: How would I go about checking that the value of the id '#name' isn't empty, and that it contains a specific piece of text?
Thanks in advance,
Richie.
Solution:
I removed the additional if statement and included the following code.
var name = $('#name').val();
if ( name.indexOf("Rich") || $.trim($("#name").val()) === ""){
If you indent your code consistently, it's fairly clear why you have a problem:
$('#submit').click(function(e) {
this.enabled = true;
if ($.trim($("#name").val()) === "" || $.trim($("#topic_title").val()) === "") {
$('#message').html('you did not fill out one of the fields').css("color", "#be4343")
return false;
if ($('#name').val().indexOf("Rich") != -1) { // Note that this is WITHIN the `if ($.trim($("#name").val()) === "" || $.trim($("#topic_title").val()) === "")` condition
$('#message').html("You have entered the wrong name.");
return false;
}
} else {
if ($('#name, #topic_title').length && $('#name, #topic_title').val().length) {
var name = $("#name").val();
var topic_title = $("#topic_title").val();
}
}
// etc etc
});
If you want it to be handled, it needs to be an else if for that condition instead:
$('#submit').click(function(e) {
this.enabled = true;
if ($.trim($("#name").val()) === "" || $.trim($("#topic_title").val()) === "") {
$('#message').html('you did not fill out one of the fields').css("color", "#be4343")
return false;
} else if ($('#name').val().indexOf("Rich") != -1) { // without this if statement, the code runs fine.
$('#message').html("You have entered the wrong name.");
return false;
} else {
if ($('#name, #topic_title').length && $('#name, #topic_title').val().length) {
var name = $("#name").val();
var topic_title = $("#topic_title").val();
}
}
// etc etc
});
(Well, as you have return, those could both just be if rather than else if...)
There are other problems though, for instance this expression in your final block:
$('#name, #topic_title').length
...which checks to see if either #name or #topic_title elements exist in your DOM at all (it doesn't do anything to check their values, and it doesn't require that they both exist, just one of them), and this:
$('#name, #topic_title').val().length
...will only check the value in #name, it will completely ignore the value in #topic_title, because when used as a getter, val only gets the value of the first element in the jQuery set. (Almost all of jQuery's functions that can be getters or setters are like that; the exception is text which is different from the others.)
Finally, this line:
this.enabled = true;
...is almost certainly a no-op, since the button cannot be clicked if it's not enabled, and as lshettyl points out, the property's name is disabled, not enabled. So this.disabled = false; if you're trying to enable it, or this.disabled = true; if you're trying to disable it.
By the look of your code, I assume you have a form that has either a class or an ID (or nothing). It'd be clever to use the form's submit event as opposed to click event of the submit button. This way you ensure that the form can also be submitted via the enter button (remember accessibility?). This is only an extension to T.J. Crowder's answer which has lots of good points from which you can learn/improve coding.
//Let's say your form has an ID 'topic'
$("#topic").on("submit", function() {
//Cache jQuery objects that would be resued, for better performance.
var $name = $("#name"),
$title = $("#topic_title"),
$msg = $('#message');
//One of the elements doesn't exist (exit)
//1 + 1 <= 1
if ($name.length + $title.length <= 1) {
return;
}
if ($.trim($name.val()) === "" || $.trim($title.val()) === "") {
$msg.html('you did not fill out one of the fields').css("color", "#be4343")
return;
} else if ($name.val().indexOf("Rich") !== -1) {
$msg.html("You have entered the wrong name.");
return;
} else {
//You do not need further checks such as length, val etc.
//as they have already been checked above.
var name = $name.val();
var topic_title = $title.val();
}
});
You can make comparison to know if it's empty:
if($('#name, #topic_title').length && $('#name, #topic_title').val().length){
var name = $("#name").val();
var topic_title = $("#topic_title").val();
}}
if(name=='' || name==undefined){
//do stuff here
}
});

What is a good strategy for custom form validation in angular?

As my app is growing, I'm finding more need for more effective form validation. I personally don't like the angular built in validation that evaluates on field change. And there are always things it won't account for like verifying that a youtube video id is valid. Currently I'm doing validation in each forms controller. I have a function that looks like this. Each field has a message and if there is an error the message will appear red using ng-class.
$scope.validate = function (callback) {
// reset default messages
setMessages();
// create shorter references
var item = $scope.item,
message = $scope.itemMessage;
// title exists
if (item.title === '') {
message.title.message = 'You must give your item a title.';
message.title.error = true;
message.errors += 1;
}
// extract and clear video id with youtube api
if ($scope.temp.video !== undefined && $scope.temp.video !== '') {
var id = '';
var url = $scope.temp.video.replace(/(>|<)/gi,'').split(/(vi\/|v=|\/v\/|youtu\.be\/|\/embed\/)/);
if(url[2] !== undefined) {
id = url[2].split(/[^0-9a-z_]/i);
id = id[0];
} else {
id = url;
}
$http.get("http://gdata.youtube.com/feeds/api/videos/" + id)
.then(function (res) {
$scope.item.video = id;
}, function (res) {
message.video.message = 'That is not a valid youtube video.';
message.video.error = true;
message.errors += 1;
$scope.item.video = '';
});
}
if (message.errors === 0) {
callback();
}
};
and then my actual form submission function calls $scope.validate(); passing it a function containing the $http.post(). The two major problems I see are that my callback isn't promise base so there's no guarantee it won't be called when an error exists and I've read again and again to keep large chunks of logic outside of your controller. I haven't found great examples of how this should be done but it must be a common problem.
You can still use Angular's built-in validation and have it not evaluate unless the form has been submitted:
http://scotch.io/tutorials/javascript/angularjs-form-validation#only-showing-errors-after-submitting-the-form
Essentially you set $scope.submitted = true when the form is submitted and set a conditional check so that error messages and classes are only shown when $scope.submitted is set.

Use jQuery.post() result in javascript function

I've got no clue how to do the following, so I wasn't sure what to search for either.
For validating my registration form I've a javascript function that checkes the existence of the inserted username in the database onblur of the username textfield.
function checkUsername(username){
$.post("checkmail.php", {username: username} , function(data){
var $response=$(data);
var response = $response.filter('#username-response').text();
if(response == "taken") {
document.getElementById('username').style.borderColor = rood;
valid = false;
}
});
}
This works fine, but now I want to validate it again onsubmit of the form in case users decide to submit an existing username.
function validateForm() {
var valid = true;
//checks different fields
//now check voor username existence
var username = document.getElementById('username').value;
checkUsername.call(username);
if (!valid) {
return false;
}
else {
return true;
}
}
I'm not familiar enough with Javascript to get this working. Probably thinking in the wrong direction...
You can use synchronous ajax call for this as you are using return data for validation.

ajax success callback executes out of expected order

I have a function that validates some fields when a button is pressed. First one checks if the username and password are authentic or not. then if the password is appropriately secure. Then if it matches the confirm-password box. However, it seems that the ajax that check to see if the user is authentic does not complete before the alert in the first function pops up.
$(document).ready(function() {
$('#submit_pw_ch').on('click', function(){
var alertString = "Please correct the following errors: \n"
//current username and password are correct
var vUsr = valUsr();
//new password is sufficiently secure
var vPwd = valPwd();
//confirmation of new password is same as previous box
var sPwd = samePwd();
console.log('valid user : ' + vUsr + ' valid password : ' + vPwd + ' same password : ' + sPwd);
//append appropriate warnings to alert string
if ( !vUsr ) { alertString += "-Your current username and password are invalid. \n"; }
if ( !vPwd ) { alertString += "-The new password you have selected is not strong enough. \n"; }
if ( !sPwd ) { alertString += "-The confirmation of your new password does not match the previous entry. \n"; }
if ( !vUsr || !vPwd || !sPwd ) {
alert(alertString);
return false;
} else {
//change password
}
});
});
So the line that checks for that is var vUsr = valUsr(); which calls
function valUsr() {
var un = $('#uNameInput').val();
var pw = $('#uPwdInput').val();
//return value
var validUsr = false;
$.ajax({
type: "post",
url: "queries/confirm_user.php?<?=time()?>",
data: "un=" + un + "&pw=" + pw,
dataType: "json",
success: function (returnedData) {
console.log(returnedData)
if (data == 'true') {
validUsr = true;
} else {
validUsr = false;
}
}
});
return validUsr;
}
Somehow though the alert is not waiting for the ajax to finish getting it's data. The console.log(returnedData) in the valUsr() function appears in the console after I've dismissed the alert box. Why is this happening? How can I prevent it? Thanks!
Thomas,
You need to cater for the inherent asynchronicity of ajax, in other words you need to wait until a response to the ajax request has arrived before deciding what to do.
jQuery's Deferreds (and promises) allow us to write simple code but Deferreds tend to blow you mind at first, at least very slightly.
There's no unique way in which to use Deferreds for a problem like this but here's one.
$(document).ready(function() {
$('#submit_pw_ch').on('click', function() {
var form = this.form; //the form containing the submit button and the fields .
//`alertArr` is an array to which messages will be added.
var alertArr = ["Please correct the following errors:"];
//`addAlert` will be called from a `Deferred.resolveWith(this, ...)` statement.
//The context, `this`, is unused.
function addAlert(index, txt) {
alertArr[index] = txt;
}
//`compositeAction` will be called from a promise.done() statement.
function compositeAction() {
//first filter out null messages (ie. validation successes) from alertArr.
var message = $.map(alertArr, function(txt, i){
return txt || null;
});
if(message.length > 1) {
//then alert the complete message with line breaks
alert(message.join("\n"));
} else {
//submit the form to change the password
//or another ajax call as required
form.submit();
}
}
// Invoke ajax validators and assign returned promises.
// An index is passed, so the text messages can be displayed in a logical order,
// regardless of the order in which the validation promises are resolved.
//If we didn't care about the order of the messages then the code would be slighly simpler.
var vUsr = valUsr(0),
vPwd = valPwd(1),
sPwd = samePwd(2);
//All validations adopt a similar pattern regardless of whether ajax is involved or not.
//Here, we establish what is to be done when the promise are resolved, or
//what is to be done immediately if the promise are alrady resolved.
vUsr.done(addAlert);
vPwd.done(addAlert);
sPwd.done(addAlert);
//At this stage, `addAlert` will contain entries for successful as well as unsuccessful validations. Successful entries will be filtered out by `compositeAction`
//Establish what is to be done when all three promises are resolved.
$.when(vUsr, vPwd, sPwd).done(compositeAction);
//Return false unconditionally
return false;
});
function valUsr(index) {
var messages = {
validated: '',//important - this message must be an empty string - do not change
notValidated: '- Your current username and password are invalid.',
ajaxError: '- Validation error: username and password.'
};
//Create a Deferred object, which will be resolved in response to several different outcomes.
var def = $.Deferred();
$.ajax({
type: "post",
url: "queries/confirm_user.php?<?=time()?>",
data: {
'un': $('#uNameInput').val(),
'pw': $('#uPwdInput').val()
},
dataType: "json",
success: function (returnedData) {
if (returnedData == 'true') {
def.resolveWith(this, [index, messages.validated]);
} else {
def.resolveWith(this, [index, messages.notValidated]);
}
},
error: function() {
def.resolveWith(this, [index, messages.ajaxError]);
}
});
return def.promise();//Return a promise derived from the as yet unresolved Deferred.
}
function samePwd(index) {
var pw1 = $('#uPwdInput').val();
var pw2 = $('#uPwdInput2').val();
var errMessage = (pw1 === pw2) ? '' : '-The confirmation of your new password does not match the previous entry';
var def = $.Deferred();//Create a Deferred object, which will be resolved immediately
def.resolveWith(this, [index, errMessage]);
return def.promise();//Return a promise derived from the already resolved Deferred.
}
});
valPwd() will be of the same format as either valUsr() or samePwd(), depending on whether ajax is involved or not.
Ajax is run on the fly, synchronously
You will need to check the validation of the other fields after the ajax request has completed in the success callback. You can turn off the synchronous request but the browser will freeze up 'till it gets one, not advised.
You will need to restructure your calls to reflect this; I would suggest that as soon as they have finished typing the password and the field blurs you send the request to check. That way, if there are any errors you will be able to prevent the wait time at the end of the form.

Javascript: onSubmit function submits form before function has finished?

I'm asking this because I am at a complete loss myself and need a fresh pair of eyes.
The following JavaScript function is successfully called on submission of the connected HTML form. The function starts and the first two if statements run (and halt the submission if they return false).
Then, the first test alert "before" appears and then the form submits, completely missing out the rest of the function. While testing I changed the final line to return false so that whatever happen the function should return false, but the form still submitted.
function validateForm(form)
{
// declare variables linked to the form
var _isbn = auto.isbn.value;
var _idisplay = auto.isbn.title;
var _iref = "1234567890X";
// call empty string function
if (EmptyString(_isbn,_idisplay)==false) return false;
// call check against reference function
if (AgainstRef(_isbn,_iref,_idisplay)==false) return false;
// call check length function
alert("before");///test alert
////// FORM SUBMITS HERE?!? /////////////
if (AutoLength(_isbn)==false) return false;
alert("after");///test alert
// if all conditions have been met allow the form to be submitted
return true;
}
Edit: this is what AutoLength looks like:
function AutoLength(_isbn) {
if (_isbn.length == 13) {
return true; {
else {
if (_isbn.length == 10) {
return true; {
else {
alert("You have not entered a valid ISBN10 or ISBN13. Please correct and try again.");
return false;
}
}
There are errors in your implementation of AutoLength. Currently, it looks like this:
function AutoLength(_isbn) {
if (_isbn.length == 13) {
return true; { // <------ incorrect brace
else {
if (_isbn.length == 10) {
return true; { // <------ incorrect brace
else {
alert("You have not entered a valid ISBN10 or ISBN13. Please correct and try again.");
return false;
}
}
See how it doesn't close all of its blocks? That's because you've used the wrong brace in two places, and you've forgotten to close the function.
You could rewrite the function like this:
function AutoLength(_isbn) {
return _isbn.length === 13 || _isbn.length === 10;
}
If you're hell-bent on using alert, you can do that inside validateForm (although I would try to find a more user-friendly way to show the error message).
In the future, when you're trying to debug code, you can use try and catch to "catch" Errors as they happen, like this:
try {
if (false === AutoLength(_isbn)) {
return false;
}
} catch (e) {
alert('AutoLength threw an error: '+e.message);
}
If the execution of the function is terminated by a runtime error, the form submits. So check out the script console log for error messages.

Categories

Resources