HTML: table of forms? - html

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
)

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!

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

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.

When to use and when not to use tables? [duplicate]

This question already has answers here:
Why not use tables for layout in HTML? [closed]
(66 answers)
Closed 9 years ago.
Some people believe table is the devil's spawn. Others primarily use to it to format their website. When do you draw the line on tables? When do you feel you're abusing them?
I, personally, use tables only to display data, which in most cases need a table. I've hit a brick wall, though. I need two text boxes to be aligned, would you use tables for this?
I'm thinking of doing something like this:
<table style="border: 0; border-collapse: separate; border-spacing: 10px; margin: 10px auto;">
<tr>
<td><label for="username">Username</label></td>
<td><input type="text" name="username" placeholder="Username"></td>
</tr>
<tr>
<td><label for="password">Password</label></td>
<td><input type="password" name="password" placeholder="••••••••"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" name="submit" class="btn btn-large btn-info" style="float: right"></td>
</tr>
</table>
Please excuse the inline CSS, I was using it for this example.
Would you draw the line there? Am I crossing this imaginary line? What would you do?
To align things, I would use either the <div> element or, if that fails, absolute positioning. Also try display:inline-block on the div element. Why won't they line up? What have you tried? Tables should never be used for formatting. That is an awful practice which tables weren't designed for. Only ever use tables if you are displaying tabular data. Otherwise see above.
Tables should be used to represent tabular data. Divs are divisions or sections and should be used to group block-elements. Spans are useful when you want to group inline-elements.
I personally think using tables for layout in regards to forms is OK, especially in the case of some super complicated form - Such as this one: http://www.wolfhair.com/consultation-options/
My reasoning behind this is that if the data that was being inputted into the text fields was actual text and not a text field, it would in fact appear to be tabular data. In fact, if you were to store this information, it would be placed into a table like structure in order to be then pulled from later.
As a demonstration, take for instance your very example. If it were filled out and the text fields were actual data results.
<table border="1">
<tr>
<td><label for="username">Username:</label></td>
<td>MyUsernameRox</td>
</tr>
<tr>
<td><label for="password">Password:</label></td>
<td>M0stSecurePasswordEv3r</td>
</tr>
</table>
http://jsfiddle.net/sGq2Q/
Outside of using it to organize and arrange a form, it should not be used for layout.

Table/Form formatting

Traditionally, I always lay out forms by styling each property, but I have read a lot lately about styling forms using a table. My problem is that with a table, when one cell is rather large, all other cells in that column become the same width. When editing them, the problem I end up with is either large gaps between input fields due to a large cell placed above them or, when you resize the screen, things get too close for comfort.
I tried setting the <td> widths individually but that doesn't work. I created a fiddle to see if someone could get me going in the right direction.
Thank you all so much in advance!
http://jsfiddle.net/uFwkd/
The table in the jsfiddle (which seems to be what the question is really about) contains rows with different numbers of cells, e.g.
<tr>
<td><input type="text" name="street" id="street" value="" size="20" /></td>
</tr>
<tr>
<td>City:</td>
<td>State:</td>
<td>Zip:</td>
</tr>
This causes rather unpredictable rendering in practice.
You could make the structure more appropriate by ensuring that all rows have the same number of slots (3, in this case), by using the colspan attribute on cells (on the first row above, with <td colspan="3">. This would require some artificial decision for the row containing two cells: one of them would need to span two columns.
This would be somewhat unnatural (cells in a column would not really be related to each other, just placed in the same column) and would imply accessibility problems. A better tabular structure for a form has one row for each input control (one field, such as one input element), with label in one column, the control itself in another, so you would start with something like
<table>
<tr><td><label for="org">Organization name:</label></td>
<td><input type="text" name="org" id="org" value="" size="20" /></td>
</tr>
There is debate between using div and table to layout a form. There are some rules of thumb about this:
Table only for display
Use div as a form layout
In your case, you can consider transforming your table into a div.

Is it possible to insert a form within an html table?

Multiple forms in one table, these forms last for varying lengths of rows, however this does not seem to work:
<table>
<form>
<tr>
<td>
</td>
<td>
</td>
</tr>
</form>
<form>
<tr>
<td>
</td>
<td>
</td>
</tr>
</form>
</table>
I believe a table has a definite structure, and this cannot be interlaced with other structures, but is there a tidy work around this?
Thanks.
No. According to this document: http://www.w3.org/TR/html401/struct/tables.html#h-11.2.1
table may contain only these:
TABLE --
(CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+)>
But you can use something like this
<div class=table>
<form>
<div class=cell>...</div>
<div class=cell>...</div>
</form>
</div>
with styles:
div.table { display:table; }
div.table > form { display:table-row; }
div.table > form > div.cell { display:table-cell; }
No, you can't do that. I guess you want it that way to have both forms aligned in a table, right?
If you are allowed javascript on the page, you could add the different text boxes etc. inside the <td> elements, and attach onchange event handlers to these boxes to populate the corresponding (hidden) fields in your actual forms.
It would be a problem in all HTML ... including both XHTML and HTML5.
XHTML table dtd ..
<!ELEMENT table (caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))>
Not between <tr> tags. They should work outside of <table> or inside of <td> though.
There's no real need to have two forms in a single table if you're looking to put them on multiple rows. The bigger the table, the longer it takes for the browser to load and display it. Instead, give each form its own table and place the table tags within the form tags, like so:
<form method="GET" action="foo.sh">
<table>
</table>
</form>
Yes! No problem to HTML5.
Now table tags are just a shorthand for table styling rules.