How to know on client side whether a postback occured? - ajax

I am developing a Greasemonkey script and this script changes some elements in a table. However, when we click a button in the table an asynchronous postback happens and the table is refreshed.
So, my elements are also refreshed. How do I know a postback has occurred so that I can run my script again to change the new elements in the table? (The page uses Telerik.)

Don't bother trying to check for a postback That's almost always a painful way of doing things. You care about the table content, monitor that.
See:
Run Greasemonkey script on the same page, multiple times?
Fire Greasemonkey script on AJAX request
How can I detect AJAX node insertion without using DOM mutation events?
and several others.

Just as Brock Adams says in his answer, I decided to monitor table and wrote this code:
function repairInputEvents() {
for (var i = 0; i < document.getElementsByTagName("input").length; i++) {
//Add event to buttons that cause postback.
document.getElementsByTagName("input")[i].addEventListener("click", function() {
//Run the following just before postback.
document.getElementsByClassName("table")[0].setAttribute("title", "old");
var checkAjaxInterval = setInterval(function() { checkAjax(); }, 1000);
function checkAjax() {
if (document.getElementsByClassName("table")[0].getAttribute("title") != "old") {
clearInterval(checkAjaxInterval);
repairInputEvents();
repairSelectEvents();
}
}
});
}
}
//First run
repairInputEvents();
repairSelectEvents();

Related

jQuery Mobile 1.4+ pagecontainerbeforechange bug?

I am experimenting with the new way of handling page events in jqM and have run into a curious issue. When handling the pagecontainerbeforechange event
$(document).on('pagecontainerbeforechange',function(e,u){test(e,u,'changing');})
function test(e,u,msg){console.log($(u.toPage));}
Attempting to put a jQuery object wrapper around u.toPage - as done above - produces strange behavior.
Check out this fiddle to see what I mean
Click on the Second Page button and then view the console. Nothing will happen (the second page is not shown) and you will see a message along the lines of *Uncaught error:syntax error, unrecognized expression http://jsfiddle.net/egn7g5xb/1/show/#second
Now comment out Line 7 and run the fiddle again. No such issue this time and the second page gets shown.
Perhaps someone here might be able to explain what is going on here?
On initial run, jQuery Mobile creates a fake page before navigating to first page in DOM. At that stage, pagecontainerbeforechange fires twice and returns .toPage as an object.
Later on, upon navigating to other pages, it fires twice again; however, it returns a string first time (URL/hash) and second time it returns an object which is the page itself.
Therefore, when using that event, you have to determine whether .toPage is an object or a string.
$(document).on("pagecontainerbeforechange", function (e, data) {
if (typeof data.toPage == "string") {
/* parse url */
}
if (typeof data.toPage == "object") {
/* manipulate page navigating to */
}
});
Note that pagecontainerbeforetransition is similar to beforechange, however, it fires once and returns .toPage as an object.
First, create your pagecontainer events within $(document).on("pagecreate", "#first", function(){ .. }).
Then the selector for these events should be $(":mobile-pagecontainer") or $("body") NOT $(document).
function test(e,u,msg)
{
console.log(msg);
var IsJQ = u.toPage instanceof $;
console.log(IsJQ);
if (IsJQ){
console.log(u.toPage.data());
} else {
console.log(u.toPage);
}
console.log('---');
}
$(document).on("pagecreate", "#first", function(){
$(":mobile-pagecontainer").on('pagecontainerbeforechange', function (e, u) {
test(e,u,'changing');
});
$(":mobile-pagecontainer").on('pagecontainerchange',function(e,u){
test(e,u,'changed');
});
});
Updated FIDDLE

Website loses performance after some jQuery $.ajax calls

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.

Problems with HtmlUnit

I'm trying use HtmlUnit to submit a form, there are two select in my form, when i selected the first select, his call a function ajax and load the second select, follow my code:
HtmlPage page5 = anchor.click();
HtmlForm form = page.getFormByName("form1");
HtmlSelect state = form.getSelectByName("ddlMarca");
state.setSelectedAttribute(state.getOptionByValue("56"), true);
state.fireEvent(Event.TYPE_CHANGE);
HtmlSelect city = form.getSelectByName("ddlModelo");
for (HtmlOption option : city.getOptions()) {
System.out.println("city : "+option.asText()+" valor: " +option.getValueAttribute());
}
I'm using the method fireEvent to call event change, but does't work, How I can do this event work?
It may be working but you're not giving the browser time to make the ajax call, get a response and edit the dom. If the page makes an ajax call after firing the change event, try letting the page wait for a moment before checking again.
I haven't tested the below code so I can't say for certain this will solve you're issues, but I have used this technique to solve a similar issue.
You'll have to find something on the page that changes when the ajax call is completed for this to work. From the above question I'm assuming that changing one select populates the 2nd select box.
state.fireEvent(Event.TYPE_CHANGE);
//try 20 times to wait .5 second each for filling the page.
for (int i = 0; i < 20; i++) {
if (condition_to_happen_after_js_execution) {
break;
}
synchronized (page) {
page.wait(500);
}
}
HtmlSelect city = form.getSelectByName("ddlModelo");
for (HtmlOption option : city.getOptions()) {
System.out.println("city : "+option.asText()+" valor: " +option.getValueAttribute());
}
Example pulled from: http://htmlunit.sourceforge.net/faq.html#AJAXDoesNotWork

Handle ajax response with node.js

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.

simulating the "add another item" ajax call in drupal 7 using jquery

I am trying to get jQuery to send a mousedown event to the Drupal 7 "add another item" button for a multi-value field, then wait until the ajax call has completed before filling in that new blank row with data from an element in a jQuery object (that has several elements). I need to use a loop to cycle through the elements (ingredients) in this jQuery object, but no matter what I try my page dies...
Currently, I have something like the following:
i = 0;
ingredients = newHtml.find('.recipe_ingredients > li');
ingredientsLength = ingredients.length;
$('#edit-field-ingredients-und-add-more').mousedown();
while(i < ingredientsLength) {
if ( document.readyState !== 'complete' ) {
// code to fill in the new blank row with data from 'ingredients'
$('#edit-field-ingredients-und-add-more').mousedown();
i++;
}
}
Because I don't yet know how to issue the ajax call myself using jQuery (or using Drupal) I've been trying to just check whether the call has completed by using .readyState and other hack-like methods. I'm just not sure what to try next!
Am I going about this the completely wrong way? Is there a straightforward way to make the "add another item" multi-value field ajax call using jQuery? Any help would be greatly appreciated...
I am not sure if there's a nicer way in Drupal 7, but in Drupal 6 you could use jQuery(document).ajaxComplete with the settings.url property to tell when a specific "Add another item" click had finished.
Start with:
(function($) {
$(document).ajaxComplete(function(e, xhr, settings)
{
alert(settings.url);
});
}(jQuery));
Once you've identified the right settings.url for your field, change that to:
(function($) {
$(document).ajaxComplete(function(e, xhr, settings)
{
if (settings.url == "the path from step 1") {
// Code to populate your fields here
}
});
}(jQuery));
And voila!
You might want to read the page by Jay Matwichuk where I originally learned this technique awhile back. All credit to him (and nclavaud for his comment there), really.

Resources