vendor: 10,409 bytes, lines 1-374
1/* smoothscroll v0.4.4 - 2019 - Dustan Kasten, Jeremias Menichelli - MIT License */ 2// polyfill 3function smoothScrollPolyfill() { 4 // aliases 5 var w = window; 6 var d = document; 7 8 // return if scroll behavior is supported and polyfill is not forced 9 if ( 10 'scrollBehavior' in d.documentElement.style && 11 w.__forceSmoothScrollPolyfill__ !== true 12 ) { 13 return; 14 } 15 16 // globals 17 var Element = w.HTMLElement || w.Element; 18 var SCROLL_TIME = 468; 19 20 // object gathering original scroll methods 21 var original = { 22 scroll: w.scroll || w.scrollTo, 23 scrollBy: w.scrollBy, 24 elementScroll: Element.prototype.scroll || scrollElement, 25 scrollIntoView: Element.prototype.scrollIntoView 26 }; 27 28 // define timing method 29 var now = 30 w.performance && w.performance.now 31 ? w.performance.now.bind(w.performance) 32 : Date.now; 33 34 /** 35 * indicates if a the current browser is made by Microsoft 36 * @method isMicrosoftBrowser 37 * @param {String} userAgent 38 * @returns {Boolean} 39 */ 40 function isMicrosoftBrowser(userAgent) { 41 var userAgentPatterns = ['MSIE ', 'Trident/', 'Edge/']; 42 43 return new RegExp(userAgentPatterns.join('|')).test(userAgent); 44 } 45 46 /* 47 * IE has rounding bug rounding down clientHeight and clientWidth and 48 * rounding up scrollHeight and scrollWidth causing false positives 49 * on hasScrollableSpace 50 */ 51 var ROUNDING_TOLERANCE = isMicrosoftBrowser(w.navigator.userAgent) ? 1 : 0; 52 53 /** 54 * changes scroll position inside an element 55 * @method scrollElement 56 * @param {Number} x 57 * @param {Number} y 58 * @returns {undefined} 59 */ 60 function scrollElement(x, y) { 61 this.scrollLeft = x; 62 this.scrollTop = y; 63 } 64 65 /** 66 * returns result of applying ease math function to a number 67 * @method ease 68 * @param {Number} k 69 * @returns {Number} 70 */ 71 function ease(k) { 72 return 0.5 * (1 - Math.cos(Math.PI * k)); 73 } 74 75 /** 76 * indicates if a smooth behavior should be applied 77 * @method shouldBailOut 78 * @param {Number|Object} firstArg 79 * @returns {Boolean} 80 */ 81 function shouldBailOut(firstArg) { 82 if ( 83 firstArg === null || 84 typeof firstArg !== 'object' || 85 firstArg.behavior === undefined || 86 firstArg.behavior === 'auto' || 87 firstArg.behavior === 'instant' 88 ) { 89 // first argument is not an object/null 90 // or behavior is auto, instant or undefined 91 return true; 92 } 93 94 if (typeof firstArg === 'object' && firstArg.behavior === 'smooth') { 95 // first argument is an object and behavior is smooth 96 return false; 97 } 98 99 // throw error when behavior is not supported 100 throw new TypeError( 101 'behavior member of ScrollOptions ' + 102 firstArg.behavior + 103 ' is not a valid value for enumeration ScrollBehavior.' 104 ); 105 } 106 107 /** 108 * indicates if an element has scrollable space in the provided axis 109 * @method hasScrollableSpace 110 * @param {Node} el 111 * @param {String} axis 112 * @returns {Boolean} 113 */ 114 function hasScrollableSpace(el, axis) { 115 if (axis === 'Y') { 116 return el.clientHeight + ROUNDING_TOLERANCE < el.scrollHeight; 117 } 118 119 if (axis === 'X') { 120 return el.clientWidth + ROUNDING_TOLERANCE < el.scrollWidth; 121 } 122 } 123 124 /** 125 * indicates if an element has a scrollable overflow property in the axis 126 * @method canOverflow 127 * @param {Node} el 128 * @param {String} axis 129 * @returns {Boolean} 130 */ 131 function canOverflow(el, axis) { 132 var overflowValue = w.getComputedStyle(el, null)['overflow' + axis]; 133 134 return overflowValue === 'auto' || overflowValue === 'scroll'; 135 } 136 137 /** 138 * indicates if an element can be scrolled in either axis 139 * @method isScrollable 140 * @param {Node} el 141 * @param {String} axis 142 * @returns {Boolean} 143 */ 144 function isScrollable(el) { 145 var isScrollableY = hasScrollableSpace(el, 'Y') && canOverflow(el, 'Y'); 146 var isScrollableX = hasScrollableSpace(el, 'X') && canOverflow(el, 'X'); 147 148 return isScrollableY || isScrollableX; 149 } 150 151 /** 152 * finds scrollable parent of an element 153 * @method findScrollableParent 154 * @param {Node} el 155 * @returns {Node} el 156 */ 157 function findScrollableParent(el) { 158 while (el !== d.body && isScrollable(el) === false) { 159 el = el.parentNode || el.host; 160 } 161 162 return el; 163 } 164 165 /** 166 * self invoked function that, given a context, steps through scrolling 167 * @method step 168 * @param {Object} context 169 * @returns {undefined} 170 */ 171 function step(context) { 172 var time = now(); 173 var value; 174 var currentX; 175 var currentY; 176 var elapsed = (time - context.startTime) / SCROLL_TIME; 177 178 // avoid elapsed times higher than one 179 elapsed = elapsed > 1 ? 1 : elapsed; 180 181 // apply easing to elapsed time 182 value = ease(elapsed); 183 184 currentX = context.startX + (context.x - context.startX) * value; 185 currentY = context.startY + (context.y - context.startY) * value; 186 187 context.method.call(context.scrollable, currentX, currentY); 188 189 // scroll more if we have not reached our destination 190 if (currentX !== context.x || currentY !== context.y) { 191 w.requestAnimationFrame(step.bind(w, context)); 192 } 193 } 194 195 /** 196 * scrolls window or element with a smooth behavior 197 * @method smoothScroll 198 * @param {Object|Node} el 199 * @param {Number} x 200 * @param {Number} y 201 * @returns {undefined} 202 */ 203 function smoothScroll(el, x, y) { 204 var scrollable; 205 var startX; 206 var startY; 207 var method; 208 var startTime = now(); 209 210 // define scroll context 211 if (el === d.body) { 212 scrollable = w; 213 startX = w.scrollX || w.pageXOffset; 214 startY = w.scrollY || w.pageYOffset; 215 method = original.scroll; 216 } else { 217 scrollable = el; 218 startX = el.scrollLeft; 219 startY = el.scrollTop; 220 method = scrollElement; 221 } 222 223 // scroll looping over a frame 224 step({ 225 scrollable: scrollable, 226 method: method, 227 startTime: startTime, 228 startX: startX, 229 startY: startY, 230 x: x, 231 y: y 232 }); 233 } 234 235 // ORIGINAL METHODS OVERRIDES 236 // w.scroll and w.scrollTo 237 w.scroll = w.scrollTo = function () { 238 // avoid action when no arguments are passed 239 if (arguments[0] === undefined) { 240 return; 241 } 242 243 // avoid smooth behavior if not required 244 if (shouldBailOut(arguments[0]) === true) { 245 original.scroll.call( 246 w, 247 arguments[0].left !== undefined 248 ? arguments[0].left 249 : typeof arguments[0] !== 'object' 250 ? arguments[0] 251 : w.scrollX || w.pageXOffset, 252 // use top prop, second argument if present or fallback to scrollY 253 arguments[0].top !== undefined 254 ? arguments[0].top 255 : arguments[1] !== undefined 256 ? arguments[1] 257 : w.scrollY || w.pageYOffset 258 ); 259 260 return; 261 } 262 263 // LET THE SMOOTHNESS BEGIN! 264 smoothScroll.call( 265 w, 266 d.body, 267 arguments[0].left !== undefined 268 ? ~~arguments[0].left 269 : w.scrollX || w.pageXOffset, 270 arguments[0].top !== undefined 271 ? ~~arguments[0].top 272 : w.scrollY || w.pageYOffset 273 ); 274 }; 275 276 // w.scrollBy 277 w.scrollBy = function () { 278 // avoid action when no arguments are passed 279 if (arguments[0] === undefined) { 280 return; 281 } 282 283 // avoid smooth behavior if not required 284 if (shouldBailOut(arguments[0])) { 285 original.scrollBy.call( 286 w, 287 arguments[0].left !== undefined 288 ? arguments[0].left 289 : typeof arguments[0] !== 'object' ? arguments[0] : 0, 290 arguments[0].top !== undefined 291 ? arguments[0].top 292 : arguments[1] !== undefined ? arguments[1] : 0 293 ); 294 295 return; 296 } 297 298 // LET THE SMOOTHNESS BEGIN! 299 smoothScroll.call( 300 w, 301 d.body, 302 ~~arguments[0].left + (w.scrollX || w.pageXOffset), 303 ~~arguments[0].top + (w.scrollY || w.pageYOffset) 304 ); 305 }; 306 307 // Element.prototype.scroll and Element.prototype.scrollTo 308 Element.prototype.scroll = Element.prototype.scrollTo = function () { 309 // avoid action when no arguments are passed 310 if (arguments[0] === undefined) { 311 return; 312 } 313 314 // avoid smooth behavior if not required 315 if (shouldBailOut(arguments[0]) === true) { 316 // if one number is passed, throw error to match Firefox implementation 317 if (typeof arguments[0] === 'number' && arguments[1] === undefined) { 318 throw new SyntaxError('Value could not be converted'); 319 } 320 321 original.elementScroll.call( 322 this, 323 // use left prop, first number argument or fallback to scrollLeft 324 arguments[0].left !== undefined 325 ? ~~arguments[0].left 326 : typeof arguments[0] !== 'object' ? ~~arguments[0] : this.scrollLeft, 327 // use top prop, second argument or fallback to scrollTop 328 arguments[0].top !== undefined 329 ? ~~arguments[0].top 330 : arguments[1] !== undefined ? ~~arguments[1] : this.scrollTop 331 ); 332 333 return; 334 } 335 336 var left = arguments[0].left; 337 var top = arguments[0].top; 338 339 // LET THE SMOOTHNESS BEGIN! 340 smoothScroll.call( 341 this, 342 this, 343 typeof left === 'undefined' ? this.scrollLeft : ~~left, 344 typeof top === 'undefined' ? this.scrollTop : ~~top 345 ); 346 }; 347 348 // Element.prototype.scrollBy 349 Element.prototype.scrollBy = function () { 350 // avoid action when no arguments are passed 351 if (arguments[0] === undefined) { 352 return; 353 } 354 355 // avoid smooth behavior if not required 356 if (shouldBailOut(arguments[0]) === true) { 357 original.elementScroll.call( 358 this, 359 arguments[0].left !== undefined 360 ? ~~arguments[0].left + this.scrollLeft 361 : ~~arguments[0] + this.scrollLeft, 362 arguments[0].top !== undefined 363 ? ~~arguments[0].top + this.scrollTop 364 : ~~arguments[1] + this.scrollTop 365 ); 366 367 return; 368 } 369 370 this.scroll({ 371 left: ~~arguments[0].left + this.scrollLeft, 372 top: ~~arguments[0].top + this.scrollTop, 373 behavior: arguments[0].behavior 374 });
375 }; 376 377 // Element.prototype.scrollIntoView 378 Element.prototype.scrollIntoView = function () { 379 // avoid smooth behavior if not required 380 if (shouldBailOut(arguments[0]) === true) { 381 original.scrollIntoView.call( 382 this, 383 arguments[0] === undefined ? true : arguments[0] 384 ); 385 386 return; 387 } 388 389 // LET THE SMOOTHNESS BEGIN! 390 var scrollableParent = findScrollableParent(this); 391 var parentRects = scrollableParent.getBoundingClientRect(); 392 var clientRects = this.getBoundingClientRect(); 393 394 if (scrollableParent !== d.body) { 395 // reveal element inside parent 396 smoothScroll.call( 397 this, 398 scrollableParent, 399 scrollableParent.scrollLeft + clientRects.left - parentRects.left, 400 scrollableParent.scrollTop + clientRects.top - parentRects.top 401 ); 402 403 // reveal parent in viewport unless is fixed 404 if (w.getComputedStyle(scrollableParent).position !== 'fixed') { 405 w.scrollBy({ 406 left: parentRects.left, 407 top: parentRects.top, 408 behavior: 'smooth' 409 }); 410 } 411 } else { 412 // reveal element in viewport 413 w.scrollBy({ 414 left: clientRects.left, 415 top: clientRects.top, 416 behavior: 'smooth' 417 }); 418 } 419 }; 420} 421 422function smoothScroll() { 423 smoothScrollPolyfill(); 424 425 window.addEventListener('load', function () { 426 setInterval(function () { 427 const jsSmoothScroll = document.getElementsByClassName('js-smooth-scroll'); 428 for (let i = 0; i < jsSmoothScroll.length; i++) { 429 jsSmoothScroll[i].addEventListener('click', function(e) { 430 const target = e.currentTarget; 431 const targetId = target.hash; 432 if (!target.classList.contains('js-smooth-scroll')) return; 433 e.preventDefault(); 434 document.querySelector(targetId).scrollIntoView({ 435 behavior: "smooth", 436 block: "start" 437 }); 438 }, false); 439 } 440 }, 100); 441 }, false); 442};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.