UNPKG

scroll-stash

Version:

A JavaScript plugin to help preserve an element's scroll position.

3 lines (2 loc) 3.52 kB
function t(){return(t=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var s=arguments[e];for(var r in s)Object.prototype.hasOwnProperty.call(s,r)&&(t[r]=s[r])}return t}).apply(this,arguments)}var e={autoInit:!1,dataScroll:"scroll-stash",dataAnchor:"scroll-stash-anchor",selectorAnchor:"",selectorAnchorParent:"",selectorTopElem:"",selectorBotElem:"",alignment:"nearest",behavior:"auto",anchorPadding:16,saveKey:"ScrollStash",throttleDelay:100,customEventPrefix:"scroll-stash:"};const s=(t,e,s)=>{let r=s.anchorPadding;if(s.selectorTopElem){const e=t.querySelector(s.selectorTopElem);e&&(r+=e.offsetHeight)}return e.offsetTop-r},r=(t,e,s)=>{let r=s.anchorPadding;if(s.selectorBotElem){const e=t.querySelector(s.selectorBotElem);e&&(r+=e.offsetHeight)}return e.offsetTop-(t.offsetHeight-(e.offsetHeight+r))},o=(t,e)=>{const s=t.getAttribute(`data-${e.dataAnchor}`);if("false"==s||"ignore"==s)return null;if(s&&t.querySelector(s))return t.querySelector(s);const r=e.selectorAnchor?t.querySelector(e.selectorAnchor):null;if(r&&e.selectorAnchorParent){const t=r.closest(e.selectorAnchorParent);if(t)return t}return r||null},n=(t,e,n)=>{const l=o(t,n);if(l){const o=((t,e,o)=>{const n=((t,e,o)=>{const n=s(t,e,o),l=r(t,e,o);return!(t.scrollTop>n||t.scrollTop<l)})(t,e,o);switch(o.alignment){case"start":return!n&&s(t,e,o);case"center":return!n&&((t,e,o)=>{const n=s(t,e,o),l=r(t,e,o);return l+(n-l)/2})(t,e,o);case"end":return!n&&r(t,e,o);case"nearest":return((t,e,o)=>{const n=s(t,e,o),l=r(t,e,o);return t.scrollTop>n?n:t.scrollTop<l&&l})(t,e,o);default:return!1}})(t,l,n);return o?(t.scroll({top:o,behavior:e=e||n.behavior}),t.dispatchEvent(new CustomEvent(n.customEventPrefix+"anchor",{bubbles:!0,detail:{scrolled:{value:o,behavior:e},key:t.getAttribute(`data-${n.dataScroll}`)}})),{scrolled:{value:o,behavior:e},msg:"Anchor was scrolled into view"}):{scrolled:!1,msg:"Anchor is already in view"}}return{scrolled:!1,msg:"Anchor was not found"}},l=t=>{const e={};return document.querySelectorAll(`[data-${t.dataScroll}]`).forEach(s=>{const r=s.getAttribute(`data-${t.dataScroll}`);r&&(e[r]=s.scrollTop)}),localStorage.setItem(t.saveKey,JSON.stringify(e)),document.dispatchEvent(new CustomEvent(t.customEventPrefix+"saved",{bubbles:!0,detail:{state:e}})),e};export default class{constructor(s){this.settings=t({},e,s),this.state={},this.scrolls=[],this.ticking=!1,this.__handler=this.handler.bind(this),this.settings.autoInit&&this.init()}init(e=null){e&&(this.settings=t({},this.settings,e)),this.state=(t=>{if(localStorage.getItem(t.saveKey)){let e=JSON.parse(localStorage.getItem(t.saveKey));return Object.keys(e).forEach(s=>{const r=document.querySelector(`[data-${t.dataScroll}="${s}"]`);r&&(r.scrollTop=e[s])}),document.dispatchEvent(new CustomEvent(t.customEventPrefix+"applied",{bubbles:!0,detail:{state:e}})),e}return{}})(this.settings),this.state=Object.keys(this.state).length?this.state:l(this.settings),this.scrolls=document.querySelectorAll(`[data-${this.settings.dataScroll}]`),this.scrolls.forEach(t=>{t.addEventListener("scroll",this.__handler,!1),n(t,!1,this.settings)})}destroy(){this.scrolls.forEach(t=>{t.removeEventListener("scroll",this.__handler,!1)}),this.state={},this.scrolls=[],localStorage.removeItem(this.settings.saveKey)}handler(){this.ticking||(this.ticking=!0,setTimeout(()=>{this.state=l(this.settings),this.ticking=!1},this.settings.throttleDelay))}anchorGet(t){return o(t,this.settings)}anchorShow(t,e){return n(t,e,this.settings)}} //# sourceMappingURL=scripts.modern.js.map