I've got a pretty strong understanding of php, html & css but i've only just started to dive into javascript & jQuery.
The problem i'm facing is that I have a form on a page that I want first to validate, then when it passes validation to submit 2 ajax requests; the first to insert data into a table in my database and the second to run a query on another table and return the result.
I've got the latter working just fine using the submitHandler method to send the ajax request and update a div on my page with it's result. When I added a second ajax call after or before this one it seems to break...
My question is should there be a problem with having 2 ajax calls in the submitHandler, like below, and if so what would be the correct way to go about this, or even a better way?
$("#contactform").validate({
rules: ...
submitHandler: function() {
// First to insert the contact details using input#firstname etc.
var firstname = $("#firstname").value();
var lastname = $("#lastname").value();
var contactString = 'firstname='+ firstname + '&lastname=' + lastname;
$.ajax({
type: "POST",
url: "insertcontact.php",
data: quoteString,
success: function(server_response){
$('#yourquote').html(server_response).show();
}
});
// Second use width & height submitted from previous page for processquote.php
var width = <?php echo json_encode($cleanpost['width']); ?>;
var height = <?php echo json_encode($cleanpost['height']); ?>;
var quoteString = 'width='+ width + '&height=' + height;
$.ajax({
type: "POST",
url: "processquote.php",
data: quoteString,
success: function(server_response){
$('#yourquote').html(server_response).show();
}
});
}
});
I'm using the 'jquery.validate.js' validation plugin. Again my goal is such that once someone has entered valid details on my form, using Ajax their contact data is inserted into the database then the database is queried using fields submitted on the previous page to retrieve a numerical result to display on the page, without a refresh.
Any pointers you could give me would be much appreciated!
Rob
EDIT: Learning Javascript & Jquery simultaneously isn't such a good idea it seems, i've confused: this.value = ''; with $(this).val(''); as shown in the first 2 variable declarations, this is what was causing problems! Thanks for your useful help anyway guys, will upboat for your assistance.
In your first .ajax() call, you are trying to pass it a value in the data: parameter that you have not created yet. I believe you are wanting to send it the contactString instead.
Unless your two queries depend on each other being done sequentially then you should be able to execute them both asynchronously (essentially at the same moment). If you want the second AJAX call to happen after the first one, you could always pass all of your data parameters to insertcontact.php and once the insertion is done, execute processquote.php with the values you already passed through.
Lastly, I wonder if you are meaning to do this, but both of your AJAX calls overwrite whatever is in the #yourquote DOM element and show it. You might want to provide a separate element to put the response in for each of your two requests. Perhaps #yourquoteinserted and #yourquoteprocessed?
Edit: BigRob, from your comment it sounds as if you want to make synchronous AJAX queries, check out the async property of your .ajax() call. This is from the .ajax() documentation:
async Boolean
Default: true
By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.
(emphasis mine)
However, I could be wrong about this but you might actually be able to call one asynchronous AJAX method from within the success function of another. If it starts looking too intermingled for you, you might want to extract the inner call into a function. Rough approximation of what it might look like:
$.ajax({url, data:contactString,
success: function(server_response) {
extractedId = server_response; // you can return data many ways
$.ajax({url2, data:quoteString+"&extra="+extractedId,...
});
}
});
If you perform a synchronous call by setting async:false in the first AJAX call, then you could just store the result into an external (to the AJAX call) variable (or if that doesn't work store it in some DOM element temporarily). Then the javascript will pause execution and won't fire your second AJAX call until the first one has returned.
This is all hypothetical for now, though, and just based off of my understanding of how it should work.
Related
I admit I'm quite noob with full ajax websites, and so I'm surely making some mistakes.
The problem is this:
in http://lamovida.arabianessence.com
every page is loaded with an $.ajax call using this function
function getAjaxPage() {
$('a.ajaxc').click(function() {
$("li.page_block").find(".wrapper").fadeOut(400).remove();
hideSplash();
var $thishref = $(this).attr('href'),
$thisurl = $thishref.replace("#!/",""),
$urlArr = $thisurl.split('-'),
$urlOk = $urlArr[0],
$dataOk = $urlArr[1];
$.ajax({
url : $urlOk + ".php",
data : 'id='+$dataOk,
success : function (data,stato) {
$("#content").css({opacity:1}).fadeIn(400);
$("li.page_block").html(data);
$("li.page_block").css('visibility', 'visible');
$("li.page_block").find(".wrapper").css({opacity:0}).show().animate({opacity:1},1000);
var $whgt = $(".wrapper").height(),
$ctop = ( ( $(window).height() - $whgt ) /2 )-40;
$("#content").stop().animate({height: $whgt+40, top: $ctop},1000);
$("li.page_block").css('padding-top',20);
$('.scrollable').jScrollPane();
$('.slider>ul>li').jScrollPane();
getAjaxPage();
},
error : function (richiesta,stato,errori) {
alert(errori);
}
});
});
}
Every time this function is called the content gets loader slower, and after about 20 clicks things get real bad, and the loading time grows and grows.
I tried to analyze the situation using the Google Chrome's Timeline, and I saw that after each click the browser uses more memory. If I comment the getAjaxPage(); row in the "success" section the situation starts to get better, but of course I lose all the internal navigation.
What could I do to avoid this problem?
Many thanks to all!
Every call to $('a.ajaxc').click() is adding new event handler thus every click causes more requests to be made. After the first click, every click will cause two requests. Another click? Another three requests. Etc.
Put the handler outside the function and you will have only one AJAX call per click:
$(document).ready(function() {
$('a.ajaxc').click(getAjaxPage);
});
I also don't see the reason behind calling getAjaxPage again from within the callback, so remove it as well to avoid infinite loop of requests.
I need to display a number of "dynamic" grids using jqGrid. By dynamic I mean that both definition and data of the grid are retrieved from a database. There are many grids on the page, so I am trying to minimize the number of server trips, and there is a lot of data, so server-side paging is a must.
My workflow is
On initialization of each grid, retrieve grid definition and first
page of data in one server call.
If a user sorts/pages, then retrieve a page of data from the server
Because I want to retrieve the grid definition and first page of data in one call, I cannot use datatype: 'json', url: '###' approach; instead I do:
grid.jqGrid({
mtype: 'post',
...
datatype: function (postdata) {
if (!init.data) {
var request = {
screenId: settings.screenId,
pageNumber: postdata.page,
pageSize: postdata.rows,
sortColumn: postdata.sidx,
sortDirection: postdata.sortd,
date: settings.date
};
site.callWs("/MyService", request, function (pageResponse) {
//WHAT TO CALL HERE TO SET A PAGE OF DATA?
});
} else {
//WHAT TO CALL HERE TO SET A PAGE OF DATA?
init.data = null;
}
}
});
My data object (pageResponse or init.data) looks like this
I am not sure what method to call on jqGrid once a page of data is returned. I considered addJSONData, but it seems so inefficient to convert JSON back to string, then use EVAL(). Also, considered addRowData or setting the data property, but I am confused how to instruct jqGrid that I am doing server-side paging -- if I set the data property to one page of records, what do I need to do to tell jqGrid that there is a total of 50 records and this is page 1 out of 10.
Thanks for your help.
It was a user error (mine :). I had some show/hide logic in loadComplete of jqGrid, but this event does not fire when addJSONData is called.
addJSONData works just fine when provided with a properly-structured JavaScript object.
I am trying to scrape information from a specified website. This site uses authentication first, thus a i use zombie.js:
var Browser = require("zombie");
var browser = new Browser();
browser.visit("https://*****login.aspx", function(){
browser.fill('#user', '*****');
browser.fill('#pwd', '*****');
var button = browser.querySelector('#btnSubmit');
browser.fire('click', button, function(){
//scraping main.aspx
});
});
It's working, i can scrape the main.aspx: there is a <table>, containig information about new messages(from, date, subject,), the problems comes here: the subject field is clickable, and clicking on it makes a new window appear with the actual message. However it is an ajaxgrid, and when i perform a click:
var field = browser.querySelector('#VeryLongIdOfTheField');
browser.fire('click', field, function(){
console.log(browser.querySelector('#VeryLongIdOfTheFieldContainingTheMessage').innerHTML);
});
it returns an error message, saying that undefined has no innerHTML. I suppose its because this action handled with some ajax magic. I am new in this js/nodejs/jquery/.. world, some help needed to enlight me.
Since the data is populated using async ajax, I'm guessing there's a lag between your click and the actual DOM population inside the node. How about waiting for a bit before checking the content inside the node.
browser.fire('click', field, function(){
setTimeout(function(){
console.log(browser.querySelector('#VeryLongIdOfTheFieldContainingTheMessage').innerHTML);
}, 3000)
});
If the time taken is not very predictable, you could also run it inside a loop until you find the content or exit after a reasonable number of retries.
On my website I have mouse over and mouse out events set up on an HTML table. These events trigger ajax requests, and perform certain actions etc. However, i want to be able to not trigger a second request if one is already running. So, is there away to detect these requests, and therefore avoid a second. Incidentally Im using the jQuery $.ajax()
if it helps at all.
Thanks in advance
Chris
I'd try something simple like:
var requestMade = false;
function yourAjaxFunction(){
if(!requestMade)
{
requestmade = true;
$.ajax({
url: "page",
success: function(){
requestMade = false;
}
error: function(){
requestMade = false;
}
});
}
}
You can use the success: and error: settings to change the variable back to false.
I have never used the error so you may have to include some other things in it, but this is the general idea.
For this suppose I'd use ajaxStart() and ajaxStop() which would change specific variable ajaxRunning which could be checked before sending the request (maybe in ajaxStart() directly?)
Set global or local static variable to true when first ajax is about to trigger, than add if before triggering the second one ;) Than after one request is finished, set this variable to false
I have a jQuery application, a shopping cart, that posts back info to the server, if the text inputfield is changed. This is done in an Ajax request. Now, if the Ajaxrequest is a success, I want to reload the shoppingcart asynchronously. The code is as follows:
$(document).ready(function() {
var jInput = $(":input");
jInput.change(function() {
var vareAntal = $(this).val();
var vareID = $(this).siblings("input#vareID").val();
$.ajax({
type: 'POST',
url: 'checkout.aspx',
data: { 'ID': vareID, 'Antal': vareAntal },
success: function() {
$("#newbasket").load(location.href + " #newbasket>*", "");
}
});
});
});
This works, but only once! If I change the text inputfield, after the page is loaded for the first time, the div with the ID of newbasket reloads asynchronously. But if I try to change it again, nothing happens.
I've tried to do some debugging with Firebug, and the first time I change the text inputfield, it fires a POST-event, and afterwards a GET-event, when the POST-event is succesful. But after that, nothing happens when I change the text inputfield again.
So, how do I achieve triggering the .load() method after each text input change?
I've also tried experimenting with the .ajaxComplete() function, but that, of course, resulted in an infinite loop, since the .load() is an ajax-object.
Instead of .change(func), use .live('change', func) here, like this:
jInput.live('change', function() {
This will make the selector work on any new inputs added as well. When you're replacing the elements like you are currently, their event handlers are lost (or rather, not re-created, because you have new elements). .live() is just for this purpose, it listens for events from old and new elements, regardless of when they were added.