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