smoothscroll-anchor-polyfill
Version:
Apply smooth scroll to anchor links to replicate CSS scroll-behavior
2 lines (1 loc) • 2.54 kB
JavaScript
const t="undefined"!=typeof window,e=t&&window,n=t&&document,o=t&&n.documentElement,r=t&&n.createElement("a"),l=t=>(t=>/^a$/i.test(t.tagName))(t)&&(t=>{if(!/#/.test(t.href))return!1;let e=t.pathname;return"/"!==e[0]&&(e="/"+e),t.hostname===location.hostname&&e===location.pathname&&(!t.search||t.search===location.search)})(t)?t:t.parentElement?l(t.parentElement):null,i=t=>{if("string"!=typeof t)return null;try{t=decodeURIComponent(t)}catch(t){}let e=t?n.getElementById(t.slice(1)):n.body;return"#top"!==t||e||(e=n.body),e},s=t=>{const e={preventScroll:!0};if(t.focus(e),n.activeElement!==t){const n=t.getAttribute("tabindex");if(t.setAttribute("tabindex","-1"),"none"===getComputedStyle(t).outlineStyle){const e=t.style.outlineStyle;t.style.outlineStyle="none",t.addEventListener("blur",(function o(){t.style.outlineStyle=e||"",null!=n?t.setAttribute("tabindex",n):t.removeAttribute("tabindex"),t.removeEventListener("blur",o)}))}t.focus(e)}};let c,a=!1;if(t)try{const t=Object.defineProperty({},"preventScroll",{get(){a=!0}});r.focus(t)}catch(t){}const u=t=>{a||clearTimeout(c);t===n.body?e.scroll({top:0,left:0,behavior:"smooth"}):t.scrollIntoView({behavior:"smooth",block:"start"}),a?s(t):c=setTimeout(s.bind(null,t),450)},f=()=>{const t=/scroll-behavior:[\s]*([^;"']+)/,e=getComputedStyle(o),n=[o.style.scrollBehavior,(t.exec(o.getAttribute("style"))||[])[1],e.getPropertyValue("--scroll-behavior"),(t.exec(e.fontFamily)||[])[1]];for(var r=0;r<n.length;r++){const t=n[r]&&n[r].trim();if(/^smooth$/.test(t))return!0;if(/^(initial|inherit|auto|unset)$/.test(t))return!1}return!1},h={polyfill:d,destroy:y};function d(o={}){if(y(),t){const l=e.__forceSmoothscrollAnchorPolyfill__,i="boolean"==typeof o.force?o.force:l;if(t&&"scrollBehavior"in r&&!i)return;n.addEventListener("click",m,!1),n.addEventListener("scroll",E),e.addEventListener("hashchange",p)}return h}function y(){return t&&(n.removeEventListener("click",m,!1),n.removeEventListener("scroll",E),e.removeEventListener("hashchange",p)),h}function m(t){const e=t.metaKey||t.ctrlKey||t.shiftKey||0!==t.button;if(t.defaultPrevented||e)return;if(!f())return;const o=l(t.target);if(!o)return;const r=i(o.hash);r&&(t.preventDefault(),u(r),history.pushState&&history.pushState(null,n.title,o.href))}const b=[],v=()=>o.scrollTop||n.body.scrollTop;function p(){if(!n.body||!f())return;const t=i(location.hash);if(!t)return;const o=v(),r=b[b[1]===o?0:1];e.scroll({top:r,behavior:"instant"}),u(t)}function E(){n.body&&(b[0]=b[1],b[1]=v())}d();export{h as default,y as destroy,d as polyfill};