Problems with HtmlUnit - 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

Related

How to know on client side whether a postback occured?

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();

Primefaces commandButton and ajax

I use a tabView component with many tabs. In many of them, I have form which are submitted by primefaces commandButton component.
By default, PF commandButton using ajax mode but when I submit my form, my page seems to be fully loaded and my tabView component lost its index view (index 0 is rendered).
Is that normal behaviour please ?
I though that I would stay in the same index because it's ajax...
Looks like there is some naming container (p:tabView maybe) that you better assign an id to it , so instead of getting prefix like j_idt16 (which could vary from time to time) you will get myTab0 , myTab1 etc prefix...
for example <p:tabView id="myTab"
Another thing you could do to be on the safe side is checking if the element exists before trying to select it with jquery and access its value, like this
if($('#j_idt16\\:register_location_choice_2_input').length > 0){
//some code here
}
Ok, my problem is the JS validateRegisterForm function. When I remove it, it works but I need it...
I use it to check if validation form can be launched.
function validateRegisterForm(){
if($('#j_idt16\\:register_location_choice_2_input').attr('checked')){
if($('#j_idt16\\:register_galaxies_input').val() == 0){
var galaxie = MUST_CHOOSE_GALAXY;
alert(galaxie.charAt(0).toUpperCase() + galaxie.slice(1));
return false;
}
if($('#j_idt16\\:register_solar_systems_input').val() == 0){
var ss = MUST_CHOOSE_SOLAR_SYSTEM;
alert(ss.charAt(0).toUpperCase() + ss.slice(1));
return false;
}
if($('#j_idt16\\:register_positions_input').val() == 0){
var position = MUST_CHOOSE_POSITION;
alert(position.charAt(0).toUpperCase() + position.slice(1));
return false;
}
}
return true;
}
So how can I check fields values before sending and allowing or not validation form with ajax please ?
EDIT :
Ok, I solved my problem by launching validation inside my JS function with button type passed to button not submit and using remoteCommand component :
My JS function :
function validateRegisterForm(){
if(...)
validateForm();
}
And my remoteCommand :
<p:remoteCommand name="validateForm" actionListener="#{login.registerAccount()}"/>

jquery mobile ajax sends both GET and POST requests

Here is the problem:
By default jQuery Mobile is using GET requests for all links in the application, so I got this small script to remove it from each link.
$('a').each(function () {
$(this).attr("data-ajax", "false");
});
But I have a pager in which I actually want to use AJAX. The pager link uses HttpPost request for a controller action. So I commented the above jQuery code so that I can actually use AJAX.
The problem is that when I click on the link there are two requests sent out, one is HttpGet - which is the jQuery Mobile AJAX default (which I don't want), and the second one is the HttpPost that I actually want to work. When I have the above jQuery code working, AJAX is turned off completely and it just goes to the URL and reloads the window.
I am using asp.net MVC 3. Thank you
Instead of disabling AJAX-linking, you can hijack clicks on the links and decide whether or not to use $.post():
$(document).delegate('a', 'click', function (event) {
//prevent the default click behavior from occuring
event.preventDefault();
//cache this link and it's href attribute
var $this = $(this),
href = $this.attr('href');
//check to see if this link has the `ajax-post` class
if ($this.hasClass('ajax-post')) {
//split the href attribute by the question mark to get just the query string, then iterate over all the key => value pairs and add them to an object to be added to the `$.post` request
var data = {};
if (href.indexOf('?') > -1) {
var tmp = href.split('?')[1].split('&'),
itmp = [];
for (var i = 0, len = tmp.length; i < len; i++) {
itmp = tmp[i].split('=');
data.[itmp[0]] = itmp[1];
}
}
//send POST request and show loading message
$.mobile.showPageLoadingMsg();
$.post(href, data, function (serverResponse) {
//append the server response to the `body` element (assuming your server-side script is outputting the proper HTML to append to the `body` element)
$('body').append(serverResponse);
//now change to the newly added page and remove the loading message
$.mobile.changePage($('#page-id'));
$.mobile.hidePageLoadingMsg();
});
} else {
$.mobile.changePage(href);
}
});
The above code expects you to add the ajax-post class to any link you want to use the $.post() method.
On a general note, event.preventDefault() is useful to stop any other handling of an event so you can do what you want with the event. If you use event.preventDefault() you must declare event as an argument for the function it's in.
Also .each() isn't necessary in your code:
$('a').attr("data-ajax", "false");
will work just fine.
You can also turn off AJAX-linking globally by binding to the mobileinit event like this:
$(document).bind("mobileinit", function(){
$.mobile.ajaxEnabled = false;
});
Source: http://jquerymobile.com/demos/1.0/docs/api/globalconfig.html

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.

Livequery fires click no matter where the user clicks in the document

I have replaced the traditional select/option form elements with a nifty little popup window when a triggering image is clicked. The page is for accounting purposes and so multiple line items are to be expected. I've written the javascript that will dynamically generate new line item select/option elements. When the page loads, the initial set of choices loads and the user can click on them, get a pop up with some choices, choose one and then the box closes. The move to the next choice and so on and so forth. I've added livequery to my code for those dynamic elements. However... the livequery("click"...) seems to fire no matter where the user clicks on the page. Very frustrating.
I've read on here how great "live()" is in jQuery 1.3, but I am not able to upgrade fully to jquery 1.3 because a custom JS file depends on 1.2, so using live() is out of the question, however I have invoked the livequery() plugin and I really need to understand if I'm using it correctly.
I will post partial code. There's just way too much to post all of it.
Basically, I'm searching for divs starting with "bubble" and then a number afterwards. Then run the event on each them. Only bubble1 is static, 2 and up are dynamic. Am I missing the whole usage of livequery?
>$jb('div[id^="bubble"]').each(function () {
> var divid = $jb('div[id^="bubble"]').filter(":first").attr("id");
>var pref = "bubble";
>var i = divid.substring((pref.length));
>var trigger = $jb('#trigger' + i, this);
>var popup = $jb('#pop'+ i, this).css('opacity', 0);
>var selectedoption = $jb('selectedOption' + i, this);
>var selectedtext = $jb('selectedOptionText' + i, this);
>$jb([trigger.get(0), popup.get(0)]).livequery("click",
> function () {
>//alert(i);
// code removed for brevity (just the contents of the popups)
>});
Live works by using event delegation. A click event is attached to the body, and anytime something is clicked the selector is tested against the target. If it passes the selector test it calls the function (thus simulating a click event).
You probably want something like this:
$('div[id^="bubble"]').livequery("click", function() {
var divId = $(this).attr("id");
var i = divId.substring("bubble".length);
var trigger = $("#trigger" + i, this);
var popup = $("#pop" + i, this).css("opacity", 0);
// alert(i);
}

Resources