1 2(function($) { 3 var defaults = { 4 topSpacing: 0, 5 bottomSpacing: 0, 6 className: 'is-sticky', 7 wrapperClassName: 'sticky-wrapper', 8 center: false, 9 getWidthFrom: '' 10 }, 11 $window = $(window), 12 $document = $(document), 13 sticked = [], 14 windowHeight = $window.height(), 15 scroller = function() { 16 var scrollTop = $window.scrollTop(), 17 documentHeight = $document.height(), 18 dwh = documentHeight - windowHeight, 19 extra = (scrollTop > dwh) ? dwh - scrollTop : 0; 20 21 for (var i = 0; i < sticked.length; i++) { 22 var s = sticked[i], 23 elementTop = s.stickyWrapper.offset().top, 24 etse = elementTop - s.topSpacing - extra; 25 26 if (scrollTop <= etse) { 27 if (s.currentTop !== null) { 28 s.stickyElement 29 .css('position', '') 30 .css('top', ''); 31 s.stickyElement.parent().removeClass(s.className); 32 s.currentTop = null; 33 } 34 } 35 else { 36 var newTop = documentHeight - s.stickyElement.outerHeight() 37 - s.topSpacing - s.bottomSpacing - scrollTop - extra; 38 if (newTop < 0) { 39 newTop = newTop + s.topSpacing; 40 } else { 41 newTop = s.topSpacing; 42 } 43 if (s.currentTop != newTop) { 44 s.stickyElement 45 .css('position', 'fixed') 46 .css('top', newTop); 47 48 if (typeof s.getWidthFrom !== 'undefined') { 49 s.stickyElement.css('width', $(s.getWidthFrom).width()); 50 } 51 52 s.stickyElement.parent().addClass(s.className); 53 s.currentTop = newTop; 54 } 55 } 56 } 57 }, 58 resizer = function() { 59 windowHeight = $window.height(); 60 }, 61 methods = { 62 init: function(options) { 63 var o = $.extend(defaults, options); 64 return this.each(function() { 65 var stickyElement = $(this); 66 67 var stickyId = stickyElement.attr('id'); 68 var wrapper = $('<div></div>') 69 .attr('id', stickyId + '-sticky-wrapper') 70 .addClass(o.wrapperClassName); 71 stickyElement.wrapAll(wrapper); 72 73 if (o.center) { 74 stickyElement.parent().css({width:stickyElement.outerWidth(),marginLeft:"auto",marginRight:"auto"}); 75 } 76 77 if (stickyElement.css("float") == "right") { 78 stickyElement.css({"float":"none"}).parent().css({"float":"right"}); 79 } 80 81 var stickyWrapper = stickyElement.parent(); 82 stickyWrapper.css('height', stickyElement.outerHeight()); 83 sticked.push({ 84 topSpacing: o.topSpacing, 85 bottomSpacing: o.bottomSpacing, 86 stickyElement: stickyElement, 87 currentTop: null, 88 stickyWrapper: stickyWrapper, 89 className: o.className, 90 getWidthFrom: o.getWidthFrom 91 }); 92 }); 93 }, 94 update: scroller 95 }; 96 97 // should be more efficient than using $window.scroll(scroller) and $window.resize(resizer): 98 if (window.addEventListener) { 99 window.addEventListener('scroll', scroller, false); 100 window.addEventListener('resize', resizer, false); 101 } else if (window.attachEvent) { 102 window.attachEvent('onscroll', scroller); 103 window.attachEvent('onresize', resizer); 104 } 105 106 $.fn.sticky = function(method) { 107 if (methods[method]) { 108 return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); 109 } else if (typeof method === 'object' || !method ) { 110 return methods.init.apply( this, arguments ); 111 } else { 112 $.error('Method ' + method + ' does not exist on jQuery.sticky'); 113 } 114 }; 115 $(function() { 116 setTimeout(scroller, 0); 117 }); 118})(jQuery); 119 120 121
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.