How to use Delay for method execution in jquery - javascript

I am using jquery in my one of the form. where on click of submit button i call one function QuoteDetailValidation(). In which i validate fields. But after validate that fields i try to get all fields which have errorActive class. But unfortunately i can't get it.
See my code
$('#saveQuote').on('click', function(event) {
var descriptionData1 = $('input[name=\"QuoteDetail[description][]\"]');
QuoteDetailValidation(descriptionData1);
var selectors = document.querySelectorAll('#quote-quoteItems-form .errorActive').length;
alert(selectors);
return false;
});
function QuoteDetailValidation(descriptionData1) {
for (var i = 0; i < descriptionData1.length; i++) {
var id = descriptionData[i].id;
var value = descriptionData[i].value;
var costid = costData[i].id;
var costValue = costData[i].value;
$.ajax({
type: 'GET',
url: "<?php echo Yii::app()->createUrl('QuoteData/validatedata'); ?>",
data: 'descvalue=' + value + '&Descname=description&costValue=' + costValue + '&costName=cost&descId=' + id + '&costId=' + costid,
success: function(data) {
var obj = $.parseJSON(data);
var cost = obj.cost;
var desc = obj.desc;
if (desc != '' || cost != '') {
if (cost != '') {
$('#' + costid).addClass('errorActive');
$('#' + costid).prev().addClass('error');
$('#' + costid).next().remove();
$('#' + costid).after(cost);
$('#' + costid).parent().removeClass('success');
$('#' + costid).parent().addClass('error');
}
}
},
error: function(data) {
alert('Your data has not been submitted..Please try again');
}
});
}
}
Now What happens, When there is error QuoteDetailValidation() append errorActive class to fields.
By var selectors = document.querySelectorAll('#quote-quoteItems-form .errorActive').length; i try to get length of the fields which have errorActive class. but in alert of selectors, it always gives 0. But when i alert something before getting all errorActive Class then alert selectors give me perfect count. i think there is delay because of alert before getting class errorActive. so that it give me count. How to use it. Any help please. Thanks in advance.

You can determine the exact delay required for selectors to be initailized properly. Whatever we add as delay will be assumption and can be short for some scen
One options using below in your ajax request
async: false
like below:-
$.ajax({
type: 'GET',
async: false,
url: "<?php echo Yii::app()->createUrl('QuoteData/validatedata'); ?>",
data: 'descvalue=' + value + '&Descname=description&costValue=' + costValue + '&costName=cost&descId=' + id + '&costId=' + costid,
success: function(data) {}});
Setting async to false means that the statement you are calling has to complete before the next statement in your function can be called. If you set async: true(it is default) then that statement will begin it's execution and the next statement will be called regardless of whether the async statement has completed yet. Helpful question
But I still will advise you to move selectors part in success of ajax like below:-
$.ajax({
type: 'GET',
url: "<?php echo Yii::app()->createUrl('QuoteData/validatedata'); ?>",
data: 'descvalue=' + value + '&Descname=description&costValue=' + costValue + '&costName=cost&descId=' + id + '&costId=' + costid,
success: function(data) {
var obj = $.parseJSON(data);
var cost = obj.cost;
var desc = obj.desc;
if (desc != '' || cost != '') {
if (cost != '') {
$('#' + costid).addClass('errorActive');
$('#' + costid).prev().addClass('error');
$('#' + costid).next().remove();
$('#' + costid).after(cost);
$('#' + costid).parent().removeClass('success');
$('#' + costid).parent().addClass('error');
}
}
var selectors = document.querySelectorAll('#quote-quoteItems-form .errorActive').length;
alert(selectors);
//some logice here or move the above in some function and call it here
},
error: function(data) {
alert('Your data has not been submitted..Please try again');
}
});
or use call back functions.
Update: try something like below It will keep async as true and keep the count logic outside $.ajax.
function QuoteDetailValidation(descriptionData1,submitFormOrAddError) {
for (var i = 0; i < descriptionData1.length; i++) {
var id = descriptionData[i].id;
var value = descriptionData[i].value;
var costid = costData[i].id;
var costValue = costData[i].value;
$.ajax({
type: 'GET',
url: "<?php echo Yii::app()->createUrl('QuoteData/validatedata'); ?>",
data: 'descvalue=' + value + '&Descname=description&costValue=' + costValue + '&costName=cost&descId=' + id + '&costId=' + costid,
success: function(data) {
var obj = $.parseJSON(data);
var cost = obj.cost;
var desc = obj.desc;
if (desc != '' || cost != '') {
if (cost != '') {
$('#' + costid).addClass('errorActive');
$('#' + costid).prev().addClass('error');
$('#' + costid).next().remove();
$('#' + costid).after(cost);
$('#' + costid).parent().removeClass('success');
$('#' + costid).parent().addClass('error');
}
}
submitFormOrAddError(data);
},
error: function(data) {
alert('Your data has not been submitted..Please try again');
}
});
}
}
Call it like this:
$('#saveQuote').on('click', function(event) {
var descriptionData1 = $('input[name=\"QuoteDetail[description][]\"]');
QuoteDetailValidation(descriptionData1);
QuoteDetailValidation(descriptionData1,function(output){
// here you use the output
var selectors = document.querySelectorAll('#quote-quoteItems-form .errorActive').length; //This line is excuted only after call completes
alert(selectors);
//form submit here if error is zero.
});
alert("hii");//this line is executed without waiting for above call..
return false;
});

You need to do this on your success callback of the QuoteDetailValidation method, because the $.ajax runs async and after invoking the method it still hasn't completed.
$.ajax({
type: 'GET',
url: "<?php echo Yii::app()->createUrl('QuoteData/validatedata'); ?>",
data: 'descvalue=' + value + '&Descname=description&costValue=' + costValue + '&costName=cost&descId=' + id + '&costId=' + costid,
success: function(data) {
var obj = $.parseJSON(data);
var cost = obj.cost;
var desc = obj.desc;
if (desc != '' || cost != '') {
if (cost != '') {
$('#' + costid).addClass('errorActive');
$('#' + costid).prev().addClass('error');
$('#' + costid).next().remove();
$('#' + costid).after(cost);
$('#' + costid).parent().removeClass('success');
$('#' + costid).parent().addClass('error');
}
}
// Here you know that the elements will have the necessary classes.
var selectors = $('#quote-quoteItems-form .errorActive').length;
alert(selectors);
},
error: function(data) {
alert('Your data has not been submitted..Please try again');
}
});

Related

Javascript error with sort

i have this code as shown below,
i got this from a developer who went afk because he has family troubles
basically this code below should grab the json results and form them into a table after sorting the price and then placing it in the table.
heres the code
//first define a function
var sortTable = function () {
$("#tableid tbody tr").detach().sort(function (a, b) {
//substring was added to omit currency sign, you can remove it if data-price attribute does not contain it.
return parseFloat($(a).data('price').substring(1)) - parseFloat($(b).data('price').substring(1));
})
.appendTo('#tableid tbody');
};
//include two files where rows are loaded
//1.js
$.ajax({
type: 'GET',
crossDomain: true,
dataType: 'json',
url: 'api link here',
success: function (json) {
//var json = $.parseJSON(data);
for (var i = 0; i < json.results.length; i++) {
var section = json.results[i].section;
var no = json.results[i].avalible;
var price = json.results[i].price;
var button = "<button class='redirect-button' data-url='LINK'>Compare</button>";
$("#tableid tbody").append("<tr data-price='" + price + "'><td>" + section + "</td><td>" + no + "</td><td>" + price + "</td><td>" + button + "</td></tr>");
$("#tableid").find(".redirect-button").click(function () {
location.href = $(this).attr("data-url");
});
}
sortTable();
},
error: function (error) {
console.log(error);
}
});
//and here is the 2nd js file
$.ajax({
type: 'GET',
crossDomain: true,
dataType: 'json',
url: '2nd api',
success: function (json) {
//var json = $.parseJSON(data);
for (var i = 0; i < json.results.length; i++) {
var section = json.results[i].section;
var no = json.results[i].avalible;
var price = json.results[i].amount;
var button = "<button class='redirect-button' data-url='LINK'>Click Here</button>";
$("#tableid tbody").append("<tr data-price='" + price + "'><td>" + section + "</td><td>" + no + "</td><td>" + price + "</td><td>" + button + "</td></tr>");
$("#tableid").find(".redirect-button").click(function () {
location.href = $(this).attr("data-url");
});
}
sortTable();
},
error: function (error) {
console.log(error);
}
});
Accessing the DOM, to get data that needs to be sorted, is a bad practice IMO. Even worse when you had the results in raw JSON form in the first place (in the success callback of the ajax call). Your success function should do something like this
success: function (json) {
//first sort the results - or better store these results somewhere
//and use that as a data store that is responsible for what is rendered in the DOM
json.results.sort(function(a,b) {
//using substring and parseFloat just like it was done in sortTable
//assuming price field has prices as strings with currency symbol in the first place
return parseFloat(a.substring(1)) - parseFloat(b.substring(1))
});
for (var i = 0; i < json.results.length; i++) {
var section = json.results[i].section;
var no = json.results[i].avalible;
var price = json.results[i].amount;
var button = "<button class='redirect-button' data-url='LINK'>Click Here</button>";
$("#tableid tbody").append("<tr data-price='" + price + "'><td>" + section + "</td><td>" + no + "</td><td>" + price + "</td><td>" + button + "</td></tr>");
$("#tableid").find(".redirect-button").click(function () {
location.href = $(this).attr("data-url");
});
}
}

jQuery ajax is calling infinily , showing too much recursion error in console

I am using jQuery.validationEngine plugin .I have a below ajax function to check duplicate unique value for a field.
function _is_unique(caller) {
var value = jQuery(caller).val();
var field_id = jQuery(caller).attr('id');
var field_name = jQuery(caller).attr('placeholder');
if (value != '') {
var uniqueObject = new Object();
uniqueObject.field_id = field_id;
uniqueObject.value = value;
var uniqueString = JSON.stringify(uniqueObject);
var getUrl = window.location;
//console.log(getUrl);
var baseUrl = getUrl.protocol + "//" + getUrl.host + "/" + getUrl.pathname.split('/')[1];
jQuery.ajax({
type: "POST",
url: baseUrl + "/dashboard/check_unique",
data: uniqueObject,
async: false,
cache: false,
dataType: "text",
success: function(msg) {
if (msg == "exist") {
isError = true;
promptText += " This " + field_name + settings.allrules["is_unique"].alertText + "<br />";
}
}
});
}
}
if the field value is present in server then from server I am returnning "exist" else I am returning "notexist".
Now while running my ajax script is calling infinitely . Can any please tell me what should I do to stop infinite loop of my ajax call.
Edited
This is the form Submit function . its also showing
too much recursion
error in console. By any chance am I having problem here ?
$('#searchform').on('submit', function(e){
var validateError ='';
var id='';
var fieldError = [];
$('#searchform :input:text').each(function(){
id = $(this).attr('id');
validateError = jQuery.fn.validationEngine.loadValidation(document.getElementById(id));
if(validateError)
{ fieldError.push(id);
}
});
if(fieldError.length!=0)
{
return false;
}
else{
$("form#searchform" ).submit();
return true;
}
});
});

Incrementally load a webpage: Where can I put: $("#LoadingImage").Hide();

I am not very experienced with JavaScript. Please see the code below:
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.1.min.js"></script>
<script type = "text/javascript">
function GetSQLTable() {
//alert($("#<%=fieldGroupReferences.ClientID%>")[0].value)
var str = $("#<%=fieldGroupReferences.ClientID%>")[0].value
var res = str.split(",");
for (var i = 0; i < res.length; i++) {
$("#LoadingImage").show();
var div = document.createElement('div');
div.id = "div" + i
document.body.appendChild(div);
//alert(res[i]);
$.ajax({
type: "POST",
url: "Default3.aspx/GetSQLTable",
data: '{username: "' + $("#<%=fieldUserName.ClientID%>")[0].value + '", terminalname: "' + $("#<%=fieldTerminalName.ClientID%>")[0].value + '", terminalip: "' + $("#<%=fieldTerminalIP.ClientID%>")[0].value + '", mappingid: "' + res[i] + '", usergroup: "' + $("#<%=fieldUserGroup.ClientID%>")[0].value + '"}',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: OnSuccess(i,res.length),
failure: function (response) {
//alert(response.d);
alert('there was an error loading the webpage')
}
});
}
function OnSuccess(i,totalrows) {
return function (response) {
if (response.d != "") {
document.getElementById('div' + i).innerHTML = document.getElementById('div' + i).innerHTML + '<br>' + '<br>' + response.d;
}
}
}
}
window.onload = GetSQLTable
</script>
The code incrementally builds a webpage i.e. x number of HTML tables are obtained and displayed to the webpage as and when they become ready. This works.
The problem is I don't know how to remove the LoadingImage once the webpage is complete i.e. $("#LoadingImage").hide();. OnSuccess is called x number of times depending on how many tables are returned so I cannot put it in there.
One way would be to count the number of successful onSuccess() calls, and hide your loading image when they are all complete:
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.1.min.js"></script>
<script type = "text/javascript">
function GetSQLTable() {
//alert($("#<%=fieldGroupReferences.ClientID%>")[0].value)
var str = $("#<%=fieldGroupReferences.ClientID%>")[0].value
var res = str.split(",");
var numSucceeded = 0;
for (var i = 0; i < res.length; i++) {
$("#LoadingImage").show();
var div = document.createElement('div');
div.id = "div" + i
document.body.appendChild(div);
//alert(res[i]);
$.ajax({
type: "POST",
url: "Default3.aspx/GetSQLTable",
data: '{username: "' + $("#<%=fieldUserName.ClientID%>")[0].value + '", terminalname: "' + $("#<%=fieldTerminalName.ClientID%>")[0].value + '", terminalip: "' + $("#<%=fieldTerminalIP.ClientID%>")[0].value + '", mappingid: "' + res[i] + '", usergroup: "' + $("#<%=fieldUserGroup.ClientID%>")[0].value + '"}',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: OnSuccess(i,res.length),
failure: function (response) {
//alert(response.d);
alert('there was an error loading the webpage')
}
});
}
function OnSuccess(i,totalrows) {
return function (response) {
if (response.d != "") {
document.getElementById('div' + i).innerHTML = document.getElementById('div' + i).innerHTML + '<br>' + '<br>' + response.d;
numSucceeded++;
if (numSucceeded === totalrows) {
$("#LoadingImage").hide();
}
}
}
}
}
window.onload = GetSQLTable
</script>
Try using .when with an array of your ajax calls. Something like this (simplified to remove the irrelevant bits):
function GetSQLTable() {
//...
var calls = [];
for (var i = 0; i < res.length; i++) {
//..
calls.push($.ajax({
type: "POST",
//..
}));
}
$.when(calls).then(function(d) {
// all done!!!
});

While appending divs, delete older appended divs when there are more than 10

Consider the following JQuery loop. It appends this:
"<div id='1'>" + feedback + "</div>"
1st Question.
I want to increment the id of the appended div after the first one has been appended so that the first appended div's id is 1, the second div's id is 2 and so on.
2nd Question.
When the number of divs reaches 10, I want to delete the first appended div. Which in our case is:
<div id="1">php result</div>
This should keep looping and deleting older divs.
Here's the Jquery ajax loop:
new get_fb();
function get_fb(){
var feedback = $.ajax({
type: "POST",
url: "algorithm.php",
async: false
}).success(function(){
setTimeout(function(){get_fb();}, 8000);
}).responseText;
$('#BuzFeed').append("<div id='1'>" + feedback + "</div>");
}
For counting:
var get_fb = (function() {
var counter = 1;
return function(){
var feedback = $.ajax({
...
}).responseText;
$('#BuzFeed').append("<div id='" + counter + "'>" + feedback + "</div>");
}
})();
get_fb();
and for automatic removal, after
var $buzfeed = $('#BuzFeed').append("<div id='" + counter + "'>" + feedback + "</div>");
add
var $buzfeedDivs = $buzfeed.children('div');
if ($buzfeedDivs.length > 10) { $buzfeedDivs.first().remove(); }
Additionally, your code uses some not-so-good practices. The re-write, including my additions would be:
var get_fb = (function() {
var counter = 0;
var $buzfeed = $('#BuzFeed');
return function(){
$.ajax({
type: "POST",
dataType: "html", // based on chat
url: "algorithm.php"
}).done(function(feedback) {
counter += 1;
var $buzfeedresults = $("<div id='BuzFeedResult" + counter + "'></div>");
$buzfeedresults.text(feedback);
$buzfeed.append($buzfeedresults);
var $buzfeedDivs = $buzfeed.children('div');
if ($buzfeedDivs.length > 10) { $buzfeedDivs.first().remove(); }
setTimeout(get_fb, 8000);
}).fail(function(jqXhr, textStatus, errorThrown) {
var $buzfeedresults = $("<div id='BuzFeedError'></div>");
$buzfeedresults.text('Error: ' + textStatus);
if (typeof console !== 'undefined') {
console.error(jqXhr, textStatus, errorThrown);
}
});
};
})();
get_fb();

Help passing variables between functions in ajax callbacks

OK I am building something that makes an ajax request to one server where it determines the url it needs to then make a new ajax request to another place. Everything is progressing thanks to all the help at SO =) .. however I am stuck again. I am struggling with getting the variables to return to the different functions as I need. The second (jsonp) request returns a json function which looks like :
jsonResponse(
{"it.exists":"1"},"");
and my code...
var img = "null";
var z = "null";
$(document).ready(function()
{
$.ajax({
type: "GET",
url: "connect.php",
dataType: "xml",
success: function parseXml(data)
{
$(data).find("ITEM").each(function()
{
query = $("SKU", this).text();
query = 'http://domain.com/' + query + '?req=exists,json';
img = $("SKU", this).text();
img = '<img src="http://domain.com/' + img + '">';
var date =$("LAST_SCAN" , this).text();
$.ajax({
url: query,
dataType: 'jsonp'
});
$("table").append('<tr>'+'<td>' + (date) + '</td>' + '<td>' + (z) + '</td>');
});
}
});
});
// function required to interpret jsonp
function jsonResponse(response){
var x = response["it.exists"];
// console.log(x);
if (x == 0) {
console.log("NO");
var z = "NO IMG";
}
if (x == 1) {
console.log(img);
//this only returns the first image path from the loop of the parseXml function over and over
var z = (img);
}
return z;
}
So I guess my problem is a two parter.. one how do I get the img variable to loop into that if statement and then once that works how can I return that z variable to be used in the first xml parser?
Try this synchronous approach:
var itemQueue = [];
$(document).ready(function ()
{
$.ajax({
type: "GET",
url: "connect.php",
dataType: "xml",
success: function parseXml(data)
{
itemQueue= $(data).find("ITEM").map(function ()
{
return {
sku: $("SKU", this).text(),
date: $("LAST_SCAN", this).text()
};
}).get();
getNextItem();
}
});
});
function getNextItem()
{
var item = itemQueue[0];
var query = "http://domain.com/" + item.sku + "?req=exists,json";
$.ajax({
url: query,
dataType: 'jsonp'
});
}
function jsonResponse(response)
{
var item = itemQueue.shift();
if (itemQueue.length)
{
getNextItem();
}
var x = response["it.exists"];
var z = x == "0" ? "NO IMG" : "<img src=\"http://domain.com/" + item.sku + "\">";
$("table").append("<tr><td>" + item.date + "</td><td>" + z + "</td>");
}
Store 'date' in a global variable, and move the logic to append HTML elements into the jsonResponse function. You cannot return control flow from jsonResponse because it's called asynchronously, but you can continue doing anything you'd like from that function.

Categories

Resources