123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847 |
- /*!
- * jQuery Scrollify
- * Version 1.0.19
- *
- * Requires:
- * - jQuery 1.7 or higher
- *
- * https://github.com/lukehaas/Scrollify
- *
- * Copyright 2016, Luke Haas
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- if touchScroll is false - update index
- */
- (function (global,factory) {
- "use strict";
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module.
- define(['jquery'], function($) {
- return factory($, global, global.document);
- });
- } else if (typeof module === 'object' && module.exports) {
- // Node/CommonJS
- module.exports = factory(require('jquery'), global, global.document);
- } else {
- // Browser globals
- factory(jQuery, global, global.document);
- }
- }(typeof window !== 'undefined' ? window : this, function ($, window, document, undefined) {
- "use strict";
- var heights = [],
- names = [],
- elements = [],
- overflow = [],
- index = 0,
- currentIndex = 0,
- interstitialIndex = 1,
- hasLocation = false,
- timeoutId,
- timeoutId2,
- $window = $(window),
- portHeight,
- top = $window.scrollTop(),
- scrollable = false,
- locked = false,
- scrolled = false,
- manualScroll,
- swipeScroll,
- util,
- disabled = false,
- scrollSamples = [],
- scrollTime = new Date().getTime(),
- firstLoad = true,
- initialised = false,
- destination = 0,
- wheelEvent = 'onwheel' in document ? 'wheel' : document.onmousewheel !== undefined ? 'mousewheel' : 'DOMMouseScroll',
- settings = {
- //section should be an identifier that is the same for each section
- section: ".section",
- sectionName: "section-name",
- interstitialSection: "",
- easing: "easeOutExpo",
- scrollSpeed: 1100,
- offset: 0,
- scrollbars: true,
- target:"html,body",
- standardScrollElements: false,
- setHeights: true,
- overflowScroll:true,
- updateHash: true,
- touchScroll:true,
- before:function() {},
- after:function() {},
- afterResize:function() {},
- afterRender:function() {}
- };
- function getportHeight() {
- return ($window.height() + settings.offset);
- }
- function animateScroll(index,instant,callbacks,toTop) {
- if(currentIndex===index) {
- callbacks = false;
- }
- if(disabled===true) {
- return true;
- }
- if(names[index]) {
- scrollable = false;
- if(firstLoad===true) {
- settings.afterRender();
- firstLoad = false;
- }
- if(callbacks) {
- if( typeof settings.before == 'function' && settings.before(index,elements) === false ){
- return true;
- }
- }
- interstitialIndex = 1;
- destination = heights[index];
- if(firstLoad===false && currentIndex>index && toTop===false) {
- //We're going backwards
- if(overflow[index]) {
- portHeight = getportHeight();
- interstitialIndex = parseInt(elements[index].outerHeight()/portHeight);
- destination = parseInt(heights[index])+(elements[index].outerHeight()-portHeight);
- }
- }
- if(settings.updateHash && settings.sectionName && !(firstLoad===true && index===0)) {
- if(history.pushState) {
- try {
- history.replaceState(null, null, names[index]);
- } catch (e) {
- if(window.console) {
- console.warn("Scrollify warning: Page must be hosted to manipulate the hash value.");
- }
- }
- } else {
- window.location.hash = names[index];
- }
- }
- currentIndex = index;
- if(instant) {
- $(settings.target).stop().scrollTop(destination);
- if(callbacks) {
- settings.after(index,elements);
- }
- } else {
- locked = true;
- if( $().velocity ) {
- $(settings.target).stop().velocity('scroll', {
- duration: settings.scrollSpeed,
- easing: settings.easing,
- offset: destination,
- mobileHA: false
- });
- } else {
- $(settings.target).stop().animate({
- scrollTop: destination
- }, settings.scrollSpeed,settings.easing);
- }
- if(window.location.hash.length && settings.sectionName && window.console) {
- try {
- if($(window.location.hash).length) {
- console.warn("Scrollify warning: ID matches hash value - this will cause the page to anchor.");
- }
- } catch (e) {}
- }
- $(settings.target).promise().done(function(){
- locked = false;
- firstLoad = false;
- if(callbacks) {
- settings.after(index,elements);
- }
- });
- }
- }
- }
- function isAccelerating(samples) {
- function average(num) {
- var sum = 0;
- var lastElements = samples.slice(Math.max(samples.length - num, 1));
- for(var i = 0; i < lastElements.length; i++){
- sum += lastElements[i];
- }
- return Math.ceil(sum/num);
- }
- var avEnd = average(10);
- var avMiddle = average(70);
- if(avEnd >= avMiddle) {
- return true;
- } else {
- return false;
- }
- }
- var scrollify = function(options) {
- initialised = true;
- $.easing['easeOutExpo'] = function(x, t, b, c, d) {
- return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
- };
- manualScroll = {
- handleMousedown:function() {
- if(disabled===true) {
- return true;
- }
- scrollable = false;
- scrolled = false;
- },
- handleMouseup:function() {
- if(disabled===true) {
- return true;
- }
- scrollable = true;
- if(scrolled) {
- //instant,callbacks
- manualScroll.calculateNearest(false,true);
- }
- },
- handleScroll:function() {
- if(disabled===true) {
- return true;
- }
- if(timeoutId){
- clearTimeout(timeoutId);
- }
- timeoutId = setTimeout(function(){
- scrolled = true;
- if(scrollable===false) {
- return false;
- }
- scrollable = false;
- //instant,callbacks
- manualScroll.calculateNearest(false,true);
- }, 200);
- },
- calculateNearest:function(instant,callbacks) {
- top = $window.scrollTop();
- var i =1,
- max = heights.length,
- closest = 0,
- prev = Math.abs(heights[0] - top),
- diff;
- for(;i<max;i++) {
- diff = Math.abs(heights[i] - top);
- if(diff < prev) {
- prev = diff;
- closest = i;
- }
- }
- if((atBottom() && closest>index) || atTop()) {
- index = closest;
- //index, instant, callbacks, toTop
- animateScroll(closest,instant,callbacks,false);
- }
- },
- wheelHandler:function(e) {
- if(disabled===true) {
- return true;
- } else if(settings.standardScrollElements) {
- if($(e.target).is(settings.standardScrollElements) || $(e.target).closest(settings.standardScrollElements).length) {
- return true;
- }
- }
- if(!overflow[index]) {
- e.preventDefault();
- }
- var currentScrollTime = new Date().getTime();
- e = e || window.event;
- var value = e.originalEvent.wheelDelta || -e.originalEvent.deltaY || -e.originalEvent.detail;
- var delta = Math.max(-1, Math.min(1, value));
- //delta = delta || -e.originalEvent.detail / 3 || e.originalEvent.wheelDelta / 120;
- if(scrollSamples.length > 149){
- scrollSamples.shift();
- }
- //scrollSamples.push(Math.abs(delta*10));
- scrollSamples.push(Math.abs(value));
- if((currentScrollTime-scrollTime) > 200){
- scrollSamples = [];
- }
- scrollTime = currentScrollTime;
- if(locked) {
- return false;
- }
- if(delta<0) {
- if(index<heights.length-1) {
- if(atBottom()) {
- if(isAccelerating(scrollSamples)) {
- e.preventDefault();
- index++;
- locked = true;
- //index, instant, callbacks, toTop
- animateScroll(index,false,true, false);
- } else {
- return false;
- }
- }
- }
- } else if(delta>0) {
- if(index>0) {
- if(atTop()) {
- if(isAccelerating(scrollSamples)) {
- e.preventDefault();
- index--;
- locked = true;
- //index, instant, callbacks, toTop
- animateScroll(index,false,true, false);
- } else {
- return false
- }
- }
- }
- }
- },
- keyHandler:function(e) {
- if(disabled===true || document.activeElement.readOnly===false) {
- return true;
- } else if(settings.standardScrollElements) {
- if($(e.target).is(settings.standardScrollElements) || $(e.target).closest(settings.standardScrollElements).length) {
- return true;
- }
- }
- if(locked===true) {
- return false;
- }
- if(e.keyCode==38 || e.keyCode==33) {
- if(index>0) {
- if(atTop()) {
- e.preventDefault();
- index--;
- //index, instant, callbacks, toTop
- animateScroll(index,false,true,false);
- }
- }
- } else if(e.keyCode==40 || e.keyCode==34) {
- if(index<heights.length-1) {
- if(atBottom()) {
- e.preventDefault();
- index++;
- //index, instant, callbacks, toTop
- animateScroll(index,false,true,false);
- }
- }
- }
- },
- init:function() {
- if(settings.scrollbars) {
- $window.on('mousedown', manualScroll.handleMousedown);
- $window.on('mouseup', manualScroll.handleMouseup);
- $window.on('scroll', manualScroll.handleScroll);
- } else {
- $("body").css({"overflow":"hidden"});
- }
- $window.on(wheelEvent,manualScroll.wheelHandler);
- //$(document).bind(wheelEvent,manualScroll.wheelHandler);
- $window.on('keydown', manualScroll.keyHandler);
- }
- };
- swipeScroll = {
- touches : {
- "touchstart": {"y":-1,"x":-1},
- "touchmove" : {"y":-1,"x":-1},
- "touchend" : false,
- "direction" : "undetermined"
- },
- options:{
- "distance" : 30,
- "timeGap" : 800,
- "timeStamp" : new Date().getTime()
- },
- touchHandler: function(event) {
- if(disabled===true) {
- return true;
- } else if(settings.standardScrollElements) {
- if($(event.target).is(settings.standardScrollElements) || $(event.target).closest(settings.standardScrollElements).length) {
- return true;
- }
- }
- var touch;
- if (typeof event !== 'undefined'){
- if (typeof event.touches !== 'undefined') {
- touch = event.touches[0];
- switch (event.type) {
- case 'touchstart':
- swipeScroll.touches.touchstart.y = touch.pageY;
- swipeScroll.touches.touchmove.y = -1;
- swipeScroll.touches.touchstart.x = touch.pageX;
- swipeScroll.touches.touchmove.x = -1;
- swipeScroll.options.timeStamp = new Date().getTime();
- swipeScroll.touches.touchend = false;
- case 'touchmove':
- swipeScroll.touches.touchmove.y = touch.pageY;
- swipeScroll.touches.touchmove.x = touch.pageX;
- if(swipeScroll.touches.touchstart.y!==swipeScroll.touches.touchmove.y && (Math.abs(swipeScroll.touches.touchstart.y-swipeScroll.touches.touchmove.y)>Math.abs(swipeScroll.touches.touchstart.x-swipeScroll.touches.touchmove.x))) {
- //if(!overflow[index]) {
- event.preventDefault();
- //}
- swipeScroll.touches.direction = "y";
- if((swipeScroll.options.timeStamp+swipeScroll.options.timeGap)<(new Date().getTime()) && swipeScroll.touches.touchend == false) {
- swipeScroll.touches.touchend = true;
- if (swipeScroll.touches.touchstart.y > -1) {
- if(Math.abs(swipeScroll.touches.touchmove.y-swipeScroll.touches.touchstart.y)>swipeScroll.options.distance) {
- if(swipeScroll.touches.touchstart.y < swipeScroll.touches.touchmove.y) {
- swipeScroll.up();
- } else {
- swipeScroll.down();
- }
- }
- }
- }
- }
- break;
- case 'touchend':
- if(swipeScroll.touches[event.type]===false) {
- swipeScroll.touches[event.type] = true;
- if (swipeScroll.touches.touchstart.y > -1 && swipeScroll.touches.touchmove.y > -1 && swipeScroll.touches.direction==="y") {
- if(Math.abs(swipeScroll.touches.touchmove.y-swipeScroll.touches.touchstart.y)>swipeScroll.options.distance) {
- if(swipeScroll.touches.touchstart.y < swipeScroll.touches.touchmove.y) {
- swipeScroll.up();
- } else {
- swipeScroll.down();
- }
- }
- swipeScroll.touches.touchstart.y = -1;
- swipeScroll.touches.touchstart.x = -1;
- swipeScroll.touches.direction = "undetermined";
- }
- }
- default:
- break;
- }
- }
- }
- },
- down: function() {
- if(index<heights.length) {
- if(atBottom() && index<heights.length-1) {
- index++;
- //index, instant, callbacks, toTop
- animateScroll(index,false,true,false);
- } else {
- portHeight = getportHeight();
- if(Math.floor(elements[index].height()/portHeight)>interstitialIndex) {
- interstitialScroll(parseInt(heights[index])+(portHeight*interstitialIndex));
- interstitialIndex += 1;
- } else {
- interstitialScroll(parseInt(heights[index])+(elements[index].outerHeight()-portHeight));
- }
- }
- }
- },
- up: function() {
- if(index>=0) {
- if(atTop() && index>0) {
- index--;
- //index, instant, callbacks, toTop
- animateScroll(index,false,true,false);
- } else {
- if(interstitialIndex>2) {
- portHeight = getportHeight();
- interstitialIndex -= 1;
- interstitialScroll(parseInt(heights[index])+(portHeight*interstitialIndex));
- } else {
- interstitialIndex = 1;
- interstitialScroll(parseInt(heights[index]));
- }
- }
- }
- },
- init: function() {
- if (document.addEventListener && settings.touchScroll) {
- var eventListenerOptions = {
- passive: false
- };
- document.addEventListener('touchstart', swipeScroll.touchHandler, eventListenerOptions);
- document.addEventListener('touchmove', swipeScroll.touchHandler, eventListenerOptions);
- document.addEventListener('touchend', swipeScroll.touchHandler, eventListenerOptions);
- }
- }
- };
- util = {
- refresh:function(withCallback,scroll) {
- clearTimeout(timeoutId2);
- timeoutId2 = setTimeout(function() {
- //retain position
- sizePanels(true);
- //scroll, firstLoad
- calculatePositions(scroll,false);
- if(withCallback) {
- settings.afterResize();
- }
- },400);
- },
- handleUpdate:function() {
- //callbacks, scroll
- //changed from false,true to false,false
- util.refresh(false,false);
- },
- handleResize:function() {
- //callbacks, scroll
- util.refresh(true,false);
- },
- handleOrientation:function() {
- //callbacks, scroll
- util.refresh(true,true);
- }
- };
- settings = $.extend(settings, options);
- //retain position
- sizePanels(false);
- calculatePositions(false,true);
- if(true===hasLocation) {
- //index, instant, callbacks, toTop
- animateScroll(index,false,true,true);
- } else {
- setTimeout(function() {
- //instant,callbacks
- manualScroll.calculateNearest(true,false);
- },200);
- }
- if(heights.length) {
- manualScroll.init();
- swipeScroll.init();
- $window.on("resize",util.handleResize);
- if (document.addEventListener) {
- window.addEventListener("orientationchange", util.handleOrientation, false);
- }
- }
- function interstitialScroll(pos) {
- if( $().velocity ) {
- $(settings.target).stop().velocity('scroll', {
- duration: settings.scrollSpeed,
- easing: settings.easing,
- offset: pos,
- mobileHA: false
- });
- } else {
- $(settings.target).stop().animate({
- scrollTop: pos
- }, settings.scrollSpeed,settings.easing);
- }
- }
- function sizePanels(keepPosition) {
- if(keepPosition) {
- top = $window.scrollTop();
- }
- var selector = settings.section;
- overflow = [];
- if(settings.interstitialSection.length) {
- selector += "," + settings.interstitialSection;
- }
- if(settings.scrollbars===false) {
- settings.overflowScroll = false;
- }
- portHeight = getportHeight();
- $(selector).each(function(i) {
- var $this = $(this);
- if(settings.setHeights) {
- if($this.is(settings.interstitialSection)) {
- overflow[i] = false;
- } else {
- if(($this.css("height","auto").outerHeight()<portHeight) || $this.css("overflow")==="hidden") {
- $this.css({"height":portHeight});
- overflow[i] = false;
- } else {
- $this.css({"height":$this.height()});
- if(settings.overflowScroll) {
- overflow[i] = true;
- } else {
- overflow[i] = false;
- }
- }
- }
- } else {
- if(($this.outerHeight()<portHeight) || (settings.overflowScroll===false)) {
- overflow[i] = false;
- } else {
- overflow[i] = true;
- }
- }
- });
- if(keepPosition) {
- $window.scrollTop(top);
- }
- }
- function calculatePositions(scroll,firstLoad) {
- var selector = settings.section;
- if(settings.interstitialSection.length) {
- selector += "," + settings.interstitialSection;
- }
- heights = [];
- names = [];
- elements = [];
- $(selector).each(function(i){
- var $this = $(this);
- if(i>0) {
- heights[i] = parseInt($this.offset().top) + settings.offset;
- } else {
- heights[i] = parseInt($this.offset().top);
- }
- if(settings.sectionName && $this.data(settings.sectionName)) {
- names[i] = "#" + $this.data(settings.sectionName).toString().replace(/ /g,"-");
- } else {
- if($this.is(settings.interstitialSection)===false) {
- names[i] = "#" + (i + 1);
- } else {
- names[i] = "#";
- if(i===$(selector).length-1 && i>1) {
- heights[i] = heights[i-1] + (parseInt($($(selector)[i-1]).outerHeight()) - parseInt($(window).height())) + parseInt($this.outerHeight());
- }
- }
- }
- elements[i] = $this;
- try {
- if($(names[i]).length && window.console) {
- console.warn("Scrollify warning: Section names can't match IDs - this will cause the browser to anchor.");
- }
- } catch (e) {}
- if(window.location.hash===names[i]) {
- index = i;
- hasLocation = true;
- }
- });
- if(true===scroll) {
- //index, instant, callbacks, toTop
- animateScroll(index,false,false,false);
- }
- }
- function atTop() {
- if(!overflow[index]) {
- return true;
- }
- top = $window.scrollTop();
- if(top>parseInt(heights[index])) {
- return false;
- } else {
- return true;
- }
- }
- function atBottom() {
- if(!overflow[index]) {
- return true;
- }
- top = $window.scrollTop();
- portHeight = getportHeight();
- if(top<parseInt(heights[index])+(elements[index].outerHeight()-portHeight)-28) {
- return false;
- } else {
- return true;
- }
- }
- }
- function move(panel,instant) {
- var z = names.length;
- for(;z>=0;z--) {
- if(typeof panel === 'string') {
- if (names[z]===panel) {
- index = z;
- //index, instant, callbacks, toTop
- animateScroll(z,instant,true,true);
- }
- } else {
- if(z===panel) {
- index = z;
- //index, instant, callbacks, toTop
- animateScroll(z,instant,true,true);
- }
- }
- }
- }
- scrollify.move = function(panel) {
- if(panel===undefined) {
- return false;
- }
- if(panel.originalEvent) {
- panel = $(this).attr("href");
- }
- move(panel,false);
- };
- scrollify.instantMove = function(panel) {
- if(panel===undefined) {
- return false;
- }
- move(panel,true);
- };
- scrollify.next = function() {
- if(index<names.length) {
- index += 1;
- //index, instant, callbacks, toTop
- animateScroll(index,false,true,true);
- }
- };
- scrollify.previous = function() {
- if(index>0) {
- index -= 1;
- //index, instant, callbacks, toTop
- animateScroll(index,false,true,true);
- }
- };
- scrollify.instantNext = function() {
- if(index<names.length) {
- index += 1;
- //index, instant, callbacks, toTop
- animateScroll(index,true,true,true);
- }
- };
- scrollify.instantPrevious = function() {
- if(index>0) {
- index -= 1;
- //index, instant, callbacks, toTop
- animateScroll(index,true,true,true);
- }
- };
- scrollify.destroy = function() {
- if(!initialised) {
- return false;
- }
- if(settings.setHeights) {
- $(settings.section).each(function() {
- $(this).css("height","auto");
- });
- }
- $window.off("resize",util.handleResize);
- if(settings.scrollbars) {
- $window.off('mousedown', manualScroll.handleMousedown);
- $window.off('mouseup', manualScroll.handleMouseup);
- $window.off('scroll', manualScroll.handleScroll);
- }
- $window.off(wheelEvent,manualScroll.wheelHandler);
- $window.off('keydown', manualScroll.keyHandler);
- if (document.addEventListener && settings.touchScroll) {
- document.removeEventListener('touchstart', swipeScroll.touchHandler, false);
- document.removeEventListener('touchmove', swipeScroll.touchHandler, false);
- document.removeEventListener('touchend', swipeScroll.touchHandler, false);
- }
- heights = [];
- names = [];
- elements = [];
- overflow = [];
- };
- scrollify.update = function() {
- if(!initialised) {
- return false;
- }
- util.handleUpdate();
- };
- scrollify.current = function() {
- return elements[index];
- };
- scrollify.currentIndex = function() {
- return index;
- };
- scrollify.disable = function() {
- disabled = true;
- };
- scrollify.enable = function() {
- disabled = false;
- if (initialised) {
- //instant,callbacks
- manualScroll.calculateNearest(false,false);
- }
- };
- scrollify.isDisabled = function() {
- return disabled;
- };
- scrollify.setOptions = function(updatedOptions) {
- if(!initialised) {
- return false;
- }
- if(typeof updatedOptions === "object") {
- settings = $.extend(settings, updatedOptions);
- util.handleUpdate();
- } else if(window.console) {
- console.warn("Scrollify warning: setOptions expects an object.");
- }
- };
- $.scrollify = scrollify;
- return scrollify;
- }));
|