3

I need a pure Javascript (no jQuery) hover effect for HTML table columns.

I found this which supposedly contains a fix for Firefox yet it still looks broken to me.

I found this which works only for the first column.

Unfortunately, my Javascript skills are amateur at best, so my attempts to modify either of these turned out to be fruitless.

Is this possible? Any suggestions would be appreciated.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
carmenism
  • 1,087
  • 3
  • 12
  • 31

7 Answers7

7

Here's a column-based approach. When the mouse enters/leaves a cell, find the corresponding <col/> by index and apply/remove the desired class:

(() => {
  const myTable = document.getElementById("myTable");
  const cols = myTable.querySelectorAll("col");
  const events = {
    mouseover: e => {
      const t = e.target.closest("td");
      if (t) {
        const cellIndex = t.cellIndex;
        for (let i = 0, n = cols.length; i < n; i++) {
          cols[i].classList[i === cellIndex ? "add" : "remove"]("hovered");
        }
      }
    },
    mouseout: e => {
      const t = e.target;
      if (t.nodeName === "TD" && !t.contains(e.relatedTarget)) {
        cols[t.cellIndex].classList.remove("hovered");
      }
    }
  };
  for (let event in events) {
    myTable.addEventListener(event, events[event]);
  }
})();
.hovered {
  background-color: #FF0000;
}
<table id="myTable" cellspacing="0">
  <col />
  <col />
  <col />
  <tbody>
    <tr>
      <td>Col1</td>
      <td>Col2</td>
      <td>Col3</td>
    </tr>
    <tr>
      <td>Col1</td>
      <td>Col2
        <span>nested</span>
      </td>
      <td>Col3</td>
    </tr>
    <tr>
      <td>Col1</td>
      <td>Col2</td>
      <td>Col3</td>
    </tr>
  </tbody>
</table>

See also:

canon
  • 40,609
  • 10
  • 73
  • 97
  • This is so close, but it seems that the last column I hover over retains the background color when I move my mouse off of the table entirely. – carmenism Aug 15 '12 at 19:41
  • I'm sorry; I wasn't trying to be ungrateful! I didn't realize I needed to specify that in my question. Thanks for providing your function. – carmenism Aug 15 '12 at 19:49
  • 1
    @vulpix, pfft... no worries. Updated. – canon Aug 15 '12 at 19:51
  • Your diligence is much appreciated! Thank you so much. If you don't mind me asking, do you have any clue why the hover disappears when I mouse over an image in my table? http://jsfiddle.net/RmrSJ/ – carmenism Aug 15 '12 at 20:28
  • 1
    Because the `td` sends a `mouseout` event when you hover over one of its children, i.e.: your nested image. You can check whether the `e.toElement` is a descendant of the `td` and, if so, stop propagation. – canon Aug 15 '12 at 20:53
  • In case anyone is wondering, here is my solution to the nested element problem: http://jsfiddle.net/PJ5QT/ – carmenism Aug 15 '12 at 21:39
2

Here are your codes (+ demo):

var HOVER_CLASS = 'hovered';
var hovered;

table.addEventListener('mouseover', function (e) {
    if (e.target.tagName.toLowerCase() == 'td') {
        var index = e.target.cellIndex;

        hovered && hovered.forEach(function (cell) {
            cell.classList.remove(HOVER_CLASS);
        });

        hovered = Array.prototype.map.call(
            table.rows,
            function (row) {
                var i = index;
                while (!cell && i >= 0) {
                    var cell = row.cells[i];
                    i -= 1;
                }
                return cell;
            }
        );

        hovered.forEach(function (cell) {
            cell.classList.add(HOVER_CLASS);
        });
    }
}, true);

table.addEventListener('mouseout', function (e) {
    hovered && hovered.forEach(function (cell) {
        cell.classList.remove(HOVER_CLASS);
    });
    hovered = null;
}, true);
katspaugh
  • 17,449
  • 11
  • 66
  • 103
  • Works nicely. I'm trying to get it to work in my code now. Thanks! – carmenism Aug 15 '12 at 19:43
  • @vulpix, not at all. You might want to work around the [`classList`](https://developer.mozilla.org/en-US/docs/DOM/element.classList) and [`map`](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map)/[`forEach`](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach) parts for older browsers. – katspaugh Aug 15 '12 at 19:47
1

Best method I can think of is to give each <td> a class name that identifies the column it's in. i.e. "col1, col2, etc"

Then you can use the document.getElementsByClassName("colX") function to get an array of those <td>s, loop through the array and modify the style. Warning, this may not work in older browsers that don't have a getElementsByClassName function, but there are workarounds you can find easily for that. The best of which would be to use jQuery, not sure why you're against it.

invertedSpear
  • 10,864
  • 5
  • 39
  • 77
0

You create a class in css

.HoverTabla > tbody > tr:hover,
.HoverTabla > tbody > tr:focus { 
    background-color: #42C6F7;
}

and then you call it from the table in the html

<table class="table HoverTabla" id="tbl_Plan">

            <thead>
                <tr>
                    <th>Tipo de plan</th>
                    <th>Tiempo en días</th>
                    <th>Max. Usuario</th>
                    <th>Max. Capacidad</th>
                    <th>Max. Casos</th>
                    <th>Valor plan</th>
                    <th></th>
                </tr>
            </thead>
 </table>
0

CSS-only answer I found after a little bit of googling: https://css-tricks.com/simple-css-row-column-highlighting/

Each cell (<td>) in the table is given some padding through pseudo elements, which is used to create the hover effect. To make sure the hover effect doesn't extend further than the table itself, an overflow: hidden is used.

The sub-title in the article summarizes it all: "The trick is using huge pseudo elements on the <td>s, hidden by the table overflow"

Daniel_I_Am
  • 196
  • 1
  • 5
-1

Try

<td onMouseOver="this.bgColor='yellow';" onMouseOut="this.bgColor='white';">
Conrad Lotz
  • 8,200
  • 3
  • 23
  • 27
-2

This will work, no javascript needed. So it should work even when people turn javascript off.

Jfiddle: http://jsfiddle.net/vJacZ/

Html:

​<table>
<tr>
    <td class="column1">
        Column1
    </td>
    <td class="column2">
        Column2
    </td>
</tr>
</table>

Css:

.column1{
    color:black;
}
.column1:hover{
    color:red;
}
.column2{
    color:black;
}
.column2:hover{
    color:green;
}