Velocity - Scroll Hijacking

by Leon Freire

HTML

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.2/velocity.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.2/velocity.ui.min.js"></script>
<!-- hijacking: on/off - animation: none/scaleDown/rotate/gallery/catch/opacity/fixed/parallax -->

<body data-hijacking="on" data-animation="scaleDown">
  <section class="cd-section visible">
    <div>
      <h2>Page Scroll Effects</h2>
    </div>
  </section>

  <section class="cd-section">
    <div>
      <h2>Section 2</h2>
    </div>
  </section>

  <section class="cd-section">
    <div>
      <h2>Section 3</h2>
    </div>
  </section>

  <section class="cd-section">
    <div>
      <h2>Section 4</h2>
    </div>
  </section>

  <section class="cd-section">
    <div>
      <h2>Section 5</h2>
    </div>
  </section>

  <nav>
    <ul class="cd-vertical-nav">
      <li><a href="#0" class="cd-prev inactive">Next</a></li>
      <li><a href="#0" class="cd-next">Prev</a></li>
    </ul>
  </nav>
  <!-- .cd-vertical-nav -->
</body>

CSS

/* -------------------------------- 

Primary style

-------------------------------- */

*,
*::after,
*::before {
  box-sizing: border-box;
}

html {
  font-size: 62.5%;
}

body {
  font-size: 1.6rem;
  font-family: "Open Sans", sans-serif;
  color: #ffffff;
  background-color: #22283f;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body::before {
  /* never visible - this is used in jQuery to check the current MQ */
  content: 'mobile';
  display: none;
}

@media only screen and (min-width: 1050px) {
  body::before {
    /* never visible - this is used in jQuery to check the current MQ */
    content: 'desktop';
  }
}

a {
  color: #267481;
  text-decoration: none;
}


/* -------------------------------- 

Main Components 

-------------------------------- */

@media only screen and (min-width: 1050px) {
  body[data-hijacking="on"] {
    overflow: hidden;
  }
}

.cd-section {
  height: 100vh;
}

.cd-section h2 {
  line-height: 100vh;
  text-align: center;
  font-size: 2.4rem;
}

.cd-section:first-of-type > div {
  background-color: #2b334f;
}

.cd-section:first-of-type > div::before {
  /* alert -> all scrolling effects are not visible on small devices */
  content: 'Effects not visible on mobile!';
  position: absolute;
  width: 100%;
  text-align: center;
  top: 20px;
  z-index: 2;
  font-weight: bold;
  font-size: 1.3rem;
  text-transform: uppercase;
  color: #6a7083;
}

.cd-section:nth-of-type(2) > div {
  background-color: #2e5367;
}

.cd-section:nth-of-type(3) > div {
  background-color: #267481;
}

.cd-section:nth-of-type(4) > div {
  background-color: #fcb052;
}

.cd-section:nth-of-type(5) > div {
  background-color: #f06a59;
}

[data-animation="parallax"] .cd-section > div,
[data-animation="fixed"] .cd-section > div,
[data-animation="opacity"] .cd-section > div {
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
}

[data-animation="parallax"] .cd-section:first-of-type >...

JavaScript

jQuery(document).ready(function($) {
  //variables
  var hijacking = $('body').data('hijacking'),
    animationType = $('body').data('animation'),
    delta = 0,
    scrollThreshold = 5,
    actual = 1,
    animating = false;

  //DOM elements
  var sectionsAvailable = $('.cd-section'),
    verticalNav = $('.cd-vertical-nav'),
    prevArrow = verticalNav.find('a.cd-prev'),
    nextArrow = verticalNav.find('a.cd-next');


  //check the media query and bind corresponding events
  var MQ = deviceType(),
    bindToggle = false;

  bindEvents(MQ, true);

  $(window).on('resize', function() {
    MQ = deviceType();
    bindEvents(MQ, bindToggle);
    if (MQ == 'mobile') bindToggle = true;
    if (MQ == 'desktop') bindToggle = false;
  });

  function bindEvents(MQ, bool) {

    if (MQ == 'desktop' && bool) {
      //bind the animation to the window scroll event, arrows click and keyboard
      if (hijacking == 'on') {
        initHijacking();
        $(window).on('DOMMouseScroll mousewheel', scrollHijacking);
      } else {
        scrollAnimation();
        $(window).on('scroll', scrollAnimation);
      }
      prevArrow.on('click', prevSection);
      nextArrow.on('click', nextSection);

      $(document).on('keydown', function(event) {
        if (event.which == '40' && !nextArrow.hasClass('inactive')) {
          event.preventDefault();
          nextSection();
        } else if (event.which == '38' && (!prevArrow.hasClass('inactive') || (prevArrow.hasClass('inactive') && $(window).scrollTop() != sectionsAvailable.eq(0).offset().top))) {
          event.preventDefault();
          prevSection();
        }
      });
      //set navigation arrows visibility
      checkNavigation();
    } else if (MQ == 'mobile') {
      //reset and unbind
      resetSectionStyle();
      $(window).off('DOMMouseScroll mousewheel', scrollHijacking);
      $(window).off('scroll', scrollAnimation);
      prevArrow.off('click', prevSection);
      nextArrow.off('click', nextSection);
    ...