tags:

views:

1081

answers:

5

I've got this little snippet that I use for row highlighting on an XSLT page that has to use an onclick event to postback some data, but because the row isn't a link I have to make sure there's a hand cursor as well as the row being highlighted so the users understand it's clickable and what row they're on.

<script type="text/javascript">
  $(document).ready(function() {
    $('#stocks tr:not(.exclude)').css('cursor', 'hand');
    $('#stocks tr:not(.exclude)').hover(function() {
      $(this).addClass('hover');
    }, function() {
      $(this).removeClass('hover');
    });
  });
</script>

The tables are large, typically up to 5000 rows. When there's a large amount of rows the row highlighting used by this jQuery script goes quite slow. I wrote the tr:not(.exclude) selector, but I'm thinking perhaps that's what's causing it to go slow? Any ideas on how to speed this up?

EDIT: I see many answers are very good, however they do not address the fact of there being over 5,000 rows at least.

EDIT EDIT: You MUST ensure that IE7 at least has the following doctype set in order for tr:hover to work. Mine still goes slow, however this must be down to something else.

<!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"&gt;
+2  A: 

It's slow to add that many events, looks like two for every row. Instead, you need to use Event Delegation. You can role your own, or maybe that link will help. The basic idea is that you attach just one or two event handlers to the table itself, and within those event handlers, you look get the info of which row was entered and change the view accordingly.

DGM
Yeah the delegation looks to be right, I can't seem to get it to work though.
Kezzer
A: 
  1. Use EventDelegation, as suggested. Add an event listener on the table. and also
  2. use explicit colors e.g. #dee9f3 (as opposed to "blue")
  3. Assign styles directly, rather than through css switches e.g.

row.style.backgroundColor = '#dee9f3';

Joel
A: 

I'm pretty sure live makes use of event delegation. This might work depending on how flaky mouseover is.

try this:

$(document).ready(function() {
    $('tr', '#stocks')
    .not('.exclude')
    .css('cursor', 'hand')
    .find('td')
    .live("mouseover", function(){

          $(this).hover(function() {
          $(this).parent('tr').addClass('hover');  
        }, function() {
            $(this).parent('tr').removeClass('hover');
      $(this).unbind();  ////not sure about this part
        });
         $(this).trigger('hover');
    });
});
thirsty93
It looked right, but doesn't seem to work. The hand cursor is working, however so it's almost there.
Kezzer
try that, I think the hover isn't firing because it is bound too late
thirsty93
Again, it's getting the cursor correct but not the background colour of the tr
Kezzer
tried one more time. Put the live events on the td's, you may want to put the hover events on the tr if it is glitchy.
thirsty93
+3  A: 

This effect can be accomplished with CSS only. Try something like:

#stocks tr:hover {
   cursor: pointer;
   background-color: khaki;
}

#stocks tr.exclude:hover {
   cursor: inherit;
   background-color: inherit;
}
spoulson
Any particular reason my solution was downvoted? Did it not work or solve the problem? I thought downvoting was for unhelpful answers.
spoulson
IE6 wouldn't work though, and IE7 needs quite a specific doctype. It'd still be slow though, would it not?
Kezzer
+1 back up for the idea, although the selectors aren't quite right (you want “#stocks tr:hover” and “#stocks tr.exclude:hover”) and the “inherit” won't work in IE (you'll have to specify explicit values). Also some hacking is needed to use ‘pointer’ on other browsers than IE instead of ‘hand’.
bobince
@Kezzer: slow? native CSS will be much faster than loads of fiddly little event handlers. And you should be in Standards Mode already if you value your sanity! However IE6, indeed, won't :hover on tr.
bobince
Oops, bobince is right on the selector and cursor setting. I fixed those. There was no stated requirement on old browsers or quirks mode. It degrades gracefully in IE6 by simply not providing the visual feedback, but not breaking functionality.
spoulson
I've put the doctype that works for IE7 in my edit. The only other thing you could do is a check for < IE7 and implement some JS to do it for you. Our company has IE7 only now so this will work as long as we ensure the correct doctype is set. Thanks very much spoulson.
Kezzer
+1  A: 

Alright! This should do it:

$(document).ready(function() {
    $('tr:not(.exclude)', '#stocks')
    .css('cursor', 'hand')
    .live("mouseover", function() {
        $(this).addClass('hover');
    }).live("mouseout", function() {
        $(this).removeClass('hover');
    });
});
Paolo Bergantino
that will not work mouseout fires when the pointer moves into or *out of* a *child* element
thirsty93
i have a test table set up and it works on it just fine
Paolo Bergantino
Have you tested it against 5,000 rows?
Kezzer
Yes. More, in fact.
Paolo Bergantino
Ah, perhaps this is an IE7 issue then? This is an internal site, we're only allowed to use IE7 *shudder*. I'm not a fan myself, but hey, requirements are requirements.
Kezzer
I tested it on IE7 and it is decent. Not as snappy as Firefox but that's IE. However, if this is IE7 only, why not use @spoulson's answer? CSS should definitely blow JS out of the water.
Paolo Bergantino
Aye, I had tried that and it was equally as slow as JS. I think I may be missing something here as I'm not sure why.
Kezzer