Column and row highlight on hover disappears after table update

I currently have a table where it gets updated every few seconds. This table also has the first row which freezes when you scroll and also highlights the row and column on hover. Everything is working except that when the table gets updated, the hovers are gone. Is there any way to make the highlighted row/column still visible after the table udpates? If so, can it be done without any flicker?

test.php

<script>
$(document).ready(function(){
setInterval(function(){
$("#screen_video").load('test2.php')
}, 2000);
});
</script>

 <div id="screen_video">
    <div id="content"></div>
    <img src="loading.gif" id="loading" alt="loading" style="display:none;" />
</div>

test2.php

<style>
   html {
  box-sizing: border-box;
}
*,
*:before,
*:after {
  box-sizing: inherit;
}
html,
body {
  margin: 0;
  padding: 0;
}
h1,
p {
  text-align: center;
}

table{border-collapse:collapse}
			td, th{padding:5px;border:solid black 1px;}
			.hover_class{background:silver;}
			
#table_grid {
  border-spacing: 0;
  border-collapse: collapse;
  font-family: arial, verdana, sans-serif;
  font-size: 1rem;
  margin: auto;
  text-align: left;
  max-width: 1200px;
  width: 100%;
  border-radius: 10px;
}

#table_grid td,
#table_grid th {

  padding: 9px 8px 4px 8px;
  padding: 0.25rem;
}
#table_grid tr.red th {
  background: red;
}

#table_grid tr.red:hover th {
  background: orange;
}
#table_grid tr.red:hover th:hover {
  background: teal;
}

#table_grid tr:hover > td {
  background-color: rgba(220, 220, 220, 0.5);
}
#table_grid .thead,
#table_grid tr.red,
#table_grid tr.red th {
  position: -webkit-sticky;
  position: sticky;
  z-index: 2;
  top: 0;
}
</style>

<!--highlights-->

  <script type="text/javascript">
		    $(document).ready(function()
		    {
			var cellClassName = false;
			$("td, th").hover
			(
				function()
				{
					cellClassName = $(this).attr("class");
					$("." + cellClassName).addClass("hover_class");
				},
				function()
				{
					$("." + cellClassName).removeClass("hover_class");
				}
			);
		    });
		</script>
<h1>Test</h1>
  <table id="table_grid">
    <thead class="thead">
      <tr class="red">
        <th class="col1">test</th>
        <th class="col2">test</th>
        <th class="col3">test</th>
        <th class="col4">test</th>
        <th class="col5">test</th>
        <th class="col6">test</th>
      </tr>
      </thead>
      <tbody>
        <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr>
        <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> <tr>
          <td class="col1">test</td>
          <td class="col2">test</td>
          <td class="col3">test</td>
          <td class="col4">test</td>
          <td class="col5">test</td>
          <td class="col6">test</td>
        </tr> </tbody></table>

Hi there, you need to call your hover scripts after and every time the table has loaded, try the following:

$(document).ready(function () {
  setInterval(function () {
    $("#screen_video").load("test2.php", function () {
      var cellClassName = false;
      $("td, th").hover(
        function () {
          cellClassName = $(this).attr("class");
          $("." + cellClassName).addClass("hover_class");
        },
        function () {
          $("." + cellClassName).removeClass("hover_class");
        }
      );
    });
  }, 2000);
});

Hope it helps, I have not tested it.

Thanks Andres. I replaced

<script>
$(document).ready(function(){
setInterval(function(){
$("#screen_video").load('test2.php')
}, 2000);
});
</script>

with your script in test.php but unfortunately I still get the flickering

Hi, my answer was related to solving the hover functionality but not the flicker, I missed the flicker bit which may be a bit more complicated to solve. Is it possible to post a codepen where we can reproduce this and try to solve it?

Thanks

Here’s the codepen

I do not know how to do a codepen for this issue becuase it spans over 2 files

I have forked it and removed some duplicate code… I do not seem to see the flicker that you are mentioning, or maybe I don’t know what you mean… Seems to work fine for me:

Edit: I see what might be the problem test2.php does not exist in the codepen server therefore there is no update being made and no flicker

test.html has your script which checks test2.php every 2 seconds along with the css
test2,php has the table. I am using Chrome and every 2 seconds, I see the grey hover colors flicker

Edit: Yes that is correct. I don;t know how to add test2.php in codepen

This is a bit of a complex problem (solving that flicker). I will have a think and reply if I get some inspiration. Otherwise hope someone else has some ideas. In the meantime maybe have a think of how can you make that flicker happen in the codepen too, because it will be easier for people to come up with a solution.

Idea: make a different codepen with the updated table HTML only. If you inspect the codepen you will notice there is an iframe with a URL that contains the HTML in your snippet. Maybe use that iframe URL in your original codepen instead of your test2.php

Edit: I have actually tried that idea above, I don’t think codepen will allow you to do this… :frowning:

Best I can do is this

I just have the JS checking itself. YOu can see the flicker. Since it is checking itself, sometimes the hover colors will disapear but I don;t see that when I have this spanned over 2 pages. At least you see an idea of the flicker

EDIT → scratch that. Its very flakey at best trying to do this in codepen. Let me know if you can think of anything for me to try. Since you really don’t see the flicker while the mouse is moving, would you know how I can add a mouse movement by a few pixels every 2 seconds? I’m thinking that since the flicker appears when the mouse is still, I can move it by 1 or 2 pixels and the flicker will not be there

Gotcha! I think the only way you are going to solve this is by replacing the contents of each cell rather than the whole table’s HTML. It can be quite a tedious task… If I really were going to do this I would return the table data as a JSON object from an API endpoint, make an AJAX request to that endpoint, grab the data and then go through each cell and replace the text…

Makes sense. I’ll have to think about that one becuase this table gets built dynamically depending on what is in the Database, so it will never be the same # of elements. Thanks alot for all you have done.

1 Like

But you will always have the same headers?
So maybe leave the headers alone and just replace the td’s…

The amount of headers will also be different. I guess I can use a counter variable for the headers

If you are changing all the cells content (including the html structure) then surely there is going to be a flicker when you update the content as you no longer will be hovering on the same cell or column?

The only advice I can offer (as js is not my area) is that I see you are adding classes to multiple cells to create your column highlight. On a large table this is a lot of work and indeed even your codepen is clunky with this method.

I suggest that you use the colgroup method I mentioned in your CSS post on the same subject and you only have to add the one hover class to two elements and not to hundreds of tds.

Or you could set up a load of defaults assuming you have a finite number of columns and just add one class to the table element itself.
e.g.

.col1 .col1,
.col2 .col2,
.col3 .col3,
.col4 .col4,
.col5 .col5,
.col6 .col6,
.col7 .col7,
.col8 .col8,
.col9 .col9,
.col10 .col10,
.col11 .col11,
.col12 .col12,
.col13 .col13{background:silver;}

So you would need to dynamically add the one relevant class to #table_grid.

i.e. Th e col4 class gets dynamically added.

<table id="table_grid" class="col4">

The col4 class gets added to the table element.

cellClassName = $(this).attr("class");
$("#table_grid").addClass(cellClassName);

The predefined css supplies the color. I’m guessing you will still get the flicker but the hover action should be smoother than before. If you are not updating the table element itself but the cells then this method should allow the previously numbered columns to remain highlighted as the class would still be in place on the table element. Unless of course there are less columns than before and then you would have to wait until the JS has run again.

I think the colgroup method is more maintainable though.

Perhaps instead you need to implement some sort of update effect to disguise the flicker

I’m just thinking out loud here so perhaps none of the above will make any difference but just trowing a few ideas out :slight_smile:

1 Like

Yes the table can grow upto a few hundred rows & columns and table updates will vary from a full table update to just a few cells. So maybe the colgroup method is best.

To minimize the flicker, I am going to try to add a checksum where the JS will only refresh the table if there is a change. Would any of you know if I can put in php code into the JS? The first thing that the JS would do (the one that checks the DB every 2s) is get all the info, create a checksum ($current_checksum) and compare with the previous checksum($previous_checksum). If matches, do nothing. If it doesn’t match, unset previous checksum ($previous_checksum), create session variable ($previous_checksum) and proceed with the update. I’m pretty good with PHP so all this is done. Not sure how to add it to the JS script

Got his all working now, I am using test2.php to get the table data and make an MD5 of it and store it in a session variable. Modified the JS on test.php to check the MD5 on test2.php and depending on the status, I either update the table or not. Doing this every second hides the flicker

<script>
    function refresh_div() {
        jQuery.ajax({
            url:'test2.php',
            type:'POST',
            success:function(results) {
                jQuery(".result").html(results);
				if (results != "no change") 
					{
						$("#screen_video").load('a2.php?lang=<?php echo $lng;?>');
					}
            }
        });
    }
    t = setInterval(refresh_div,1000);
</script>


Hi guys, I am trying to add a scroll bar to the bottom of the table but when I do this, the first row is no longer sticking

I added the following in the CSS above and just put it in a dive around the table

#scroll_table{
	overflow-x:scroll;
	width:1200px;
}

I’m just signing off the evening but wanted to reply quickly before I go.

When you use position sticky it becomes sticky in its current context so when you add a div around the table the div is the context for the sticky item.

That means that if your table scrolls with the viewport scroll bar your sticky header will not be sticky. It will only be sticky when you scroll vertically using the vertical scroll bar on that parent div. You would need to give a height to the parent div and when the content in that div scrolls the header will be sticky.

It won’t be sticky if you simply scroll the whole thing away with the viewport scroll.

Back tomorrow now :slight_smile:

Thanks Paul.

SO when I add height, I still get no sticky, but most likely I am doing something worng

#scroll_table{
	overflow-x:scroll;
	width:1200px;
        height:1000px;
}

Is the content in the table over 1000px tall? The content will only scroll within the height of that div.

Here’s an old example.

I’d probably need to see your exact set up.

Are your codepen demos above still relevant for this issue?

Edit:

Just added the css and extra div to your codepen in post#9 and it works as I explained except of course that the 1000px height would be nonsense as the div is only just over that height. You would need a much smaller height so the content can scroll within that div.