ic3
ic3

Reputation: 7680

Complex Table with Rowspan Hover and Zebra effect

I'm trying to make a hover effect for a table with multiple rowspan but I don't manage to make it fully work.

The css as described in another stackoverflow is not working (see solution here https://codepen.io/cimmanon/pen/KqoCs ).

The example here (rowspan on multiple columns) : https://codepen.io/anon/pen/rJXgzW

The hover css effect is defined as :

tbody:hover td[rowspan], tr:hover td {
   background: red; 
}

Any suggestions?

Upvotes: 0

Views: 958

Answers (2)

Baptiste Placé
Baptiste Placé

Reputation: 396

sharing the vanilla JS I wrote specifically for this case, it works on the complex codepen, just add .u-table-hover to the CSS hover rule (tr:hover th , tr:hover td to tr:hover th , tr:hover td, .u-table-hover) and paste the script.

This can probably be more compact, any suggestion is welcome.

function initTableHover() {

    /**
     * Mouse events only on tables with rowspan cells
     */
    document.querySelectorAll('td[rowspan], th[rowspan]').forEach(function (cellRowspan) {
        // Only match on tbody elements, you may extend this to thead
        cellRowspan.closest('table').querySelectorAll('tbody td, tbody th').forEach(function (tableCell) {
            tableCell.addEventListener('mouseover', function () {
                let parentTr = tableCell.closest('tr');
                if (parentTr) {
                    let trPreviousSibling = parentTr.previousElementSibling;
                    let previousSiblingDistance = 1;
                    // previousSiblingDistance < 100 probably useless, just a safety
                    while (null !== trPreviousSibling && previousSiblingDistance < 100) {
                        trPreviousSibling.querySelectorAll('td[rowspan], th[rowspan]').forEach(function (cellRowspan) {
                            if (cellRowspan.getAttribute('rowspan') > previousSiblingDistance) {
                                /**
                                  * You can change the hover class here
                                  * This class is added to the cell with the rowspan attribute
                                  */
                                cellRowspan.classList.add('u-table-hover'); 
                            }
                        });
                        trPreviousSibling = trPreviousSibling.previousElementSibling;
                        previousSiblingDistance++;
                    }
                }
            });

            /**
              * Remove the class anywhere, should be fine
              */
            tableCell.addEventListener('mouseleave', function () {
                tableCell.closest('tbody').querySelectorAll('.u-table-hover').forEach(function (tableElement) {
                    tableElement.classList.remove('u-table-hover');
                })
            });
        });
    });
}

if (document.readyState !== 'loading') {
    initTableHover();
} else {
    document.addEventListener('DOMContentLoaded', initTableHover);
}

Upvotes: 0

Paul
Paul

Reputation: 9022

The trick in the working example is to use multiple <tbody> elements in the table where each table body contains one table cell spanning multiple rows. That way

tbody:hover td[rowspan] { background: red; }

makes it magically appear as requested. This doesn't work with the second example in the same way, as there are (1) multiple row-spanning elements and (2) it's using <th> elements (which is easy to address, though).

To get it working using CSS only, you would need to nest tables inside table cells.

Upvotes: 1

Related Questions