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