Let's say you have a <table>
of Cats, each of which has a link
to a "more info" page:
Name | Born | Adopted? |
---|---|---|
Claudius | 17 Feb | Yes |
Willow | 29 Feb | No |
Sawtooth Sparrow-Eater | 08 Mar | No |
<!-- source: -->
<table class='cats'>
<thead>
<tr><th>Name</th><th>Born</th><th>Adopted?</th></tr>
</thead>
<tbody>
<tr><td><a href='#/cats/14-claudius'>Claudius</a></td><td><time datetime="2011-02-17">17 Feb</td><td>Yes</td></tr>
<tr><td><a href='#/cats/15-willow'>Willow</a></td><td><time datetime="2011-02-29">29 Feb</td><td>No</td></tr>
<tr><td><a href='#/cats/16-Sawtooth-Sparrow-Eater'>Sawtooth Sparrow-Eater</a></td><td><time datetime="2011-03-08">08 Mar</td><td>No</td></tr>
</tbody>
</table>
Your product team says, "we'd really like it if the user could click
anywhere on the row to go to the 'more info' page." Your first thought
is to move the <a>
tags outside the <tr>
s:
Name | Born | Adopted? |
---|---|---|
Claudius | 17 Feb | Yes |
Willow | 29 Feb | No |
Sawtooth Sparrow-Eater | 08 Mar | No |
<!-- source: -->
<table class='cats'>
<thead>
<tr><th>Name</th><th>Born</th><th>Adopted?</th></tr>
</thead>
<tbody>
<a href='#/cats/14-claudius'><tr><td>Claudius</td><td><time datetime="2011-02-17">17 Feb</td><td>Yes</td></tr></a>
<a href='#/cats/15-willow'><tr><td>Willow</td><td><time datetime="2011-02-29">29 Feb</td><td>No</td></tr></a>
<a href='#/cats/16-Sawtooth-Sparrow-Eater'><tr><td>Sawtooth Sparrow-Eater</td><td><time datetime="2011-03-08">08 Mar</td><td>No</td></tr></a>
</tbody>
</table>
Sadly, that's not valid HTML. Even more sadly, browsers aren't too happy with this markup.
"I know," you say, "let's solve the problem with some spiffy Javascript." You return to the original markup and add some jQuery:
$('table.cats tr').each(function() {
var href = $('td:first-child a', this).attr('href');
$(this).click(function() { window.location.href = href; });
});
Ruxpin, Your UX-professional alter-ego
also reminds you to make the whole <tr>
feel like a link since it's
clickable:
table.cats tr { pointer: cursor; }
This solves the problem, but it introduces a new one: users who command-click (or control-click on Windows) will get both the browser default behavior (opening the "more info" page in a new tab) and your custom behavior (opening the "more info" page in the current tab). This is... less than optimal.
One solution to the double-open problem is to prevent the default behavior
on the <a>
:
$('table.cats tr td:first-child a').click(function(event) {
event.preventDefault();
event.stopPropagation();
});
But this is a cut-off-the-PBR-to-spite-the-hipster problem since this now stops the user from ever using command-click on the link to open the "more info" page in a new tab.
I haven't been able to think of any semantically-correct solutions that work across browsers.
I tried the following:
$('table.cats tr').click(function(event) {
$('td:first-child a', this).trigger(event);
});
but triggering a click
event doesn't actually cause the browser to follow the link; it only triggers any registered click
handlers.
The best I've come up with that actually works is
$('table.cats tbody tr').each(function() {
var myInfoLink = $('td:first-child a', this)[0];
if (!myInfoLink) { return; }
$(this).click(function(event) {
if (!event) { return; }
// don't override link-click behavior:
if (event.target === myInfoLink) { return; }
event.preventDefault();
event.stopPropagation();
if (event.ctrlKey || event.metaKey) {
window.open(myInfoLink.href, '_blank');
} else {
window.location.href = myInfoLink.href;
}
});
});
I'd love to hear any suggestions.
Ruxpin, Your UX-professional alter-ego...
huh? :P