13

I have div with vertical scroll bar. Div is being updated dynamically via ajax and html is inserted using jQuery's .html method. After div is updated scroll bar returns to top and I am trying to keep it in the previous position.

This is how I'm trying it:

var scrollPos = $('div#some_id').scrollTop(); //remember scroll pos
$.ajax({...
    success: function(data) {
        $('div#some_id').html(data.html_content); //insert html content
        $('div#some_id').scrollTop(scrollPos); //restore scroll pos
    }
});

This fails. My best guess is that it is failing due to inserted html not rendered (ie. no scroll).

For example this works.

setTimeout(function(){
    $('div#some_id').scrollTop(scrollPos);
}, 200);

But this is dirty hack in my opinion. I have no way of knowing that some browsers won't take more then these 200ms to render inserted content.

Is there a way to wait for browser to finish rendering inserted html before continuing ?

Vladimir Cvetic
  • 832
  • 3
  • 8
  • 23
  • http://stackoverflow.com/questions/2030497/how-can-you-get-your-code-to-wait-for-html-and-append-functions-to-complete should help – Dhiraj May 20 '12 at 13:06

4 Answers4

10

It's still a hack, and there really is no callback available for when the HTML is actually inserted and ready, but you could check if the elements in html_content is inserted every 200ms to make sure they really are ready etc.

Check the last element in the HTML from the ajax call:

var timer = setInterval(function(){
   if ($("#lastElementFromAjaxID").length) {
       $('div#some_id').scrollTop(scrollPos);
       clearInterval(timer);
   }
}, 200);

For a more advanced option you could probably do something like this without the interval, and bind it to DOMnodeInserted, and check if the last element is inserted.

adeneo
  • 312,895
  • 29
  • 395
  • 388
  • Thanks, it's sad no such callback exists. – Vladimir Cvetic May 20 '12 at 13:15
  • 2
    Well, there is the native [DOMNodeInserted](http://help.dottoro.com/ljmcxjla.php) event that will fire every time an element is inserted, You can bind a function to that event that checks the target element to see if it's the last element from the ajax call, and then do your scroll thing, but it will probably be less efficient then the interval, and there are some cross browser issues as well. I'd just go for the interval, it takes little resources to run an interval like that, and it will probably run max a couple of times, checking every inserted element will be worse IMO. – adeneo May 20 '12 at 13:19
4

I will just like to point out one difference here: One thing, is when the .html() have completed loading, but the browser actually render the content is something different. If the loaded content is somewhat complex, like tables, divs, css styling, images, etc - the rendering will complete somewhat later than all the dom ellements are present on the page. To check if everything is there, does not mean the rendering is complete. I have been looking for an answer to this by myself, as now I use the setTimeout function.

olekeh
  • 537
  • 5
  • 10
0

Such callback does not exists because .html() always works synchronously

danza
  • 11,511
  • 8
  • 40
  • 47
0

If you are waiting for images loading, there's one approach https://github.com/desandro/imagesloaded

Feuda
  • 2,335
  • 30
  • 28