Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mouse hover with multiple td rowspan

Tags:

html

jquery

css

I have a table with multiple td rowspan. On mouse hover the entire alphabet row should change to red colour. For example, if we keep the mouse on any alphabet value the entire alphabet section should appear red. Same case for numbers as well.

I tried some jQuery to achieve this, but couldn't get the entire row of alphabet or numbers in same colour.

$("td").hover(function() {
  $el = $(this);
  $el.parent().addClass("hover");

  if ($el.parent().has('td[rowspan]').length == 0) {
    $el
      .parent()
      .prevAll('tr:has(td[rowspan]):first')
      .find('td[rowspan]')
      .addClass("hover");
  }
}, function() {
  $el
    .parent()
    .removeClass("hover")
    .prevAll('tr:has(td[rowspan]):first')
    .find('td[rowspan]')
    .removeClass("hover");
});
body {
  padding: 50px;
}

table {
  width: 100%;
  border-collapse: collapse;
}

td,
th {
  padding: 20px;
  border: 1px solid black;
}

.hover {
  background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
  <tbody>
    <tr>
      <td rowspan="3">Alphabet</td>
      <td rowspan="2">a</td>
      <td>b</td>
      <td>c</td>
    </tr>
    <tr>
      <td>d</td>
      <td>e</td>
    </tr>
    <tr>
      <td>f</td>
      <td>g</td>
      <td>h</td>
    </tr>
    <tr>
      <td rowspan="3">Number</td>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>4</td>
      <td>5</td>
      <td>6</td>
    </tr>
    <tr>
      <td>7</td>
      <td>8</td>
      <td>9</td>
    </tr>
  </tbody>
</table>

How can we solve this?

like image 437
Rajasekhar Bammidi Avatar asked Oct 10 '14 12:10

Rajasekhar Bammidi


3 Answers

EDIT: Added a way to find the top of each block.

EDIT 2 - Do the hard work up front Thinking about this again, it is better to just work out at the start which rows are in each block and store that list with each row, e.g. each alphabet row stores a reference to an array containing rows 1-4. So when you hover, you just need to get the array of rows stored in the parent row and apply the class to those.

By checking the maximum rowspan in the top row of the block, you aren't restricted to just checking the first cell. In the updated code, I have moved Alphabet to the middle to demonstrate this and add a couple of other blocks to demonstrate single row blocks work.

function findBlocks(theTable) {
    if ($(theTable).data('hasblockrows') == null) {
        console.log('findBlocks'); // to prove we only run this once

        // we will loop through the rows but skip the ones not in a block
        var rows = $(theTable).find('tr');
        for (var i = 0; i < rows.length;) {

            var firstRow = rows[i];

            // find max rowspan in this row - this represents the size of the block
            var maxRowspan = 1;
            $(firstRow).find('td').each(function () {
                var attr = parseInt($(this).attr('rowspan') || '1', 10)
                if (attr > maxRowspan) maxRowspan = attr;
            });

            // set to the index in rows we want to go up to
            maxRowspan += i;

            // build up an array and store with each row in this block
            // this is still memory-efficient, as we are just storing a pointer to the same array
            // ... which is also nice becuase we can build the array up in the same loop
            var blockRows = [];
            for (; i < maxRowspan; i++) {
                $(rows[i]).data('blockrows', blockRows);
                blockRows.push(rows[i]);
            }

            // i is now the start of the next block
        }

        // set data against table so we know it has been inited (for if we call it in the hover event)
        $(theTable).data('hasblockrows', 1);
    }
}

$("td").hover(function () {
    $el = $(this);
    //findBlocks($el.closest('table')); // you can call it here or onload as below
    $.each($el.parent().data('blockrows'), function () {
        $(this).find('td').addClass('hover');
    });
}, function () {
    $el = $(this);
    $.each($el.parent().data('blockrows'), function () {
        $(this).find('td').removeClass('hover');
    });
});

findBlocks($('table'));
body {
    padding: 50px;
}
table {
    width: 100%;
    border-collapse: collapse;
}
td, th {
    padding: 20px;
    border: 1px solid black;
}
.hover {
    background: red;
}
<table>
    <tbody>
        <tr>
            <td>Symbols</td>
            <td>+</td>
            <td>-</td>
            <td>*</td>
        </tr>
        <tr>
            <td rowspan="2">a</td>
            <td>b</td>
            <td rowspan="4">Alphabet</td>
            <td>c</td>
        </tr>
        <tr>
            <td>d</td>
            <td>e</td>
        </tr>
        <tr>
            <td rowspan="2">f</td>
            <td>g</td>
            <td>h</td>
        </tr>
        <tr>
            <td>i</td>
            <td>j</td>
        </tr>
        <tr>
            <td>Bitwise</td>
            <td>&amp;</td>
            <td>|</td>
            <td>^</td>
        </tr>
        <tr>
            <td rowspan="3">Number</td>
            <td>1</td>
            <td>2</td>
            <td>3</td>
        </tr>
        <tr>
            <td>4</td>
            <td>5</td>
            <td>6</td>
        </tr>
        <tr>
            <td>7</td>
            <td>8</td>
            <td>9</td>
        </tr>
    </tbody>
</table>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
like image 176
Rhumborl Avatar answered Nov 15 '22 18:11

Rhumborl


Try this

        $(function () {
        $("td").hover(function () {
            $el = $(this);
            $el.parent().addClass("hover");
            var tdIndex = $('tr').index($el.parent());
            if ($el.parent().has('td[rowspan]').length == 0) {
                $el.parent().prevAll('tr:has(td[rowspan]):first')
                        .find('td[rowspan]').filter(function () {
                            return checkRowSpan(this, tdIndex);
                        }).addClass("hover");
            }
        }, function () {
            $el.parent()
    .removeClass("hover")
    .prevAll('tr:has(td[rowspan]):first')
    .find('td[rowspan]')
    .removeClass("hover");

        });
    });
    function checkRowSpan(element, pIndex) {
        var rowSpan = parseInt($(element).attr('rowspan'));
        var cIndex = $('tr').index($(element).parent());
        return rowSpan >= pIndex + 1 || (cIndex + rowSpan) > pIndex;
    }

Fiddler here

like image 2
Aravind Sivam Avatar answered Nov 15 '22 19:11

Aravind Sivam


Your table structure is irregular, so it's very hard to find a selector that will select the visual "row", as it spans different rows. One solution is to color the cells by hand, take a look at http://jsfiddle.net/2szxsfcs/2/

Basically you tag the rows that are meant to be colored together with the same id, then using jquery you color / uncolor all related TR's:

<table>
  <tbody>
        <tr class="fullrow row1" data-id="1">
            <td rowspan="3">Alphabet</td>
            <td rowspan="2">a</td>
            <td>b</td>
            <td>c</td>
        </tr>
        <tr  class="fullrow row1" data-id="1">
            <td>d</td>
            <td>e</td>          
        </tr>
        <tr class="fullrow row1" data-id="1">
            <td>f</td>
            <td>g</td>
            <td>h</td>
        </tr>
        <tr class="fullrow row2" data-id="2">
            <td rowspan="3">Number</td>
            <td>1</td>
            <td>2</td>
            <td>3</td>
        </tr>
        <tr class="fullrow row2" data-id="2">
            <td>4</td>
            <td>5</td>
            <td>6</td>
        </tr>
        <tr class="fullrow row2" data-id="2">
            <td>7</td>
            <td>8</td>
            <td>9</td>
        </tr>   
    </tbody>
</table>

and

  $(".fullrow")
    .hover(function() {
        var id=this.getAttribute("data-id");
        // on hover, we get an "id", and all tr's that have class "row<id>" are the ones to color
        $(".row"+id).addClass("hovering"); 
    })
    .on ("blur mouseleave", function() {
      var id=this.getAttribute("data-id");
      $(".row"+id).removeClass("hovering"); 
    });

and

.hovering { background-color:red; }
like image 1
rupps Avatar answered Nov 15 '22 17:11

rupps