1(function ($) { 2 "use strict"; 3 $.fn.pin = function (options) { 4 var scrollY = 0, elements = [], disabled = false, $window = $(window); 5 6 options = options || {}; 7 8 var recalculateLimits = function () { 9 for (var i=0, len=elements.length; i<len; i++) { 10 var $this = elements[i]; 11 12 if (options.minWidth && $window.width() <= options.minWidth) { 13 if ($this.parent().is(".pin-wrapper")) { $this.unwrap(); } 14 $this.css({width: "", left: "", top: "", position: ""}); 15 if (options.activeClass) { $this.removeClass(options.activeClass); } 16 disabled = true; 17 continue; 18 } else { 19 disabled = false; 20 } 21 22 var $container = options.containerSelector ? $this.closest(options.containerSelector) : $(document.body); 23 var offset = $this.offset(); 24 var containerOffset = $container.offset(); 25 var parentOffset = $this.offsetParent().offset(); 26 27 if (!$this.parent().is(".pin-wrapper")) { 28 $this.wrap("<div class='pin-wrapper'>"); 29 } 30 31 var pad = $.extend({ 32 top: 0, 33 bottom: 0 34 }, options.padding || {}); 35 36 $this.data("pin", { 37 pad: pad, 38 from: (options.containerSelector ? containerOffset.top : offset.top) - pad.top, 39 to: containerOffset.top + $container.height() - $this.outerHeight() - pad.bottom, 40 end: containerOffset.top + $container.height(), 41 parentTop: parentOffset.top 42 }); 43 44 $this.css({width: $this.outerWidth()}); 45 $this.parent().css("height", $this.outerHeight()); 46 } 47 }; 48 49 var onScroll = function () { 50 if (disabled) { return; } 51 52 scrollY = $window.scrollTop(); 53 54 var elmts = []; 55 for (var i=0, len=elements.length; i<len; i++) { 56 var $this = $(elements[i]), 57 data = $this.data("pin"); 58 59 if (!data) { // Removed element 60 continue; 61 } 62 63 elmts.push($this); 64 65 var from = data.from - data.pad.bottom, 66 to = data.to - data.pad.top; 67 68 if (from + $this.outerHeight() > data.end) { 69 $this.css('position', ''); 70 continue; 71 } 72 73 if (from < scrollY && to > scrollY) { 74 !($this.css("position") == "fixed") && $this.css({ 75 left: $this.offset().left, 76 top: data.pad.top 77 }).css("position", "fixed"); 78 if (options.activeClass) { $this.addClass(options.activeClass); } 79 } else if (scrollY >= to) { 80 $this.css({ 81 left: "", 82 top: to - data.parentTop + data.pad.top - 100 83 }).css("position", "absolute"); 84 if (options.activeClass) { $this.addClass(options.activeClass); } 85 } else { 86 $this.css({position: "", top: "", left: ""}); 87 if (options.activeClass) { $this.removeClass(options.activeClass); } 88 } 89 } 90 elements = elmts; 91 }; 92 93 var update = function () { recalculateLimits(); onScroll(); }; 94 95 this.each(function () { 96 var $this = $(this), 97 data = $(this).data('pin') || {}; 98 99 if (data && data.update) { return; } 100 elements.push($this); 101 $("img", this).one("load", recalculateLimits); 102 data.update = update; 103 $(this).data('pin', data); 104 }); 105 106 $window.scroll(onScroll); 107 $window.resize(function () { recalculateLimits(); }); 108 recalculateLimits(); 109 110 $window.load(update); 111 112 return this; 113 }; 114})(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.