Search code examples
javascriptjqueryhtmlcsshighlighting

How do I highlight only the innermost table row of a nested table?


I have several nested tables and I want to highlight the innermost row that is below the mouse pointer. How can I do that?

Some pointers: I use nested tables to display recursive tabular data. The tables can be nested 10 levels deep. The nesting is just like you would expect:

<table><tr><td>
   <table><tr><td>
      <table><tr><td>
          ...

There are can be rows which don't have nested tables. I want the highlight on the deepest / innermost <tr> that is under the mouse cursor.

I can use CSS or jQuery.


Solution

  • I would like to propose something slightly more elegant (at least shorter):

    Using delegated mouse events:

    $('#mainTable').on('mouseenter mouseleave', 'tr', {el: false}, function (e) {
        var hl = e.data.el;
        hl && hl.removeClass('hover');
    
        e.data.el = (e.type === 'mouseenter') ?
            $(this).addClass('hover') :
            $(this).parent().closest('tr:hover').addClass('hover');
    });
    

    It stores the currently highlighted node in the (persistent) delegated data object and handles the mouse events, as follows:

    • If the mouse enters an element (the innermost hovered tr), remove the current highlight and highlight current element.
    • If the mouse leaves an element, highlight the closest hovered ancestor tr instead of the current one.

    The main advantages of solutions using event delegation (such as $.delegate() and $.on() with a selector) are attaching only a single event listener (compared to potentially dozens, hundreds or more using traditional, per-element, methods) and being able to support dynamic changes to the element.

    I chose this solution over the use if the mouseover event since I believe the enter/leave events should provide better performance, as they do not bubble.

    JSFiddle.

    Note:

    It has a problem with jQuery 1.9.x but works with the rest, as far as I tested, including newer and older releases. This is due to an issue with the :hover pseudo-selector in that version.


    CSS4

    CSS level-4 has a suggested feature that can enable this behavior using CSS only:

    tr, !tr:hover tr:hover {
        background-color: transparent;
    }
    tr:hover {
        background-color: #DDFF75;
    }
    

    Of course, since this feature is not currently final and is not supported by any major browser at the moment, this section will serve as future reference.