1(function($) { 2 3 var version = '1.4.10', 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 autoCoefficent: 2 31 }, 32 33 getScrollable = function(opts) { 34 var scrollable = [], 35 scrolled = false, 36 dir = opts.dir && opts.dir == 'left' ? 'scrollLeft' : 'scrollTop'; 37 38 this.each(function() { 39 40 if (this == document || this == window) { return; } 41 var el = $(this); 42 if ( el[dir]() > 0 ) { 43 scrollable.push(this); 44 } else { 45 // if scroll(Top|Left) === 0, nudge the element 1px and see if it moves 46 el[dir](1); 47 scrolled = el[dir]() > 0; 48 if ( scrolled ) { 49 scrollable.push(this); 50 } 51 // then put it back, of course 52 el[dir](0); 53 } 54 }); 55 56 // If no scrollable elements, fall back to <body>, 57 // if it's in the jQuery collection 58 // (doing this because Safari sets scrollTop async, 59 // so can't set it to 1 and immediately get the value.) 60 if (!scrollable.length) { 61 this.each(function(index) { 62 if (this.nodeName === 'BODY') { 63 scrollable = [this]; 64 } 65 }); 66 } 67 68 // Use the first scrollable element if we're calling firstScrollable() 69 if ( opts.el === 'first' && scrollable.length > 1 ) { 70 scrollable = [ scrollable[0] ]; 71 } 72 73 return scrollable; 74 }, 75 isTouch = 'ontouchend' in document; 76 77 $.fn.extend({ 78 scrollable: function(dir) { 79 var scrl = getScrollable.call(this, {dir: dir}); 80 return this.pushStack(scrl); 81 }, 82 firstScrollable: function(dir) { 83 var scrl = getScrollable.call(this, {el: 'first', dir: dir}); 84 return this.pushStack(scrl); 85 }, 86 87 smoothScroll: function(options) { 88 options = options || {}; 89 var opts = $.extend({}, $.fn.smoothScroll.defaults, options), 90 locationPath = $.smoothScroll.filterPath(location.pathname); 91 92 this 93 .unbind('click.smoothscroll') 94 .bind('click.smoothscroll', function(event) { 95 var link = this, 96 $link = $(this), 97 exclude = opts.exclude, 98 excludeWithin = opts.excludeWithin, 99 elCounter = 0, ewlCounter = 0, 100 include = true, 101 clickOpts = {}, 102 hostMatch = ((location.hostname === link.hostname) || !link.hostname), 103 pathMatch = opts.scrollTarget || ( $.smoothScroll.filterPath(link.pathname) || locationPath ) === locationPath, 104 thisHash = escapeSelector(link.hash); 105 106 if ( !opts.scrollTarget && (!hostMatch || !pathMatch || !thisHash) ) { 107 include = false; 108 } else { 109 while (include && elCounter < exclude.length) { 110 if ($link.is(escapeSelector(exclude[elCounter++]))) { 111 include = false; 112 } 113 } 114 while ( include && ewlCounter < excludeWithin.length ) { 115 if ($link.closest(excludeWithin[ewlCounter++]).length) { 116 include = false; 117 } 118 } 119 } 120 121 if ( include ) { 122 event.preventDefault(); 123 124 $.extend( clickOpts, opts, { 125 scrollTarget: opts.scrollTarget || thisHash, 126 link: link 127 }); 128 129 $.smoothScroll( clickOpts ); 130 } 131 }); 132 133 return this; 134 } 135 }); 136 137 $.smoothScroll = function(options, px) { 138 var opts, $scroller, scrollTargetOffset, speed, 139 scrollerOffset = 0, 140 offPos = 'offset', 141 scrollDir = 'scrollTop', 142 aniProps = {}, 143 aniOpts = {}, 144 scrollprops = []; 145 146 147 if (typeof options === 'number') { 148 opts = $.fn.smoothScroll.defaults; 149 scrollTargetOffset = options; 150 } else { 151 opts = $.extend({}, $.fn.smoothScroll.defaults, options || {}); 152 if (opts.scrollElement) { 153 offPos = 'position'; 154 if (opts.scrollElement.css('position') == 'static') { 155 opts.scrollElement.css('position', 'relative'); 156 } 157 } 158 } 159 160 opts = $.extend({link: null}, opts); 161 scrollDir = opts.direction == 'left' ? 'scrollLeft' : scrollDir; 162 163 if ( opts.scrollElement ) { 164 $scroller = opts.scrollElement; 165 scrollerOffset = $scroller[scrollDir](); 166 } else { 167 $scroller = $('html, body').firstScrollable(); 168 } 169 170 // beforeScroll callback function must fire before calculating offset 171 opts.beforeScroll.call($scroller, opts); 172 173 scrollTargetOffset = (typeof options === 'number') ? options : 174 px || 175 ( $(opts.scrollTarget)[offPos]() && 176 $(opts.scrollTarget)[offPos]()[opts.direction] ) || 177 0; 178 179 aniProps[scrollDir] = scrollTargetOffset + scrollerOffset + opts.offset; 180 speed = opts.speed; 181 182 // automatically calculate the speed of the scroll based on distance / coefficient 183 if (speed === 'auto') { 184 185 // if aniProps[scrollDir] == 0 then we'll use scrollTop() value instead 186 speed = aniProps[scrollDir] || $scroller.scrollTop(); 187 188 // divide the speed by the coefficient 189 speed = speed / opts.autoCoefficent; 190 } 191 192 aniOpts = { 193 duration: speed, 194 easing: opts.easing, 195 complete: function() { 196 opts.afterScroll.call(opts.link, opts); 197 } 198 }; 199 200 if (opts.step) { 201 aniOpts.step = opts.step; 202 } 203 204 if ($scroller.length) { 205 $scroller.stop().animate(aniProps, aniOpts); 206 } else { 207 opts.afterScroll.call(opts.link, opts); 208 } 209 }; 210 211 $.smoothScroll.version = version; 212 $.smoothScroll.filterPath = function(string) { 213 return string 214 .replace(/^\//,'') 215 .replace(/(index|default).[a-zA-Z]{3,4}$/,'') 216 .replace(/\/$/,''); 217 }; 218 219// default options 220 $.fn.smoothScroll.defaults = defaults; 221 222 function escapeSelector (str) { 223 return str.replace(/(:|\.)/g,'\\$1'); 224 } 225 226})(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.