1 line
12 KiB
JavaScript
1 line
12 KiB
JavaScript
!function(T,w,B,P){"use strict";w=void 0!==w&&w.Math==Math?w:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")(),T.fn.sticky=function(b){var v,e=T(this),x=e.selector||"",S=(new Date).getTime(),C=[],y=b,k="string"==typeof y,z=[].slice.call(arguments,1);return e.each(function(){var n,i,e,t,m=T.isPlainObject(b)?T.extend(!0,{},T.fn.sticky.settings,b):T.extend({},T.fn.sticky.settings),o=m.className,s=m.namespace,r=m.error,c="."+s,l="module-"+s,a=T(this),f=T(w),u=T(m.scrollContext),h=(a.selector,a.data(l)),d=w.requestAnimationFrame||w.mozRequestAnimationFrame||w.webkitRequestAnimationFrame||w.msRequestAnimationFrame||function(e){setTimeout(e,0)},g=this,p={initialize:function(){p.determineContainer(),p.determineContext(),p.verbose("Initializing sticky",m,n),p.save.positions(),p.checkErrors(),p.bind.events(),m.observeChanges&&p.observeChanges(),p.instantiate()},instantiate:function(){p.verbose("Storing instance of module",p),h=p,a.data(l,p)},destroy:function(){p.verbose("Destroying previous instance"),p.reset(),e&&e.disconnect(),t&&t.disconnect(),f.off("load"+c,p.event.load).off("resize"+c,p.event.resize),u.off("scrollchange"+c,p.event.scrollchange),a.removeData(l)},observeChanges:function(){"MutationObserver"in w&&(e=new MutationObserver(p.event.documentChanged),t=new MutationObserver(p.event.changed),e.observe(B,{childList:!0,subtree:!0}),t.observe(g,{childList:!0,subtree:!0}),t.observe(i[0],{childList:!0,subtree:!0}),p.debug("Setting up mutation observer",t))},determineContainer:function(){n=m.container?T(m.container):a.offsetParent()},determineContext:function(){0!==(i=m.context?T(m.context):n).length||p.error(r.invalidContext,m.context,a)},checkErrors:function(){if(p.is.hidden()&&p.error(r.visible,a),p.cache.element.height>p.cache.context.height)return p.reset(),void p.error(r.elementSize,a)},bind:{events:function(){f.on("load"+c,p.event.load).on("resize"+c,p.event.resize),u.off("scroll"+c).on("scroll"+c,p.event.scroll).on("scrollchange"+c,p.event.scrollchange)}},event:{changed:function(e){clearTimeout(p.timer),p.timer=setTimeout(function(){p.verbose("DOM tree modified, updating sticky menu",e),p.refresh()},100)},documentChanged:function(e){[].forEach.call(e,function(e){e.removedNodes&&[].forEach.call(e.removedNodes,function(e){(e==g||0<T(e).find(g).length)&&(p.debug("Element removed from DOM, tearing down events"),p.destroy())})})},load:function(){p.verbose("Page contents finished loading"),d(p.refresh)},resize:function(){p.verbose("Window resized"),d(p.refresh)},scroll:function(){d(function(){u.triggerHandler("scrollchange"+c,u.scrollTop())})},scrollchange:function(e,t){p.stick(t),m.onScroll.call(g)}},refresh:function(e){p.reset(),m.context||p.determineContext(),e&&p.determineContainer(),p.save.positions(),p.stick(),m.onReposition.call(g)},supports:{sticky:function(){var e=T("<div/>");e[0];return e.addClass(o.supported),e.css("position").match("sticky")}},save:{lastScroll:function(e){p.lastScroll=e},elementScroll:function(e){p.elementScroll=e},positions:function(){var e={height:u.height()},t={margin:{top:parseInt(a.css("margin-top"),10),bottom:parseInt(a.css("margin-bottom"),10)},offset:a.offset(),width:a.outerWidth(),height:a.outerHeight()},o={offset:i.offset(),height:i.outerHeight()};n.outerHeight();p.is.standardScroll()||(p.debug("Non-standard scroll. Removing scroll offset from element offset"),e.top=u.scrollTop(),e.left=u.scrollLeft(),t.offset.top+=e.top,o.offset.top+=e.top,t.offset.left+=e.left,o.offset.left+=e.left),p.cache={fits:t.height+m.offset<=e.height,sameHeight:t.height==o.height,scrollContext:{height:e.height},element:{margin:t.margin,top:t.offset.top-t.margin.top,left:t.offset.left,width:t.width,height:t.height,bottom:t.offset.top+t.height},context:{top:o.offset.top,height:o.height,bottom:o.offset.top+o.height}},p.set.containerSize(),p.stick(),p.debug("Caching element positions",p.cache)}},get:{direction:function(e){var t="down";return e=e||u.scrollTop(),p.lastScroll!==P&&(p.lastScroll<e?t="down":p.lastScroll>e&&(t="up")),t},scrollChange:function(e){return e=e||u.scrollTop(),p.lastScroll?e-p.lastScroll:0},currentElementScroll:function(){return p.elementScroll?p.elementScroll:p.is.top()?Math.abs(parseInt(a.css("top"),10))||0:Math.abs(parseInt(a.css("bottom"),10))||0},elementScroll:function(e){e=e||u.scrollTop();var t=p.cache.element,o=p.cache.scrollContext,n=p.get.scrollChange(e),i=t.height-o.height+m.offset,s=p.get.currentElementScroll(),r=s+n;return s=p.cache.fits||r<0?0:i<r?i:r}},remove:{lastScroll:function(){delete p.lastScroll},elementScroll:function(e){delete p.elementScroll},minimumSize:function(){n.css("min-height","")},offset:function(){a.css("margin-top","")}},set:{offset:function(){p.verbose("Setting offset on element",m.offset),a.css("margin-top",m.offset)},containerSize:function(){var e,t=n.get(0).tagName;"HTML"===t||"body"==t?p.determineContainer():((e=Math.max(p.cache.context.height,p.cache.element.height))-n.outerHeight()>m.jitter?(p.debug("Context is taller than container. Specifying exact height for container",p.cache.context.height),n.css({height:e})):n.css({height:""}),Math.abs(n.outerHeight()-p.cache.context.height)>m.jitter&&(p.debug("Context has padding, specifying exact height for container",p.cache.context.height),n.css({height:p.cache.context.height})))},minimumSize:function(){var e=p.cache.element;n.css("min-height",e.height)},scroll:function(e){p.debug("Setting scroll on element",e),p.elementScroll!=e&&(p.is.top()&&a.css("bottom","").css("top",-e),p.is.bottom()&&a.css("top","").css("bottom",e))},size:function(){0!==p.cache.element.height&&0!==p.cache.element.width&&(g.style.setProperty("width",p.cache.element.width+"px","important"),g.style.setProperty("height",p.cache.element.height+"px","important"))}},is:{standardScroll:function(){return u[0]==w},top:function(){return a.hasClass(o.top)},bottom:function(){return a.hasClass(o.bottom)},initialPosition:function(){return!p.is.fixed()&&!p.is.bound()},hidden:function(){return!a.is(":visible")},bound:function(){return a.hasClass(o.bound)},fixed:function(){return a.hasClass(o.fixed)}},stick:function(e){var t=e||u.scrollTop(),o=p.cache,n=o.fits,i=o.sameHeight,s=o.element,r=o.scrollContext,c=o.context,l=p.is.bottom()&&m.pushing?m.bottomOffset:m.offset,e={top:t+l,bottom:t+l+r.height},a=(p.get.direction(e.top),n?0:p.get.elementScroll(e.top)),f=!n;0===s.height||i||(p.is.initialPosition()?e.top>=c.bottom?(p.debug("Initial element position is bottom of container"),p.bindBottom()):e.top>s.top&&(s.height+e.top-a>=c.bottom&&s.height<c.height?(p.debug("Initial element position is bottom of container"),p.bindBottom()):(p.debug("Initial element position is fixed"),p.fixTop())):p.is.fixed()?p.is.top()?e.top<=s.top?(p.debug("Fixed element reached top of container"),p.setInitialPosition()):s.height+e.top-a>=c.bottom?(p.debug("Fixed element reached bottom of container"),p.bindBottom()):f&&(p.set.scroll(a),p.save.lastScroll(e.top),p.save.elementScroll(a)):p.is.bottom()&&(e.bottom-s.height<=s.top?(p.debug("Bottom fixed rail has reached top of container"),p.setInitialPosition()):e.bottom>=c.bottom?(p.debug("Bottom fixed rail has reached bottom of container"),p.bindBottom()):f&&(p.set.scroll(a),p.save.lastScroll(e.top),p.save.elementScroll(a))):p.is.bottom()&&(e.top<=s.top?(p.debug("Jumped from bottom fixed to top fixed, most likely used home/end button"),p.setInitialPosition()):m.pushing?p.is.bound()&&e.bottom<=c.bottom&&(p.debug("Fixing bottom attached element to bottom of browser."),p.fixBottom()):p.is.bound()&&e.top<=c.bottom-s.height&&(p.debug("Fixing bottom attached element to top of browser."),p.fixTop())))},bindTop:function(){p.debug("Binding element to top of parent container"),p.remove.offset(),m.setSize&&p.set.size(),a.css({left:"",top:"",marginBottom:""}).removeClass(o.fixed).removeClass(o.bottom).addClass(o.bound).addClass(o.top),m.onTop.call(g),m.onUnstick.call(g)},bindBottom:function(){p.debug("Binding element to bottom of parent container"),p.remove.offset(),m.setSize&&p.set.size(),a.css({left:"",top:""}).removeClass(o.fixed).removeClass(o.top).addClass(o.bound).addClass(o.bottom),m.onBottom.call(g),m.onUnstick.call(g)},setInitialPosition:function(){p.debug("Returning to initial position"),p.unfix(),p.unbind()},fixTop:function(){p.debug("Fixing element to top of page"),m.setSize&&p.set.size(),p.set.minimumSize(),p.set.offset(),a.css({left:p.cache.element.left,bottom:"",marginBottom:""}).removeClass(o.bound).removeClass(o.bottom).addClass(o.fixed).addClass(o.top),m.onStick.call(g)},fixBottom:function(){p.debug("Sticking element to bottom of page"),m.setSize&&p.set.size(),p.set.minimumSize(),p.set.offset(),a.css({left:p.cache.element.left,bottom:"",marginBottom:""}).removeClass(o.bound).removeClass(o.top).addClass(o.fixed).addClass(o.bottom),m.onStick.call(g)},unbind:function(){p.is.bound()&&(p.debug("Removing container bound position on element"),p.remove.offset(),a.removeClass(o.bound).removeClass(o.top).removeClass(o.bottom))},unfix:function(){p.is.fixed()&&(p.debug("Removing fixed position on element"),p.remove.minimumSize(),p.remove.offset(),a.removeClass(o.fixed).removeClass(o.top).removeClass(o.bottom),m.onUnstick.call(g))},reset:function(){p.debug("Resetting elements position"),p.unbind(),p.unfix(),p.resetCSS(),p.remove.offset(),p.remove.lastScroll()},resetCSS:function(){a.css({width:"",height:""}),n.css({height:""})},setting:function(e,t){if(T.isPlainObject(e))T.extend(!0,m,e);else{if(t===P)return m[e];m[e]=t}},internal:function(e,t){if(T.isPlainObject(e))T.extend(!0,p,e);else{if(t===P)return p[e];p[e]=t}},debug:function(){!m.silent&&m.debug&&(m.performance?p.performance.log(arguments):(p.debug=Function.prototype.bind.call(console.info,console,m.name+":"),p.debug.apply(console,arguments)))},verbose:function(){!m.silent&&m.verbose&&m.debug&&(m.performance?p.performance.log(arguments):(p.verbose=Function.prototype.bind.call(console.info,console,m.name+":"),p.verbose.apply(console,arguments)))},error:function(){m.silent||(p.error=Function.prototype.bind.call(console.error,console,m.name+":"),p.error.apply(console,arguments))},performance:{log:function(e){var t,o;m.performance&&(o=(t=(new Date).getTime())-(S||t),S=t,C.push({Name:e[0],Arguments:[].slice.call(e,1)||"",Element:g,"Execution Time":o})),clearTimeout(p.performance.timer),p.performance.timer=setTimeout(p.performance.display,0)},display:function(){var e=m.name+":",o=0;S=!1,clearTimeout(p.performance.timer),T.each(C,function(e,t){o+=t["Execution Time"]}),e+=" "+o+"ms",x&&(e+=" '"+x+"'"),(console.group!==P||console.table!==P)&&0<C.length&&(console.groupCollapsed(e),console.table?console.table(C):T.each(C,function(e,t){console.log(t.Name+": "+t["Execution Time"]+"ms")}),console.groupEnd()),C=[]}},invoke:function(n,e,t){var i,s,o,r=h;return e=e||z,t=g||t,"string"==typeof n&&r!==P&&(n=n.split(/[\. ]/),i=n.length-1,T.each(n,function(e,t){var o=e!=i?t+n[e+1].charAt(0).toUpperCase()+n[e+1].slice(1):n;if(T.isPlainObject(r[o])&&e!=i)r=r[o];else{if(r[o]!==P)return s=r[o],!1;if(!T.isPlainObject(r[t])||e==i)return r[t]!==P&&(s=r[t]),!1;r=r[t]}})),T.isFunction(s)?o=s.apply(t,e):s!==P&&(o=s),T.isArray(v)?v.push(o):v!==P?v=[v,o]:o!==P&&(v=o),s}};k?(h===P&&p.initialize(),p.invoke(y)):(h!==P&&h.invoke("destroy"),p.initialize())}),v!==P?v:this},T.fn.sticky.settings={name:"Sticky",namespace:"sticky",silent:!1,debug:!1,verbose:!0,performance:!0,pushing:!1,context:!1,container:!1,scrollContext:w,offset:0,bottomOffset:0,jitter:5,setSize:!0,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. Use silent setting to surpress this warning in production.",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); |