XPath to get <input>s belonging to a specific html form - html

How do I pick up <input>s belonging to a certain <form> using XPath? By belonging, I mean input where the .form attribute in JavaScript equals the specific form instance.
In the general case, I want an XPath that returns the same inputs this JavaScript returns:
Array.prototype.filter.call(document.getElementsByTagName("input"),
function(x) { return x.form == f1; })
Note: This does not mean is-a-child-of w.r.t. the DOM-tree!
For example, given the following (malformed) html:
<html>
<body>
<table>
<form name="foo">
<input name="bar"/>
<tr>
<td>
<input name="baz"/>
</td>
</tr>
</form>
</table>
</body>
</html>
bar.form == foo and baz.form == foo hold true, but the DOM-tree can be generated in a way that "//form[#name='foo']//input" contains neither bar nor baz.
e.g. Chrome/Firefox/IE will produce this DOM-tree for the above source:
<html>
<head/>
<body>
<input name="foo"/>
<table>
<form name="bar"></form>
<tbody>
<tr>
<td>
<input name="baz"/>
</td>
</tr>
</tbody>
</table>
</body>
</html>
P.S. An acceptable answer could simply state why this isn't possible.
Edit: Clarified the meaning of the bottom example. Updated the example to show why simply traversing the DOM-tree will not work.

Your input is invalid HTML. Form inputs have to be inside a <form/> element, otherwise it is not clear how they correlate. For example, in the following HTML snippet, how should a browser or any HTML parser now to which form the input belongs:
<table>
<form name="foo"></form>
<form name="foo2"></form>
<tr>
<td><input name="bar" /></td>
</tr>
</table>
That being said, many browser are very relaxed and basically allow HTML designers to not use any standard. So they could use metric and say each input belongs to the last preceding form element. Maybe their heuristic is more elaborate, so you might not get each and every corner-case with this. However, the following XPath should work at least for your two examples:
//input[(preceding::form)[last()]/#name="foo"]
This way, you get all input elements, which had as last form element the one with the specified name, in this case foo.

With the examples you posted, I don't see this possible. You would do this with an event based (SAX) parser, where you keep the name of the "last seen form name" and allocate each input element to that form.
Of course, especially for the second example, this isn't how the browser sees it.
Since I can't use comments yet:
#dirkk: preceding won't work, because the axis is "excluding any ancestors". So for the valid HTML case, it actually doesn't work, as a form is considered an ancestor. It's a good idea though, maybe preceding|ancestor will work.

Related

Screen readers: How to create multiple radiobutton groups in a <table>?

I'm working on taking an existing webapp and making it WCAG AA compliant.
Part of the app involves displaying a "choice matrix": a series of questions presented in a tabular format. Here's a simplified example.
<table>
<thead>
<tr>
<th>Question</th>
<th>True</th>
<th>False</th>
</tr>
</thead>
<tbody>
<tr>
<td>google.com is hosted on the internet</td>
<td><input name="q1" type="radio" aria-label="google.com is hosted on the internet: True"></td>
<td><input name="q1" type="radio" aria-label="google.com is hosted on the internet: False"></td>
</tr>
<tr>
<td>January is the third day of the week</td>
<td><input name="q2" type="radio" aria-label="January is the third day of the week: True"></td>
<td><input name="q2" type="radio" aria-label="January is the third day of the week: False"></td>
</tr>
</tbody>
</table>
Now -- if we run aXe Chrome Extension against this snippet, it complains:
Radio inputs with the same name attribute value must be part of a group
So it seems that we need to group the radiobuttons together in order to satisfy WCAG 1.3.1. This makes sense and seems worthwhile.
aXe suggests two ways to do that:
1) All elements with the name "q1" do not reference the same element with aria-labelledby
2) Element does not have a containing fieldset or ARIA group
But neither of those solutions seems to solve my issue.
The first solution seems nonsensical -- why would I give multiple radiobuttons the same aria-label? How would the screen reader user choose between them, if they're all the same?
So I'm looking into how to apply role="group" or role="radiogroup" to my radiobuttons.
There's a good example of using role="radiogroup" on the aXe site.
But... when I add role="radiogroup" to a element, jsx-a11y gives a warning:
Interactive elements should not be assigned non-interactive roles
It seems that by giving the a role, we're likely to cause problems because has implicit roles that are now being overwritten.
I'm not clear what havoc this may cause, but it gives me pause.
I also can't use this:
<table><div role="radiogroup"><tr>
without breaking the rules of html.
So it appears that I either need to break the rules of ARIA, HTML5, or usability if I want to resolve these warning messages.
Or, change this from a to a group of s. But it seems to me that is semantically appropriate in this use-case, right?
Is there a solution here that will work well across different screen readers? Currently the winner is to just put role="group" on the and ignore the warnings, but I haven't tested it sufficiently across screen readers yet.
It looks like we can use multiple <tbody> tags inside a <table>.
https://stackoverflow.com/a/3076790/2253611
So, the best solution I've seen so far is to wrap each <tr> in a <tbody role="radiogroup">, and take the role="radiogroup" away from the <tr>.
So far, in my testing, it seems solid!

Changing text within a <Div>

Have some issue with coding here. If there is no class assigned to the tag, how can I change the content using a external script? I would like to change the addition operator.
<tr>
<td><div id="number1">1</div></td>
<td><div>+</div></td>
<td><div id="number2">2</div></td>
<td><div>=</div></td>
<td><input type="text"></input></td>
<td><input type="button" value="Check"></input></td>
Thank you
<tr>
<td><div id="number1">1</div></td>
<td><div>+</div></td>
<td><div id="number2">2</div></td>
<td><div>= <span id="result"></></div></td>
<td><input type="text"></input></td>
<td><input type="button" value="Check"></input></td>
Jquery code :
$(function(){
$('#result').text('your text here ....');
});
I'm assuming you want to change the markup client-side using JS or similar - I've provided some examples below using jQuery.
The most robust solution would involve changing the markup so that there is some identifying feature of the DIV, so for example adding a class, e.g.
<td><div class="operator">+</div></td>
Once you have that, you can select the element and change its content with jQuery like this:
jQuery('.operator').html("added to");
If you can't change the markup then you need to find some other way of identifying the element.
Without access to your whole markup it's difficult to say reliably what the best way will be, but here's one example based on the markup you provided. It works by finding the second TD element within each TR element.
jQuery('tr td:nth-child(2)').html("added to");
Reference: http://api.jquery.com/nth-child-selector/
Use like
var elem = document.getElementById("number1"); /*this will get the div element for which you want to change the text. "number1" can be any ID*/
elem.innerHTML="123" /* this will update the text of that div*/

When using <s:select /> tag in Struts2, how to make colon disappear?

I have a problem when using UI tags (ex: <s:select />) in Struts.
I use the default theme in a form (theme='xhtml')
CASE 1
When using
<s:select label="FIELD1" ....../>
Struts2 will generate the HTML code shown below (I skipped the non-important portions)
<table>
<tr>
<td>FIELD1:</td>
<td> <select ...... > </td>
</tr>
</table>
CASE2
When using
<s:select label='' .....>
the generated HTML code is shown below:
<table>
<tr>
<td>:</td>
<td> <select ...... > </td>
</tr>
</table>
In the HTML code generated by Struts2, you still see a colon in the label field in table.
CASE3
When using
<s:select .....>
If I do not use a label attribute, Struts2 will generate the HTML code shown below:
<table>
<tr>
<td></td>
<td> <select ...... > </td>
</tr>
</table>
In the HTML code generated by Struts2, you will see the label text is completely empty.
What I wish is, I set the attribute label='', and the label text in the HTML code generated by Struts2 is empty (no colon).
How do I do this?
Use the labelSeparator attribute to empty string and your requirement would be satisfied. Please refer the document for other attribute references for <s:select>:
http://struts.apache.org/2.x/docs/select.html
This is due to the xhtml theme which you are using and based on that Struts2 tags are generating the HTML output for you.
here is what happening inside Struts2 free marker template which is being used to generate the HTML output.
${parameters.labelseparator?default(":")?html}<#t/>
so what happening when you have no labelseparator it is using default seperator which Struts2 internally using :
So either you should provide labelSeparator as said by James and for better control of the output use simple theme and defined/design page as per your choice.

Is it valid HTML to insert a hidden input between table rows?

Background: I am writing a Java app which auto generates a HTML table. As well as adding table rows, this app may insert hidden inputs. However, at present it simply inserts them into the table at the next opportunity, for example:
<table>
<tr> ... </tr>
<input type="hidden" />
<tr> ... </tr>
</table>
So, my question: Is it valid HTML to insert a hidden input between rows like this, or is this likely to cause problems?
It's not valid.
<!ELEMENT TABLE - -
(CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+)>
No, it's not.
You should use the W3C validator and check by yourself your webpages : http://validator.w3.org/.
It's not valid.
From http://validator.w3.org/
Line 9, Column 27: document type does not allow element "input" here
It's not valid, after closing </tr> tag it can have only <tr> or </tbody> or </table>. If you test it with w3c validator It will fail.

HTML: table of forms?

I frequently find myself wanting to make a table of forms -- a bunch of rows, each row being a separate form with its own fields and submit button. For instance, here's an example pet shop application -- imagine this is a checkout screen which gives you the option to update the quantities and attributes of the pets you've selected and save your changes before checking out:
Pet Quantity Color Variety Update
snake 4 black rattle update
puppy 3 pink dalmatian update
I would love to be able to do this using HTML that looks like this:
<table>
<thead><tr><th>Pet</th> <th>Quantity</th> <th>Color</th> <th>Variety</th> <th>Update</th></tr></thead>
<tbody>
<tr>
<form>
<td>snake<input type="hidden" name="cartitem" value="55"></td>
<td><input name="count" value=4/></td>
<td><select name="color"></select></td>
<td><select name="variety"></select></td>
<td><input type="submit"></td>
</form>
</tr>
</tbody>
</table>
This is basically a table full of forms, one form per row. Hitting update once allows you to update that specific row (this is not a real example, my real applications really do require independence of rows).
But this is not valid HTML. According to spec, a <form> has to be either completely inside a <td> or completely outside a <table>. This invalid html breaks javascript libraries and is a huge pain to deal with.
I end up making one table to contain column headings, and then making one table per form. But this requires fixed column widths to have the inputs lined up in neat columns, which is sub-par. How do you end up dealing with this problem? Is there an obvious easy solution I'm missing? How to I make a table of forms?
You can use css to give table layout to other elements.
.table { display: table; }
.table>* { display: table-row; }
.table>*>* { display: table-cell; }
Then you use the following valid html.
<div class="table">
<form>
<div>snake<input type="hidden" name="cartitem" value="55"></div>
<div><input name="count" value=4/></div>
</form>
</div>
The trick here is to just use a single form, e.g.
<form>
<table>
<!-- rows... -->
</table>
<p><input type="submit" value="Update quantity"></p>
</form>
Say you have a product snake with id 6. You then name the input for that item's quantity field quantity[6].
I don't know what server side language you are using, but in PHP you can then iterate over the quantites and update based on the ID. You'd get an array like this:
$_POST['quantity'] = array(
'6' => 4
)