HtmlUnit and XPath fail to retrieve HTML element - xpath

I am trying to get an input element from this web:
https://www.milanuncios.com/textos-del-anuncio/?demandax=n&c=131&idlocalidad=8&p=almeria&x=27&y=0
The input itself is:
<input class="inputs campoGrande" name="marca" value="" maxlength="120" size="12" id="marca" tabindex="1" type="text">
I have tried different approaches but all I always get is a "null" reference:
HtmlInput inputZona = (HtmlInput) currentPage.getElementById("marca");
HtmlInput inputZona = (HtmlInput) currentPage.getFirstByXPath("//input[#name='marca']");
Also tried JSoup with same results :-(
Both, HTMLUnit and XPAth fail to get the item.
What is going on with this?
Thanks in advance,
Jose

This code works here with the latest version of HtmlUnit (2.28-SNAPSHOT).
public static void main(String[] args) throws Exception {
WebClient webClient = new WebClient(BrowserVersion.BEST_SUPPORTED);
HtmlPage page = webClient.getPage("https://www.milanuncios.com/textos-del-anuncio/?demandax=n&c=131&idlocalidad=8&p=almeria&x=27&y=0");
System.out.println(page.asXml());
HtmlInput inputZona = (HtmlInput) page.getElementById("marca");
System.out.println(inputZona.asXml());
}

Related

How to find element's xpath in chrome for selenium testing

When I inspected my page in chrome, I get this:
<input class="form-control form-text required" title="" data-toggle="tooltip" type="text" id="edit-name" name="name" value="" size="60" maxlength="60" data-original-title="Enter your username.">
1.
I right clicked on this code and selected Copy > Xpath. I got this:
//*[#id="edit-name"]
I created a variable:
final By userNameField = By.xpath ("//*[#id="edit-name"]");
I get syntax error.
2.
Then I tried this by id
public void enterUserName(){
driver.findElement(By.id("edit-name")).sendKeys("admin");
System.out.println("User name is entered");
}
It entered the user name just fine. How do I find the correct xpath in chrome so I can create a variable like I tried in step 1?
final By userNameField = By.xpath ("//*[#id="edit-name"]");
You've got double quotes inside your quotes.
change to:
final By userNameField = By.xpath ("//*[#id='edit-name']");

use Ajax to call data from servlet

I know this question probably has been asked before, but I can't seem to find the awnser on it.
I'm trying to call a servlet method when a page is loaded, at this moment it's an endless loop cause every time the servlet posts the response the page gets reloaded and calls the servlet again which then calls reloads the page again etc etc..
I'm collecting an ID from the url which I then use in the servlet to collect the data I need.
Here is the code I'm currently using.
<form style="display:none;" action="ServletC" method="POST">
<input type="hidden" name="hdn_parameter" value="<%= request.getParameter("productID")%>"/>
<input type="submit" id="btn_loadform" name="loadform" style="display: none;"/>
<script>
document.getElementById('btn_loadform').click();
</script>
</form>
and I got a couple pieces of code like this throughout the page
<img id="picture_img" class="" style="width:300px;" src="${ImageResponse}" />
The following code is on my servlet
if (request.getParameter("loadform") != null)
{
int productID = Integer.parseInt(request.getParameter("hdn_parameter"));
String link = "PictureDetail.jsp?productID=" + Integer.toString(productID);
Product p = null;
try
{
p = DBConnect.getProduct(productID);
}
catch (SQLException ex)
{
Logger.getLogger(ServletC.class.getName()).log(Level.SEVERE, null, ex);
}
request.setAttribute("ImageResponse", p.getPath());
request.setAttribute("TitleResponse", p.getName());
request.setAttribute("DescriptionResponse", p.getDescription());
request.setAttribute("PriceResponse", p.getPrice());
loaded = true;
RequestDispatcher dis = request.getRequestDispatcher(link);
dis.forward(request, response);
}
could anyone help me on what I should do now to make this happen without refreshing the page so it will work smoothly.
Thanks in advance.
The request that goes out on click of that button is a proper http request and its response would naturally repaint the page. You will have to form an AJAX request on button click, parse the response on success and then do something on the page (with the parsed response data).

Custom renderer not triggering listener for ajax event

Hello again JSF Gurus.
I am looking for help on custom renderers and ajax handlers. Our project cannot use the normal radio button and check box renderers as they render in tables and this is against our corporate standards. Neither can we use third party component libraries.
We have a custom renderer that we have used in a few projects now that works fine. However, on this particular project, I need to render the ajax click handler for some radio buttons. Following the advice in the answer to this question I have added the call to RenderKitUtils.renderSelectOnclick(); and whilst it appears to render the same javaScript as the standard renderer, and indeed, firebug network panel shows the outgoing request, my value change listener is not being fired and I am looking for help as to why (it fires perfectly well with the standard renderer)
Some code:
Firstly, the creation of the ajax handler (the radio button is created programatically)
AjaxBehavior valueChangeAction = (AjaxBehavior) FacesUtils.getApplication().createBehavior(AjaxBehavior.BEHAVIOR_ID);
valueChangeAction.addAjaxBehaviorListener(new ProbeQuestionListener(currentQuestion, "probeDiv" + questionNumber,
probeDiv));
selectUI.addClientBehavior("valueChange", valueChangeAction);
valueChangeAction.setRender(Collections.singletonList("probeDiv" + questionNumber));
Wih the standard renderer, this produces:
<table id="answer_1" class="marginLeft1a">
<tbody>
<tr>
<td>
<input id="answer_1:0" type="radio" onclick="mojarra.ab(this,event,'valueChange',0,'probeDiv2')" value="0" name="answer_1">
<label for="answer_1:0"> Yes</label>
</td><td>
<input id="answer_1:1" type="radio" onclick="mojarra.ab(this,event,'valueChange',0,'probeDiv2')" value="1" name="answer_1">
<label for="answer_1:1"> No</label>
</td>
</tr>
and all is well. The ajax request is posted and my server side listener gets fired.
The relevant parts of my custom renderer:
public void encodeEnd(final FacesContext p_context, final UIComponent p_component) throws IOException {
/* set up convenience fields */
context = p_context;
component = p_component;
componentId = component.getClientId(context);
// rendering divs etc omitted.
while (iterator.hasNext()) {
final UIComponent childComponent = iterator.next();
// irrelevant code omited
if ("javax.faces.SelectItem".equals(childComponent.getFamily())) {
renderSelectItem(idIndex, childComponent);
idIndex++;
}
}
}
private void renderSelectItem(final int p_idIndex, final UIComponent p_childComponent) throws IOException {
// unrelated code omitted
writer.startElement("input", component);
writer.writeAttribute("type", getInputType(), null);
writer.writeAttribute("id", p_childComponentId, "id");
writer.writeAttribute("name", componentId, "clientId");
RenderKitUtils.renderSelectOnclick(context, component, false);
writer.endElement("input");
// unrelated code omitted
}
Update: The decode method in the base class for my renderer is:
#Override
public void decode(final FacesContext p_context, final UIComponent p_component) {
final Map<String, String> valuesMap = p_context.getExternalContext().getRequestParameterMap();
final UIInput input = (UIInput) p_component; // NOSONAR
final Object value = valuesMap.get(input.getClientId(p_context));
// System.out.println("radio button decode: found " + value);
input.setSubmittedValue(value);
}
This renders as :
<span class="marginLeft1a" id="answer_1">
<label for="answer_1:0">
<input type="radio" value="0" onclick="mojarra.ab(this,event,'valueChange',0,'probeDiv2')" name="answer_1" id="answer_1:0">
Yes
</label>
<label for="answer_1:1">
<input type="radio" value="1" onclick="mojarra.ab(this,event,'valueChange',0,'probeDiv2')" name="answer_1" id="answer_1:1">
No
</label>
</span>
As you can see, the javaScript click handler is identical, as are the name and id attribute values of the input tags. Although this triggers the Ajax request, the listener is not fired server side as it is with the first version.
Any ideas ?
The decode() method of the Renderer (or UIComponent if there's no renderer) is supposed to decode the ajax request based on javax.faces.behavior.event request parameter and trigger ClientBehavior#decode() on the matching client behaviors.
Basically, the logic is as follows:
Map<String, List<ClientBehavior>> behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();
if (!behaviors.isEmpty()) {
Map<String, String> params = context.getExternalContext().getRequestParameterMap();
String behaviorEvent = params.get("javax.faces.behavior.event");
if (behaviorEvent != null) {
List<ClientBehavior> behaviorsForEvent = behaviors.get(behaviorEvent);
if (behaviorsForEvent != null && !behaviorsForEvent.isEmpty()) {
String behaviorSource = params.get("javax.faces.source");
if (isBehaviorSource(context, behaviorSource, component.getClientId())) {
for (ClientBehavior behavior: behaviorsForEvent) {
behavior.decode(context, component);
}
}
}
}
}
Given the fact that you're using RenderKitUtils and the generated HTML output contains mojarra.ab(), I'll assume that you're using Mojarra. In that case, it's perhaps wiser to extend your custom renderer from RadioRenderer instead which has all this logic already implemented in HtmlBasicRenderer and SelectManyCheckboxListRenderer so that you don't need to reinvent the wheel.

play 2.0 form date validation fail

I'm using "Play 2.0"-Framework (v. 2.0.1) and running into some troubles with form validation of a date value.
Peace of my Model code:
#Entity
public class Appointment extends Model {
public Date start;
public Date end;
}
Peace of my template code:
<input type="text" id="start" name="start" placeholder="yyyy-mm-dd" />
<!-- ALSO tested with chrome beta v. 20 with html5 support-->
<input type="date" id="end" name="end" placeholder="yyyy-mm-dd" />
My Controller:
public class Appointment extends Controller {
static Form<Appointment> appointmentForm = form(Appointment.class);
//on calling form page
public static Result create() {
return ok(create.render("create", appointmentForm));
}
//called on saving form data
public static Result save() {
Form<Appointment> filledForm = appointmentForm.bindFromRequest();
if (filledForm.hasErrors()) {
return badRequest(
create.render("create", filledForm)
);
} else {
Appointment.create(filledForm.get());
return redirect(routes.Appointment.index());
}
}
}
If I select a date via jquery ui datepicker or type in myself in a format like "yyyy-mm-dd" or doesn't matter, but must be correct format I run into a validation error in my controller save()-method with the check "filledForm.hasErrors()" and the error message "wrong date format".
I thought it would be converted automatically from play, so that I don't have to add a convertion by my self. What can I do to solve this problem? Is it still an issue from play 2.0?
Thanky you.
Cheers,
Marco
I think you must define the format of the date. See Play Framework 2.0: Custom formatters for custom formatters. Perhaps a custom binder is necessary see https://groups.google.com/d/topic/play-framework/Xi2xAiCnINs/discussion
Just as some hints to give you a direction. Hopefully someone can give you a better answer.

Model isn't updatd on AJAX submit link invocation

I'm trying to implement an AJAXfied Wicket list view. On my research I stumbled upon the code on this site and modified it a bit.
The model is not updated properly. So whenever a value is entered in a text field, it is forgotten if the AJAX submit link is invoked (the text field is empty). Why does this happen? I don't see any issue with this code. Wicket version is 1.5.2.
Here is the Java code:
// Initialization of form
...
// List all rows
ArrayList<String> rows = new ArrayList<String>(2);
rows.add(new String());
rows.add(new String());
final ListView<String> lv = new ListView<String>("rows", rows) {
#Override
protected void populateItem(ListItem<String> item) {
int index = item.getIndex() + 1;
item.add(new Label("index", index + "."));
TextField<String> text = new TextField<String>("text", item.getModel());
item.add(text);
}
};
rowPanel.add(lv);
AjaxSubmitLink addLink = new AjaxSubmitLink("addRow", form) {
#Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
if (target != null) target.add(rowPanel);
}
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
lv.getModelObject().add(new String());
if (target != null) target.add(rowPanel);
}
};
addLink.setDefaultFormProcessing(false);
rowPanel.add(addLink);
...
And here is the mark up:
<div wicket:id="rowPanel">
<span wicket:id="rows">
<span wicket:id="index">1.</span>
<input type="text" wicket:id="text"/>
</span>
Add row
</div>
My previous comment as anwser:
You may need to call setReuseItems(true) on the listview.
Another way of ajaxifying a listview can be found at the Wicket in Action blog
Your example would work fine if you hadn't added the following line:
addLink.setDefaultFormProcessing(false);
Your link doesnt process the form like he would normally do (update models etc, see IFormSubmitter)
You could use nested Forms to updated only the area you need and set defaultFormProcessing back to true.
Like:
<form wicket:id="form">
(...) <!-- (other form elements you dont want to get updated -->
<form wicket:id="repeaterForm"> <!-- form for your repeater textfields-->
<div wicket:id="refreshDiv">
<input type="textfield" wicket:id="repeaterText" />
</div>
<a wicket:id="addMoreLink>add more</a>
</form>
</form>
Wicket will make sure you don't actually have nested forms within your markup (it will replace the nested form with a div) because it ain't valid HTML. But it would work as if the forms are nested nevertheless.
You have to use the model from the target like this:
IModel model = target.getModel();
Then cast to the listView. I don't know if this works, but I have some similar code here.

Resources