14
votes

I am using Turbolinks and I have a loading animation that happens between pages. I am currently using page:load to complete the animation however, it seems as if page:load is acting like document ready rather than window.on load.

The desired effect is I have an overlay that is displayed over the content while the page is loading with a loading animation on top of it. Once the page is fully loaded (with images, objects, etc) it will then fade out the overlay to show the content.

What is happening is the content is being shown before the page is fully loaded. Here is the javascript I am using.

    (function () {

      function showPreloader() {
        Turbolinks.enableProgressBar();
        $('#status').fadeIn('slow');
        $('#preloader').delay(300).fadeIn('slow'); 
      }

      function hidePreloader() {
        $('#status').fadeOut();
        $('#preloader').delay(300).fadeOut('slow');
      }

      $(document).on('page:fetch', showPreloader);
      $(document).on('page:load', hidePreloader);
      $(window).on('load', hidePreloader);
    })()
3

3 Answers

5
votes

This workaround is for turbolinks 5, but should be easy to adapt.

The loading appears instantly because turbolinks cache, it renders the page before the ajax call is made, breaking the animation.

In order to get a loading effect working we must disable it:

<head>
....
  <meta name="turbolinks-cache-control" content="no-cache">

Then we can do something like: (using animated.css)

$(document).on('turbolinks:click', function(){
  $('.page-content')
    .addClass('animated fadeOut')
    .off('webkitAnimationEnd oanimationend msAnimationEnd animationend')
});


$(document).on('turbolinks:load', function(event){
    // if call was fired by turbolinks
    if (event.originalEvent.data.timing.visitStart) { 
      $('.page-content')
        .addClass('animated fadeIn')
        .one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function(){
          $('.page-content').removeClass('animated');
        });
    }else{
      $('.page-content').removeClass('hide')
    }  
...

With that, the transition is nice and smooth.

2
votes

Out of the box this seems not possible.

My strategy for a solution would be to use a library like imagesLoaded.

On page:load you would setup an imagesLoaded observer in which you trigger your animation ending. This way you can delay it until all new images are loaded...

The code would look something like this:

$(document).on('page:load', function() {
  $('body').imagesLoaded(hidePreloader);
});
0
votes

Try this:

HTML:

<!--top-->
<div style="background-color:
/*background color*/
white
;width:100vw;height:100vh;z-index:999999;position:fixed;top:0;left:0;right:0;bottom:0;background:url(
/*or URL*/
background.jpg
) center center no-repeat;background-size:cover;" id="pgLoader">
<!--document.querySelector("#pgloader loader")
where loader goes-->
<loader style="position:fixed;top:
/*may need to change*/
40%
;left:0;right:0;bottom:0;width:100%;height:100%;text-align:center;">
Loading...
</loader>
</div>
<!--rest of page-->
<h1>hello!</h1>
Blablabla
<img src="http://lorempixel.com/200/200/abstract/">

JS:

window.onload=function(){
document.querySelector("#pgloader").style.display="none";
//maybe other stuff too
}

Demo

(Press the output button again to refresh demo)