Search code examples
jqueryanimationscrollcallbackskrollr

Javascript callbacks not firing in correct order


I am using jQuery, skrollr, and skrollr-menu to create a specific navigation animation. The animation I want is the following:

  1. User clicks on a link
  2. A black div fades over the page
  3. The page scrolls underneath to the location
  4. The black div fades out and off the page

You can see an example of that animation at http://www.gramercyparkhotel.com/. It seems simple enough; however, as the <div> is fading in, the scroll is triggered before the animation ends, resulting in a flashing of scrolling content before the screen goes black. This shouldn't be happening because everything is timed using callbacks, so if the animation hasn't finished, why is the subsequent function with the scroll being called?

EDIT

I added a codesnippet below. It looks as if the animateTo call is being called before the animation completes. animateTo scrolls to the top, then to the correct location. I don't care about that behavior if the callbacks actually function as they should.

$(document).ready( function() {
  // Initialize skrollr
  var s = skrollr.init({
    keyframe: function(element, name, direction) {
      $(element).trigger(name, [direction]);
    }
  });

  function hideFader($fader, callback) {
    var callback = callback || function() { return false; };
    $fader.animate({
      'opacity': 0
    }, 500, function() {
      $fader.css('top', '-100%');
      callback();
    });
  }

  function showFader($fader, callback) {
    var callback = callback || function() { return false; };
    $fader.css('top', '0%');

    $fader.animate({
      'opacity': 1
    }, 500, callback);
  }

  var $fader = $('#fader');
  hideFader($fader);

  skrollr.menu.init(s, {
    animate: false,
    handleLink: function(link) {
      showFader($fader, function() {
        var $location = $($(link).attr('href')),
            menuTop;

        if($(link).attr('href') === '#home') {
          menuTop = 0;
        } else {
          menuTop = Math.round(parseInt($location.attr('data-dtcp')) / 100 * $('#home').height());
        }

        s.animateTo(menuTop, {
          duration: 0,
          done: function() {
            hideFader($fader);
          }
        });
      });
    },
    complexLinks: false,
    updateUrl: false
  });
});
.navigation-centered {
  position: fixed;
  bottom: 0;
  width: 100%;
  background-color: #171511;
  background-color: rgba(23, 21, 17, 0.9);
  z-index: 1000;
}
.navigation-centered .navigation-centered-wrapper {
  position: relative;
  border: 10px solid transparent;
  padding: 15px 0;
  min-width: 100%;
}
.navigation-centered ul.navigation-centered-menu {
  clear: both;
  display: none;
  margin: 0 auto;
  overflow: visible;
  padding: 0;
  width: 100%;
  display: block;
  text-align: center;
}
.navigation-centered ul.navigation-centered-menu.show {
  display: block;
}
.navigation-centered ul li.nav-link {
  display: block;
  text-align: right;
  width: 100%;
  display: inline;
}
.navigation-centered ul li.nav-link a {
  display: inline-block;
  color: #b5b4b2;
  text-decoration: none;
  outline: none;
}
.navigation-centered ul li.nav-link a:hover, .navigation-centered ul li.nav-link a:active, .navigation-centered ul li.nav-link a:visited, .navigation-centered ul li.nav-link a:focus {
  color: #b5b4b2;
  text-decoration: none;
  outline: none;
}
.navigation-centered ul li.nav-link:after {
  content: '\00B7';
  padding-right: 1em;
  display: inline-block;
  color: #b5b4b2;
}
.navigation-centered ul li.nav-link:last-child:after {
  content: '';
  display: none;
}
.navigation-centered ul li.nav-link a {
  padding-right: 1em;
}

.fullscreen, #fader {
  height: 100%;
  width: 100%;
  height: 100vh;
  width: 100vw;
}

#home {
  background-color: red;
}

#about {
  background-color: blue;
}

#gallery {
  background-color: green;
}

#contact {
  background-color: yellow;
}

#blog {
  background-color: purple;
}

#fader {
  position: fixed;
  z-index: 10000;
  background: #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://sid.artlyticalmedia.com/wp-content/themes/sanctuariesinteriordesign/bower_components/skrollr/dist/skrollr.min.js"></script>
<script src="http://sid.artlyticalmedia.com/wp-content/themes/sanctuariesinteriordesign/bower_components/skrollr-menu/dist/skrollr.menu.min.js"></script>

<div id="home" class="fullscreen"
  data-dtcp="0"
  data-0p="top: 0%;"
  data-100p="top: -100%;">
  <h1>home</h1>
</div>

<div id="gallery" class="fullscreen"
  data-dtcp="100"
  data-100p="top: 100%;"
  data-200p="top: 0%;"
  data-300p="top: -100%;">
  <h1>gallery</h1>
</div>

<div id="about" class="fullscreen"
  data-dtcp="200"
  data-200p="top: 100%;"
  data-300p="top: 0%;"
  data-400p="top: -100%;">
  <h1>about</h1>
</div>

<div id="blog" class="fullscreen"
  data-dtcp="400"
  data-300p="top: 100%;"
  data-400p="top: 0%;"
  data-500p="top: -100%;">
  <h1>blog</h1>
</div>

<div id="contact" class="fullscreen"
  data-dtcp="500"
  data-400p="top: 100%;"
  data-500p="top: 0%;"
  data-600p="top: -100%;">
  <h1>contact</h1>
</div>

<div id="fader"></div>

<footer id="footer">
  <nav id="nav-main" class="nav-main" role="navigation">
    <div class="navigation-centered" role="banner">
      <div class="navigation-centered-wrapper">
        <nav role="navigation">
          <ul id="js-navigation-centered-menu" class="navigation-centered-menu show">
            <li class="nav-link">
              <a href="#home">home</a>
            </li>
            <li class="nav-link">
              <a href="#gallery">gallery</a>
            </li>
            <li class="nav-link">
              <a href="#about">about</a>
            </li>
            <li class="nav-link">
              <a href="#blog">blog</a>
            </li>
            <li class="nav-link">
              <a href="#contact">contact</a>
            </li>
          </ul>
        </nav>
      </div>
    </div>
  </nav><!-- #nav -->
</footer>


Solution

  • The issue is that without returning any value in the handleLink function, skrollr-menu will scroll to 0 on default. I fixed it by adding return null; at the end of the function.