1// Sticky Plugin v1.0.4 for jQuery 2// ============= 3// Author: Anthony Garand 4// Improvements by German M. Bravo (Kronuz) and Ruud Kamphuis (ruudk) 5// Improvements by Leonardo C. Daronco (daronco) 6// Created: 02/14/2011 7// Date: 07/20/2015 8// Website: http://stickyjs.com/ 9// Description: Makes an element on the page stick on the screen as you scroll 10// It will only set the 'top' and 'position' of your element, you 11// might need to adjust the width in some cases. 12 13(function (factory) { 14 if (typeof define === 'function' && define.amd) { 15 // AMD. Register as an anonymous module. 16 define(['jquery'], factory) 17 } else if (typeof module === 'object' && module.exports) { 18 // Node/CommonJS 19 module.exports = factory(require('jquery')) 20 } else { 21 // Browser globals 22 factory(jQuery) 23 } 24})(function ($) { 25 var slice = Array.prototype.slice // save ref to original slice() 26 var splice = Array.prototype.splice // save ref to original slice() 27 28 var defaults = { 29 topSpacing: 0, 30 bottomSpacing: 0, 31 className: 'is-sticky', 32 wrapperClassName: 'sticky-wrapper', 33 center: false, 34 getWidthFrom: '', 35 widthFromWrapper: true, // works only when .getWidthFrom is empty 36 responsiveWidth: false, 37 zIndex: 'auto' 38 }, 39 $window = $(window), 40 $document = $(document), 41 sticked = [], 42 windowHeight = $window.height(), 43 scroller = function () { 44 var scrollTop = $window.scrollTop(), 45 documentHeight = $document.height(), 46 dwh = documentHeight - windowHeight, 47 extra = scrollTop > dwh ? dwh - scrollTop : 0 48 49 for (var i = 0, l = sticked.length; i < l; i++) { 50 var s = sticked[i], 51 elementTop = s.stickyWrapper.offset().top, 52 etse = elementTop - s.topSpacing - extra 53 54 //update height in case of dynamic content 55 //s.stickyWrapper.css('height', s.stickyElement.outerHeight()); 56 57 if (scrollTop <= etse) { 58 if (s.currentTop !== null) { 59 s.stickyElement.css({ 60 width: '', 61 position: '', 62 top: '', 63 'z-index': '' 64 }) 65 s.stickyElement.parent().removeClass(s.className) 66 s.stickyElement.trigger('sticky-end', [s]) 67 s.currentTop = null 68 } 69 } else { 70 var newTop = 71 documentHeight - 72 s.stickyElement.outerHeight() - 73 s.topSpacing - 74 s.bottomSpacing - 75 scrollTop - 76 extra 77 if (newTop < 0) { 78 newTop = newTop + s.topSpacing 79 } else { 80 newTop = s.topSpacing 81 } 82 if (s.currentTop !== newTop) { 83 var newWidth 84 if (s.getWidthFrom) { 85 newWidth = $(s.getWidthFrom).width() || null 86 } else if (s.widthFromWrapper) { 87 newWidth = s.stickyWrapper.width() 88 } 89 if (newWidth == null) { 90 newWidth = s.stickyElement.width() 91 } 92 s.stickyElement 93 .css('width', newWidth) 94 .css('position', 'fixed') 95 .css('top', newTop) 96 .css('z-index', s.zIndex) 97 98 s.stickyElement.parent().addClass(s.className) 99 100 if (s.currentTop === null) { 101 s.stickyElement.trigger('sticky-start', [s]) 102 } else { 103 // sticky is started but it have to be repositioned 104 s.stickyElement.trigger('sticky-update', [s]) 105 } 106 107 if ( 108 (s.currentTop === s.topSpacing && s.currentTop > newTop) || 109 (s.currentTop === null && newTop < s.topSpacing) 110 ) { 111 // just reached bottom || just started to stick but bottom is already reached 112 s.stickyElement.trigger('sticky-bottom-reached', [s]) 113 } else if ( 114 s.currentTop !== null && 115 newTop === s.topSpacing && 116 s.currentTop < newTop 117 ) { 118 // sticky is started && sticked at topSpacing && overflowing from top just finished 119 s.stickyElement.trigger('sticky-bottom-unreached', [s]) 120 } 121 122 s.currentTop = newTop 123 } 124 125 // Check if sticky has reached end of container and stop sticking 126 var stickyWrapperContainer = s.stickyWrapper.parent() 127 var unstick = 128 s.stickyElement.offset().top + s.stickyElement.outerHeight() >= 129 stickyWrapperContainer.offset().top + 130 stickyWrapperContainer.outerHeight() && 131 s.stickyElement.offset().top <= s.topSpacing 132 //console.log('var unstick = ' + unstick); 133
134 /* this is the original code, i made the stick and unstick equal 135 if( unstick ) { 136 s.stickyElement 137 .css('position', 'absolute') 138 .css('top', '') 139 .css('bottom', 0) 140 .css('z-index', ''); 141 } else { 142 s.stickyElement 143 .css('position', 'fixed') 144 .css('top', newTop) 145 .css('bottom', '') 146 .css('z-index', s.zIndex); 147 } 148 */ 149 150 if (unstick) { 151 s.stickyElement 152 .css('position', 'fixed') 153 .css('top', newTop) 154 .css('bottom', '') 155 .css('z-index', s.zIndex) 156 } else { 157 s.stickyElement 158 .css('position', 'fixed') 159 .css('top', newTop) 160 .css('bottom', '') 161 .css('z-index', s.zIndex) 162 } 163 } 164 } 165 }, 166 resizer = function () { 167 windowHeight = $window.height() 168 169 for (var i = 0, l = sticked.length; i < l; i++) { 170 var s = sticked[i] 171 var newWidth = null 172 if (s.getWidthFrom) { 173 if (s.responsiveWidth) { 174 newWidth = $(s.getWidthFrom).width() 175 } 176 } else if (s.widthFromWrapper) { 177 newWidth = s.stickyWrapper.width() 178 } 179 if (newWidth != null) { 180 s.stickyElement.css('width', newWidth) 181 } 182 } 183 }, 184 methods = { 185 init: function (options) { 186 return this.each(function () { 187 var o = $.extend({}, defaults, options) 188 var stickyElement = $(this) 189 190 var stickyId = stickyElement.attr('id') 191 var wrapperId = stickyId 192 ? stickyId + '-' + defaults.wrapperClassName 193 : defaults.wrapperClassName 194 var wrapper = $('<div></div>') 195 .attr('id', wrapperId) 196 .addClass(o.wrapperClassName) 197 198 stickyElement.wrapAll(function () { 199 if ($(this).parent('#' + wrapperId).length == 0) { 200 return wrapper 201 } 202 }) 203 204 var stickyWrapper = stickyElement.parent() 205 206 if (o.center) { 207 stickyWrapper.css({ 208 width: stickyElement.outerWidth(), 209 marginLeft: 'auto', 210 marginRight: 'auto' 211 }) 212 } 213 214 if (stickyElement.css('float') === 'right') { 215 stickyElement 216 .css({ 217 float: 'none' 218 }) 219 .parent() 220 .css({ 221 float: 'right' 222 }) 223 } 224 225 o.stickyElement = stickyElement 226 o.stickyWrapper = stickyWrapper 227 o.currentTop = null 228 229 sticked.push(o) 230 231 methods.setWrapperHeight(this) 232 methods.setupChangeListeners(this) 233 }) 234 }, 235 236 setWrapperHeight: function (stickyElement) { 237 var element = $(stickyElement) 238 var stickyWrapper = element.parent() 239 if (stickyWrapper) { 240 // stickyWrapper.css('height', element.outerHeight()); 241 } 242 }, 243 244 setupChangeListeners: function (stickyElement) { 245 if (window.MutationObserver) { 246 var mutationObserver = new window.MutationObserver(function ( 247 mutations 248 ) { 249 if ( 250 mutations[0].addedNodes.length || 251 mutations[0].removedNodes.length 252 ) { 253 methods.setWrapperHeight(stickyElement) 254 } 255 }) 256 mutationObserver.observe(stickyElement, { 257 subtree: true, 258 childList: true 259 }) 260 } else { 261 if (window.addEventListener) { 262 stickyElement.addEventListener( 263 'DOMNodeInserted', 264 function () { 265 methods.setWrapperHeight(stickyElement) 266 }, 267 false 268 ) 269 stickyElement.addEventListener( 270 'DOMNodeRemoved', 271 function () { 272 methods.setWrapperHeight(stickyElement) 273 }, 274 false 275 ) 276 } else if (window.attachEvent) { 277 stickyElement.attachEvent('onDOMNodeInserted', function () { 278 methods.setWrapperHeight(stickyElement) 279 }) 280 stickyElement.attachEvent('onDOMNodeRemoved', function () { 281 methods.setWrapperHeight(stickyElement) 282 }) 283 } 284 } 285 }, 286 update: scroller, 287 unstick: function (options) { 288 return this.each(function () { 289 var that = this 290 var unstickyElement = $(that) 291 292 var removeIdx = -1 293 var i = sticked.length 294 while (i-- > 0) { 295 if (sticked[i].stickyElement.get(0) === that) { 296 splice.call(sticked, i, 1) 297 removeIdx = i 298 } 299 } 300 if (removeIdx !== -1) { 301 unstickyElement.unwrap() 302 unstickyElement.css({ 303 width: '', 304 position: '', 305 top: '', 306 float: '', 307 'z-index': '' 308 }) 309 } 310 }) 311 } 312 } 313 314 // should be more efficient than using $window.scroll(scroller) and $window.resize(resizer): 315 if (window.addEventListener) { 316 window.addEventListener('scroll', scroller, false) 317 window.addEventListener('resize', resizer, false) 318 } else if (window.attachEvent) { 319 window.attachEvent('onscroll', scroller) 320 window.attachEvent('onresize', resizer) 321 } 322 323 $.fn.sticky = function (method) { 324 if (methods[method]) { 325 return methods[method].apply(this, slice.call(arguments, 1)) 326 } else if (typeof method === 'object' || !method) { 327 return methods.init.apply(this, arguments) 328 } else { 329 $.error('Method ' + method + ' does not exist on jQuery.sticky') 330 } 331 } 332 333 $.fn.unstick = function (method) { 334 if (methods[method]) { 335 return methods[method].apply(this, slice.call(arguments, 1)) 336 } else if (typeof method === 'object' || !method) { 337 return methods.unstick.apply(this, arguments) 338 } else { 339 $.error('Method ' + method + ' does not exist on jQuery.sticky') 340 } 341 } 342 $(function () { 343 setTimeout(scroller, 0) 344 }) 345})
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.