SOCIALIZE IT

Thursday 26 February 2015

Parallax Scroling...

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Parallax</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width; initial-scale=1.0, user-scalable=no,  maximum-scale=1.0">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="stylesheet" href="css/bootstrap.css" />

<style>
body, html {
height: 100%;
min-height: 100%;
}
/*---------------------- Banner -------------------------*/
section.hero {
    padding: 100px 0;
}
.banner {
    background-image: url("../images/banner.jpg");
    background-size: auto 100%;
    min-height: 100px;
    transition: all 1ms linear 0s;
    width: 100%;
}
/*---------------------- Banner End -------------------------*/
article {
    float: left;
    margin: 50px auto 0;
    width: 100%;
}
.loading {
background: url('../img/ico_loading.gif') no-repeat center center;
}
.no-js {
padding-top: 106px;
}
.loaded section, .no-js section {
opacity: 1;
-webkit-transition: opacity 300ms ease-out;
-moz-transition: opacity 300ms ease-out;
transition: opacity 300ms ease-out;
}
main {
overflow-x: hidden;
}
#preload {
width: 1px;
height: 1px;
overflow: hidden;
position: absolute;
top: 0;
left: 0;
}
.bcg {
    background-attachment: fixed;
    background-position: center center;
    background-repeat: no-repeat;
    background-size: cover;
    height: 100%;
    width: 100%;
}

.fixbg {
    background-attachment: fixed;
    background-position: center center;
    background-size: cover;
    color: #fff;
}
.hsContainer { padding: 50px 0px; }
/* Slide 1 */
#section1 .bcg {
    background-image: url("../images/section1bg.jpg"); }

/* Slide 2 */
#slide-2 .hsContent { }

/* Slide 3 */
#section3 .bcg { background-image: url("../images/section1bg.jpg"); }

/* Slide 4 */
#slide-4 .hsContent {  }
 </style>            


</head>

<body>
<!-- Start Loader -->
<div class="loader-start"></div>
<!-- End Loader -->
<div>


<nav class="navbar navbar-default navbar-fixed-top">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
   
        </div>
        <div id="navbar" class="navbar-collapse collapse">
       
          <div class="pull-left logo">
   <a data-scroll="section0" href="#">Project name</a>
 </div>
         
          <ul class="nav navbar-nav navbar-right">
<li><a href="#" data-scroll="section1">What is FaceCandi?</a></li>
<li><a href="#" data-scroll="section2">So What?</a></li>
<li><a href="#" data-scroll="section3">Benefits</a></li>
<li><a href="#" data-scroll="section4">Who Is It For?</a></li>
          </ul>
        </div><!--/.nav-collapse -->
      </div>
</nav>


<article>
<section  class="hero banner" data-anchor="section0">
<div class="container">
<div class="col-md-12">
Banner text

</div>
 </div>
  </section>

<section class="section1 fixbg homeSlide" id="section1" data-anchor="section1">
<div class="bcg" data-center="background-position: 50% 0px;" data-top-bottom="background-position: 50% -200px;" data-anchor-target="#section1">
<div class="hsContainer container">
<div class="row">
<div class="hsContent col-md-7" data--20-bottom="opacity: 0;" data--100-bottom="opacity: 1;" data--150-center="opacity: 1" data--400-top="opacity: 0" data-anchor-target="#section1 h2">
  <h2>WHAT IS FACECANDI?</h2>
<p><span>Connect</span> with <span>customers</span> in a way that <span>competitors cannot.</span></p>

<p class="with_mng">Be the <span>relief</span> to when customers  - all of us really -
scream in our own heads  <span>"CAN I JUST PLEASE GET A
HUMAN BEING TO HELP ME</span> make my purchase
or resolve my problem?!”</p>
<p class="with_mng2">
<span>Woo</span> your customers with <span>human warmth</span> and
<span>competence</span>, and in return they will <span>wow</span> you with relationships of <span>trust</span> and <span>loyalty.</span>
</p>
  </div>
</div>
</div>
</div>
</section>

<section class="section2" id="section2" data-anchor="section2" style="min-height: 250px;">
<div class="container">
<h2>so what? <i class="bottom_line"></i></h2>
</div>
</section>

<section class="section3 fixbg homeSlide" id="section3" data-anchor="section3">
<div class="bcg" data-center="background-position: 50% 0px;" data-top-bottom="background-position: 50% -200px;" data-anchor-target="#section3">
<div class="hsContainer container">
<div class="row">
<div class="col-md-12">
<h2>Benefits</h2>
<p><span>Connect</span> with <span>customers</span> in a way that <span>competitors cannot.</span></p>

<p class="with_mng">Be the <span>relief</span> to when customers  - all of us really -
scream in our own heads  <span>"CAN I JUST PLEASE GET A
HUMAN BEING TO HELP ME</span> make my purchase
or resolve my problem?!”</p>
<p class="with_mng2">
<span>Woo</span> your customers with <span>human warmth</span> and
<span>competence</span>, and in return they will <span>wow</span> you with relationships of <span>trust</span> and <span>loyalty.</span>
</p>
</div>
</div>
</div>
</div>
</section>

<section class="section4" id="section4" data-anchor="section4" style="min-height: 250px;">
<div class="container">
<h2>so what? <i class="bottom_line"></i></h2>
</div>
</section>

</article>

<footer>
<div class="container">
<p>
Be the to when customers <br /> - all of us really - scream in <br />our own heads "CAN I JUST PLEASE <br />GET A  HUMAN BEING TO HELP<br /> ME make my purchase or resolve my problem?!”
Be the to when customers <br /> - all of us really - scream in <br />
Be the to when customers <br /> - all of us really - scream in <br />
</p>
</div>
</footer>
</div>
</body>

<script src="js/jquery-1.11.1.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/custem.js"></script>
<script src="js/imagesloaded.js"></script>  <!-- ---- paralax js --- -->
  <script src="js/skrollr.js"></script> <!-- ---- paralax js --- -->
  <script src="js/main.js"></script> <!-- ---- paralax js --- -->

</html>

---------------------------------------custem.js-------------------------------------------------
$(document).ready(function(){

(function($) {

            var x = 0;
            var y = 0;
            //cache a reference to the banner
            var banner = $(".banner");

            // set initial banner background position
            banner.css('backgroundPosition', x + 'px' + ' ' + y + 'px');

            // scroll up background position every 90 milliseconds
            window.setInterval(function() {
                banner.css("backgroundPosition", x + 'px' + ' ' + y + 'px');
               // y--;
                x--;

                //if you need to scroll image horizontally -
                // uncomment x and comment y

            }, 90);

})(jQuery);



$('#navbar ul li a, .ftr-lnk li a, .banner_arw a, .logo a').on('click', function() {

    var scrollAnchor = $(this).attr('data-scroll'),
        scrollPoint = $('section[data-anchor="' + scrollAnchor + '"]').offset().top - 50;

    $('body,html').animate({
        scrollTop: scrollPoint
    }, 550);

    return false;

})


$(window).scroll(function() {
    var windscroll = $(window).scrollTop();
    if (windscroll >= 50) {
     
        $('section').each(function(i) {
            if ($(this).position().top <= windscroll - 20) {
                $('.nav li.active').removeClass('active');
                $('.nav li').eq(i).addClass('active');
            }
        });

    } else {

   
        $('.nav li.active').removeClass('active');
               // $('.nav a:first').addClass('active');
    }

}).scroll();


});
// $('#myModal').on('show.bs.modal', function (e) {
// $('.modal-body').scrollTop();
// })

$('#myModal').on('shown.bs.modal', function () {
    var html = $(this).children().children().children(".modal-body").scrollTop(0);
});

$('#myModal2').on('shown.bs.modal', function () {
    var html = $(this).children().children().children(".modal-body").scrollTop(0);
});

$(document).ready(function(){
$('.menu-icn').click(function(){
// event.stopPropagation();
  $(this).parent().find('.mobilemenu').toggleClass('menu-opn');
  $(this).parent().find('.mobilemenu').parent().toggleClass('heightfix');
});

if(parseInt($(window).width()) < 768){
var h = parseInt($(window).height());
if(h<480){
$('.modal-body').css('height', h-130);
}
else{
$('.modal-body').css('height', h-100);
}

}
if(parseInt($(window).width()) > 1199)
    {
  $('.mobilemenu li a').click(function(){
  $('.mobilemenu li a').removeClass('');
  $(this).addClass('');
 })
if($('.menu').hasClass('mobilemenu')){
$('.menu').removeClass('mobilemenu').addClass('mainmenu');
}
else{
$('.menu').addClass('mainmenu');
}
    }
else if(parseInt($(window).width()) < 1199){

if($('.menu').hasClass('mainmenu')){
$('.menu').removeClass('mainmenu').addClass('mobilemenu');
}
else{
$('.menu').addClass('mobilemenu');
}

 
}
});

$(window).bind( "orientationchange resize", function( event ) {
if(parseInt($(window).width()) < 768){
var h = parseInt($(window).height());
if(h<480){
$('.modal-body').css('height', h-130);
}
else{
$('.modal-body').css('height', h-100);
}

}
if(parseInt($(window).width()) > 1199)
    {
  $('.mobilemenu li a').click(function(){
  $('.mobilemenu li a').removeClass('');
  $(this).addClass('');
 })
if($('.menu').hasClass('mobilemenu')){
$('.menu').removeClass('mobilemenu').addClass('mainmenu');
}
else{
$('.menu').addClass('mainmenu');
}
    }
else if(parseInt($(window).width()) < 1199){

if($('.menu').hasClass('mainmenu')){
$('.menu').removeClass('mainmenu').addClass('mobilemenu');
}
else{
$('.menu').addClass('mobilemenu');
}

 
}
});


$(document).ready(function(){
$('.mobilemenu li a').click(function(){
$('.mobilemenu').removeClass( "menu-opn" );
});


});
--------------------------------------custem.js end----------------------------------------
-------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------
---------------------------------------imagesloaded.js-------------------------------------

(function () {

function EventEmitter() {}

// Shortcuts to improve speed and size

// Easy access to the prototype
var proto = EventEmitter.prototype;

function indexOfListener(listeners, listener) {
var i = listeners.length;
while (i--) {
if (listeners[i].listener === listener) {
return i;
}
}

return -1;
}

function alias(name) {
return function aliasClosure() {
return this[name].apply(this, arguments);
};
}
proto.getListeners = function getListeners(evt) {
var events = this._getEvents();
var response;
var key;

// Return a concatenated array of all matching events if
// the selector is a regular expression.
if (typeof evt === 'object') {
response = {};
for (key in events) {
if (events.hasOwnProperty(key) && evt.test(key)) {
response[key] = events[key];
}
}
}
else {
response = events[evt] || (events[evt] = []);
}

return response;
};

proto.flattenListeners = function flattenListeners(listeners) {
var flatListeners = [];
var i;

for (i = 0; i < listeners.length; i += 1) {
flatListeners.push(listeners[i].listener);
}

return flatListeners;
};

proto.getListenersAsObject = function getListenersAsObject(evt) {
var listeners = this.getListeners(evt);
var response;

if (listeners instanceof Array) {
response = {};
response[evt] = listeners;
}

return response || listeners;
};

proto.addListener = function addListener(evt, listener) {
var listeners = this.getListenersAsObject(evt);
var listenerIsWrapped = typeof listener === 'object';
var key;

for (key in listeners) {
if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
listeners[key].push(listenerIsWrapped ? listener : {
listener: listener,
once: false
});
}
}

return this;
};

proto.on = alias('addListener');

proto.addOnceListener = function addOnceListener(evt, listener) {
return this.addListener(evt, {
listener: listener,
once: true
});
};

proto.once = alias('addOnceListener');

proto.defineEvent = function defineEvent(evt) {
this.getListeners(evt);
return this;
};

proto.defineEvents = function defineEvents(evts) {
for (var i = 0; i < evts.length; i += 1) {
this.defineEvent(evts[i]);
}
return this;
};


proto.removeListener = function removeListener(evt, listener) {
var listeners = this.getListenersAsObject(evt);
var index;
var key;

for (key in listeners) {
if (listeners.hasOwnProperty(key)) {
index = indexOfListener(listeners[key], listener);

if (index !== -1) {
listeners[key].splice(index, 1);
}
}
}

return this;
};

proto.off = alias('removeListener');

proto.addListeners = function addListeners(evt, listeners) {
// Pass through to manipulateListeners
return this.manipulateListeners(false, evt, listeners);
};

proto.removeListeners = function removeListeners(evt, listeners) {
// Pass through to manipulateListeners
return this.manipulateListeners(true, evt, listeners);
};

proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
var i;
var value;
var single = remove ? this.removeListener : this.addListener;
var multiple = remove ? this.removeListeners : this.addListeners;

// If evt is an object then pass each of it's properties to this method
if (typeof evt === 'object' && !(evt instanceof RegExp)) {
for (i in evt) {
if (evt.hasOwnProperty(i) && (value = evt[i])) {
// Pass the single listener straight through to the singular method
if (typeof value === 'function') {
single.call(this, i, value);
}
else {
// Otherwise pass back to the multiple function
multiple.call(this, i, value);
}
}
}
}
else {
// So evt must be a string
// And listeners must be an array of listeners
// Loop over it and pass each one to the multiple method
i = listeners.length;
while (i--) {
single.call(this, evt, listeners[i]);
}
}

return this;
};

proto.removeEvent = function removeEvent(evt) {
var type = typeof evt;
var events = this._getEvents();
var key;

// Remove different things depending on the state of evt
if (type === 'string') {
// Remove all listeners for the specified event
delete events[evt];
}
else if (type === 'object') {
// Remove all events matching the regex.
for (key in events) {
if (events.hasOwnProperty(key) && evt.test(key)) {
delete events[key];
}
}
}
else {
// Remove all listeners in all events
delete this._events;
}

return this;
};

proto.removeAllListeners = alias('removeEvent');

proto.emitEvent = function emitEvent(evt, args) {
var listeners = this.getListenersAsObject(evt);
var listener;
var i;
var key;
var response;

for (key in listeners) {
if (listeners.hasOwnProperty(key)) {
i = listeners[key].length;

while (i--) {
// If the listener returns true then it shall be removed from the event
// The function is executed either with a basic call or an apply if there is an args array
listener = listeners[key][i];

if (listener.once === true) {
this.removeListener(evt, listener.listener);
}

response = listener.listener.apply(this, args || []);

if (response === this._getOnceReturnValue()) {
this.removeListener(evt, listener.listener);
}
}
}
}

return this;
};

proto.trigger = alias('emitEvent');

proto.emit = function emit(evt) {
var args = Array.prototype.slice.call(arguments, 1);
return this.emitEvent(evt, args);
};

proto.setOnceReturnValue = function setOnceReturnValue(value) {
this._onceReturnValue = value;
return this;
};

proto._getOnceReturnValue = function _getOnceReturnValue() {
if (this.hasOwnProperty('_onceReturnValue')) {
return this._onceReturnValue;
}
else {
return true;
}
};

proto._getEvents = function _getEvents() {
return this._events || (this._events = {});
};

// Expose the class either via AMD, CommonJS or the global object
if (typeof define === 'function' && define.amd) {
define('eventEmitter/EventEmitter',[],function () {
return EventEmitter;
});
}
else if (typeof module === 'object' && module.exports){
module.exports = EventEmitter;
}
else {
this.EventEmitter = EventEmitter;
}
}.call(this));


( function( window ) {



var docElem = document.documentElement;

var bind = function() {};

if ( docElem.addEventListener ) {
  bind = function( obj, type, fn ) {
    obj.addEventListener( type, fn, false );
  };
} else if ( docElem.attachEvent ) {
  bind = function( obj, type, fn ) {
    obj[ type + fn ] = fn.handleEvent ?
      function() {
        var event = window.event;
        // add event.target
        event.target = event.target || event.srcElement;
        fn.handleEvent.call( fn, event );
      } :
      function() {
        var event = window.event;
        // add event.target
        event.target = event.target || event.srcElement;
        fn.call( obj, event );
      };
    obj.attachEvent( "on" + type, obj[ type + fn ] );
  };
}

var unbind = function() {};

if ( docElem.removeEventListener ) {
  unbind = function( obj, type, fn ) {
    obj.removeEventListener( type, fn, false );
  };
} else if ( docElem.detachEvent ) {
  unbind = function( obj, type, fn ) {
    obj.detachEvent( "on" + type, obj[ type + fn ] );
    try {
      delete obj[ type + fn ];
    } catch ( err ) {
      // can't delete window object properties
      obj[ type + fn ] = undefined;
    }
  };
}

var eventie = {
  bind: bind,
  unbind: unbind
};

// transport
if ( typeof define === 'function' && define.amd ) {
  // AMD
  define( 'eventie/eventie',eventie );
} else {
  // browser global
  window.eventie = eventie;
}

})( this );

/*!
 * imagesLoaded v3.0.4
 * JavaScript is all like "You images are done yet or what?"
 * MIT License
 */

( function( window ) {



var $ = window.jQuery;
var console = window.console;
var hasConsole = typeof console !== 'undefined';

// -------------------------- helpers -------------------------- //

// extend objects
function extend( a, b ) {
  for ( var prop in b ) {
    a[ prop ] = b[ prop ];
  }
  return a;
}

var objToString = Object.prototype.toString;
function isArray( obj ) {
  return objToString.call( obj ) === '[object Array]';
}

// turn element or nodeList into an array
function makeArray( obj ) {
  var ary = [];
  if ( isArray( obj ) ) {
    // use object if already an array
    ary = obj;
  } else if ( typeof obj.length === 'number' ) {
    // convert nodeList to array
    for ( var i=0, len = obj.length; i < len; i++ ) {
      ary.push( obj[i] );
    }
  } else {
    // array of single index
    ary.push( obj );
  }
  return ary;
}

// --------------------------  -------------------------- //

function defineImagesLoaded( EventEmitter, eventie ) {


  function ImagesLoaded( elem, options, onAlways ) {
    // coerce ImagesLoaded() without new, to be new ImagesLoaded()
    if ( !( this instanceof ImagesLoaded ) ) {
      return new ImagesLoaded( elem, options );
    }
    // use elem as selector string
    if ( typeof elem === 'string' ) {
      elem = document.querySelectorAll( elem );
    }

    this.elements = makeArray( elem );
    this.options = extend( {}, this.options );

    if ( typeof options === 'function' ) {
      onAlways = options;
    } else {
      extend( this.options, options );
    }

    if ( onAlways ) {
      this.on( 'always', onAlways );
    }

    this.getImages();

    if ( $ ) {
      // add jQuery Deferred object
      this.jqDeferred = new $.Deferred();
    }

    // HACK check async to allow time to bind listeners
    var _this = this;
    setTimeout( function() {
      _this.check();
    });
  }

  ImagesLoaded.prototype = new EventEmitter();

  ImagesLoaded.prototype.options = {};

  ImagesLoaded.prototype.getImages = function() {
    this.images = [];

    // filter & find items if we have an item selector
    for ( var i=0, len = this.elements.length; i < len; i++ ) {
      var elem = this.elements[i];
      // filter siblings
      if ( elem.nodeName === 'IMG' ) {
        this.addImage( elem );
      }
      // find children
      var childElems = elem.querySelectorAll('img');
      // concat childElems to filterFound array
      for ( var j=0, jLen = childElems.length; j < jLen; j++ ) {
        var img = childElems[j];
        this.addImage( img );
      }
    }
  };


  ImagesLoaded.prototype.addImage = function( img ) {
    var loadingImage = new LoadingImage( img );
    this.images.push( loadingImage );
  };

  ImagesLoaded.prototype.check = function() {
    var _this = this;
    var checkedCount = 0;
    var length = this.images.length;
    this.hasAnyBroken = false;
    // complete if no images
    if ( !length ) {
      this.complete();
      return;
    }

    function onConfirm( image, message ) {
      if ( _this.options.debug && hasConsole ) {
        console.log( 'confirm', image, message );
      }

      _this.progress( image );
      checkedCount++;
      if ( checkedCount === length ) {
        _this.complete();
      }
      return true; // bind once
    }

    for ( var i=0; i < length; i++ ) {
      var loadingImage = this.images[i];
      loadingImage.on( 'confirm', onConfirm );
      loadingImage.check();
    }
  };

  ImagesLoaded.prototype.progress = function( image ) {
    this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
    // HACK - Chrome triggers event before object properties have changed. #83
    var _this = this;
    setTimeout( function() {
      _this.emit( 'progress', _this, image );
      if ( _this.jqDeferred ) {
        _this.jqDeferred.notify( _this, image );
      }
    });
  };

  ImagesLoaded.prototype.complete = function() {
    var eventName = this.hasAnyBroken ? 'fail' : 'done';
    this.isComplete = true;
    var _this = this;
    // HACK - another setTimeout so that confirm happens after progress
    setTimeout( function() {
      _this.emit( eventName, _this );
      _this.emit( 'always', _this );
      if ( _this.jqDeferred ) {
        var jqMethod = _this.hasAnyBroken ? 'reject' : 'resolve';
        _this.jqDeferred[ jqMethod ]( _this );
      }
    });
  };

  // -------------------------- jquery -------------------------- //

  if ( $ ) {
    $.fn.imagesLoaded = function( options, callback ) {
      var instance = new ImagesLoaded( this, options, callback );
      return instance.jqDeferred.promise( $(this) );
    };
  }


  // --------------------------  -------------------------- //

  var cache = {};

  function LoadingImage( img ) {
    this.img = img;
  }

  LoadingImage.prototype = new EventEmitter();

  LoadingImage.prototype.check = function() {
    // first check cached any previous images that have same src
    var cached = cache[ this.img.src ];
    if ( cached ) {
      this.useCached( cached );
      return;
    }
    // add this to cache
    cache[ this.img.src ] = this;

    // If complete is true and browser supports natural sizes,
    // try to check for image status manually.
    if ( this.img.complete && this.img.naturalWidth !== undefined ) {
      // report based on naturalWidth
      this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
      return;
    }

    // If none of the checks above matched, simulate loading on detached element.
    var proxyImage = this.proxyImage = new Image();
    eventie.bind( proxyImage, 'load', this );
    eventie.bind( proxyImage, 'error', this );
    proxyImage.src = this.img.src;
  };

  LoadingImage.prototype.useCached = function( cached ) {
    if ( cached.isConfirmed ) {
      this.confirm( cached.isLoaded, 'cached was confirmed' );
    } else {
      var _this = this;
      cached.on( 'confirm', function( image ) {
        _this.confirm( image.isLoaded, 'cache emitted confirmed' );
        return true; // bind once
      });
    }
  };

  LoadingImage.prototype.confirm = function( isLoaded, message ) {
    this.isConfirmed = true;
    this.isLoaded = isLoaded;
    this.emit( 'confirm', this, message );
  };

  // trigger specified handler for event type
  LoadingImage.prototype.handleEvent = function( event ) {
    var method = 'on' + event.type;
    if ( this[ method ] ) {
      this[ method ]( event );
    }
  };

  LoadingImage.prototype.onload = function() {
    this.confirm( true, 'onload' );
    this.unbindProxyEvents();
  };

  LoadingImage.prototype.onerror = function() {
    this.confirm( false, 'onerror' );
    this.unbindProxyEvents();
  };

  LoadingImage.prototype.unbindProxyEvents = function() {
    eventie.unbind( this.proxyImage, 'load', this );
    eventie.unbind( this.proxyImage, 'error', this );
  };

  // -----  ----- //

  return ImagesLoaded;
}

// -------------------------- transport -------------------------- //

if ( typeof define === 'function' && define.amd ) {
  // AMD
  define( [
      'eventEmitter/EventEmitter',
      'eventie/eventie'
    ],
    defineImagesLoaded );
} else {
  // browser global
  window.imagesLoaded = defineImagesLoaded(
    window.EventEmitter,
    window.eventie
  );
}

})( window );

---------------------------------------imagesloaded.js END-------------------------------------
--------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------
---------------------------------------skrollr.js--------------------------------------------

/*!
 * skrollr core
 *
 * Alexander Prinzhorn - https://github.com/Prinzhorn/skrollr
 *
 * Free to use under terms of MIT license
 */
(function(window, document, undefined) {
'use strict';

/*
* Global api.
*/
var skrollr = window.skrollr = {
get: function() {
return _instance;
},
//Main entry point.
init: function(options) {
return _instance || new Skrollr(options);
},
VERSION: '0.6.21'
};

//Minify optimization.
var hasProp = Object.prototype.hasOwnProperty;
var Math = window.Math;
var getStyle = window.getComputedStyle;

//They will be filled when skrollr gets initialized.
var documentElement;
var body;

var EVENT_TOUCHSTART = 'touchstart';
var EVENT_TOUCHMOVE = 'touchmove';
var EVENT_TOUCHCANCEL = 'touchcancel';
var EVENT_TOUCHEND = 'touchend';

var SKROLLABLE_CLASS = 'skrollable';
var SKROLLABLE_BEFORE_CLASS = SKROLLABLE_CLASS + '-before';
var SKROLLABLE_BETWEEN_CLASS = SKROLLABLE_CLASS + '-between';
var SKROLLABLE_AFTER_CLASS = SKROLLABLE_CLASS + '-after';

var SKROLLR_CLASS = 'skrollr';
var NO_SKROLLR_CLASS = 'no-' + SKROLLR_CLASS;
var SKROLLR_DESKTOP_CLASS = SKROLLR_CLASS + '-desktop';
var SKROLLR_MOBILE_CLASS = SKROLLR_CLASS + '-mobile';

var DEFAULT_EASING = 'linear';
var DEFAULT_DURATION = 1000;//ms
var DEFAULT_MOBILE_DECELERATION = 0.004;//pixel/ms²

var DEFAULT_SMOOTH_SCROLLING_DURATION = 200;//ms

var ANCHOR_START = 'start';
var ANCHOR_END = 'end';
var ANCHOR_CENTER = 'center';
var ANCHOR_BOTTOM = 'bottom';

//The property which will be added to the DOM element to hold the ID of the skrollable.
var SKROLLABLE_ID_DOM_PROPERTY = '___skrollable_id';

var rxTouchIgnoreTags = /^(?:input|textarea|button|select)$/i;

var rxTrim = /^\s+|\s+$/g;

//Find all data-attributes. data-[_constant]-[offset]-[anchor]-[anchor].
var rxKeyframeAttribute = /^data(?:-(_\w+))?(?:-?(-?\d*\.?\d+p?))?(?:-?(start|end|top|center|bottom))?(?:-?(top|center|bottom))?$/;

var rxPropValue = /\s*([\w\-\[\]]+)\s*:\s*(.+?)\s*(?:;|$)/gi;

//Easing function names follow the property in square brackets.
var rxPropEasing = /^([a-z\-]+)\[(\w+)\]$/;

var rxCamelCase = /-([a-z])/g;
var rxCamelCaseFn = function(str, letter) {
return letter.toUpperCase();
};

//Numeric values with optional sign.
var rxNumericValue = /[\-+]?[\d]*\.?[\d]+/g;

//Used to replace occurences of {?} with a number.
var rxInterpolateString = /\{\?\}/g;

//Finds rgb(a) colors, which don't use the percentage notation.
var rxRGBAIntegerColor = /rgba?\(\s*-?\d+\s*,\s*-?\d+\s*,\s*-?\d+/g;

//Finds all gradients.
var rxGradient = /[a-z\-]+-gradient/g;

//Vendor prefix. Will be set once skrollr gets initialized.
var theCSSPrefix = '';
var theDashedCSSPrefix = '';

//Will be called once (when skrollr gets initialized).
var detectCSSPrefix = function() {
//Only relevant prefixes. May be extended.
//Could be dangerous if there will ever be a CSS property which actually starts with "ms". Don't hope so.
var rxPrefixes = /^(?:O|Moz|webkit|ms)|(?:-(?:o|moz|webkit|ms)-)/;

//Detect prefix for current browser by finding the first property using a prefix.
if(!getStyle) {
return;
}

var style = getStyle(body, null);

for(var k in style) {
//We check the key and if the key is a number, we check the value as well, because safari's getComputedStyle returns some weird array-like thingy.
theCSSPrefix = (k.match(rxPrefixes) || (+k == k && style[k].match(rxPrefixes)));

if(theCSSPrefix) {
break;
}
}

//Did we even detect a prefix?
if(!theCSSPrefix) {
theCSSPrefix = theDashedCSSPrefix = '';

return;
}

theCSSPrefix = theCSSPrefix[0];

//We could have detected either a dashed prefix or this camelCaseish-inconsistent stuff.
if(theCSSPrefix.slice(0,1) === '-') {
theDashedCSSPrefix = theCSSPrefix;

//There's no logic behind these. Need a look up.
theCSSPrefix = ({
'-webkit-': 'webkit',
'-moz-': 'Moz',
'-ms-': 'ms',
'-o-': 'O'
})[theCSSPrefix];
} else {
theDashedCSSPrefix = '-' + theCSSPrefix.toLowerCase() + '-';
}
};

var polyfillRAF = function() {
var requestAnimFrame = window.requestAnimationFrame || window[theCSSPrefix.toLowerCase() + 'RequestAnimationFrame'];

var lastTime = _now();

if(_isMobile || !requestAnimFrame) {
requestAnimFrame = function(callback) {
//How long did it take to render?
var deltaTime = _now() - lastTime;
var delay = Math.max(0, 1000 / 60 - deltaTime);

return window.setTimeout(function() {
lastTime = _now();
callback();
}, delay);
};
}

return requestAnimFrame;
};

var polyfillCAF = function() {
var cancelAnimFrame = window.cancelAnimationFrame || window[theCSSPrefix.toLowerCase() + 'CancelAnimationFrame'];

if(_isMobile || !cancelAnimFrame) {
cancelAnimFrame = function(timeout) {
return window.clearTimeout(timeout);
};
}

return cancelAnimFrame;
};

//Built-in easing functions.
var easings = {
begin: function() {
return 0;
},
end: function() {
return 1;
},
linear: function(p) {
return p;
},
quadratic: function(p) {
return p * p;
},
cubic: function(p) {
return p * p * p;
},
swing: function(p) {
return (-Math.cos(p * Math.PI) / 2) + 0.5;
},
sqrt: function(p) {
return Math.sqrt(p);
},
outCubic: function(p) {
return (Math.pow((p - 1), 3) + 1);
},
//see https://www.desmos.com/calculator/tbr20s8vd2 for how I did this
bounce: function(p) {
var a;

if(p <= 0.5083) {
a = 3;
} else if(p <= 0.8489) {
a = 9;
} else if(p <= 0.96208) {
a = 27;
} else if(p <= 0.99981) {
a = 91;
} else {
return 1;
}

return 1 - Math.abs(3 * Math.cos(p * a * 1.028) / a);
}
};

/**
* Constructor.
*/
function Skrollr(options) {
documentElement = document.documentElement;
body = document.body;

detectCSSPrefix();

_instance = this;

options = options || {};

_constants = options.constants || {};

//We allow defining custom easings or overwrite existing.
if(options.easing) {
for(var e in options.easing) {
easings[e] = options.easing[e];
}
}

_edgeStrategy = options.edgeStrategy || 'set';

_listeners = {
//Function to be called right before rendering.
beforerender: options.beforerender,

//Function to be called right after finishing rendering.
render: options.render
};

//forceHeight is true by default
_forceHeight = options.forceHeight !== false;

if(_forceHeight) {
_scale = options.scale || 1;
}

_mobileDeceleration = options.mobileDeceleration || DEFAULT_MOBILE_DECELERATION;

_smoothScrollingEnabled = options.smoothScrolling !== false;
_smoothScrollingDuration = options.smoothScrollingDuration || DEFAULT_SMOOTH_SCROLLING_DURATION;

//Dummy object. Will be overwritten in the _render method when smooth scrolling is calculated.
_smoothScrolling = {
targetTop: _instance.getScrollTop()
};

//A custom check function may be passed.
_isMobile = ((options.mobileCheck || function() {
return (/Android|iPhone|iPad|iPod|BlackBerry/i).test(navigator.userAgent || navigator.vendor || window.opera);
})());

if(_isMobile) {
_skrollrBody = document.getElementById('skrollr-body');

//Detect 3d transform if there's a skrollr-body (only needed for #skrollr-body).
if(_skrollrBody) {
_detect3DTransforms();
}

_initMobile();
_updateClass(documentElement, [SKROLLR_CLASS, SKROLLR_MOBILE_CLASS], [NO_SKROLLR_CLASS]);
} else {
_updateClass(documentElement, [SKROLLR_CLASS, SKROLLR_DESKTOP_CLASS], [NO_SKROLLR_CLASS]);
}

//Triggers parsing of elements and a first reflow.
_instance.refresh();

_addEvent(window, 'resize orientationchange', function() {
var width = documentElement.clientWidth;
var height = documentElement.clientHeight;

//Only reflow if the size actually changed (#271).
if(height !== _lastViewportHeight || width !== _lastViewportWidth) {
_lastViewportHeight = height;
_lastViewportWidth = width;

_requestReflow = true;
}
});

var requestAnimFrame = polyfillRAF();

//Let's go.
(function animloop(){
_render();
_animFrame = requestAnimFrame(animloop);
}());

return _instance;
}

/**
* (Re)parses some or all elements.
*/
Skrollr.prototype.refresh = function(elements) {
var elementIndex;
var elementsLength;
var ignoreID = false;

//Completely reparse anything without argument.
if(elements === undefined) {
//Ignore that some elements may already have a skrollable ID.
ignoreID = true;

_skrollables = [];
_skrollableIdCounter = 0;

elements = document.getElementsByTagName('*');
} else {
//We accept a single element or an array of elements.
elements = [].concat(elements);
}

elementIndex = 0;
elementsLength = elements.length;

for(; elementIndex < elementsLength; elementIndex++) {
var el = elements[elementIndex];
var anchorTarget = el;
var keyFrames = [];

//If this particular element should be smooth scrolled.
var smoothScrollThis = _smoothScrollingEnabled;

//The edge strategy for this particular element.
var edgeStrategy = _edgeStrategy;

if(!el.attributes) {
continue;
}

//Iterate over all attributes and search for key frame attributes.
var attributeIndex = 0;
var attributesLength = el.attributes.length;

for (; attributeIndex < attributesLength; attributeIndex++) {
var attr = el.attributes[attributeIndex];

if(attr.name === 'data-anchor-target') {
anchorTarget = document.querySelector(attr.value);

if(anchorTarget === null) {
throw 'Unable to find anchor target "' + attr.value + '"';
}

continue;
}

//Global smooth scrolling can be overridden by the element attribute.
if(attr.name === 'data-smooth-scrolling') {
smoothScrollThis = attr.value !== 'off';

continue;
}

//Global edge strategy can be overridden by the element attribute.
if(attr.name === 'data-edge-strategy') {
edgeStrategy = attr.value;

continue;
}

var match = attr.name.match(rxKeyframeAttribute);

if(match === null) {
continue;
}

var kf = {
props: attr.value,
//Point back to the element as well.
element: el
};

keyFrames.push(kf);

var constant = match[1];

if(constant) {
//Strip the underscore prefix.
kf.constant = constant.substr(1);
}

//Get the key frame offset.
var offset = match[2];

//Is it a percentage offset?
if(/p$/.test(offset)) {
kf.isPercentage = true;
kf.offset = (offset.slice(0, -1) | 0) / 100;
} else {
kf.offset = (offset | 0);
}

var anchor1 = match[3];

//If second anchor is not set, the first will be taken for both.
var anchor2 = match[4] || anchor1;

//"absolute" (or "classic") mode, where numbers mean absolute scroll offset.
if(!anchor1 || anchor1 === ANCHOR_START || anchor1 === ANCHOR_END) {
kf.mode = 'absolute';

//data-end needs to be calculated after all key frames are known.
if(anchor1 === ANCHOR_END) {
kf.isEnd = true;
} else if(!kf.isPercentage) {
//For data-start we can already set the key frame w/o calculations.
//#59: "scale" options should only affect absolute mode.
kf.offset = kf.offset * _scale;
}
}
//"relative" mode, where numbers are relative to anchors.
else {
kf.mode = 'relative';
kf.anchors = [anchor1, anchor2];
}
}

//Does this element have key frames?
if(!keyFrames.length) {
continue;
}

//Will hold the original style and class attributes before we controlled the element (see #80).
var styleAttr, classAttr;

var id;

if(!ignoreID && SKROLLABLE_ID_DOM_PROPERTY in el) {
//We already have this element under control. Grab the corresponding skrollable id.
id = el[SKROLLABLE_ID_DOM_PROPERTY];
styleAttr = _skrollables[id].styleAttr;
classAttr = _skrollables[id].classAttr;
} else {
//It's an unknown element. Asign it a new skrollable id.
id = (el[SKROLLABLE_ID_DOM_PROPERTY] = _skrollableIdCounter++);
styleAttr = el.style.cssText;
classAttr = _getClass(el);
}

_skrollables[id] = {
element: el,
styleAttr: styleAttr,
classAttr: classAttr,
anchorTarget: anchorTarget,
keyFrames: keyFrames,
smoothScrolling: smoothScrollThis,
edgeStrategy: edgeStrategy
};

_updateClass(el, [SKROLLABLE_CLASS], []);
}

//Reflow for the first time.
_reflow();

//Now that we got all key frame numbers right, actually parse the properties.
elementIndex = 0;
elementsLength = elements.length;

for(; elementIndex < elementsLength; elementIndex++) {
var sk = _skrollables[elements[elementIndex][SKROLLABLE_ID_DOM_PROPERTY]];

if(sk === undefined) {
continue;
}

//Parse the property string to objects
_parseProps(sk);

//Fill key frames with missing properties from left and right
_fillProps(sk);
}

return _instance;
};

/**
* Transform "relative" mode to "absolute" mode.
* That is, calculate anchor position and offset of element.
*/
Skrollr.prototype.relativeToAbsolute = function(element, viewportAnchor, elementAnchor) {
var viewportHeight = documentElement.clientHeight;
var box = element.getBoundingClientRect();
var absolute = box.top;

//#100: IE doesn't supply "height" with getBoundingClientRect.
var boxHeight = box.bottom - box.top;

if(viewportAnchor === ANCHOR_BOTTOM) {
absolute -= viewportHeight;
} else if(viewportAnchor === ANCHOR_CENTER) {
absolute -= viewportHeight / 2;
}

if(elementAnchor === ANCHOR_BOTTOM) {
absolute += boxHeight;
} else if(elementAnchor === ANCHOR_CENTER) {
absolute += boxHeight / 2;
}

//Compensate scrolling since getBoundingClientRect is relative to viewport.
absolute += _instance.getScrollTop();

return (absolute + 0.5) | 0;
};

/**
* Animates scroll top to new position.
*/
Skrollr.prototype.animateTo = function(top, options) {
options = options || {};

var now = _now();
var scrollTop = _instance.getScrollTop();

//Setting this to a new value will automatically cause the current animation to stop, if any.
_scrollAnimation = {
startTop: scrollTop,
topDiff: top - scrollTop,
targetTop: top,
duration: options.duration || DEFAULT_DURATION,
startTime: now,
endTime: now + (options.duration || DEFAULT_DURATION),
easing: easings[options.easing || DEFAULT_EASING],
done: options.done
};

//Don't queue the animation if there's nothing to animate.
if(!_scrollAnimation.topDiff) {
if(_scrollAnimation.done) {
_scrollAnimation.done.call(_instance, false);
}

_scrollAnimation = undefined;
}

return _instance;
};

/**
* Stops animateTo animation.
*/
Skrollr.prototype.stopAnimateTo = function() {
if(_scrollAnimation && _scrollAnimation.done) {
_scrollAnimation.done.call(_instance, true);
}

_scrollAnimation = undefined;
};

/**
* Returns if an animation caused by animateTo is currently running.
*/
Skrollr.prototype.isAnimatingTo = function() {
return !!_scrollAnimation;
};

Skrollr.prototype.setScrollTop = function(top, force) {
_forceRender = (force === true);

if(_isMobile) {
_mobileOffset = Math.min(Math.max(top, 0), _maxKeyFrame);
} else {
window.scrollTo(0, top);
}

return _instance;
};

Skrollr.prototype.getScrollTop = function() {
if(_isMobile) {
return _mobileOffset;
} else {
return window.pageYOffset || documentElement.scrollTop || body.scrollTop || 0;
}
};

Skrollr.prototype.getMaxScrollTop = function() {
return _maxKeyFrame;
};

Skrollr.prototype.on = function(name, fn) {
_listeners[name] = fn;

return _instance;
};

Skrollr.prototype.off = function(name) {
delete _listeners[name];

return _instance;
};

Skrollr.prototype.destroy = function() {
var cancelAnimFrame = polyfillCAF();
cancelAnimFrame(_animFrame);
_removeAllEvents();

_updateClass(documentElement, [NO_SKROLLR_CLASS], [SKROLLR_CLASS, SKROLLR_DESKTOP_CLASS, SKROLLR_MOBILE_CLASS]);

var skrollableIndex = 0;
var skrollablesLength = _skrollables.length;

for(; skrollableIndex < skrollablesLength; skrollableIndex++) {
_reset(_skrollables[skrollableIndex].element);
}

documentElement.style.overflow = body.style.overflow = 'auto';
documentElement.style.height = body.style.height = 'auto';

if(_skrollrBody) {
skrollr.setStyle(_skrollrBody, 'transform', 'none');
}

_instance = undefined;
_skrollrBody = undefined;
_listeners = undefined;
_forceHeight = undefined;
_maxKeyFrame = 0;
_scale = 1;
_constants = undefined;
_mobileDeceleration = undefined;
_direction = 'down';
_lastTop = -1;
_lastViewportWidth = 0;
_lastViewportHeight = 0;
_requestReflow = false;
_scrollAnimation = undefined;
_smoothScrollingEnabled = undefined;
_smoothScrollingDuration = undefined;
_smoothScrolling = undefined;
_forceRender = undefined;
_skrollableIdCounter = 0;
_edgeStrategy = undefined;
_isMobile = false;
_mobileOffset = 0;
_translateZ = undefined;
};

/*
Private methods.
*/

var _initMobile = function() {
var initialElement;
var initialTouchY;
var initialTouchX;
var currentElement;
var currentTouchY;
var currentTouchX;
var lastTouchY;
var deltaY;

var initialTouchTime;
var currentTouchTime;
var lastTouchTime;
var deltaTime;

_addEvent(documentElement, [EVENT_TOUCHSTART, EVENT_TOUCHMOVE, EVENT_TOUCHCANCEL, EVENT_TOUCHEND].join(' '), function(e) {
var touch = e.changedTouches[0];

currentElement = e.target;

//We don't want text nodes.
while(currentElement.nodeType === 3) {
currentElement = currentElement.parentNode;
}

currentTouchY = touch.clientY;
currentTouchX = touch.clientX;
currentTouchTime = e.timeStamp;

if(!rxTouchIgnoreTags.test(currentElement.tagName)) {
e.preventDefault();
}

switch(e.type) {
case EVENT_TOUCHSTART:
//The last element we tapped on.
if(initialElement) {
initialElement.blur();
}

_instance.stopAnimateTo();

initialElement = currentElement;

initialTouchY = lastTouchY = currentTouchY;
initialTouchX = currentTouchX;
initialTouchTime = currentTouchTime;

break;
case EVENT_TOUCHMOVE:
//Prevent default event on touchIgnore elements in case they don't have focus yet.
if(rxTouchIgnoreTags.test(currentElement.tagName) && document.activeElement !== currentElement) {
e.preventDefault();
}

deltaY = currentTouchY - lastTouchY;
deltaTime = currentTouchTime - lastTouchTime;

_instance.setScrollTop(_mobileOffset - deltaY, true);

lastTouchY = currentTouchY;
lastTouchTime = currentTouchTime;
break;
default:
case EVENT_TOUCHCANCEL:
case EVENT_TOUCHEND:
var distanceY = initialTouchY - currentTouchY;
var distanceX = initialTouchX - currentTouchX;
var distance2 = distanceX * distanceX + distanceY * distanceY;

//Check if it was more like a tap (moved less than 7px).
if(distance2 < 49) {
if(!rxTouchIgnoreTags.test(initialElement.tagName)) {
initialElement.focus();

//It was a tap, click the element.
var clickEvent = document.createEvent('MouseEvents');
clickEvent.initMouseEvent('click', true, true, e.view, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, 0, null);
initialElement.dispatchEvent(clickEvent);
}

return;
}

initialElement = undefined;

var speed = deltaY / deltaTime;

//Cap speed at 3 pixel/ms.
speed = Math.max(Math.min(speed, 3), -3);

var duration = Math.abs(speed / _mobileDeceleration);
var targetOffset = speed * duration + 0.5 * _mobileDeceleration * duration * duration;
var targetTop = _instance.getScrollTop() - targetOffset;

//Relative duration change for when scrolling above bounds.
var targetRatio = 0;

//Change duration proportionally when scrolling would leave bounds.
if(targetTop > _maxKeyFrame) {
targetRatio = (_maxKeyFrame - targetTop) / targetOffset;

targetTop = _maxKeyFrame;
} else if(targetTop < 0) {
targetRatio = -targetTop / targetOffset;

targetTop = 0;
}

duration = duration * (1 - targetRatio);

_instance.animateTo((targetTop + 0.5) | 0, {easing: 'outCubic', duration: duration});
break;
}
});

//Just in case there has already been some native scrolling, reset it.
window.scrollTo(0, 0);
documentElement.style.overflow = body.style.overflow = 'hidden';
};

/**
* Updates key frames which depend on others / need to be updated on resize.
* That is "end" in "absolute" mode and all key frames in "relative" mode.
* Also handles constants, because they may change on resize.
*/
var _updateDependentKeyFrames = function() {
var viewportHeight = documentElement.clientHeight;
var processedConstants = _processConstants();
var skrollable;
var element;
var anchorTarget;
var keyFrames;
var keyFrameIndex;
var keyFramesLength;
var kf;
var skrollableIndex;
var skrollablesLength;
var offset;
var constantValue;

//First process all relative-mode elements and find the max key frame.
skrollableIndex = 0;
skrollablesLength = _skrollables.length;

for(; skrollableIndex < skrollablesLength; skrollableIndex++) {
skrollable = _skrollables[skrollableIndex];
element = skrollable.element;
anchorTarget = skrollable.anchorTarget;
keyFrames = skrollable.keyFrames;

keyFrameIndex = 0;
keyFramesLength = keyFrames.length;

for(; keyFrameIndex < keyFramesLength; keyFrameIndex++) {
kf = keyFrames[keyFrameIndex];

offset = kf.offset;
constantValue = processedConstants[kf.constant] || 0;

kf.frame = offset;

if(kf.isPercentage) {
//Convert the offset to percentage of the viewport height.
offset = offset * viewportHeight;

//Absolute + percentage mode.
kf.frame = offset;
}

if(kf.mode === 'relative') {
_reset(element);

kf.frame = _instance.relativeToAbsolute(anchorTarget, kf.anchors[0], kf.anchors[1]) - offset;

_reset(element, true);
}

kf.frame += constantValue;

//Only search for max key frame when forceHeight is enabled.
if(_forceHeight) {
//Find the max key frame, but don't use one of the data-end ones for comparison.
if(!kf.isEnd && kf.frame > _maxKeyFrame) {
_maxKeyFrame = kf.frame;
}
}
}
}

//#133: The document can be larger than the maxKeyFrame we found.
_maxKeyFrame = Math.max(_maxKeyFrame, _getDocumentHeight());

//Now process all data-end keyframes.
skrollableIndex = 0;
skrollablesLength = _skrollables.length;

for(; skrollableIndex < skrollablesLength; skrollableIndex++) {
skrollable = _skrollables[skrollableIndex];
keyFrames = skrollable.keyFrames;

keyFrameIndex = 0;
keyFramesLength = keyFrames.length;

for(; keyFrameIndex < keyFramesLength; keyFrameIndex++) {
kf = keyFrames[keyFrameIndex];

constantValue = processedConstants[kf.constant] || 0;

if(kf.isEnd) {
kf.frame = _maxKeyFrame - kf.offset + constantValue;
}
}

skrollable.keyFrames.sort(_keyFrameComparator);
}
};

/**
* Calculates and sets the style properties for the element at the given frame.
* @param fakeFrame The frame to render at when smooth scrolling is enabled.
* @param actualFrame The actual frame we are at.
*/
var _calcSteps = function(fakeFrame, actualFrame) {
//Iterate over all skrollables.
var skrollableIndex = 0;
var skrollablesLength = _skrollables.length;

for(; skrollableIndex < skrollablesLength; skrollableIndex++) {
var skrollable = _skrollables[skrollableIndex];
var element = skrollable.element;
var frame = skrollable.smoothScrolling ? fakeFrame : actualFrame;
var frames = skrollable.keyFrames;
var firstFrame = frames[0].frame;
var lastFrame = frames[frames.length - 1].frame;
var beforeFirst = frame < firstFrame;
var afterLast = frame > lastFrame;
var firstOrLastFrame = frames[beforeFirst ? 0 : frames.length - 1];
var key;
var value;

//If we are before/after the first/last frame, set the styles according to the given edge strategy.
if(beforeFirst || afterLast) {
//Check if we already handled this edge case last time.
//Note: using setScrollTop it's possible that we jumped from one edge to the other.
if(beforeFirst && skrollable.edge === -1 || afterLast && skrollable.edge === 1) {
continue;
}

//Add the skrollr-before or -after class.
_updateClass(element, [beforeFirst ? SKROLLABLE_BEFORE_CLASS : SKROLLABLE_AFTER_CLASS], [SKROLLABLE_BEFORE_CLASS, SKROLLABLE_BETWEEN_CLASS, SKROLLABLE_AFTER_CLASS]);

//Remember that we handled the edge case (before/after the first/last keyframe).
skrollable.edge = beforeFirst ? -1 : 1;

switch(skrollable.edgeStrategy) {
case 'reset':
_reset(element);
continue;
case 'ease':
//Handle this case like it would be exactly at first/last keyframe and just pass it on.
frame = firstOrLastFrame.frame;
break;
default:
case 'set':
var props = firstOrLastFrame.props;

for(key in props) {
if(hasProp.call(props, key)) {
value = _interpolateString(props[key].value);

skrollr.setStyle(element, key, value);
}
}

continue;
}
} else {
//Did we handle an edge last time?
if(skrollable.edge !== 0) {
_updateClass(element, [SKROLLABLE_CLASS, SKROLLABLE_BETWEEN_CLASS], [SKROLLABLE_BEFORE_CLASS, SKROLLABLE_AFTER_CLASS]);
skrollable.edge = 0;
}
}

//Find out between which two key frames we are right now.
var keyFrameIndex = 0;
var framesLength = frames.length - 1;

for(; keyFrameIndex < framesLength; keyFrameIndex++) {
if(frame >= frames[keyFrameIndex].frame && frame <= frames[keyFrameIndex + 1].frame) {
var left = frames[keyFrameIndex];
var right = frames[keyFrameIndex + 1];

for(key in left.props) {
if(hasProp.call(left.props, key)) {
var progress = (frame - left.frame) / (right.frame - left.frame);

//Transform the current progress using the given easing function.
progress = left.props[key].easing(progress);

//Interpolate between the two values
value = _calcInterpolation(left.props[key].value, right.props[key].value, progress);

value = _interpolateString(value);

skrollr.setStyle(element, key, value);
}
}

break;
}
}
}
};

/**
* Renders all elements.
*/
var _render = function() {
if(_requestReflow) {
_requestReflow = false;
_reflow();
}

//We may render something else than the actual scrollbar position.
var renderTop = _instance.getScrollTop();

//If there's an animation, which ends in current render call, call the callback after rendering.
var afterAnimationCallback;
var now = _now();
var progress;

//Before actually rendering handle the scroll animation, if any.
if(_scrollAnimation) {
//It's over
if(now >= _scrollAnimation.endTime) {
renderTop = _scrollAnimation.targetTop;
afterAnimationCallback = _scrollAnimation.done;
_scrollAnimation = undefined;
} else {
//Map the current progress to the new progress using given easing function.
progress = _scrollAnimation.easing((now - _scrollAnimation.startTime) / _scrollAnimation.duration);

renderTop = (_scrollAnimation.startTop + progress * _scrollAnimation.topDiff) | 0;
}

_instance.setScrollTop(renderTop, true);
}
//Smooth scrolling only if there's no animation running and if we're not forcing the rendering.
else if(!_forceRender) {
var smoothScrollingDiff = _smoothScrolling.targetTop - renderTop;

//The user scrolled, start new smooth scrolling.
if(smoothScrollingDiff) {
_smoothScrolling = {
startTop: _lastTop,
topDiff: renderTop - _lastTop,
targetTop: renderTop,
startTime: _lastRenderCall,
endTime: _lastRenderCall + _smoothScrollingDuration
};
}

//Interpolate the internal scroll position (not the actual scrollbar).
if(now <= _smoothScrolling.endTime) {
//Map the current progress to the new progress using easing function.
progress = easings.sqrt((now - _smoothScrolling.startTime) / _smoothScrollingDuration);

renderTop = (_smoothScrolling.startTop + progress * _smoothScrolling.topDiff) | 0;
}
}

//That's were we actually "scroll" on mobile.
if(_isMobile && _skrollrBody) {
//Set the transform ("scroll it").
skrollr.setStyle(_skrollrBody, 'transform', 'translate(0, ' + -(_mobileOffset) + 'px) ' + _translateZ);
}

//Did the scroll position even change?
if(_forceRender || _lastTop !== renderTop) {
//Remember in which direction are we scrolling?
_direction = (renderTop > _lastTop) ? 'down' : (renderTop < _lastTop ? 'up' : _direction);

_forceRender = false;

var listenerParams = {
curTop: renderTop,
lastTop: _lastTop,
maxTop: _maxKeyFrame,
direction: _direction
};

//Tell the listener we are about to render.
var continueRendering = _listeners.beforerender && _listeners.beforerender.call(_instance, listenerParams);

//The beforerender listener function is able the cancel rendering.
if(continueRendering !== false) {
//Now actually interpolate all the styles.
_calcSteps(renderTop, _instance.getScrollTop());

//Remember when we last rendered.
_lastTop = renderTop;

if(_listeners.render) {
_listeners.render.call(_instance, listenerParams);
}
}

if(afterAnimationCallback) {
afterAnimationCallback.call(_instance, false);
}
}

_lastRenderCall = now;
};

/**
* Parses the properties for each key frame of the given skrollable.
*/
var _parseProps = function(skrollable) {
//Iterate over all key frames
var keyFrameIndex = 0;
var keyFramesLength = skrollable.keyFrames.length;

for(; keyFrameIndex < keyFramesLength; keyFrameIndex++) {
var frame = skrollable.keyFrames[keyFrameIndex];
var easing;
var value;
var prop;
var props = {};

var match;

while((match = rxPropValue.exec(frame.props)) !== null) {
prop = match[1];
value = match[2];

easing = prop.match(rxPropEasing);

//Is there an easing specified for this prop?
if(easing !== null) {
prop = easing[1];
easing = easing[2];
} else {
easing = DEFAULT_EASING;
}

//Exclamation point at first position forces the value to be taken literal.
value = value.indexOf('!') ? _parseProp(value) : [value.slice(1)];

//Save the prop for this key frame with his value and easing function
props[prop] = {
value: value,
easing: easings[easing]
};
}

frame.props = props;
}
};

/**
* Parses a value extracting numeric values and generating a format string
* for later interpolation of the new values in old string.
*
* @param val The CSS value to be parsed.
* @return Something like ["rgba(?%,?%, ?%,?)", 100, 50, 0, .7]
* where the first element is the format string later used
* and all following elements are the numeric value.
*/
var _parseProp = function(val) {
var numbers = [];

//One special case, where floats don't work.
//We replace all occurences of rgba colors
//which don't use percentage notation with the percentage notation.
rxRGBAIntegerColor.lastIndex = 0;
val = val.replace(rxRGBAIntegerColor, function(rgba) {
return rgba.replace(rxNumericValue, function(n) {
return n / 255 * 100 + '%';
});
});

//Handle prefixing of "gradient" values.
//For now only the prefixed value will be set. Unprefixed isn't supported anyway.
if(theDashedCSSPrefix) {
rxGradient.lastIndex = 0;
val = val.replace(rxGradient, function(s) {
return theDashedCSSPrefix + s;
});
}

//Now parse ANY number inside this string and create a format string.
val = val.replace(rxNumericValue, function(n) {
numbers.push(+n);
return '{?}';
});

//Add the formatstring as first value.
numbers.unshift(val);

return numbers;
};

/**
* Fills the key frames with missing left and right hand properties.
* If key frame 1 has property X and key frame 2 is missing X,
* but key frame 3 has X again, then we need to assign X to key frame 2 too.
*
* @param sk A skrollable.
*/
var _fillProps = function(sk) {
//Will collect the properties key frame by key frame
var propList = {};
var keyFrameIndex;
var keyFramesLength;

//Iterate over all key frames from left to right
keyFrameIndex = 0;
keyFramesLength = sk.keyFrames.length;

for(; keyFrameIndex < keyFramesLength; keyFrameIndex++) {
_fillPropForFrame(sk.keyFrames[keyFrameIndex], propList);
}

//Now do the same from right to fill the last gaps

propList = {};

//Iterate over all key frames from right to left
keyFrameIndex = sk.keyFrames.length - 1;

for(; keyFrameIndex >= 0; keyFrameIndex--) {
_fillPropForFrame(sk.keyFrames[keyFrameIndex], propList);
}
};

var _fillPropForFrame = function(frame, propList) {
var key;

//For each key frame iterate over all right hand properties and assign them,
//but only if the current key frame doesn't have the property by itself
for(key in propList) {
//The current frame misses this property, so assign it.
if(!hasProp.call(frame.props, key)) {
frame.props[key] = propList[key];
}
}

//Iterate over all props of the current frame and collect them
for(key in frame.props) {
propList[key] = frame.props[key];
}
};

/**
* Calculates the new values for two given values array.
*/
var _calcInterpolation = function(val1, val2, progress) {
var valueIndex;
var val1Length = val1.length;

//They both need to have the same length
if(val1Length !== val2.length) {
throw 'Can\'t interpolate between "' + val1[0] + '" and "' + val2[0] + '"';
}

//Add the format string as first element.
var interpolated = [val1[0]];

valueIndex = 1;

for(; valueIndex < val1Length; valueIndex++) {
//That's the line where the two numbers are actually interpolated.
interpolated[valueIndex] = val1[valueIndex] + ((val2[valueIndex] - val1[valueIndex]) * progress);
}

return interpolated;
};

/**
* Interpolates the numeric values into the format string.
*/
var _interpolateString = function(val) {
var valueIndex = 1;

rxInterpolateString.lastIndex = 0;

return val[0].replace(rxInterpolateString, function() {
return val[valueIndex++];
});
};

/**
* Resets the class and style attribute to what it was before skrollr manipulated the element.
* Also remembers the values it had before reseting, in order to undo the reset.
*/
var _reset = function(elements, undo) {
//We accept a single element or an array of elements.
elements = [].concat(elements);

var skrollable;
var element;
var elementsIndex = 0;
var elementsLength = elements.length;

for(; elementsIndex < elementsLength; elementsIndex++) {
element = elements[elementsIndex];
skrollable = _skrollables[element[SKROLLABLE_ID_DOM_PROPERTY]];

//Couldn't find the skrollable for this DOM element.
if(!skrollable) {
continue;
}

if(undo) {
//Reset class and style to the "dirty" (set by skrollr) values.
element.style.cssText = skrollable.dirtyStyleAttr;
_updateClass(element, skrollable.dirtyClassAttr);
} else {
//Remember the "dirty" (set by skrollr) class and style.
skrollable.dirtyStyleAttr = element.style.cssText;
skrollable.dirtyClassAttr = _getClass(element);

//Reset class and style to what it originally was.
element.style.cssText = skrollable.styleAttr;
_updateClass(element, skrollable.classAttr);
}
}
};

/**
* Detects support for 3d transforms by applying it to the skrollr-body.
*/
var _detect3DTransforms = function() {
_translateZ = 'translateZ(0)';
skrollr.setStyle(_skrollrBody, 'transform', _translateZ);

var computedStyle = getStyle(_skrollrBody);
var computedTransform = computedStyle.getPropertyValue('transform');
var computedTransformWithPrefix = computedStyle.getPropertyValue(theDashedCSSPrefix + 'transform');
var has3D = (computedTransform && computedTransform !== 'none') || (computedTransformWithPrefix && computedTransformWithPrefix !== 'none');

if(!has3D) {
_translateZ = '';
}
};

/**
* Set the CSS property on the given element. Sets prefixed properties as well.
*/
skrollr.setStyle = function(el, prop, val) {
var style = el.style;

//Camel case.
prop = prop.replace(rxCamelCase, rxCamelCaseFn).replace('-', '');

//Make sure z-index gets a <integer>.
//This is the only <integer> case we need to handle.
if(prop === 'zIndex') {
if(isNaN(val)) {
//If it's not a number, don't touch it.
//It could for example be "auto" (#351).
style[prop] = val;
} else {
//Floor the number.
style[prop] = '' + (val | 0);
}
}
//#64: "float" can't be set across browsers. Needs to use "cssFloat" for all except IE.
else if(prop === 'float') {
style.styleFloat = style.cssFloat = val;
}
else {
//Need try-catch for old IE.
try {
//Set prefixed property if there's a prefix.
if(theCSSPrefix) {
style[theCSSPrefix + prop.slice(0,1).toUpperCase() + prop.slice(1)] = val;
}

//Set unprefixed.
style[prop] = val;
} catch(ignore) {}
}
};

/**
* Cross browser event handling.
*/
var _addEvent = skrollr.addEvent = function(element, names, callback) {
var intermediate = function(e) {
//Normalize IE event stuff.
e = e || window.event;

if(!e.target) {
e.target = e.srcElement;
}

if(!e.preventDefault) {
e.preventDefault = function() {
e.returnValue = false;
};
}

return callback.call(this, e);
};

names = names.split(' ');

var name;
var nameCounter = 0;
var namesLength = names.length;

for(; nameCounter < namesLength; nameCounter++) {
name = names[nameCounter];

if(element.addEventListener) {
element.addEventListener(name, callback, false);
} else {
element.attachEvent('on' + name, intermediate);
}

//Remember the events to be able to flush them later.
_registeredEvents.push({
element: element,
name: name,
listener: callback
});
}
};

var _removeEvent = skrollr.removeEvent = function(element, names, callback) {
names = names.split(' ');

var nameCounter = 0;
var namesLength = names.length;

for(; nameCounter < namesLength; nameCounter++) {
if(element.removeEventListener) {
element.removeEventListener(names[nameCounter], callback, false);
} else {
element.detachEvent('on' + names[nameCounter], callback);
}
}
};

var _removeAllEvents = function() {
var eventData;
var eventCounter = 0;
var eventsLength = _registeredEvents.length;

for(; eventCounter < eventsLength; eventCounter++) {
eventData = _registeredEvents[eventCounter];

_removeEvent(eventData.element, eventData.name, eventData.listener);
}

_registeredEvents = [];
};

var _reflow = function() {
var pos = _instance.getScrollTop();

//Will be recalculated by _updateDependentKeyFrames.
_maxKeyFrame = 0;

if(_forceHeight && !_isMobile) {
//un-"force" the height to not mess with the calculations in _updateDependentKeyFrames (#216).
body.style.height = 'auto';
}

_updateDependentKeyFrames();

if(_forceHeight && !_isMobile) {
//"force" the height.
body.style.height = (_maxKeyFrame + documentElement.clientHeight) + 'px';
}

//The scroll offset may now be larger than needed (on desktop the browser/os prevents scrolling farther than the bottom).
if(_isMobile) {
_instance.setScrollTop(Math.min(_instance.getScrollTop(), _maxKeyFrame));
} else {
//Remember and reset the scroll pos (#217).
_instance.setScrollTop(pos, true);
}

_forceRender = true;
};

/*
* Returns a copy of the constants object where all functions and strings have been evaluated.
*/
var _processConstants = function() {
var viewportHeight = documentElement.clientHeight;
var copy = {};
var prop;
var value;

for(prop in _constants) {
value = _constants[prop];

if(typeof value === 'function') {
value = value.call(_instance);
}
//Percentage offset.
else if((/p$/).test(value)) {
value = (value.slice(0, -1) / 100) * viewportHeight;
}

copy[prop] = value;
}

return copy;
};

/*
* Returns the height of the document.
*/
var _getDocumentHeight = function() {
var skrollrBodyHeight = (_skrollrBody && _skrollrBody.offsetHeight || 0);
var bodyHeight = Math.max(skrollrBodyHeight, body.scrollHeight, body.offsetHeight, documentElement.scrollHeight, documentElement.offsetHeight, documentElement.clientHeight);

return bodyHeight - documentElement.clientHeight;
};

/**
* Returns a string of space separated classnames for the current element.
* Works with SVG as well.
*/
var _getClass = function(element) {
var prop = 'className';

//SVG support by using className.baseVal instead of just className.
if(window.SVGElement && element instanceof window.SVGElement) {
element = element[prop];
prop = 'baseVal';
}

return element[prop];
};

/**
* Adds and removes a CSS classes.
* Works with SVG as well.
* add and remove are arrays of strings,
* or if remove is ommited add is a string and overwrites all classes.
*/
var _updateClass = function(element, add, remove) {
var prop = 'className';

//SVG support by using className.baseVal instead of just className.
if(window.SVGElement && element instanceof window.SVGElement) {
element = element[prop];
prop = 'baseVal';
}

//When remove is ommited, we want to overwrite/set the classes.
if(remove === undefined) {
element[prop] = add;
return;
}

//Cache current classes. We will work on a string before passing back to DOM.
var val = element[prop];

//All classes to be removed.
var classRemoveIndex = 0;
var removeLength = remove.length;

for(; classRemoveIndex < removeLength; classRemoveIndex++) {
val = _untrim(val).replace(_untrim(remove[classRemoveIndex]), ' ');
}

val = _trim(val);

//All classes to be added.
var classAddIndex = 0;
var addLength = add.length;

for(; classAddIndex < addLength; classAddIndex++) {
//Only add if el not already has class.
if(_untrim(val).indexOf(_untrim(add[classAddIndex])) === -1) {
val += ' ' + add[classAddIndex];
}
}

element[prop] = _trim(val);
};

var _trim = function(a) {
return a.replace(rxTrim, '');
};

/**
* Adds a space before and after the string.
*/
var _untrim = function(a) {
return ' ' + a + ' ';
};

var _now = Date.now || function() {
return +new Date();
};

var _keyFrameComparator = function(a, b) {
return a.frame - b.frame;
};

/*
* Private variables.
*/

//Singleton
var _instance;

/*
A list of all elements which should be animated associated with their the metadata.
Exmaple skrollable with two key frames animating from 100px width to 20px:

skrollable = {
element: <the DOM element>,
styleAttr: <style attribute of the element before skrollr>,
classAttr: <class attribute of the element before skrollr>,
keyFrames: [
{
frame: 100,
props: {
width: {
value: ['{?}px', 100],
easing: <reference to easing function>
}
},
mode: "absolute"
},
{
frame: 200,
props: {
width: {
value: ['{?}px', 20],
easing: <reference to easing function>
}
},
mode: "absolute"
}
]
};
*/
var _skrollables;

var _skrollrBody;

var _listeners;
var _forceHeight;
var _maxKeyFrame = 0;

var _scale = 1;
var _constants;

var _mobileDeceleration;

//Current direction (up/down).
var _direction = 'down';

//The last top offset value. Needed to determine direction.
var _lastTop = -1;

//The last time we called the render method (doesn't mean we rendered!).
var _lastRenderCall = _now();

//For detecting if it actually resized (#271).
var _lastViewportWidth = 0;
var _lastViewportHeight = 0;

var _requestReflow = false;

//Will contain data about a running scrollbar animation, if any.
var _scrollAnimation;

var _smoothScrollingEnabled;

var _smoothScrollingDuration;

//Will contain settins for smooth scrolling if enabled.
var _smoothScrolling;

//Can be set by any operation/event to force rendering even if the scrollbar didn't move.
var _forceRender;

//Each skrollable gets an unique ID incremented for each skrollable.
//The ID is the index in the _skrollables array.
var _skrollableIdCounter = 0;

var _edgeStrategy;


//Mobile specific vars. Will be stripped by UglifyJS when not in use.
var _isMobile = false;

//The virtual scroll offset when using mobile scrolling.
var _mobileOffset = 0;

//If the browser supports 3d transforms, this will be filled with 'translateZ(0)' (empty string otherwise).
var _translateZ;

//Will contain data about registered events by skrollr.
var _registeredEvents = [];

//Animation frame id returned by RequestAnimationFrame (or timeout when RAF is not supported).
var _animFrame;
}(window, document));

---------------------------------------skrollr.js END---------------------------------------------
--------------------------------------------------------------------------------------------

---------------------------------------main.js---------------------------------------------
--------------------------------------------------------------------------------------------


jQuery(document).ready(function($){

if(parseInt($(window).width()) > 1199)
    {
   
   
// Setup variables
$window = $(window);
$slide = $('.homeSlide');
$body = $('body');

    //FadeIn all sections
$body.imagesLoaded( function() {
setTimeout(function() {
   
     // Resize sections
     adjustWindow();
   
     // Fade in sections
 $body.removeClass('loading').addClass('loaded');

}, 00);
});

function adjustWindow(){

// Init Skrollr
var s = skrollr.init({
   forceHeight: false,
   render: function(data) {
 
       //Debugging - Log the current scroll position.
       //console.log(data.curTop);
   }
});

// Get window size
   winH = $window.height();
 
   // Keep minimum height 550
   if(winH <= 550) {
winH = 550;
}
 
   // Resize our slides
   // $slide.height(winH);
 
   // Refresh Skrollr after resizing our sections
   s.refresh($('.homeSlide'));
 
}
}

} );

--------------------------------------------------------------------------------------------
---------------------------------------main.js End-------------------------------------

No comments:

Post a Comment