1/*! 2 * jQuery Smooth Scroll - v2.2.0 - 2017-05-05 3 * https://github.com/kswedberg/jquery-smooth-scroll 4 * Copyright (c) 2017 Karl Swedberg 5 * Licensed MIT 6 */ 7 8(function(factory) { 9 if (typeof define === 'function' && define.amd) { 10 // AMD. Register as an anonymous module. 11 define(['jquery'], factory); 12 } else if (typeof module === 'object' && module.exports) { 13 // CommonJS 14 factory(require('jquery')); 15 } else { 16 // Browser globals 17 factory(jQuery); 18 } 19}(function($) { 20 21 var version = '2.2.0'; 22 var optionOverrides = {}; 23 var defaults = { 24 exclude: [], 25 excludeWithin: [], 26 offset: 0, 27 28 // one of 'top' or 'left' 29 direction: 'top', 30 31 // if set, bind click events through delegation 32 // supported since jQuery 1.4.2 33 delegateSelector: null, 34 35 // jQuery set of elements you wish to scroll (for $.smoothScroll). 36 // if null (default), $('html, body').firstScrollable() is used. 37 scrollElement: null, 38 39 // only use if you want to override default behavior 40 scrollTarget: null, 41 42 // automatically focus the target element after scrolling to it 43 autoFocus: false, 44 45 // fn(opts) function to be called before scrolling occurs. 46 // `this` is the element(s) being scrolled 47 beforeScroll: function() {}, 48 49 // fn(opts) function to be called after scrolling occurs. 50 // `this` is the triggering element 51 afterScroll: function() {}, 52 53 // easing name. jQuery comes with "swing" and "linear." For others, you'll need an easing plugin 54 // from jQuery UI or elsewhere 55 easing: 'swing', 56 57 // speed can be a number or 'auto' 58 // if 'auto', the speed will be calculated based on the formula: 59 // (current scroll position - target scroll position) / autoCoeffic 60 speed: 400, 61 62 // coefficient for "auto" speed 63 autoCoefficient: 2, 64 65 // $.fn.smoothScroll only: whether to prevent the default click action 66 preventDefault: true 67 }; 68 69 var getScrollable = function(opts) { 70 var scrollable = []; 71 var scrolled = false; 72 var dir = opts.dir && opts.dir === 'left' ? 'scrollLeft' : 'scrollTop'; 73 74 this.each(function() { 75 var el = $(this); 76 77 if (this === document || this === window) { 78 return; 79 } 80 81 if (document.scrollingElement && (this === document.documentElement || this === document.body)) { 82 scrollable.push(document.scrollingElement); 83 84 return false; 85 } 86 87 if (el[dir]() > 0) { 88 scrollable.push(this); 89 } else { 90 // if scroll(Top|Left) === 0, nudge the element 1px and see if it moves 91 el[dir](1); 92 scrolled = el[dir]() > 0; 93 94 if (scrolled) { 95 scrollable.push(this); 96 } 97 // then put it back, of course 98 el[dir](0); 99 } 100 }); 101 102 if (!scrollable.length) { 103 this.each(function() { 104 // If no scrollable elements and <html> has scroll-behavior:smooth because 105 // "When this property is specified on the root element, it applies to the viewport instead." 106 // and "The scroll-behavior property of the ⦠body element is *not* propagated to the viewport." 107 // â https://drafts.csswg.org/cssom-view/#propdef-scroll-behavior 108 if (this === document.documentElement && $(this).css('scrollBehavior') === 'smooth') { 109 scrollable = [this]; 110 } 111 112 // If still no scrollable elements, fall back to <body>, 113 // if it's in the jQuery collection 114 // (doing this because Safari sets scrollTop async, 115 // so can't set it to 1 and immediately get the value.) 116 if (!scrollable.length && this.nodeName === 'BODY') { 117 scrollable = [this]; 118 } 119 }); 120 } 121 122 // Use the first scrollable element if we're calling firstScrollable() 123 if (opts.el === 'first' && scrollable.length > 1) { 124 scrollable = [scrollable[0]]; 125 } 126 127 return scrollable; 128 }; 129 130 var rRelative = /^([\-\+]=)(\d+)/; 131 132 $.fn.extend({ 133 scrollable: function(dir) { 134 var scrl = getScrollable.call(this, {dir: dir}); 135 136 return this.pushStack(scrl); 137 }, 138 firstScrollable: function(dir) { 139 var scrl = getScrollable.call(this, {el: 'first', dir: dir}); 140 141 return this.pushStack(scrl); 142 }, 143 144 smoothScroll: function(options, extra) { 145 options = options || {}; 146 147 if (options === 'options') { 148 if (!extra) { 149 return this.first().data('ssOpts'); 150 } 151 152 return this.each(function() { 153 var $this = $(this); 154 var opts = $.extend($this.data('ssOpts') || {}, extra); 155 156 $(this).data('ssOpts', opts); 157 }); 158 } 159 160 var opts = $.extend({}, $.fn.smoothScroll.defaults, options); 161 162 var clickHandler = function(event) { 163 var escapeSelector = function(str) { 164 return str.replace(/(:|\.|\/)/g, '\\$1'); 165 }; 166 167 var link = this; 168 var $link = $(this); 169 var thisOpts = $.extend({}, opts, $link.data('ssOpts') || {}); 170 var exclude = opts.exclude; 171 var excludeWithin = thisOpts.excludeWithin; 172 var elCounter = 0; 173 var ewlCounter = 0; 174 var include = true; 175 var clickOpts = {}; 176 var locationPath = $.smoothScroll.filterPath(location.pathname); 177 var linkPath = $.smoothScroll.filterPath(link.pathname); 178 var hostMatch = location.hostname === link.hostname || !link.hostname; 179 var pathMatch = thisOpts.scrollTarget || (linkPath === locationPath); 180 var thisHash = escapeSelector(link.hash); 181 182 if (thisHash && !$(thisHash).length) { 183 include = false;
184 } 185 186 if (!thisOpts.scrollTarget && (!hostMatch || !pathMatch || !thisHash)) { 187 include = false; 188 } else { 189 while (include && elCounter < exclude.length) { 190 if ($link.is(escapeSelector(exclude[elCounter++]))) { 191 include = false; 192 } 193 } 194 195 while (include && ewlCounter < excludeWithin.length) { 196 if ($link.closest(excludeWithin[ewlCounter++]).length) { 197 include = false; 198 } 199 } 200 } 201 202 if (include) { 203 if (thisOpts.preventDefault) { 204 event.preventDefault(); 205 } 206 207 $.extend(clickOpts, thisOpts, { 208 scrollTarget: thisOpts.scrollTarget || thisHash, 209 link: link 210 }); 211 212 $.smoothScroll(clickOpts); 213 } 214 }; 215 216 if (options.delegateSelector !== null) { 217 this 218 .off('click.smoothscroll', options.delegateSelector) 219 .on('click.smoothscroll', options.delegateSelector, clickHandler); 220 } else { 221 this 222 .off('click.smoothscroll') 223 .on('click.smoothscroll', clickHandler); 224 } 225 226 return this; 227 } 228 }); 229 230 var getExplicitOffset = function(val) { 231 var explicit = {relative: ''}; 232 var parts = typeof val === 'string' && rRelative.exec(val); 233 234 if (typeof val === 'number') { 235 explicit.px = val; 236 } else if (parts) { 237 explicit.relative = parts[1]; 238 explicit.px = parseFloat(parts[2]) || 0; 239 } 240 241 return explicit; 242 }; 243 244 var onAfterScroll = function(opts) { 245 var $tgt = $(opts.scrollTarget); 246 247 if (opts.autoFocus && $tgt.length) { 248 $tgt[0].focus(); 249 250 if (!$tgt.is(document.activeElement)) { 251 $tgt.prop({tabIndex: -1}); 252 $tgt[0].focus(); 253 } 254 } 255 256 opts.afterScroll.call(opts.link, opts); 257 }; 258 259 $.smoothScroll = function(options, px) { 260 if (options === 'options' && typeof px === 'object') { 261 return $.extend(optionOverrides, px); 262 } 263 var opts, $scroller, speed, delta; 264 var explicitOffset = getExplicitOffset(options); 265 var scrollTargetOffset = {}; 266 var scrollerOffset = 0; 267 var offPos = 'offset'; 268 var scrollDir = 'scrollTop'; 269 var aniProps = {}; 270 var aniOpts = {}; 271 272 if (explicitOffset.px) { 273 opts = $.extend({link: null}, $.fn.smoothScroll.defaults, optionOverrides); 274 } else { 275 opts = $.extend({link: null}, $.fn.smoothScroll.defaults, options || {}, optionOverrides); 276 277 if (opts.scrollElement) { 278 offPos = 'position'; 279 280 if (opts.scrollElement.css('position') === 'static') { 281 opts.scrollElement.css('position', 'relative'); 282 } 283 } 284 285 if (px) { 286 explicitOffset = getExplicitOffset(px); 287 } 288 } 289 290 scrollDir = opts.direction === 'left' ? 'scrollLeft' : scrollDir; 291 292 if (opts.scrollElement) { 293 $scroller = opts.scrollElement; 294 295 if (!explicitOffset.px && !(/^(?:HTML|BODY)$/).test($scroller[0].nodeName)) { 296 scrollerOffset = $scroller[scrollDir](); 297 } 298 } else { 299 $scroller = $('html, body').firstScrollable(opts.direction); 300 } 301 302 // beforeScroll callback function must fire before calculating offset 303 opts.beforeScroll.call($scroller, opts); 304 305 scrollTargetOffset = explicitOffset.px ? explicitOffset : { 306 relative: '', 307 px: ($(opts.scrollTarget)[offPos]() && $(opts.scrollTarget)[offPos]()[opts.direction]) || 0 308 }; 309 310 aniProps[scrollDir] = scrollTargetOffset.relative + (scrollTargetOffset.px + scrollerOffset + opts.offset); 311 312 speed = opts.speed; 313 314 // automatically calculate the speed of the scroll based on distance / coefficient 315 if (speed === 'auto') { 316 317 // $scroller[scrollDir]() is position before scroll, aniProps[scrollDir] is position after 318 // When delta is greater, speed will be greater. 319 delta = Math.abs(aniProps[scrollDir] - $scroller[scrollDir]()); 320 321 // Divide the delta by the coefficient 322 speed = delta / opts.autoCoefficient; 323 } 324 325 aniOpts = { 326 duration: speed, 327 easing: opts.easing, 328 complete: function() { 329 onAfterScroll(opts); 330 } 331 }; 332 333 if (opts.step) { 334 aniOpts.step = opts.step; 335 } 336 337 if ($scroller.length) { 338 $scroller.stop().animate(aniProps, aniOpts); 339 } else { 340 onAfterScroll(opts); 341 } 342 }; 343 344 $.smoothScroll.version = version; 345 $.smoothScroll.filterPath = function(string) { 346 string = string || ''; 347 348 return string 349 .replace(/^\//, '') 350 .replace(/(?:index|default).[a-zA-Z]{3,4}$/, '') 351 .replace(/\/$/, ''); 352 }; 353 354 // default options 355 $.fn.smoothScroll.defaults = defaults; 356 357}));
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.