diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index f06eb9e..cba6807 100755 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,3 +1,8 @@ +### Version 2.1.5 - Nov 1, 2015 + +- **Sticky** - Fixes bug where sticky would stick at incorrect times when using a different scroll container than `body` and scrollTop is not 0 on page load. +- **Sticky** - Fixed issue where pressing home/end button would cause sticky to break due to internal logic not allowing immediate jump from bottom attached to top attached, experienced most likely when pressing "home" or "end" key [#3011](https://github.com/Semantic-Org/Semantic-UI/issues/3011) + #### Bugs - **Sticky** - Sticky now sets width and height with `!important` to avoid inheritance issues in some cases **Thanks @lauri-elevant** [#2710](https://github.com/Semantic-Org/Semantic-UI/issues/2710) diff --git a/composer.json b/composer.json index 4a4df3d..10a0a7c 100755 --- a/composer.json +++ b/composer.json @@ -15,5 +15,5 @@ "framework" ], "license": "MIT", - "version": "2.1.4" + "version": "2.1.6" } \ No newline at end of file diff --git a/index.js b/index.js index b4275fa..e527f8f 100755 --- a/index.js +++ b/index.js @@ -1,5 +1,5 @@ /*! - * # Semantic UI 2.1.4 - Sticky + * # Semantic UI 2.1.6 - Sticky * http://github.com/semantic-org/semantic-ui/ * * @@ -224,8 +224,8 @@ module.exports = function(parameters) { }, positions: function() { var - window = { - height: $window.height() + scrollContext = { + height : $scroll.height() }, element = { margin: { @@ -237,17 +237,28 @@ module.exports = function(parameters) { height : $module.outerHeight() }, context = { - offset : $context.offset(), - height : $context.outerHeight() + offset : $context.offset(), + height : $context.outerHeight() }, container = { height: $container.outerHeight() } ; + if( !module.is.standardScroll() ) { + module.debug('Non-standard scroll. Removing scroll offset from element offset'); + + scrollContext.top = $scroll.scrollTop(); + scrollContext.left = $scroll.scrollLeft(); + + element.offset.top += scrollContext.top; + context.offset.top += scrollContext.top; + element.offset.left += scrollContext.left; + context.offset.left += scrollContext.left; + } module.cache = { - fits : ( element.height < window.height ), - window: { - height: window.height + fits : ( element.height < scrollContext.height ), + scrollContext : { + height : scrollContext.height }, element: { margin : element.margin, @@ -307,9 +318,9 @@ module.exports = function(parameters) { scroll = scroll || $scroll.scrollTop(); var element = module.cache.element, - window = module.cache.window, + scrollContext = module.cache.scrollContext, delta = module.get.scrollChange(scroll), - maxScroll = (element.height - window.height + settings.offset), + maxScroll = (element.height - scrollContext.height + settings.offset), elementScroll = module.get.currentElementScroll(), possibleScroll = (elementScroll + delta) ; @@ -398,6 +409,9 @@ module.exports = function(parameters) { }, is: { + standardScroll: function() { + return ($scroll[0] == window); + }, top: function() { return $module.hasClass(className.top); }, @@ -424,14 +438,14 @@ module.exports = function(parameters) { cache = module.cache, fits = cache.fits, element = cache.element, - window = cache.window, + scrollContext = cache.scrollContext, context = cache.context, offset = (module.is.bottom() && settings.pushing) ? settings.bottomOffset : settings.offset, scroll = { top : cachedPosition + offset, - bottom : cachedPosition + offset + window.height + bottom : cachedPosition + offset + scrollContext.height }, direction = module.get.direction(scroll.top), elementScroll = (fits) @@ -505,16 +519,22 @@ module.exports = function(parameters) { } } else if( module.is.bottom() ) { - if(settings.pushing) { - if(module.is.bound() && scroll.bottom <= context.bottom ) { - module.debug('Fixing bottom attached element to bottom of browser.'); - module.fixBottom(); - } + if( scroll.top <= element.top ) { + module.debug('Jumped from bottom fixed to top fixed, most likely used home/end button'); + module.setInitialPosition(); } else { - if(module.is.bound() && (scroll.top <= context.bottom - element.height) ) { - module.debug('Fixing bottom attached element to top of browser.'); - module.fixTop(); + if(settings.pushing) { + if(module.is.bound() && scroll.bottom <= context.bottom ) { + module.debug('Fixing bottom attached element to bottom of browser.'); + module.fixBottom(); + } + } + else { + if(module.is.bound() && (scroll.top <= context.bottom - element.height) ) { + module.debug('Fixing bottom attached element to top of browser.'); + module.fixTop(); + } } } } @@ -885,4 +905,4 @@ _module.exports.settings = { }; -})( require("jquery"), window , document ); +})( require("jquery"), window, document ); \ No newline at end of file diff --git a/package.js b/package.js index c899f61..2194a43 100755 --- a/package.js +++ b/package.js @@ -2,7 +2,7 @@ Package.describe({ name : 'semantic:ui-sticky', summary : 'Semantic UI - Sticky: Single component release', - version : '2.1.4', + version : '2.1.6', git : 'git://github.com/Semantic-Org/UI-Sticky.git', }); diff --git a/package.json b/package.json index e197f10..3993618 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "semantic-ui-sticky", - "version": "2.1.4", + "version": "2.1.6", "title": "Semantic UI - Sticky", "description": "Single component release of sticky", "homepage": "http://www.semantic-ui.com", diff --git a/sticky.css b/sticky.css index 69e30ab..8c4bbb9 100755 --- a/sticky.css +++ b/sticky.css @@ -1,5 +1,5 @@ /*! - * # Semantic UI 2.1.4 - Sticky + * # Semantic UI 2.1.6 - Sticky * http://github.com/semantic-org/semantic-ui/ * * diff --git a/sticky.js b/sticky.js index 3dec426..519a64a 100755 --- a/sticky.js +++ b/sticky.js @@ -1,5 +1,5 @@ /*! - * # Semantic UI 2.1.4 - Sticky + * # Semantic UI 2.1.6 - Sticky * http://github.com/semantic-org/semantic-ui/ * * @@ -223,8 +223,8 @@ $.fn.sticky = function(parameters) { }, positions: function() { var - window = { - height: $window.height() + scrollContext = { + height : $scroll.height() }, element = { margin: { @@ -236,17 +236,28 @@ $.fn.sticky = function(parameters) { height : $module.outerHeight() }, context = { - offset : $context.offset(), - height : $context.outerHeight() + offset : $context.offset(), + height : $context.outerHeight() }, container = { height: $container.outerHeight() } ; + if( !module.is.standardScroll() ) { + module.debug('Non-standard scroll. Removing scroll offset from element offset'); + + scrollContext.top = $scroll.scrollTop(); + scrollContext.left = $scroll.scrollLeft(); + + element.offset.top += scrollContext.top; + context.offset.top += scrollContext.top; + element.offset.left += scrollContext.left; + context.offset.left += scrollContext.left; + } module.cache = { - fits : ( element.height < window.height ), - window: { - height: window.height + fits : ( element.height < scrollContext.height ), + scrollContext : { + height : scrollContext.height }, element: { margin : element.margin, @@ -306,9 +317,9 @@ $.fn.sticky = function(parameters) { scroll = scroll || $scroll.scrollTop(); var element = module.cache.element, - window = module.cache.window, + scrollContext = module.cache.scrollContext, delta = module.get.scrollChange(scroll), - maxScroll = (element.height - window.height + settings.offset), + maxScroll = (element.height - scrollContext.height + settings.offset), elementScroll = module.get.currentElementScroll(), possibleScroll = (elementScroll + delta) ; @@ -397,6 +408,9 @@ $.fn.sticky = function(parameters) { }, is: { + standardScroll: function() { + return ($scroll[0] == window); + }, top: function() { return $module.hasClass(className.top); }, @@ -423,14 +437,14 @@ $.fn.sticky = function(parameters) { cache = module.cache, fits = cache.fits, element = cache.element, - window = cache.window, + scrollContext = cache.scrollContext, context = cache.context, offset = (module.is.bottom() && settings.pushing) ? settings.bottomOffset : settings.offset, scroll = { top : cachedPosition + offset, - bottom : cachedPosition + offset + window.height + bottom : cachedPosition + offset + scrollContext.height }, direction = module.get.direction(scroll.top), elementScroll = (fits) @@ -504,16 +518,22 @@ $.fn.sticky = function(parameters) { } } else if( module.is.bottom() ) { - if(settings.pushing) { - if(module.is.bound() && scroll.bottom <= context.bottom ) { - module.debug('Fixing bottom attached element to bottom of browser.'); - module.fixBottom(); - } + if( scroll.top <= element.top ) { + module.debug('Jumped from bottom fixed to top fixed, most likely used home/end button'); + module.setInitialPosition(); } else { - if(module.is.bound() && (scroll.top <= context.bottom - element.height) ) { - module.debug('Fixing bottom attached element to top of browser.'); - module.fixTop(); + if(settings.pushing) { + if(module.is.bound() && scroll.bottom <= context.bottom ) { + module.debug('Fixing bottom attached element to bottom of browser.'); + module.fixBottom(); + } + } + else { + if(module.is.bound() && (scroll.top <= context.bottom - element.height) ) { + module.debug('Fixing bottom attached element to top of browser.'); + module.fixTop(); + } } } } @@ -884,4 +904,4 @@ $.fn.sticky.settings = { }; -})( jQuery, window , document ); +})( jQuery, window, document ); \ No newline at end of file diff --git a/sticky.min.css b/sticky.min.css index 1637b42..01fc3a9 100755 --- a/sticky.min.css +++ b/sticky.min.css @@ -1,5 +1,5 @@ /*! - * # Semantic UI 2.1.4 - Sticky + * # Semantic UI 2.1.6 - Sticky * http://github.com/semantic-org/semantic-ui/ * * diff --git a/sticky.min.js b/sticky.min.js index 4987efb..9ed0ead 100755 --- a/sticky.min.js +++ b/sticky.min.js @@ -1,5 +1,5 @@ /*! - * # Semantic UI 2.1.4 - Sticky + * # Semantic UI 2.1.6 - Sticky * http://github.com/semantic-org/semantic-ui/ * * @@ -8,4 +8,4 @@ * http://opensource.org/licenses/MIT * */ -!function(e,t,o,n){"use strict";e.fn.sticky=function(o){var i,s=e(this),r=s.selector||"",c=(new Date).getTime(),l=[],a=arguments[0],m="string"==typeof a,f=[].slice.call(arguments,1);return s.each(function(){var s,u,d,h,g=e.isPlainObject(o)?e.extend(!0,{},e.fn.sticky.settings,o):e.extend({},e.fn.sticky.settings),b=g.className,p=g.namespace,v=g.error,x="."+p,C="module-"+p,S=e(this),y=e(t),k=e(g.scrollContext),w=(S.selector||"",S.data(C)),T=t.requestAnimationFrame||t.mozRequestAnimationFrame||t.webkitRequestAnimationFrame||t.msRequestAnimationFrame||function(e){setTimeout(e,0)},z=this;h={initialize:function(){h.determineContainer(),h.determineContext(),h.verbose("Initializing sticky",g,s),h.save.positions(),h.checkErrors(),h.bind.events(),g.observeChanges&&h.observeChanges(),h.instantiate()},instantiate:function(){h.verbose("Storing instance of module",h),w=h,S.data(C,h)},destroy:function(){h.verbose("Destroying previous instance"),h.reset(),d&&d.disconnect(),y.off("load"+x,h.event.load).off("resize"+x,h.event.resize),k.off("scrollchange"+x,h.event.scrollchange),S.removeData(C)},observeChanges:function(){var e=u[0];"MutationObserver"in t&&(d=new MutationObserver(function(e){clearTimeout(h.timer),h.timer=setTimeout(function(){h.verbose("DOM tree modified, updating sticky menu",e),h.refresh()},100)}),d.observe(z,{childList:!0,subtree:!0}),d.observe(e,{childList:!0,subtree:!0}),h.debug("Setting up mutation observer",d))},determineContainer:function(){s=S.offsetParent()},determineContext:function(){return u=g.context?e(g.context):s,0===u.length?void h.error(v.invalidContext,g.context,S):void 0},checkErrors:function(){return h.is.hidden()&&h.error(v.visible,S),h.cache.element.height>h.cache.context.height?(h.reset(),void h.error(v.elementSize,S)):void 0},bind:{events:function(){y.on("load"+x,h.event.load).on("resize"+x,h.event.resize),k.off("scroll"+x).on("scroll"+x,h.event.scroll).on("scrollchange"+x,h.event.scrollchange)}},event:{load:function(){h.verbose("Page contents finished loading"),T(h.refresh)},resize:function(){h.verbose("Window resized"),T(h.refresh)},scroll:function(){T(function(){k.triggerHandler("scrollchange"+x,k.scrollTop())})},scrollchange:function(e,t){h.stick(t),g.onScroll.call(z)}},refresh:function(e){h.reset(),g.context||h.determineContext(),e&&h.determineContainer(),h.save.positions(),h.stick(),g.onReposition.call(z)},supports:{sticky:function(){{var t=e("
");t[0]}return t.addClass(b.supported),t.css("position").match("sticky")}},save:{lastScroll:function(e){h.lastScroll=e},elementScroll:function(e){h.elementScroll=e},positions:function(){{var e={height:y.height()},t={margin:{top:parseInt(S.css("margin-top"),10),bottom:parseInt(S.css("margin-bottom"),10)},offset:S.offset(),width:S.outerWidth(),height:S.outerHeight()},o={offset:u.offset(),height:u.outerHeight()};({height:s.outerHeight()})}h.cache={fits:t.heighte&&(t="up")),t},scrollChange:function(e){return e=e||k.scrollTop(),h.lastScroll?e-h.lastScroll:0},currentElementScroll:function(){return h.elementScroll?h.elementScroll:h.is.top()?Math.abs(parseInt(S.css("top"),10))||0:Math.abs(parseInt(S.css("bottom"),10))||0},elementScroll:function(e){e=e||k.scrollTop();var t=h.cache.element,o=h.cache.window,n=h.get.scrollChange(e),i=t.height-o.height+g.offset,s=h.get.currentElementScroll(),r=s+n;return s=h.cache.fits||0>r?0:r>i?i:r}},remove:{lastScroll:function(){delete h.lastScroll},elementScroll:function(e){delete h.elementScroll},offset:function(){S.css("margin-top","")}},set:{offset:function(){h.verbose("Setting offset on element",g.offset),S.css("margin-top",g.offset)},containerSize:function(){var e=s.get(0).tagName;"HTML"===e||"body"==e?h.determineContainer():Math.abs(s.outerHeight()-h.cache.context.height)>g.jitter&&(h.debug("Context has padding, specifying exact height for container",h.cache.context.height),s.css({height:h.cache.context.height}))},minimumSize:function(){var e=h.cache.element;s.css("min-height",e.height)},scroll:function(e){h.debug("Setting scroll on element",e),h.elementScroll!=e&&(h.is.top()&&S.css("bottom","").css("top",-e),h.is.bottom()&&S.css("top","").css("bottom",e))},size:function(){0!==h.cache.element.height&&0!==h.cache.element.width&&(z.style.setProperty("width",h.cache.element.width+"px","important"),z.style.setProperty("height",h.cache.element.height+"px","important"))}},is:{top:function(){return S.hasClass(b.top)},bottom:function(){return S.hasClass(b.bottom)},initialPosition:function(){return!h.is.fixed()&&!h.is.bound()},hidden:function(){return!S.is(":visible")},bound:function(){return S.hasClass(b.bound)},fixed:function(){return S.hasClass(b.fixed)}},stick:function(e){var t=e||k.scrollTop(),o=h.cache,n=o.fits,i=o.element,s=o.window,r=o.context,c=h.is.bottom()&&g.pushing?g.bottomOffset:g.offset,e={top:t+c,bottom:t+c+s.height},l=(h.get.direction(e.top),n?0:h.get.elementScroll(e.top)),a=!n,m=0!==i.height;m&&(h.is.initialPosition()?e.top>=r.bottom?(h.debug("Initial element position is bottom of container"),h.bindBottom()):e.top>i.top&&(i.height+e.top-l>=r.bottom?(h.debug("Initial element position is bottom of container"),h.bindBottom()):(h.debug("Initial element position is fixed"),h.fixTop())):h.is.fixed()?h.is.top()?e.top<=i.top?(h.debug("Fixed element reached top of container"),h.setInitialPosition()):i.height+e.top-l>=r.bottom?(h.debug("Fixed element reached bottom of container"),h.bindBottom()):a&&(h.set.scroll(l),h.save.lastScroll(e.top),h.save.elementScroll(l)):h.is.bottom()&&(e.bottom-i.height<=i.top?(h.debug("Bottom fixed rail has reached top of container"),h.setInitialPosition()):e.bottom>=r.bottom?(h.debug("Bottom fixed rail has reached bottom of container"),h.bindBottom()):a&&(h.set.scroll(l),h.save.lastScroll(e.top),h.save.elementScroll(l))):h.is.bottom()&&(g.pushing?h.is.bound()&&e.bottom<=r.bottom&&(h.debug("Fixing bottom attached element to bottom of browser."),h.fixBottom()):h.is.bound()&&e.top<=r.bottom-i.height&&(h.debug("Fixing bottom attached element to top of browser."),h.fixTop())))},bindTop:function(){h.debug("Binding element to top of parent container"),h.remove.offset(),S.css({left:"",top:"",marginBottom:""}).removeClass(b.fixed).removeClass(b.bottom).addClass(b.bound).addClass(b.top),g.onTop.call(z),g.onUnstick.call(z)},bindBottom:function(){h.debug("Binding element to bottom of parent container"),h.remove.offset(),S.css({left:"",top:""}).removeClass(b.fixed).removeClass(b.top).addClass(b.bound).addClass(b.bottom),g.onBottom.call(z),g.onUnstick.call(z)},setInitialPosition:function(){h.debug("Returning to initial position"),h.unfix(),h.unbind()},fixTop:function(){h.debug("Fixing element to top of page"),h.set.minimumSize(),h.set.offset(),S.css({left:h.cache.element.left,bottom:"",marginBottom:""}).removeClass(b.bound).removeClass(b.bottom).addClass(b.fixed).addClass(b.top),g.onStick.call(z)},fixBottom:function(){h.debug("Sticking element to bottom of page"),h.set.minimumSize(),h.set.offset(),S.css({left:h.cache.element.left,bottom:"",marginBottom:""}).removeClass(b.bound).removeClass(b.top).addClass(b.fixed).addClass(b.bottom),g.onStick.call(z)},unbind:function(){h.is.bound()&&(h.debug("Removing container bound position on element"),h.remove.offset(),S.removeClass(b.bound).removeClass(b.top).removeClass(b.bottom))},unfix:function(){h.is.fixed()&&(h.debug("Removing fixed position on element"),h.remove.offset(),S.removeClass(b.fixed).removeClass(b.top).removeClass(b.bottom),g.onUnstick.call(z))},reset:function(){h.debug("Reseting elements position"),h.unbind(),h.unfix(),h.resetCSS(),h.remove.offset(),h.remove.lastScroll()},resetCSS:function(){S.css({width:"",height:""}),s.css({height:""})},setting:function(t,o){if(e.isPlainObject(t))e.extend(!0,g,t);else{if(o===n)return g[t];g[t]=o}},internal:function(t,o){if(e.isPlainObject(t))e.extend(!0,h,t);else{if(o===n)return h[t];h[t]=o}},debug:function(){g.debug&&(g.performance?h.performance.log(arguments):(h.debug=Function.prototype.bind.call(console.info,console,g.name+":"),h.debug.apply(console,arguments)))},verbose:function(){g.verbose&&g.debug&&(g.performance?h.performance.log(arguments):(h.verbose=Function.prototype.bind.call(console.info,console,g.name+":"),h.verbose.apply(console,arguments)))},error:function(){h.error=Function.prototype.bind.call(console.error,console,g.name+":"),h.error.apply(console,arguments)},performance:{log:function(e){var t,o,n;g.performance&&(t=(new Date).getTime(),n=c||t,o=t-n,c=t,l.push({Name:e[0],Arguments:[].slice.call(e,1)||"",Element:z,"Execution Time":o})),clearTimeout(h.performance.timer),h.performance.timer=setTimeout(h.performance.display,0)},display:function(){var t=g.name+":",o=0;c=!1,clearTimeout(h.performance.timer),e.each(l,function(e,t){o+=t["Execution Time"]}),t+=" "+o+"ms",r&&(t+=" '"+r+"'"),(console.group!==n||console.table!==n)&&l.length>0&&(console.groupCollapsed(t),console.table?console.table(l):e.each(l,function(e,t){console.log(t.Name+": "+t["Execution Time"]+"ms")}),console.groupEnd()),l=[]}},invoke:function(t,o,s){var r,c,l,a=w;return o=o||f,s=z||s,"string"==typeof t&&a!==n&&(t=t.split(/[\. ]/),r=t.length-1,e.each(t,function(o,i){var s=o!=r?i+t[o+1].charAt(0).toUpperCase()+t[o+1].slice(1):t;if(e.isPlainObject(a[s])&&o!=r)a=a[s];else{if(a[s]!==n)return c=a[s],!1;if(!e.isPlainObject(a[i])||o==r)return a[i]!==n?(c=a[i],!1):!1;a=a[i]}})),e.isFunction(c)?l=c.apply(s,o):c!==n&&(l=c),e.isArray(i)?i.push(l):i!==n?i=[i,l]:l!==n&&(i=l),c}},m?(w===n&&h.initialize(),h.invoke(a)):(w!==n&&w.invoke("destroy"),h.initialize())}),i!==n?i:this},e.fn.sticky.settings={name:"Sticky",namespace:"sticky",debug:!1,verbose:!0,performance:!0,pushing:!1,context:!1,scrollContext:t,offset:0,bottomOffset:0,jitter:5,observeChanges:!1,onReposition:function(){},onScroll:function(){},onStick:function(){},onUnstick:function(){},onTop:function(){},onBottom:function(){},error:{container:"Sticky element must be inside a relative container",visible:"Element is hidden, you must call refresh after element becomes visible",method:"The method you called is not defined.",invalidContext:"Context specified does not exist",elementSize:"Sticky element is larger than its container, cannot create sticky."},className:{bound:"bound",fixed:"fixed",supported:"native",top:"top",bottom:"bottom"}}}(jQuery,window,document); \ No newline at end of file +!function(e,t,o,n){"use strict";e.fn.sticky=function(o){var i,s=e(this),r=s.selector||"",l=(new Date).getTime(),c=[],a=arguments[0],f="string"==typeof a,m=[].slice.call(arguments,1);return s.each(function(){var s,u,d,h,g=e.isPlainObject(o)?e.extend(!0,{},e.fn.sticky.settings,o):e.extend({},e.fn.sticky.settings),p=g.className,b=g.namespace,v=g.error,x="."+b,C="module-"+b,S=e(this),y=e(t),k=e(g.scrollContext),T=(S.selector||"",S.data(C)),z=t.requestAnimationFrame||t.mozRequestAnimationFrame||t.webkitRequestAnimationFrame||t.msRequestAnimationFrame||function(e){setTimeout(e,0)},w=this;h={initialize:function(){h.determineContainer(),h.determineContext(),h.verbose("Initializing sticky",g,s),h.save.positions(),h.checkErrors(),h.bind.events(),g.observeChanges&&h.observeChanges(),h.instantiate()},instantiate:function(){h.verbose("Storing instance of module",h),T=h,S.data(C,h)},destroy:function(){h.verbose("Destroying previous instance"),h.reset(),d&&d.disconnect(),y.off("load"+x,h.event.load).off("resize"+x,h.event.resize),k.off("scrollchange"+x,h.event.scrollchange),S.removeData(C)},observeChanges:function(){var e=u[0];"MutationObserver"in t&&(d=new MutationObserver(function(e){clearTimeout(h.timer),h.timer=setTimeout(function(){h.verbose("DOM tree modified, updating sticky menu",e),h.refresh()},100)}),d.observe(w,{childList:!0,subtree:!0}),d.observe(e,{childList:!0,subtree:!0}),h.debug("Setting up mutation observer",d))},determineContainer:function(){s=S.offsetParent()},determineContext:function(){return u=g.context?e(g.context):s,0===u.length?void h.error(v.invalidContext,g.context,S):void 0},checkErrors:function(){return h.is.hidden()&&h.error(v.visible,S),h.cache.element.height>h.cache.context.height?(h.reset(),void h.error(v.elementSize,S)):void 0},bind:{events:function(){y.on("load"+x,h.event.load).on("resize"+x,h.event.resize),k.off("scroll"+x).on("scroll"+x,h.event.scroll).on("scrollchange"+x,h.event.scrollchange)}},event:{load:function(){h.verbose("Page contents finished loading"),z(h.refresh)},resize:function(){h.verbose("Window resized"),z(h.refresh)},scroll:function(){z(function(){k.triggerHandler("scrollchange"+x,k.scrollTop())})},scrollchange:function(e,t){h.stick(t),g.onScroll.call(w)}},refresh:function(e){h.reset(),g.context||h.determineContext(),e&&h.determineContainer(),h.save.positions(),h.stick(),g.onReposition.call(w)},supports:{sticky:function(){var t=e("
");t[0];return t.addClass(p.supported),t.css("position").match("sticky")}},save:{lastScroll:function(e){h.lastScroll=e},elementScroll:function(e){h.elementScroll=e},positions:function(){var e={height:k.height()},t={margin:{top:parseInt(S.css("margin-top"),10),bottom:parseInt(S.css("margin-bottom"),10)},offset:S.offset(),width:S.outerWidth(),height:S.outerHeight()},o={offset:u.offset(),height:u.outerHeight()};({height:s.outerHeight()});h.is.standardScroll()||(h.debug("Non-standard scroll. Removing scroll offset from element offset"),e.top=k.scrollTop(),e.left=k.scrollLeft(),t.offset.top+=e.top,o.offset.top+=e.top,t.offset.left+=e.left,o.offset.left+=e.left),h.cache={fits:t.heighte&&(t="up")),t},scrollChange:function(e){return e=e||k.scrollTop(),h.lastScroll?e-h.lastScroll:0},currentElementScroll:function(){return h.elementScroll?h.elementScroll:h.is.top()?Math.abs(parseInt(S.css("top"),10))||0:Math.abs(parseInt(S.css("bottom"),10))||0},elementScroll:function(e){e=e||k.scrollTop();var t=h.cache.element,o=h.cache.scrollContext,n=h.get.scrollChange(e),i=t.height-o.height+g.offset,s=h.get.currentElementScroll(),r=s+n;return s=h.cache.fits||0>r?0:r>i?i:r}},remove:{lastScroll:function(){delete h.lastScroll},elementScroll:function(e){delete h.elementScroll},offset:function(){S.css("margin-top","")}},set:{offset:function(){h.verbose("Setting offset on element",g.offset),S.css("margin-top",g.offset)},containerSize:function(){var e=s.get(0).tagName;"HTML"===e||"body"==e?h.determineContainer():Math.abs(s.outerHeight()-h.cache.context.height)>g.jitter&&(h.debug("Context has padding, specifying exact height for container",h.cache.context.height),s.css({height:h.cache.context.height}))},minimumSize:function(){var e=h.cache.element;s.css("min-height",e.height)},scroll:function(e){h.debug("Setting scroll on element",e),h.elementScroll!=e&&(h.is.top()&&S.css("bottom","").css("top",-e),h.is.bottom()&&S.css("top","").css("bottom",e))},size:function(){0!==h.cache.element.height&&0!==h.cache.element.width&&(w.style.setProperty("width",h.cache.element.width+"px","important"),w.style.setProperty("height",h.cache.element.height+"px","important"))}},is:{standardScroll:function(){return k[0]==t},top:function(){return S.hasClass(p.top)},bottom:function(){return S.hasClass(p.bottom)},initialPosition:function(){return!h.is.fixed()&&!h.is.bound()},hidden:function(){return!S.is(":visible")},bound:function(){return S.hasClass(p.bound)},fixed:function(){return S.hasClass(p.fixed)}},stick:function(e){var t=e||k.scrollTop(),o=h.cache,n=o.fits,i=o.element,s=o.scrollContext,r=o.context,l=h.is.bottom()&&g.pushing?g.bottomOffset:g.offset,e={top:t+l,bottom:t+l+s.height},c=(h.get.direction(e.top),n?0:h.get.elementScroll(e.top)),a=!n,f=0!==i.height;f&&(h.is.initialPosition()?e.top>=r.bottom?(h.debug("Initial element position is bottom of container"),h.bindBottom()):e.top>i.top&&(i.height+e.top-c>=r.bottom?(h.debug("Initial element position is bottom of container"),h.bindBottom()):(h.debug("Initial element position is fixed"),h.fixTop())):h.is.fixed()?h.is.top()?e.top<=i.top?(h.debug("Fixed element reached top of container"),h.setInitialPosition()):i.height+e.top-c>=r.bottom?(h.debug("Fixed element reached bottom of container"),h.bindBottom()):a&&(h.set.scroll(c),h.save.lastScroll(e.top),h.save.elementScroll(c)):h.is.bottom()&&(e.bottom-i.height<=i.top?(h.debug("Bottom fixed rail has reached top of container"),h.setInitialPosition()):e.bottom>=r.bottom?(h.debug("Bottom fixed rail has reached bottom of container"),h.bindBottom()):a&&(h.set.scroll(c),h.save.lastScroll(e.top),h.save.elementScroll(c))):h.is.bottom()&&(e.top<=i.top?(h.debug("Jumped from bottom fixed to top fixed, most likely used home/end button"),h.setInitialPosition()):g.pushing?h.is.bound()&&e.bottom<=r.bottom&&(h.debug("Fixing bottom attached element to bottom of browser."),h.fixBottom()):h.is.bound()&&e.top<=r.bottom-i.height&&(h.debug("Fixing bottom attached element to top of browser."),h.fixTop())))},bindTop:function(){h.debug("Binding element to top of parent container"),h.remove.offset(),S.css({left:"",top:"",marginBottom:""}).removeClass(p.fixed).removeClass(p.bottom).addClass(p.bound).addClass(p.top),g.onTop.call(w),g.onUnstick.call(w)},bindBottom:function(){h.debug("Binding element to bottom of parent container"),h.remove.offset(),S.css({left:"",top:""}).removeClass(p.fixed).removeClass(p.top).addClass(p.bound).addClass(p.bottom),g.onBottom.call(w),g.onUnstick.call(w)},setInitialPosition:function(){h.debug("Returning to initial position"),h.unfix(),h.unbind()},fixTop:function(){h.debug("Fixing element to top of page"),h.set.minimumSize(),h.set.offset(),S.css({left:h.cache.element.left,bottom:"",marginBottom:""}).removeClass(p.bound).removeClass(p.bottom).addClass(p.fixed).addClass(p.top),g.onStick.call(w)},fixBottom:function(){h.debug("Sticking element to bottom of page"),h.set.minimumSize(),h.set.offset(),S.css({left:h.cache.element.left,bottom:"",marginBottom:""}).removeClass(p.bound).removeClass(p.top).addClass(p.fixed).addClass(p.bottom),g.onStick.call(w)},unbind:function(){h.is.bound()&&(h.debug("Removing container bound position on element"),h.remove.offset(),S.removeClass(p.bound).removeClass(p.top).removeClass(p.bottom))},unfix:function(){h.is.fixed()&&(h.debug("Removing fixed position on element"),h.remove.offset(),S.removeClass(p.fixed).removeClass(p.top).removeClass(p.bottom),g.onUnstick.call(w))},reset:function(){h.debug("Reseting elements position"),h.unbind(),h.unfix(),h.resetCSS(),h.remove.offset(),h.remove.lastScroll()},resetCSS:function(){S.css({width:"",height:""}),s.css({height:""})},setting:function(t,o){if(e.isPlainObject(t))e.extend(!0,g,t);else{if(o===n)return g[t];g[t]=o}},internal:function(t,o){if(e.isPlainObject(t))e.extend(!0,h,t);else{if(o===n)return h[t];h[t]=o}},debug:function(){g.debug&&(g.performance?h.performance.log(arguments):(h.debug=Function.prototype.bind.call(console.info,console,g.name+":"),h.debug.apply(console,arguments)))},verbose:function(){g.verbose&&g.debug&&(g.performance?h.performance.log(arguments):(h.verbose=Function.prototype.bind.call(console.info,console,g.name+":"),h.verbose.apply(console,arguments)))},error:function(){h.error=Function.prototype.bind.call(console.error,console,g.name+":"),h.error.apply(console,arguments)},performance:{log:function(e){var t,o,n;g.performance&&(t=(new Date).getTime(),n=l||t,o=t-n,l=t,c.push({Name:e[0],Arguments:[].slice.call(e,1)||"",Element:w,"Execution Time":o})),clearTimeout(h.performance.timer),h.performance.timer=setTimeout(h.performance.display,0)},display:function(){var t=g.name+":",o=0;l=!1,clearTimeout(h.performance.timer),e.each(c,function(e,t){o+=t["Execution Time"]}),t+=" "+o+"ms",r&&(t+=" '"+r+"'"),(console.group!==n||console.table!==n)&&c.length>0&&(console.groupCollapsed(t),console.table?console.table(c):e.each(c,function(e,t){console.log(t.Name+": "+t["Execution Time"]+"ms")}),console.groupEnd()),c=[]}},invoke:function(t,o,s){var r,l,c,a=T;return o=o||m,s=w||s,"string"==typeof t&&a!==n&&(t=t.split(/[\. ]/),r=t.length-1,e.each(t,function(o,i){var s=o!=r?i+t[o+1].charAt(0).toUpperCase()+t[o+1].slice(1):t;if(e.isPlainObject(a[s])&&o!=r)a=a[s];else{if(a[s]!==n)return l=a[s],!1;if(!e.isPlainObject(a[i])||o==r)return a[i]!==n?(l=a[i],!1):!1;a=a[i]}})),e.isFunction(l)?c=l.apply(s,o):l!==n&&(c=l),e.isArray(i)?i.push(c):i!==n?i=[i,c]:c!==n&&(i=c),l}},f?(T===n&&h.initialize(),h.invoke(a)):(T!==n&&T.invoke("destroy"),h.initialize())}),i!==n?i:this},e.fn.sticky.settings={name:"Sticky",namespace:"sticky",debug:!1,verbose:!0,performance:!0,pushing:!1,context:!1,scrollContext:t,offset:0,bottomOffset:0,jitter:5,observeChanges:!1,onReposition:function(){},onScroll:function(){},onStick:function(){},onUnstick:function(){},onTop:function(){},onBottom:function(){},error:{container:"Sticky element must be inside a relative container",visible:"Element is hidden, you must call refresh after element becomes visible",method:"The method you called is not defined.",invalidContext:"Context specified does not exist",elementSize:"Sticky element is larger than its container, cannot create sticky."},className:{bound:"bound",fixed:"fixed",supported:"native",top:"top",bottom:"bottom"}}}(jQuery,window,document); \ No newline at end of file