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