I have a document containing several forms similar to the example posted below. I want to extract all the name/value pairs from the hidden input fields of one of the forms, the form is identified by its name and I don't know in advance how many hidden fields will be present.
I am able to select all the relevant input fields in the document using the selector query: input[type=hidden][name][value]
Is there a way to only select the input fields which has FORM[name=lgo] as parent? Using some kind filter maybe?
<FORM METHOD='POST' onSubmit='javascript:isWaitForm();' ACTION='https://abc-azerty.querty.se/carmon/servlet/action/change_1 ' name='lgo'>
<input type='hidden' name='LogInFlag' value='1'>
<input type='hidden' name='LogInTime' value='2011-07-26 11:10'>
<input type='hidden' name='cCode2' value='SE'>
<a href='javascript:isWaitForm();javascript:document.lgo.submit();' class='linkNone'>Business Monitor</a>
<a href='javascript:isWaitForm();javascript:document.lgo.submit();' class='linkNone'>
<input type='image' src='/images/button_arrow_right.gif' height=19 width=22 border=0 style='float:left;'></A>
</FORM>
Based on this info, at least one of following should work -
doc.select("form[name=lgo] > input[type=hidden]");
Or, you can chain your selects -
doc.select("form[name=lgo]").select("input[type=hidden]");
The select method is available in a Document, Element, or in Elements. It is contextual, so you can filter by selecting from a specific element, or by chaining select calls.
<script type="text/javascript">
var inputs = document.getElementsByName('lgo')[0].getElementsByTagName('input');
for(var i = 0 ; i < inputs.length ; i++){
if(inputs[i].getAttribute('type') == "hidden") {
// This will get the name: inputs[i].getAttribute('name')
// This will get the value: inputs[i].value)
console.log(inputs[i].getAttribute('name') + ": " + inputs[i].value);
}}
</script>
Related
How my web application works:
My web application loads a div with radio button input elements after conditions in the form above are changed. The form above will allow the manager to select a date and time. The div below will load with all the employees available at that date and time. I give this div the id "EmployeeListBox". Everytime conditions change in the form above the EmployeeListBox gets radio buttons injected using jquery's append method.
Okay so that's the idea of how my web application works. What I am trying to do is click the first radio button in the div EmployeeListBox after the form gets changed, using selenium web driver for Firefox in java. This is the line that I need to fix:
`driver.findElement(By.xpath("//[#id="EmployeeCell"]/span[2]/input")).click();`
When I run this xpath I recive this error:
Exception processing script - Element not found in the cache - perhaps the page has changed since it was looked up.
I guess the xpaths I have tried do not work because the elements are dynamically loaded.
Here is the JS code that loads the EmployeeListBox.
AvialableStaff = JSON.parse( data );
var MSG = "";
$('#EmployeeListBox').empty();
/*for each employee in AvialableStaff load the #CreateShiftLifeOfEmployees Select option*/
var eico = 0;
for ( var Staff in AvialableStaff )
{
var ID = AvialableStaff[Staff]["employeeID"];
var name = AvialableStaff[Staff]["Firstname"]+" "+ AvialableStaff[Staff]["Lastname"];
MSG += "<div id = \"EmployeeCell\">";
MSG += "<span class = \"MakeLeft\" id = \"EI"+eico+"\" > "+name+" </span>";
MSG += "<span class = \"MakeRight\"><input type = \"radio\" name=\"ChooseStaff\" value = \""+ID+"\" class = \"CSTAFFradioButtons\" /> </span>";
MSG += "</div>";
eico++;
}
$('#EmployeeListBox').append( MSG );
Here is my EmployeeListBox without the employee cells:
<p>Select an available employee</p>
<div id = "CSEmployeeList" >
<div id = "StaffAvaileP"> <h3> Staff Available</h3> </div>
<div id = "EmployeeListBox">
<!-- Radio Buttons go here -->
</div>
</div>
This is what the employee box looks like after the form has been changed and employee radio buttons have been inserted:
<div id="EmployeeListBox">
<div id="EmployeeCell">
<span class="MakeLeft" id="EI0"> Person One </span>
<span class="MakeRight">
<input type="radio" name="ChooseStaff" value="9" class="CSTAFFradioButtons">
</span>
</div>
<div id="EmployeeCell">
<span class="MakeLeft" id="EI1"> Person Two </span>
<span class="MakeRight">
<input type="radio" name="ChooseStaff" value="10" class="CSTAFFradioButtons">
</span>
</div>
<div id="EmployeeCell">
<span class="MakeLeft" id="EI2"> Person Three </span>
<span class="MakeRight">
<input type="radio" name="ChooseStaff" value="11" class="CSTAFFradioButtons">
</span>
</div>
</div><!--End of EmployeeListBox -->
Here is my java method which runs the test:
/** Method testCreateShifts
* purpose: Loads shifts with realistic shift data like the
* real life Saturday schedule.
*/
public static void testCreateShifts()
{
driver.get(theurl);
String createshiftPage = "https://***/index.php?/CreateAShift";
driver.get(createshiftPage);
new Select(driver.findElement(By.id("Day"))).selectByVisibleText("11");
new Select(driver.findElement(By.id("StartTime"))).selectByVisibleText("8:30am");
new Select(driver.findElement(By.id("EndTime"))).selectByVisibleText("2:00pm");
driver.findElement(By.id("Instructor")).click();
/*TODO: Currently trying to click on first employee in employee list box*/
driver.findElement(By.xpath("//*[#id=\"EmployeeCell\"]/span[2]/input")).click();
driver.findElement(By.id("CreateShiftSubmit")).click();
}/*End of Method testCreateShifts*/
So using selenium in java how do I click first radio button that is in the list after the EmployeeListBox gets reloaded by jquery?
I found out what was wrong. I needed to give my webapplication time to load.
I told my java test to wait 1 second with this line.
try {Thread.sleep(2000);}catch (InterruptedException ex) { }
I have 2 jsp's:
createEdit.jsp and save.jsp
Inside createEdit.jsp I have a an html code inside a form and since it includes file upload, I am using encoding type "multipart/form-data". Inside the form I have a table. The requirement is to save the data from the table to the database. I can add row to the table dynamically through Jquery or Javascript.
This is my sample form having table:
<form action="save.jsp" method="post" enctype="multipart/form-data" name="frm">
<table id="tblRating">
<tr><td><input id="e1">Element1</input><input id="e2"></input><td><tr>
</table>
</form>
The javascript code am using for adding rows dynamically to the exisitng table:
function generateRow(){
console.log("Generate the row");
var table = document.getElementById('tblRating');
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var colCount = table.rows[0].cells.length;
for(var i=0; i<colCount; i++) {
var newcell = row.insertCell(i);
newcell.innerHTML = table.rows[1].cells[i].innerHTML;
console.log(newcell.childNodes);
switch(newcell.childNodes[0].type) {
case "text":
newcell.childNodes[0].value = "";
break;
case "checkbox":
newcell.childNodes[0].checked = false;
break;
case "select":
newcell.childNodes[0].selectedIndex = 'null';
break;
}
}
return false;
}
Inside save.jsp I have a scriplet code (the code is quite old so it has scriplet).
It parses the request using Oreilly Multipart parser and fetches input element one by one.
Sample code for my save.jsp:
MultipartParser parser = new MultipartParser(request, 2 * 1024 * 1024);
String e1Value = ((ParamPart) parser.readNextPart()).getStringValue()); //reads the input elements only
String e2Value = ((ParamPart) parser.readNextPart()).getStringValue());
The issue is when I tried to read the elements through the parser, its able to get the existing rows on the form. But the parser doesn't take up the rows created through javascript.
I have tried printing the form on submit. It has the dynamically created rows. But when I tried to get the data from the parser it doesn't provide the rows created through javascript.
Please help. Thanks in advance.
I'd make sure each input has a unique name="..." attribute by appending the row number and column number to the name (e.g. myInput_2_3 would be the input in row 2, column 3). You can use setAttribute('name', ...) on your newcell to set the input's name.
Finally I am able to get through it.
The issue was not related to the multipart parser. It was the structure of the JSP that was crating an issue. Because of the existing structure the jsp form was not able to take up the Dynamically created elements.
Earlier the jsp structure was like this:
<table align=center border=0 cellpadding=0 cellspacing=0 width=75%>
<form onSubmit="return validate()" action=".." method="post" enctype="multipart/form-data" name="frmEntry">
<tr><td>........</td></tr>
</form>
</table>
The above structure was creating problem. So I just took the table inside of the form.
<form onSubmit="return validate()" action=".." method="post" enctype="multipart/form-data" name="frmEntry">
<table align=center border=0 cellpadding=0 cellspacing=0 width=75%>
<tr><td>........</td></tr>
</table>
</form>
And it worked :)
I have a form which has multiple input fields that will be added dynamically when user click the Add button.
I already managed to achieve this, but the problem I am facing now is I cannot pass the parameters that has been added dynamically using JavaScript function, to a servlet.
This is the code of dynamically adding multiple input fields:
<script type="text/javascript">
$(document).ready(function(){
var counter = 2;
$("#addDynamicDivs").click(function () {
var newTextBoxDiv1 = $(document.createElement('div'))
.attr("id", 'TextBoxDiv1');
newTextBoxDiv1.attr("style",'float: left;');
var newTextBoxDiv2 = $(document.createElement('div'))
.attr("id", 'TextBoxDiv2');
newTextBoxDiv2.attr("style",'float: left;');
var newTextBoxDiv3 = $(document.createElement('div'))
.attr("id", 'TextBoxDiv3');
newTextBoxDiv3.attr("style",'float: left;');
var newTextBoxDiv4 = $(document.createElement('div'))
.attr("id", 'TextBoxDiv4');
newTextBoxDiv4.attr("style",'float: left;');
newTextBoxDiv1.after().html('<label class="inputlabel2">Speaker Name : </label>' +
'<input type="text" name="speakername" id="speakername" value="" >');
newTextBoxDiv2.after().html('<label class="inputlabel2">Speaker Country : </label>' +
'<input type="text" name="speakercountry" id="speakercountry" value="" >');
newTextBoxDiv3.after().html('<label class="inputlabel2">Speaker Company : </label>' +
'<input type="text" name="speakercompany" id="textbox" value="" >');
newTextBoxDiv4.after().html('<label class="inputlabel2">Speaker Desc : </label>' +
'<textarea name="speakerdesc" id="speakerdesc" rows="10" cols="30" ></textarea>');
newTextBoxDiv1.appendTo("#TextBoxesGroup");
newTextBoxDiv2.appendTo("#TextBoxesGroup");
newTextBoxDiv3.appendTo("#TextBoxesGroup");
newTextBoxDiv4.appendTo("#TextBoxesGroup");
});
});
</script>
It appears that the only parameters passed to the servlet are from the form, not including the parameters from the dynamically added input fields.
How can I pass all the parameters from the function to the servlet?
Thanks,
raz
You have to include the dynamic params inside the form. You should put inside the form the div elemt where you are including the dynamic params.
<form>
<div id="TextBoxesGroup">
</div>
</form>
In jsp, is there any attribute to provide the information that values in the dropdown got changed?
Say Example:
I have dropdown country - On page load it have "US" in the dropdown and I'm changing to "UK" and then again changing to "US". In this case I have not done any change so I have nothing to save but if I click save button my page is getting submitted. Is there anyway to avoid this page submission.?
Yes, it is. But you have to use javascript, not jsp. Example code
html:
<form class="checked">
<input type="hidden" id="countrySelectInitial" value="UK" /> <!-- we need this element to store initial value -->
<select name="country" class="checkedInput" id="countrySelect">
<option value="US">US</option>
<option value="UK" selected>UK</option>
</select>
<input type="submit" class="submitButton" disabled />
</form>
js:
$(".checkedInput").change(function() {
var newValue = $(this).val();
var idValue = $(this).attr('id'); // we need id to retrieve initial value. Initial value is stored in element with id <id>Initial
var oldValue = $("#" + idValue + "Initial").val();
if(newValue === oldValue) {
// if value don't changed - disable button. user have no possibility to submit form
$(this).parents("form.checked").find(".submitButton").attr("disabled", true);
} else {
// if value changed - remove "disabled" attribute. User can click button and submit form
$(this).parents("form".checked).find(".submitButton").removeAttr("disabled");
}
});
I have a form having fields like:
<div class="row">
<div class="field">
<input class="" type="text" name="college" id="college"/>
</div>
<div class="field">
<input class="" type="text" name="city" id="city"/>
</div>
<div class="field">
<input class="" type="text" name="zip" id="zip"/>
</div>
</div>
<input type="button" class="buttonWidth" id="btnAddressAdd" value="Add Worksite Addressess"/>
I have a Add extra address button that add's another copy of div "row" to the page. I need to send all data from the page as a request to the Controller. How do I write a script that add's extra div copy onclick of the button and also appends a unique id to each of the new fields?
See working example in Dojo: http://jsfiddle.net/phusick/PeQCN/
And the same code in plain vanilla JavaScript: http://jsfiddle.net/phusick/Rceua/
The Dojo version employs dojo/_base/lang::clone as #Peter Rader mentioned:
// var lang = require("dojo/_base/lang");
// var array = require("dojo/_base/array");
// var query = require("dojo/query");
// var domAttr = require("dojo/dom-attr");
var counter = 0;
function duplicate(/*Node*/sourceNode, /*Array*/attributesToBump) {
counter++;
var out = lang.clone(sourceNode);
if (domAttr.has(out, "id")) { out.id = bump(out.id); }
query("*", out).forEach(function(node) {
array.forEach(attributesToBump, function(attribute) {
if (domAttr.has(node, attribute)) {
domAttr.set(node, attribute, bump(domAttr.get(node, attribute)));
}
})
});
function bump(/*String*/str) {
return str + "_" + counter;
}
return out;
}
How to use the aforementioned duplicate function:
// var dom = require("dojo/dom");
// var domConstruct = require("dojo/dom-construct");
var sourceNode = dom.byId("fieldset");
var node = duplicate(sourceNode, ["id", "name", "placeholder"]);
domConstruct.place(node, sourceNode, "after");
I have written code to achieve this.
Logic:
1) get the innerHTML of desired parent
2) replace id in the text
3) Insert the new html
See a working code
Pardon me for bad style of coding on JS part. I am not use to coding directly on DOM. I prefer JQuery.
Try
to use this snipplet (see usage)
http://dojotoolkit.org/reference-guide/1.8/dojo/_base/lang.html#dojo-base-lang-clone