pagesnap
Version:
Lightweight full-page scrolling library in vanilla JavaScript.
2 lines (1 loc) • 14.2 kB
JavaScript
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).pagesnap=e()}(this,(function(){"use strict";var t,e,i="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function o(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var n=function(){if(e)return t;e=1;var o="Expected a function",n=/^\s+|\s+$/g,s=/^[-+]0x[0-9a-f]+$/i,h=/^0b[01]+$/i,l=/^0o[0-7]+$/i,r=parseInt,u="object"==typeof i&&i&&i.Object===Object&&i,d="object"==typeof self&&self&&self.Object===Object&&self,c=u||d||Function("return this")(),a=Object.prototype.toString,v=Math.max,p=Math.min,f=function(){return c.Date.now()};function m(t,e,i){var n,s,h,l,r,u,d=0,c=!1,a=!1,m=!0;if("function"!=typeof t)throw new TypeError(o);function T(e){var i=n,o=s;return n=s=void 0,d=e,l=t.apply(o,i)}function y(t){var i=t-u;return void 0===u||i>=e||i<0||a&&t-d>=h}function M(){var t=f();if(y(t))return b(t);r=setTimeout(M,function(t){var i=e-(t-u);return a?p(i,h-(t-d)):i}(t))}function b(t){return r=void 0,m&&n?T(t):(n=s=void 0,l)}function X(){var t=f(),i=y(t);if(n=arguments,s=this,u=t,i){if(void 0===r)return function(t){return d=t,r=setTimeout(M,e),c?T(t):l}(u);if(a)return r=setTimeout(M,e),T(u)}return void 0===r&&(r=setTimeout(M,e)),l}return e=w(e)||0,g(i)&&(c=!!i.leading,h=(a="maxWait"in i)?v(w(i.maxWait)||0,e):h,m="trailing"in i?!!i.trailing:m),X.cancel=function(){void 0!==r&&clearTimeout(r),d=0,n=u=s=r=void 0},X.flush=function(){return void 0===r?l:b(f())},X}function g(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}function w(t){if("number"==typeof t)return t;if(function(t){return"symbol"==typeof t||function(t){return!!t&&"object"==typeof t}(t)&&"[object Symbol]"==a.call(t)}(t))return NaN;if(g(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=g(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(n,"");var i=h.test(t);return i||l.test(t)?r(t.slice(2),i?2:8):s.test(t)?NaN:+t}return t=function(t,e,i){var n=!0,s=!0;if("function"!=typeof t)throw new TypeError(o);return g(i)&&(n="leading"in i?!!i.leading:n,s="trailing"in i?!!i.trailing:s),m(t,e,{leading:n,maxWait:e,trailing:s})}}(),s=o(n);class h{constructor(t,e){this.element=t,this.touch1=null,this.touch2=null,this.touchStartX=null,this.touchStartY=null,this.touchEndX=null,this.touchEndY=null,this.touchMove1=null,this.touchMove2=null,this.touchMoveX=null,this.touchMoveY=null,this.velocityX=null,this.velocityY=null,this.longPressTimer=null,this.doubleTapTimer=null,this.doubleTapWaiting=!1,this.thresholdX=0,this.thresholdY=0,this.disregardVelocityThresholdX=0,this.disregardVelocityThresholdY=0,this.swipingHorizontal=!1,this.swipingVertical=!1,this.swipingDirection=null,this.swipedHorizontal=!1,this.swipedVertical=!1,this.originalDistance=null,this.newDistance=null,this.scale=null,this.originalAngle=null,this.newAngle=null,this.rotation=null,this.handlers={panstart:[],panmove:[],panend:[],swipeleft:[],swiperight:[],swipeup:[],swipedown:[],tap:[],doubletap:[],longpress:[],pinch:[],pinchend:[],rotate:[],rotateend:[]},this._onTouchStart=this.onTouchStart.bind(this),this._onTouchMove=this.onTouchMove.bind(this),this._onTouchEnd=this.onTouchEnd.bind(this),this.opts=Object.assign({},h.defaults,e),this.element.addEventListener("touchstart",this._onTouchStart,l),this.element.addEventListener("touchmove",this._onTouchMove,l),this.element.addEventListener("touchend",this._onTouchEnd,l),this.opts.mouseSupport&&!("ontouchstart"in window)&&(this.element.addEventListener("mousedown",this._onTouchStart,l),document.addEventListener("mousemove",this._onTouchMove,l),document.addEventListener("mouseup",this._onTouchEnd,l))}destroy(){var t,e;this.element.removeEventListener("touchstart",this._onTouchStart),this.element.removeEventListener("touchmove",this._onTouchMove),this.element.removeEventListener("touchend",this._onTouchEnd),this.element.removeEventListener("mousedown",this._onTouchStart),document.removeEventListener("mousemove",this._onTouchMove),document.removeEventListener("mouseup",this._onTouchEnd),clearTimeout(null!==(t=this.longPressTimer)&&void 0!==t?t:void 0),clearTimeout(null!==(e=this.doubleTapTimer)&&void 0!==e?e:void 0)}on(t,e){if(this.handlers[t])return this.handlers[t].push(e),{type:t,fn:e,cancel:()=>this.off(t,e)}}off(t,e){if(this.handlers[t]){const i=this.handlers[t].indexOf(e);-1!==i&&this.handlers[t].splice(i,1)}}fire(t,e){for(let i=0;i<this.handlers[t].length;i++)this.handlers[t][i](e)}onTouchStart(t){var e,i,o,n,s,h,l,r,u,d,c,a,v,p,f,m,g,w,T,y,M,b,X,Y,E,L;let S=!1;if("mousedown"!==t.type){if(this.touch1||(this.touch1=t.changedTouches[0],S=!0),(S&&t.changedTouches.length>1||!S)&&!this.touch2)return this.touch2=[...t.changedTouches].find((t=>{var e;return t.identifier!==(null===(e=this.touch1)||void 0===e?void 0:e.identifier)}))||null,this.originalDistance=Math.sqrt(Math.pow((null!==(i=null===(e=this.touch2)||void 0===e?void 0:e.screenX)&&void 0!==i?i:0)-(null!==(h=null!==(n=null===(o=this.touchMove1)||void 0===o?void 0:o.screenX)&&void 0!==n?n:null===(s=this.touch1)||void 0===s?void 0:s.screenX)&&void 0!==h?h:0),2)+Math.pow((null!==(r=null===(l=this.touch2)||void 0===l?void 0:l.screenY)&&void 0!==r?r:0)-(null!==(a=null!==(d=null===(u=this.touchMove1)||void 0===u?void 0:u.screenY)&&void 0!==d?d:null===(c=this.touch1)||void 0===c?void 0:c.screenY)&&void 0!==a?a:0),2)),void(this.originalAngle=Math.atan2((null!==(p=null===(v=this.touch2)||void 0===v?void 0:v.screenY)&&void 0!==p?p:0)-(null!==(w=null!==(m=null===(f=this.touchMove1)||void 0===f?void 0:f.screenY)&&void 0!==m?m:null===(g=this.touch1)||void 0===g?void 0:g.screenY)&&void 0!==w?w:0),(null!==(y=null===(T=this.touch2)||void 0===T?void 0:T.screenX)&&void 0!==y?y:0)-(null!==(Y=null!==(b=null===(M=this.touchMove1)||void 0===M?void 0:M.screenX)&&void 0!==b?b:null===(X=this.touch1)||void 0===X?void 0:X.screenX)&&void 0!==Y?Y:0))/(Math.PI/180));if(!S)return}(S||"mousedown"===t.type)&&(this.thresholdX=this.opts.threshold("x",this),this.thresholdY=this.opts.threshold("y",this),this.disregardVelocityThresholdX=this.opts.disregardVelocityThreshold("x",this),this.disregardVelocityThresholdY=this.opts.disregardVelocityThreshold("y",this),this.touchStartX="mousedown"===t.type?t.screenX:(null===(E=this.touch1)||void 0===E?void 0:E.screenX)||0,this.touchStartY="mousedown"===t.type?t.screenY:(null===(L=this.touch1)||void 0===L?void 0:L.screenY)||0,this.touchMoveX=null,this.touchMoveY=null,this.touchEndX=null,this.touchEndY=null,this.swipingDirection=null,this.longPressTimer=setTimeout((()=>this.fire("longpress",t)),this.opts.longPressTime),this.scale=1,this.rotation=0,this.fire("panstart",t))}onTouchMove(t){var e,i,o,n,s,h,l,r,u,d,c,a,v;if("mousemove"===t.type&&(!this.touchStartX||null!==this.touchEndX))return;let p,f;if("mousemove"!==t.type&&(p=[...t.changedTouches].find((t=>{var e;return t.identifier===(null===(e=this.touch1)||void 0===e?void 0:e.identifier)})),this.touchMove1=p||this.touchMove1,f=[...t.changedTouches].find((t=>{var e;return t.identifier===(null===(e=this.touch2)||void 0===e?void 0:e.identifier)})),this.touchMove2=f||this.touchMove2),"mousemove"===t.type||p){const r=("mousemove"===t.type?t.screenX:null!==(e=null==p?void 0:p.screenX)&&void 0!==e?e:0)-(null!==(i=this.touchStartX)&&void 0!==i?i:0);this.velocityX=r-(null!==(o=this.touchMoveX)&&void 0!==o?o:0),this.touchMoveX=r;const u=("mousemove"===t.type?t.screenY:null!==(n=null==p?void 0:p.screenY)&&void 0!==n?n:0)-(null!==(s=this.touchStartY)&&void 0!==s?s:0);this.velocityY=u-(null!==(h=this.touchMoveY)&&void 0!==h?h:0),this.touchMoveY=u;const d=Math.abs(this.touchMoveX),c=Math.abs(this.touchMoveY);this.swipingHorizontal=d>this.thresholdX,this.swipingVertical=c>this.thresholdY,this.swipingDirection=d>c?this.swipingHorizontal?"horizontal":"pre-horizontal":this.swipingVertical?"vertical":"pre-vertical",Math.max(d,c)>this.opts.pressThreshold&&clearTimeout(null!==(l=this.longPressTimer)&&void 0!==l?l:void 0),this.fire("panmove",t)}"mousemove"!==t.type&&null!=this.touchMove1&&null!=this.touchMove2&&(this.newDistance=Math.sqrt(Math.pow(this.touchMove2.screenX-this.touchMove1.screenX,2)+Math.pow(this.touchMove2.screenY-this.touchMove1.screenY,2)),this.scale=this.newDistance/(null!==(r=this.originalDistance)&&void 0!==r?r:0),this.fire("pinch",t),this.newAngle=Math.atan2((null!==(u=this.touchMove2.screenY)&&void 0!==u?u:0)-(null!==(d=this.touchMove1.screenY)&&void 0!==d?d:0),(null!==(c=this.touchMove2.screenX)&&void 0!==c?c:0)-(null!==(a=this.touchMove1.screenX)&&void 0!==a?a:0))/(Math.PI/180),this.rotation=this.newAngle-(null!==(v=this.originalAngle)&&void 0!==v?v:0),this.fire("rotate",t))}onTouchEnd(t){var e,i,o,n,s,h,l,r,u,d;let c;if("mouseup"!==t.type&&(c=[...t.changedTouches].find((t=>{var e;return t.identifier===(null===(e=this.touch1)||void 0===e?void 0:e.identifier)})),[...t.touches].find((t=>{var e;return t.identifier===(null===(e=this.touch1)||void 0===e?void 0:e.identifier)}))||(this.touch1=null,this.touchMove1=null),[...t.touches].find((t=>{var e;return t.identifier===(null===(e=this.touch2)||void 0===e?void 0:e.identifier)}))||(this.touch2=null,this.touchMove2=null)),"mouseup"!==t.type||this.touchStartX&&null===this.touchEndX){if("mouseup"===t.type||c){this.touchEndX="mouseup"===t.type?t.screenX:null!==(e=null==c?void 0:c.screenX)&&void 0!==e?e:0,this.touchEndY="mouseup"===t.type?t.screenY:null!==(i=null==c?void 0:c.screenY)&&void 0!==i?i:0,this.fire("panend",t),clearTimeout(null!==(o=this.longPressTimer)&&void 0!==o?o:void 0);const a=this.touchEndX-(null!==(n=this.touchStartX)&&void 0!==n?n:0),v=Math.abs(a),p=this.touchEndY-(null!==(s=this.touchStartY)&&void 0!==s?s:0),f=Math.abs(p),m=Math.sqrt(Math.pow(a,2)+Math.pow(p,2)),g=Math.abs(m),w=f/v;v>this.thresholdX||f>this.thresholdY||this.opts.diagonalSwipes&&(g>this.thresholdX||g>this.thresholdY)?(this.swipedHorizontal=v>this.thresholdX||this.opts.diagonalSwipes&&g>this.thresholdX,this.swipedVertical=f>this.thresholdY||this.opts.diagonalSwipes&&g>this.thresholdY,(!this.opts.diagonalSwipes||w<Math.tan((45-this.opts.diagonalLimit)*Math.PI/180)||w>Math.tan((45+this.opts.diagonalLimit)*Math.PI/180))&&(v>=f&&(this.swipedVertical=!1),f>v&&(this.swipedHorizontal=!1)),this.swipedHorizontal&&(a<0?((null!==(h=this.velocityX)&&void 0!==h?h:0)<-this.opts.velocityThreshold||m<-this.disregardVelocityThresholdX)&&this.fire("swipeleft",t):((null!==(l=this.velocityX)&&void 0!==l?l:0)>this.opts.velocityThreshold||m>this.disregardVelocityThresholdX)&&this.fire("swiperight",t)),this.swipedVertical&&(p<0?((null!==(r=this.velocityY)&&void 0!==r?r:0)<-this.opts.velocityThreshold||m<-this.disregardVelocityThresholdY)&&this.fire("swipeup",t):((null!==(u=this.velocityY)&&void 0!==u?u:0)>this.opts.velocityThreshold||m>this.disregardVelocityThresholdY)&&this.fire("swipedown",t))):v<this.opts.pressThreshold&&f<this.opts.pressThreshold&&(this.doubleTapWaiting?(this.doubleTapWaiting=!1,clearTimeout(null!==(d=this.doubleTapTimer)&&void 0!==d?d:void 0),this.fire("doubletap",t)):(this.doubleTapWaiting=!0,this.doubleTapTimer=setTimeout((()=>this.doubleTapWaiting=!1),this.opts.doubleTapTime),this.fire("tap",t)))}this.touch1||this.touch2||(this.fire("pinchend",t),this.fire("rotateend",t),this.originalDistance=null,this.newDistance=null,this.scale=null,this.originalAngle=null,this.newAngle=null,this.rotation=null)}}}h.defaults={threshold:(t,e)=>Math.max(25,Math.floor(.15*("x"===t?window.innerWidth||document.body.clientWidth:window.innerHeight||document.body.clientHeight))),velocityThreshold:10,disregardVelocityThreshold:(t,e)=>Math.floor(.5*("x"===t?e.element.clientWidth:e.element.clientHeight)),pressThreshold:8,diagonalSwipes:!1,diagonalLimit:15,longPressTime:500,doubleTapTime:300,mouseSupport:!0};let l=!1;try{window.addEventListener("test",null,Object.defineProperty({},"passive",{get:function(){l={passive:!0}}}))}catch(t){}return function(t,e={}){const i=document.querySelector(t),o=Array.from(i?.children??[]),n=e.delay||700,l=e.loop??!1,r=e.hash??!1,u=e.disableBelow||0,d=e.onBeforeLeave||null,c=e.onAfterLoad||null;if(!i||0===o.length)throw new Error("pagesnap error: Container or sections not found.");let a=0,v="",p=null,f=null,m=!1;i.style.transition=`transform ${n}ms ease`,i.classList.add("pagesnap-container");const g=document.createElement("div");function w(){return window.innerWidth>=u}function T(t){if(!w())return;const e=o.length-1;t<0&&(t=l?e:0),t>e&&(t=l?0:e),t!==a&&(d&&d(a,t),a=t,p&&cancelAnimationFrame(p),p=requestAnimationFrame((()=>{i.style.transform=`translateY(-${100*a}vh)`,X(),r&&function(){const t=o[a].id;t&&t!==v&&(v=t,history.replaceState(null,"",`#${t}`))}(),c&&c(a)})))}function y(){if(!r)return;const t=window.location.hash.slice(1),e=o.findIndex((e=>e.id===t));-1!==e&&T(e)}g.className="pagesnap-nav",document.body.appendChild(g);const M=s((t=>{if(!w())return;(function(t,e){const{scrollTop:i,scrollHeight:o,clientHeight:n}=t;return e>0?i+n>=o-1:i<=1})(o[a],t.deltaY)&&(t.preventDefault(),T(a+(t.deltaY>0?1:-1)))}),n,{trailing:!1}),b=s((t=>{if(!w())return;const e="ArrowDown"===t.key?1:"ArrowUp"===t.key?-1:0;e&&T(a+e)}),n,{trailing:!1});function X(){g.childNodes.forEach(((t,e)=>{t.classList.toggle("active",e===a)}))}function Y(){const t=document.createDocumentFragment();o.forEach(((e,i)=>{const o=document.createElement("div");o.className="pagesnap-dot",o.addEventListener("click",(()=>T(i))),t.appendChild(o)})),g.innerHTML="",g.appendChild(t),X()}function E(){window.addEventListener("wheel",M,{passive:!1}),window.addEventListener("keydown",b),window.addEventListener("hashchange",y),w()&&(f=new h(window,{threshold:50,velocityThreshold:.3}),f.on("swipeup",(()=>T(a+1))),f.on("swipedown",(()=>T(a-1))))}return Y(),E(),y(),{goTo:T,getCurrent:()=>a,destroy:function(){window.removeEventListener("wheel",M),window.removeEventListener("keydown",b),window.removeEventListener("hashchange",y),f&&f.destroy(),m=!0,i.style.transform="",g.remove()},rebuild:function(){m&&(m=!1,document.body.appendChild(g),Y(),E(),y())}}}}));