Helmut Applebaum
Helmut Applebaum

Reputation: 97

Double buffering divs flicker when refreshing in Ajax

I have code that refreshes a div running on local server without flickering, but when hosting it on a webserver, it does flicker (disappear to background) when refreshing:

 <script>
    setTimeout(function() {
        $.ajax({      
            url: "",
            context: document.body,
            success: function(s,x){
                $(this).html(s);
            }
        });
    }, 1000);
</script>

I've had a good look around SO and the web, and it seems I want to double buffer the div table I am refreshing - have one hidden, refresh that, then swap the display style of the two divs

I started with How to avoid blinking when updating page from ajax

moved on to http://www.brightcherry.co.uk/scribbles/jquery-auto-refresh-div-every-x-seconds/ and Trouble with dynamic refreshing div

And got some good ideas from:How to toggle between two divs

The code I am trying to get to work may be too complicated. I feels like it should work, and the tables refresh, but they flicker with a long time between display.

Divs;

<div id="id1" style="display: none";>
    <div id="allTable1" class = "tableCenter">
        <div id="hiTable" class = "table">
            {% for entry in high_entry_list %}
            <li>
                <a href="/entries/{{ entry.id }}/"> 
                    <div class = "high" style = "text-align: left";>
                        {{ entry.text }}&nbsp;&nbsp;&nbsp;&nbsp;
                        <div style="float: right">
                            {{ entry.score }}
                        </div>
                    </div>
                </a>
            </li>
            {% endfor %}
        </div>
        ....and two more tables as hiTable above...
    </div>
</div>

<div id="id2" style="display: block";>
    <div id="allTable2" class = "tableCenter">
        <div id="hiTable" class = "table">
            {% for entry in high_entry_list %}
            <li>
                <a href="/entries/{{ entry.id }}/"> 
                    <div class = "high" style = "text-align: left";>
                        {{ entry.text }}&nbsp;&nbsp;&nbsp;&nbsp;
                        <div style="float: right">
                            {{ entry.score }}
                        </div>
                    </div>
                </a>
            </li>
            {% endfor %}
        </div>
        ....and two more tables as hiTable above...
    </div>
</div>

Script:

<script>
    var visible_id = 'id2';
    setInterval(function() {
        if(visible_id == 'id2') {               
            document.getElementById('id1').style.display = 'block';             
            document.getElementById('id2').style.display = 'none';
            $.ajax({
                url: "/index",
                context: document.getElementById('allTable2'),
                success: function (s) {
                    $("#allTable2").html(s).load;
                }
            });
            visible_id = 'id1';
        } else {
            document.getElementById('id1').style.display = 'none';            
            document.getElementById('id2').style.display = 'block';
            $.ajax({
                url: "/index",
                context: document.getElementById('allTable1'),
                success: function (s) {
                    $("#allTable1").html(s).load;
                }
            });
            visible_id = 'id2';
        }
    }, 1000);
</script>

So I have div wrappers for the two copies of three tables (one hidden, one shown), the javascript checks the visibility, swaps display style for the two wrappers, and updates the hidden one with an ajax refresh (which works). Is there an obvious logic or coding flaw that may be causing the flicker?

Upvotes: 0

Views: 2054

Answers (1)

JDB
JDB

Reputation: 25820

AJAX requests can take significantly longer than a second. You are toggling between the tables whether or not a particular AJAX request has finished, but the AJAX will still execute (perhaps 1.5 seconds later), giving you that undesired flickering behavior.

Rather than setting an interval which will execute whether or not the AJAX request has finished, set a timeout from the AJAX callback. Something like this (you'll probably need to fiddle with it some):

<script>

(function(){
  var visible_id = 'id2';

  function toggleDisplay(){
    // toggle displayed table
    document.getElementById('id1').style.display = visible_id === 'id2' ? 'block' : 'none';
    document.getElementById('id2').style.display = visible_id === 'id2' ? 'none' : 'block';
    var tableId = visible_id === 'id2' ? 'allTable1' : 'allTable2';
    $.ajax({
        url: "/index",
        context: document.getElementById(tableId),
        success: function (s) {
          $("#" + tableId).html(s).load;
          // when the ajax request has finished, initiate the next ajax request
          // after a 1 second delay
          window.setTimeout( toggleDisplay, 1000 );
        }
    });
    visible_id = visible_id === 'id2' ? 'id1' : 'id2';
  }

})();

</script>

Upvotes: 1

Related Questions