How to highlight cells in one table as matching cells in another table are highlighted

I have two tables in an html document <table id="table1"> and <table id="table2">.
There are 10 columns and 5 rows in each table.
Each cell contains either one or two alphanumeric or special (e.g. *, $, % etc) characters.

I would like it to function as follows:

When I hover or select a cell (on a specific row - e.g. top row) of table1, e.g. containing the “Z” character, then the “Z” character will be highlighted /selected on table2 if it appears on the same specific row (i.e. top row of table2).
This should work in reverse (i.e. hovering /selecting table2 cell causes table1 cell to highlight /select)
Only one cell at a time on each row can be highlighted /selected.
Rows can be independently controlled (i.e. without affecting any other row’s cell highlighting).
With a second click the highlight should be removed.

Can this be done with CSS or JavaScript? (CSS preferred) but both useful.

Many thanks in advance for your kind help.

Regards,

Fred

1 Like

You won’t be able to do it in pure CSS. At least not until CSS4 if the :has selector passes muster.

Pure javascript, define an onmouseover event that finds the content of the cell, finds the matching cell(s) in the other table, and applies a class to them, and an onmouseout event that removes it.

1 Like

Hi there 77713,

and a warm welcome to these forums. :winky:

Here is one possible solution…

<!DOCTYPE HTML>
<html lang="en">
<head>

<meta charset="utf-8">
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1">

<title>table stuff</title>

<!--<link rel="stylesheet" href="screen.css" media="screen">-->

<style media="screen">
body {
    background-color: #f9f9f9;
    font: normal 1em / 1.5em BlinkMacSystemFont, -apple-system, 'Segoe UI', roboto, helvetica, arial, sans-serif;
 }

table {
    border-collapse: collapse;
    background-color: #fff;
 }

td {
    padding: 0.4em;
    border: 1px solid #999;
    cursor:pointer
 }

td:hover, td:active {
    background-color: #fc9; 
 }

</style>

</head>
<body> 

<h2>Table One</h2>

 <table id="table1">
  <tbody>
   <tr>
    <td>a</td><td>b</td><td>c</td><td>d</td><td>e</td><td>f</td><td>g</td><td>h</td><td>i</td><td>j</td>
   </tr>
   <tr>
    <td>k</td><td>l</td><td>m</td><td>n</td><td>o</td><td>p</td><td>q</td><td>r</td><td>s</td><td>t</td>
   </tr>
   <tr>
    <td>u</td><td>v</td><td>w</td><td>x</td><td>y</td><td>z</td><td>1</td><td>2</td><td>3</td><td>4</td>
   </tr>
   <tr>
    <td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>0</td><td>!</td><td>@</td><td>£</td>
   </tr>
   <tr>
    <td>$</td><td>%</td><td>^</td><td>&</td><td>*</td><td>(</td><td>)</td><td>!</td><td>-</td><td>+</td>
   </tr>
  </tbody>
 </table>

<h2>Table two</h2>

 <table id="table2">
  <tbody>
   <tr>
    <td>a</td><td>%</td><td>e</td><td>&</td><td>*</td><td>(</td><td>)</td><td>h</td><td>-</td><td>+</td>
   </tr>
   <tr>
    <td>5</td><td>6</td><td>p</td><td>8</td><td>n</td><td>0</td><td>!</td><td>z</td><td>£</td><td>?</td>
   </tr>
   <tr>
    <td>k</td><td>4</td><td>m</td><td>9</td><td>o</td><td>7</td><td>q</td><td>r</td><td>s</td><td>w</td>
   </tr>
   <tr>
    <td>u</td><td>v</td><td>t</td><td>x</td><td>y</td><td>@</td><td>1</td><td>2</td><td>3</td><td>l</td>
   </tr>
   <tr>
    <td>$</td><td>b</td><td>c</td><td>d</td><td>^</td><td>f</td><td>g</td><td>!</td><td>i</td><td>j</td>
   </tr>
  </tbody>
 </table>

<script>
(function( d ) {
   'use strict';
   var c, k, cont, el, td1, td2,
       t1 = d.getElementById( 'table1' ),
       t2 = d.getElementById( 'table2' ),
       tr1 = t1.querySelectorAll( 'tr' ), 
       tr2 = t2.querySelectorAll( 'tr' );

   for ( c = 0; c < tr1.length;  c ++ ) {
         td1 = tr1[ c ].querySelectorAll( 'td' ); 
         td2 = tr2[ c ].querySelectorAll( 'td' ); 

   for ( k = 0; k < td1.length;  k ++ ) {
         td1[ k ].addEventListener( 'hover', testIt( tr2[ c ],td1[ k ] ), false ); 
         td2[ k ].addEventListener( 'hover', testIt( tr1[ c ],td2[ k ] ), false ); 
       }
    }

function testIt( tr, td ) {
   td.onmouseover = function() { 
      cont = td.textContent; 
      for ( k = 0; k < td2.length;  k ++ ) {
         if ( tr.children.item( k ).textContent === cont ) {
              tr.children.item( k ).style.backgroundColor = '#fc9';
              el = tr.children.item( k );
          td.onmouseout = function() {
              el.style.backgroundColor = 'transparent';
            }
          }
        }
      }
     }
}( document ));
</script>

</body>
</html>

coothead

2 Likes

Hi coothead and thank you for your warm welcome!
Also, thank you so much for your super-fast response to my query - I will give it a go later and get back to you.

Once again, thank you very much coothead - excellent of you!.

All the best. 77713

Hi m_huntley,
Thank you for your helpful and prompt response - your kind help is much appreciated. Any further advice welcomed.
All the best,
77713

Hi there 77713,

although this code worked OK in my test browsers, with these two lines…

         td1[ k ].addEventListener( 'hover', testIt( tr2[ c ],td1[ k ] ), false ); 
         td2[ k ].addEventListener( 'hover', testIt( tr1[ c ],td2[ k ] ), false );

…to be on the safe side, they really should be…

         td1[ k ].addEventListener( 'mouseover', testIt( tr2[ c ],td1[ k ] ), false ); 
         td2[ k ].addEventListener( 'mouseover', testIt( tr1[ c ],td2[ k ] ), false );

coothead

1 Like

Thanks for the update coothead, I have changed “hover” to “mouseover” - both seem to work okay.

I tried your solution and it does work to a large degree, but seems to have a few little issues:

At first the page may seem to work okay, e.g. when hovering Table One cells the Table Two cells highlight where appropriate. However, when i then hover the cells of Table Two, if any character is hovered that has a match in Table One, only the Table One character is highlighted - this doesn’t always happen with all (Table Two) rows, and may firstly begin to happen on the top row (of Table Two) (i.e. there is no highlighting on Table One when there is a match hovered on Table Two, on some or all rows). If upon refresh, Table Two is the first one to be hovered, then this issue happens in reverse.

Other than that, it would be great if the cells can be clicked and the highlighting remains on mouseOut, so that a cell can become highlighted on every row where appropriate (apologies i I wasn’t clear on that at first).

Also that a second click on that cell (or a click on another cell) unhighlights it (and highlight the other cell, where other cell is clicked).

Any further advice much appreciated.

Many thanks for your time and expertise once again coothead.

All the best, 77713

Hi there 77713,

I do not have any of the problems which you mentioned in my test browsers…

IE11, Firefox 68, Chrome 75 or Vivaldi 2.6. :unhappy:

Which of your browser(s) are having problems?

Here is the amended code for cell clicking…

<!DOCTYPE HTML>
<html lang="en">
<head>

<meta charset="utf-8">
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1">

<title>table stuff</title>

<!--<link rel="stylesheet" href="screen.css" media="screen">-->

<style media="screen">
body {
    background-color: #f9f9f9;
    font: normal 1em / 1.5em BlinkMacSystemFont, -apple-system, 'Segoe UI', roboto, helvetica, arial, sans-serif;
 }

table {
    border-collapse: collapse;
    background-color: #fff;
 }

td {
    padding: 0.4em;
    border: 1px solid #999;
    cursor:pointer
 }

td:hover, td:active , .match {
    background-color: #fc9; 
 }

.match1{
    background-color: #9ce; 
 }

</style>

</head>
<body> 

<h2>Table One</h2>

 <table id="table1">
  <tbody>
   <tr>
    <td>a</td><td>b</td><td>c</td><td>d</td><td>e</td><td>f</td><td>g</td><td>h</td><td>i</td><td>j</td>
   </tr>
   <tr>
    <td>k</td><td>l</td><td>m</td><td>n</td><td>o</td><td>p</td><td>q</td><td>r</td><td>s</td><td>t</td>
   </tr>
   <tr>
    <td>u</td><td>v</td><td>w</td><td>x</td><td>y</td><td>z</td><td>1</td><td>2</td><td>3</td><td>4</td>
   </tr>
   <tr>
    <td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>0</td><td>!</td><td>@</td><td>£</td>
   </tr>
   <tr>
    <td>$</td><td>%</td><td>^</td><td>&</td><td>*</td><td>(</td><td>)</td><td>!</td><td>-</td><td>+</td>
   </tr>
  </tbody>
 </table>

<h2>Table two</h2>

 <table id="table2">
  <tbody>
   <tr>
    <td>a</td><td>%</td><td>e</td><td>&</td><td>*</td><td>(</td><td>)</td><td>h</td><td>-</td><td>+</td>
   </tr>
   <tr>
    <td>5</td><td>6</td><td>p</td><td>8</td><td>n</td><td>0</td><td>!</td><td>z</td><td>£</td><td>?</td>
   </tr>
   <tr>
    <td>k</td><td>4</td><td>m</td><td>9</td><td>o</td><td>7</td><td>q</td><td>r</td><td>s</td><td>w</td>
   </tr>
   <tr>
    <td>u</td><td>v</td><td>t</td><td>x</td><td>y</td><td>@</td><td>1</td><td>2</td><td>3</td><td>l</td>
   </tr>
   <tr>
    <td>$</td><td>b</td><td>c</td><td>d</td><td>^</td><td>f</td><td>g</td><td>!</td><td>i</td><td>j</td>
   </tr>
  </tbody>
 </table>

<script>
(function( d ) {
   'use strict';
   var c, k, cont, el, td1, td2, num1, n2, ary1 = [], ary2 = [],
       t1 = d.getElementById( 'table1' ),
       t2 = d.getElementById( 'table2' ),
       tr1 = t1.querySelectorAll( 'tr' ), 
       tr2 = t2.querySelectorAll( 'tr' );

   for ( c = 0; c < tr1.length;  c ++ ) {
         td1 = tr1[ c ].querySelectorAll( 'td' ); 
         td2 = tr2[ c ].querySelectorAll( 'td' ); 

   for ( k = 0; k < td1.length;  k ++ ) {
         num1 =  c + k  + ( td1.length - 1 ) * c ;

         ary1[ num1 ] = true;
         ary2[ num1 ] = true;

         td1[ k ].addEventListener( 'mouseover', testIt( c, tr2[ c ], td1[ k ], num1, 's1'), false ); 
         td2[ k ].addEventListener( 'mouseover', testIt( c, tr1[ c ], td2[ k ], num1, 's2' ), false ); 

       }
    }

function testIt( x, tr, td, n1, swap) {
   td.onmouseover = function() {  
      cont = td.textContent; 

      for ( k = 0; k < td2.length;  k ++ ) {
         if ( tr.children.item( k ).textContent === cont ) {
              tr.children.item( k ).classList.add( 'match' );
              el = tr.children.item( k );
              n2 = x * 10 + k ;

          td.onmouseout = function() {
              el.classList.remove( 'match' );
             }
            }
          }
        }

          td.onclick = function() {
           if ( swap === 's2' ) {
                n1 = n2;
              }
           if ( ary1[ n1 ] == true  ) {                      
               this.classList.add( 'match1' ); 
               el.classList.add( 'match1' );
               ary1[ n1 ] = false; 
               ary2[ n2 ] = false; 
              }
           else {
               this.classList.remove( 'match1' );
               el.classList.remove( 'match1' );
               ary1[ n1 ] = true; 
               ary2[ n2 ] = true; 
              }
            }
          }
      
}( document ));
</script>

</body>
</html>

Bear in mind that javascript is not really my forte, so the gurus here
may be able to provide you with better methods for your project. :winky:

coothead

1 Like

If you hover the dollar symbol in the bottom row of the bottom table first then you may see the problem mentioned.

It goes away if you have hovered the top table first.

Hi there Paul,

I am not seeing that problem in my test browsers. :unhappy:

My tests, though, are now being made with the code from post #8. :winky:

coothead

I’ll double check when I get back to my computer but I’m sure I randomly saw the issue in chrome (didn’t test others)

When I hovered the bottom dollar sign both the bottom and top were highlighted. This only seem to happen first time.

I may need to double check later to make sure I wasn’t seeing things:)

1 Like

Hi there coothead,

That’s really awesome of you! Thanks so much, you’re brilliant (and humble with it too).

The issue I spoke of seems to have gone now with the latest code you wrote and the clicking works just great - fantastic.

Sorry to say, but, just one little thing - it would be good if… only one cell at a time on each row can be selected - i.e. selecting another cell, un-highlights an already highlighted one.

Sorry to ask so much of you. I definitely owe you for this…

Cheers coothead - You Rock!

Forgot to say:
Firefox Quantum 66.0.2 (64-bit) on Linux Mint 19 Tara

Yes that one is working ok as far as I can tell :slight_smile:

1 Like

Hi there 77713,

I have just noticed a flaw in the code of post #8
which renders it as worse than useless. :wonky:

I had not thought about the consequences of
clicking cells other than those that contained
matches”. This action now highlights that cell
and has other very strange effects. :eek:

So, I’m afraid, it’s back to the drawing board. :banghead:

coothead

1 Like

Hi there coothead,
thank you for your response - I don’t seem to have any problems with your code (at the moment) - just wondering what the problem you’re experiencing is.
I will test it further…
Thank you very much once again coothead.
Cheers, 77713
(can we PM on this site?)

Hi there 77713,

I am unable to fulfill your requirements for the two tables. :banghead:

What I can do though, is show how I would’ve have done it. :winky:

77713.zip (2.4 KB)

You can also view the contents of this file here at …

John Betong’s Site

If that is not to your liking, then I would suggest that you try
to get one of our resident javascript gurus to help you out. :biggrin:

As I mentioned in a previous post javascript, is not really my forte. :unhappy:

coothead

3 Likes

Hi coothead,
Thank you for that - very kind of you indeed - you are greatly appreciated for what you do.
I hope I can help you someday.
All the best,
77713

I wrote another solution. I wasn’t sure if you want single cells to be selectable or only pairs. You can toggle the “onlyPairs” variable to switch mode.

<!DOCTYPE HTML>
<html lang="en">
<head>

<meta charset="utf-8">
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1">

<title>table stuff</title>

<!--<link rel="stylesheet" href="screen.css" media="screen">-->

<style media="screen">
body {
    background-color: #f9f9f9;
    font: normal 1em / 1.5em BlinkMacSystemFont, -apple-system, 'Segoe UI', roboto, helvetica, arial, sans-serif;
 }

table {
    border-collapse: collapse;
    background-color: #fff;
 }

td {
    padding: 0.4em;
    border: 1px solid #999;
    cursor:pointer
 }

.highlight {
    background-color: #fc9; 
 }

.selected{
    background-color: #9ce; 
 }

</style>

</head>
<body> 

<h2>Table One</h2>

 <table id="table1">
  <tbody>
   <tr>
    <td>a</td><td>b</td><td>c</td><td>d</td><td>e</td><td>f</td><td>g</td><td>h</td><td>i</td><td>j</td>
   </tr>
   <tr>
    <td>k</td><td>l</td><td>m</td><td>n</td><td>o</td><td>p</td><td>q</td><td>r</td><td>s</td><td>t</td>
   </tr>
   <tr>
    <td>u</td><td>v</td><td>w</td><td>x</td><td>y</td><td>z</td><td>1</td><td>2</td><td>3</td><td>4</td>
   </tr>
   <tr>
    <td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>0</td><td>!</td><td>@</td><td>£</td>
   </tr>
   <tr>
    <td>$</td><td>%</td><td>^</td><td>&</td><td>*</td><td>(</td><td>)</td><td>!</td><td>-</td><td>+</td>
   </tr>
  </tbody>
 </table>

<h2>Table two</h2>

 <table id="table2">
  <tbody>
   <tr>
    <td>a</td><td>%</td><td>e</td><td>&</td><td>*</td><td>(</td><td>)</td><td>h</td><td>-</td><td>+</td>
   </tr>
   <tr>
    <td>5</td><td>6</td><td>p</td><td>8</td><td>n</td><td>0</td><td>!</td><td>z</td><td>£</td><td>?</td>
   </tr>
   <tr>
    <td>k</td><td>4</td><td>m</td><td>9</td><td>o</td><td>7</td><td>q</td><td>r</td><td>s</td><td>w</td>
   </tr>
   <tr>
    <td>u</td><td>v</td><td>t</td><td>x</td><td>y</td><td>@</td><td>1</td><td>2</td><td>3</td><td>l</td>
   </tr>
   <tr>
    <td>$</td><td>b</td><td>c</td><td>d</td><td>^</td><td>f</td><td>g</td><td>!</td><td>i</td><td>j</td>
   </tr>
  </tbody>
 </table>

<script>

(function() {
 "use strict";

 var onlyPairs = true;

 var t1 = document.getElementById('table1');
 var t2 = document.getElementById('table2');
 
 var arr1 = ArrayFromTable(t1);
 var arr2 = ArrayFromTable(t2);
 
 t1.addEventListener('mouseover', highlight.bind(t1, t2, arr2, true));
 t2.addEventListener('mouseover', highlight.bind(t2, t1, arr1, true));
 t1.addEventListener('mouseout', highlight.bind(t1, t2, arr2, false));
 t2.addEventListener('mouseout', highlight.bind(t2, t1, arr1, false));
 t1.addEventListener('click', select);
 t2.addEventListener('click', select);

 function ArrayFromTable(tbl) {
  return Array.from(tbl.rows).map(function(row) {
   return Array.from(row.cells).map(function(cell) {
    return cell.textContent;
   });
  });
 };
 

 function highlight(tbl, arr, s, event) {
  if(event.target.tagName != 'TD') {
   return;
  }
  var r = event.target.parentNode.rowIndex;
  var c = event.target.cellIndex;
  this.rows[r].cells[c].classList.toggle('highlight', s);
 
  c = arr[r].indexOf(event.target.textContent);
  if(~c) {
   tbl.rows[r].cells[c].classList.toggle('highlight', s);
  }
 };


 function select(event) {
  if(event.target.tagName != 'TD') {
   return;
  }
  var r = event.target.parentNode.rowIndex;
  var a = t1.rows[r].querySelector('.selected');
  var A = t1.rows[r].querySelector('.highlight');
  var b = t2.rows[r].querySelector('.selected');
  var B = t2.rows[r].querySelector('.highlight');
 
  if(a) { a.classList.remove('selected'); }
  if(b) { b.classList.remove('selected'); }

  if((!onlyPairs || A && B) && A && A != a) { A.classList.add('selected'); }
  if((!onlyPairs || A && B) && B && B != b) { B.classList.add('selected'); }
 };

}());

</script>

</body>
</html>```
2 Likes

Hi alperquin,

Thank you very much for writing me an alternative solution - I tested it and it works very well - and it’s billiant to have the “onlyPairs” variable too.
Your help is much appreciated.

Woulds it be possible that if there were several of the same character on either of two related table rows, then they would all Highlight /Select at the same time?

Thank you once again alperquin - that’s excellent of you.

All the best, 77713