views:

40

answers:

1

I have a set of items that can be in various states. I want to allow a user to use an (X)HTML form to

  • change the state, and
  • easily view the state of a group of objects

...so to this end, I'd like a layout like:

| item1 | radio button for state 1 | radio for state 2 | ... | [update button] |
| item2 | radio button for state 1 | radio for state 2 | ... | [update button] |

etc. I prefer the radio buttons to list boxes so that it's easy for a user to visually scan for things in a certain state.

It seemed like perfectly tabular data to me. The only problem is, you can't have forms inside a table that cross table cells (ie. <tr> <form> <td> ... is invalid).

I thought, "hey, I could have one giant form wrapping a table, and make the [update button] value contain the IDs for each row!" Turns out certain versions of IE send ALL THE SUBMIT BUTTON VALUES on any single form.

So I thought perhaps to to lay it out with <div>s and place the forms inside a single <td>. But then they break a line on each <div>. So I fixed their width and made them float: left. But then they wrap inside the table cells if the table row is wider than the page, and the radio controls don't line up with the headings.

Is it possible to lay this out as I intend? The XHTML below shows the intended structure. Observe what happens if you resize the browser window below the width of the table (ideally, the name would break or the table would show a scroll bar).

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head><title>Test</title>

<style type="text/css">

.state-select, .thing-state-name, .update {
    float: left;
    width: 8em;
}

.state-select {
    text-align: center;
}

</style>

</head>

<body>

<table>

<thead>

<tr>
<th class="thing-name-header">Thing</th>

<th>
<div class="thing-state-name">Present</div>
<div class="thing-state-name">Absent</div>
<div class="thing-state-name">Haven't looked</div>
</th>

</tr>
</thead>

<tbody>

<tr>
<td>Apple</td>

<td>
<form action="something" method="post">

<input type="hidden" name="id" value="1" />

<div class="state-select"><input type="radio" name="presence" value="present" checked="checked" /></div>
<div class="state-select"><input type="radio" name="presence" value="absent" /></div>
<div class="state-select"><input type="radio" name="presence" value="unknown" /></div>
<div class="update"><input type="submit" value="Update" /></div>

</form>

</td></tr>

<tr>

<td>Orange</td>

<td>
<form action="something" method="post">

<input type="hidden" name="id" value="2" />

<div class="state-select"><input type="radio" name="presence" value="present" /></div>
<div class="state-select"><input type="radio" name="presence" value="absent" checked="checked" /></div>
<div class="state-select"><input type="radio" name="presence" value="unknown" /></div>
<div class="update"><input type="submit" value="Update" /></div>

</form>

</td></tr>

<tr>

<td>David Bowie</td>

<td>
<form action="something" method="post">

<input type="hidden" name="id" value="3" />

<div class="state-select"><input type="radio" name="presence" value="present" /></div>
<div class="state-select"><input type="radio" name="presence" value="absent" /></div>
<div class="state-select"><input type="radio" name="presence" value="unknown" checked="checked" /></div>
<div class="update"><input type="submit" value="Update" /></div>

</form>

</td></tr>

</tbody>

</table>

</body>
</html>
+1  A: 

Why not wrap the entire table with one form element, as you said and instead of naming each group of radio buttons "presence" name them "presence[ID]" where ID is the ID of the row you are updating. Eg:

<div class="state-select"><input type="radio" name="presence[0]" value="ipresent" checked="checked" /></div>
<div class="state-select"><input type="radio" name="presence[0]" value="absent" /></div>
<div class="state-select"><input type="radio" name="presence[0]" value="unknown" /></div>
<div class="update"><input type="submit" value="Update" /></div>

...

<div class="state-select"><input type="radio" name="presence[1]" value="present" checked="checked" /></div>
<div class="state-select"><input type="radio" name="presence[1]" value="absent" /></div>
<div class="state-select"><input type="radio" name="presence[1]" value="unknown" /></div>
<div class="update"><input type="submit" value="Update" /></div>

Then you can use PHP to loop through each group of radio buttons easily and update all the fields easily. I tested the below code along with the above code and it worked pretty well.

<?
foreach($_POST['presence'] as $id => $value){
    echo "ID ".$id." is ". $value . "<br>";
    //Run your update code with the variables $id and $value
}
?>

Implementing this with the code you provided looks something like this:

<?

if(isset($_POST['update'])){
    foreach($_POST['presence'] as $id => $value){
        echo "ID ".$id." is ". $value . "<br>";
        //Run your update code with the variables $id and $value
    }
} ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head><title>Test</title>

<style type="text/css">

.state-select, .thing-state-name, .update {
    float: left;
    width: 8em;
}

.state-select {
    text-align: center;
}

</style>

</head>

<body>

<form method="post">
<table>

<thead>

<tr>
<th class="thing-name-header">Thing</th>

<th>
<div class="thing-state-name">Present</div>
<div class="thing-state-name">Absent</div>
<div class="thing-state-name">Haven't looked</div>
</th>

</tr>
</thead>

<tbody>

<tr>
<td>Apple</td>

<td>

<div class="state-select"><input type="radio" name="presence[1]" value="present" checked="checked" /></div>
<div class="state-select"><input type="radio" name="presence[1]" value="absent" /></div>
<div class="state-select"><input type="radio" name="presence[1]" value="unknown" /></div>
<div class="update"><input type="submit" name="update" value="Update" /></div>

</td></tr>

<tr>

<td>Orange</td>

<td>

<div class="state-select"><input type="radio" name="presence[2]" value="present" /></div>
<div class="state-select"><input type="radio" name="presence[2]" value="absent" checked="checked" /></div>
<div class="state-select"><input type="radio" name="presence[2]" value="unknown" /></div>
<div class="update"><input type="submit" name="update" value="Update" /></div>
</td></tr>

<tr>

<td>David Bowie</td>

<td>

<div class="state-select"><input type="radio" name="presence[3]" value="present" /></div>
<div class="state-select"><input type="radio" name="presence[3]" value="absent" /></div>
<div class="state-select"><input type="radio" name="presence[3]" value="unknown" checked="checked" /></div>
<div class="update"><input type="submit" name="update" value="Update" /></div>

</td></tr>

</tbody>

</table>
</form>

</body>
</html>

And submitting the form will give you:

ID 1 is present
ID 2 is absent
ID 3 is unknown
Sam152
Interesting approach, but if there are say 20 items per page, and one is updated, the server has to process 20 times as much unchanged data. Still, multiple updates might be a benefit. (Also, it's a CherryPy backend + Cheetah templating, so no PHP, but possible nonetheless.)
detly
Balls, I have no idea why I assumed it was PHP.
Sam152
Sorry, I almost forgot to accept this. This approach works best with a bit of client-side JS and AJAX to prevent overworking the server. After all that I ended up using a list box anyway, but this helped to figure out what was sensible or not.
detly