vendor: 20,969 bytes, lines 1-567
1/* 2 * ScrollToFixed 3 * https://github.com/bigspotteddog/ScrollToFixed 4 * 5 * Copyright (c) 2011 Joseph Cava-Lynch 6 * MIT license 7 */ 8(function($) { 9 $.isScrollToFixed = function(el) { 10 return !!$(el).data('ScrollToFixed'); 11 }; 12 13 $.ScrollToFixed = function(el, options) { 14 // To avoid scope issues, use 'base' instead of 'this' to reference this 15 // class from internal events and functions. 16 var base = this; 17 18 // Access to jQuery and DOM versions of element. 19 base.$el = $(el); 20 base.el = el; 21 22 // Add a reverse reference to the DOM object. 23 base.$el.data('ScrollToFixed', base); 24 25 // A flag so we know if the scroll has been reset. 26 var isReset = false; 27 28 // The element that was given to us to fix if scrolled above the top of 29 // the page. 30 var target = base.$el; 31 32 var position; 33 var originalPosition; 34 var originalFloat; 35 var originalOffsetTop; 36 var originalZIndex; 37 38 // The offset top of the element when resetScroll was called. This is 39 // used to determine if we have scrolled past the top of the element. 40 var offsetTop = 0; 41 42 // The offset left of the element when resetScroll was called. This is 43 // used to move the element left or right relative to the horizontal 44 // scroll. 45 var offsetLeft = 0; 46 var originalOffsetLeft = -1; 47 48 // This last offset used to move the element horizontally. This is used 49 // to determine if we need to move the element because we would not want 50 // to do that for no reason. 51 var lastOffsetLeft = -1; 52 53 // This is the element used to fill the void left by the target element 54 // when it goes fixed; otherwise, everything below it moves up the page. 55 var spacer = null; 56 57 var spacerClass; 58 59 var className; 60 61 // Capture the original offsets for the target element. This needs to be 62 // called whenever the page size changes or when the page is first 63 // scrolled. For some reason, calling this before the page is first 64 // scrolled causes the element to become fixed too late. 65 function resetScroll() { 66 // Set the element to it original positioning. 67 target.trigger('preUnfixed.ScrollToFixed'); 68 setUnfixed(); 69 target.trigger('unfixed.ScrollToFixed'); 70 71 // Reset the last offset used to determine if the page has moved 72 // horizontally. 73 lastOffsetLeft = -1; 74 75 // Capture the offset top of the target element. 76 offsetTop = target.offset().top; 77 78 // Capture the offset left of the target element. 79 offsetLeft = target.offset().left; 80 81 // If the offsets option is on, alter the left offset. 82 if (base.options.offsets) { 83 offsetLeft += (target.offset().left - target.position().left); 84 } 85 86 if (originalOffsetLeft == -1) { 87 originalOffsetLeft = offsetLeft; 88 } 89 90 position = target.css('position'); 91 92 // Set that this has been called at least once. 93 isReset = true; 94 95 if (base.options.bottom != -1) { 96 target.trigger('preFixed.ScrollToFixed'); 97 setFixed(); 98 target.trigger('fixed.ScrollToFixed'); 99 } 100 } 101 102 function getLimit() { 103 var limit = base.options.limit; 104 if (!limit) return 0; 105 106 if (typeof(limit) === 'function') { 107 return limit.apply(target); 108 } 109 return limit; 110 } 111 112 // Returns whether the target element is fixed or not. 113 function isFixed() { 114 return position === 'fixed'; 115 } 116 117 // Returns whether the target element is absolute or not. 118 function isAbsolute() { 119 return position === 'absolute'; 120 } 121 122 function isUnfixed() { 123 return !(isFixed() || isAbsolute()); 124 } 125 126 // Sets the target element to fixed. Also, sets the spacer to fill the 127 // void left by the target element. 128 function setFixed() { 129 // Only fix the target element and the spacer if we need to. 130 if (!isFixed()) { 131 //get REAL dimensions (decimal fix) 132 //Ref. http://stackoverflow.com/questions/3603065/how-to-make-jquery-to-not-round-value-returned-by-width 133 var dimensions = target[0].getBoundingClientRect(); 134 135 // Set the spacer to fill the height and width of the target 136 // element, then display it. 137 spacer.css({ 138 'display' : target.css('display'), 139 'width' : dimensions.width, 140 'height' : dimensions.height, 141 'float' : target.css('float') 142 }); 143 144 // Set the target element to fixed and set its width so it does 145 // not fill the rest of the page horizontally. Also, set its top 146 // to the margin top specified in the options. 147 148 cssOptions={ 149 'z-index' : base.options.zIndex, 150 'position' : 'fixed', 151 'top' : base.options.bottom == -1?getMarginTop():'', 152 'bottom' : base.options.bottom == -1?'':base.options.bottom, 153 'margin-left' : '0px' 154 } 155 if (!base.options.dontSetWidth){ cssOptions['width']=target.css('width'); }; 156 157 target.css(cssOptions); 158 159 target.addClass(base.options.baseClassName); 160 161 if (base.options.className) { 162 target.addClass(base.options.className); 163 } 164 165 position = 'fixed'; 166 } 167 } 168 169 function setAbsolute() { 170 171 var top = getLimit(); 172 var left = offsetLeft; 173 174 if (base.options.removeOffsets) { 175 left = ''; 176 top = top - offsetTop; 177 } 178 179 cssOptions={ 180 'position' : 'absolute', 181 'top' : top, 182 'left' : left, 183 'margin-left' : '0px', 184 'bottom' : '' 185 } 186 if (!base.options.dontSetWidth){ cssOptions['width']=target.css('width'); }; 187 188 target.css(cssOptions); 189 190 position = 'absolute'; 191 } 192 193 // Sets the target element back to unfixed. Also, hides the spacer. 194 function setUnfixed() { 195 // Only unfix the target element and the spacer if we need to. 196 if (!isUnfixed()) { 197 lastOffsetLeft = -1; 198 199 // Hide the spacer now that the target element will fill the 200 // space. 201 spacer.css('display', 'none'); 202 203 // Remove the style attributes that were added to the target. 204 // This will reverse the target back to the its original style. 205 target.css({ 206 'z-index' : originalZIndex, 207 'width' : '', 208 'position' : originalPosition, 209 'left' : '', 210 'top' : originalOffsetTop, 211 'margin-left' : '' 212 }); 213 214 target.removeClass('scroll-to-fixed-fixed'); 215 216 if (base.options.className) { 217 target.removeClass(base.options.className); 218 } 219 220 position = null; 221 } 222 } 223 224 // Moves the target element left or right relative to the horizontal 225 // scroll position. 226 function setLeft(x) { 227 // Only if the scroll is not what it was last time we did this. 228 if (x != lastOffsetLeft) { 229 // Move the target element horizontally relative to its original 230 // horizontal position. 231 target.css('left', offsetLeft - x); 232 233 // Hold the last horizontal position set. 234 lastOffsetLeft = x; 235 } 236 } 237 238 function getMarginTop() { 239 var marginTop = base.options.marginTop; 240 if (!marginTop) return 0; 241 242 if (typeof(marginTop) === 'function') { 243 return marginTop.apply(target); 244 } 245 return marginTop; 246 } 247 248 // Checks to see if we need to do something based on new scroll position 249 // of the page. 250 function checkScroll() { 251 if (!$.isScrollToFixed(target) || target.is(':hidden')) return; 252 var wasReset = isReset; 253 var wasUnfixed = isUnfixed(); 254 255 // If resetScroll has not yet been called, call it. This only 256 // happens once. 257 if (!isReset) { 258 resetScroll(); 259 } else if (isUnfixed()) { 260 // if the offset has changed since the last scroll, 261 // we need to get it again. 262 263 // Capture the offset top of the target element. 264 offsetTop = target.offset().top; 265 266 // Capture the offset left of the target element. 267 offsetLeft = target.offset().left; 268 } 269 270 // Grab the current horizontal scroll position. 271 var x = $(window).scrollLeft(); 272 273 // Grab the current vertical scroll position. 274 var y = $(window).scrollTop(); 275 276 // Get the limit, if there is one. 277 var limit = getLimit(); 278 279 // If the vertical scroll position, plus the optional margin, would 280 // put the target element at the specified limit, set the target 281 // element to absolute. 282 if (base.options.minWidth && $(window).width() < base.options.minWidth) { 283 if (!isUnfixed() || !wasReset) { 284 postPosition(); 285 target.trigger('preUnfixed.ScrollToFixed'); 286 setUnfixed(); 287 target.trigger('unfixed.ScrollToFixed'); 288 } 289 } else if (base.options.maxWidth && $(window).width() > base.options.maxWidth) { 290 if (!isUnfixed() || !wasReset) { 291 postPosition(); 292 target.trigger('preUnfixed.ScrollToFixed'); 293 setUnfixed(); 294 target.trigger('unfixed.ScrollToFixed'); 295 } 296 } else if (base.options.bottom == -1) { 297 // If the vertical scroll position, plus the optional margin, would 298 // put the target element at the specified limit, set the target 299 // element to absolute. 300 if (limit > 0 && y >= limit - getMarginTop()) { 301 if (!wasUnfixed && (!isAbsolute() || !wasReset)) { 302 postPosition(); 303 target.trigger('preAbsolute.ScrollToFixed'); 304 setAbsolute(); 305 target.trigger('unfixed.ScrollToFixed'); 306 } 307 // If the vertical scroll position, plus the optional margin, would 308 // put the target element above the top of the page, set the target 309 // element to fixed. 310 } else if (y >= offsetTop - getMarginTop()) { 311 if (!isFixed() || !wasReset) { 312 postPosition(); 313 target.trigger('preFixed.ScrollToFixed'); 314 315 // Set the target element to fixed. 316 setFixed(); 317 318 // Reset the last offset left because we just went fixed. 319 lastOffsetLeft = -1; 320 321 target.trigger('fixed.ScrollToFixed'); 322 } 323 // If the page has been scrolled horizontally as well, move the 324 // target element accordingly. 325 setLeft(x); 326 } else { 327 // Set the target element to unfixed, placing it where it was 328 // before. 329 if (!isUnfixed() || !wasReset) { 330 postPosition(); 331 target.trigger('preUnfixed.ScrollToFixed'); 332 setUnfixed(); 333 target.trigger('unfixed.ScrollToFixed'); 334 } 335 } 336 } else { 337 if (limit > 0) { 338 if (y + $(window).height() - target.outerHeight(true) >= limit - (getMarginTop() || -getBottom())) { 339 if (isFixed()) { 340 postPosition(); 341 target.trigger('preUnfixed.ScrollToFixed'); 342 343 if (originalPosition === 'absolute') { 344 setAbsolute(); 345 } else { 346 setUnfixed(); 347 } 348 349 target.trigger('unfixed.ScrollToFixed'); 350 } 351 } else { 352 if (!isFixed()) { 353 postPosition(); 354 target.trigger('preFixed.ScrollToFixed'); 355 setFixed(); 356 } 357 setLeft(x); 358 target.trigger('fixed.ScrollToFixed'); 359 } 360 } else { 361 setLeft(x); 362 } 363 } 364 } 365 366 function getBottom() { 367 if (!base.options.bottom) return 0; 368 return base.options.bottom; 369 } 370 371 function postPosition() { 372 var position = target.css('position'); 373 374 if (position == 'absolute') { 375 target.trigger('postAbsolute.ScrollToFixed'); 376 } else if (position == 'fixed') { 377 target.trigger('postFixed.ScrollToFixed'); 378 } else { 379 target.trigger('postUnfixed.ScrollToFixed'); 380 } 381 } 382 383 var windowResize = function(event) { 384 // Check if the element is visible before updating it's position, which 385 // improves behavior with responsive designs where this element is hidden. 386 if(target.is(':visible')) { 387 isReset = false; 388 checkScroll(); 389 } else { 390 // Ensure the spacer is hidden 391 setUnfixed(); 392 } 393 } 394 395 var windowScroll = function(event) { 396 (!!window.requestAnimationFrame) ? requestAnimationFrame(checkScroll) : checkScroll(); 397 } 398 399 // From: http://kangax.github.com/cft/#IS_POSITION_FIXED_SUPPORTED 400 var isPositionFixedSupported = function() { 401 var container = document.body; 402 403 if (document.createElement && container && container.appendChild && container.removeChild) { 404 var el = document.createElement('div'); 405 406 if (!el.getBoundingClientRect) return null; 407 408 el.innerHTML = 'x'; 409 el.style.cssText = 'position:fixed;top:100px;'; 410 container.appendChild(el); 411 412 var originalHeight = container.style.height, 413 originalScrollTop = container.scrollTop; 414 415 container.style.height = '3000px'; 416 container.scrollTop = 500; 417 418 var elementTop = el.getBoundingClientRect().top; 419 container.style.height = originalHeight; 420 421 var isSupported = (elementTop === 100); 422 container.removeChild(el); 423 container.scrollTop = originalScrollTop; 424 425 return isSupported; 426 } 427 428 return null; 429 } 430 431 var preventDefault = function(e) { 432 e = e || window.event; 433 if (e.preventDefault) { 434 e.preventDefault(); 435 } 436 e.returnValue = false; 437 } 438 439 // Initializes this plugin. Captures the options passed in, turns this 440 // off for devices that do not support fixed position, adds the spacer, 441 // and binds to the window scroll and resize events. 442 base.init = function() { 443 // Capture the options for this plugin. 444 base.options = $.extend({}, $.ScrollToFixed.defaultOptions, options); 445 446 originalZIndex = target.css('z-index') 447 448 // Turn off this functionality for devices that do not support it. 449 // if (!(base.options && base.options.dontCheckForPositionFixedSupport)) { 450 // var fixedSupported = isPositionFixedSupported(); 451 // if (!fixedSupported) return; 452 // } 453 454 // Put the target element on top of everything that could be below 455 // it. This reduces flicker when the target element is transitioning 456 // to fixed. 457 base.$el.css('z-index', base.options.zIndex); 458 459 // Create a spacer element to fill the void left by the target 460 // element when it goes fixed. 461 spacer = $('<div />'); 462 463 position = target.css('position'); 464 originalPosition = target.css('position'); 465 originalFloat = target.css('float'); 466 originalOffsetTop = target.css('top'); 467 468 // Place the spacer right after the target element. 469 if (isUnfixed()) base.$el.after(spacer); 470 471 // Reset the target element offsets when the window is resized, then 472 // check to see if we need to fix or unfix the target element. 473 $(window).bind('resize.ScrollToFixed', windowResize); 474 475 // When the window scrolls, check to see if we need to fix or unfix 476 // the target element. 477 $(window).bind('scroll.ScrollToFixed', windowScroll); 478 479 // For touch devices, call checkScroll directlly rather than 480 // rAF wrapped windowScroll to animate the element 481 if ('ontouchmove' in window) { 482 $(window).bind('touchmove.ScrollToFixed', checkScroll); 483 } 484 485 if (base.options.preFixed) { 486 target.bind('preFixed.ScrollToFixed', base.options.preFixed); 487 } 488 if (base.options.postFixed) { 489 target.bind('postFixed.ScrollToFixed', base.options.postFixed); 490 } 491 if (base.options.preUnfixed) { 492 target.bind('preUnfixed.ScrollToFixed', base.options.preUnfixed); 493 } 494 if (base.options.postUnfixed) { 495 target.bind('postUnfixed.ScrollToFixed', base.options.postUnfixed); 496 } 497 if (base.options.preAbsolute) { 498 target.bind('preAbsolute.ScrollToFixed', base.options.preAbsolute); 499 } 500 if (base.options.postAbsolute) { 501 target.bind('postAbsolute.ScrollToFixed', base.options.postAbsolute); 502 } 503 if (base.options.fixed) { 504 target.bind('fixed.ScrollToFixed', base.options.fixed); 505 } 506 if (base.options.unfixed) { 507 target.bind('unfixed.ScrollToFixed', base.options.unfixed); 508 } 509 510 if (base.options.spacerClass) { 511 spacer.addClass(base.options.spacerClass); 512 } 513 514 target.bind('resize.ScrollToFixed', function() { 515 spacer.height(target.height()); 516 }); 517 518 target.bind('scroll.ScrollToFixed', function() { 519 target.trigger('preUnfixed.ScrollToFixed'); 520 setUnfixed(); 521 target.trigger('unfixed.ScrollToFixed'); 522 checkScroll(); 523 }); 524 525 target.bind('detach.ScrollToFixed', function(ev) { 526 preventDefault(ev); 527 528 target.trigger('preUnfixed.ScrollToFixed'); 529 setUnfixed(); 530 target.trigger('unfixed.ScrollToFixed'); 531 532 $(window).unbind('resize.ScrollToFixed', windowResize); 533 $(window).unbind('scroll.ScrollToFixed', windowScroll); 534 535 target.unbind('.ScrollToFixed'); 536 537 //remove spacer from dom 538 spacer.remove(); 539 540 base.$el.removeData('ScrollToFixed'); 541 }); 542 543 // Reset everything. 544 windowResize(); 545 }; 546 547 // Initialize the plugin. 548 base.init(); 549 }; 550 551 // Sets the option defaults. 552 $.ScrollToFixed.defaultOptions = { 553 marginTop : 0, 554 limit : 0, 555 bottom : -1, 556 zIndex : 1000, 557 baseClassName: 'scroll-to-fixed-fixed' 558 }; 559 560 // Returns enhanced elements that will fix to the top of the page when the 561 // page is scrolled. 562 $.fn.scrollToFixed = function(options) { 563 return this.each(function() { 564 (new $.ScrollToFixed(this, options)); 565 }); 566 }; 567})(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.