stickybits
Advanced tools
Comparing version 3.2.3 to 3.2.4
@@ -0,1 +1,13 @@ | ||
<a name="3.2.3"></a> | ||
## [3.2.3](https://github.com/dollarshaveclub/stickybits/compare/3.2.0...3.2.3) (2018-04-10) | ||
<a name="3.2.0"></a> | ||
# [3.2.0](https://github.com/dollarshaveclub/stickybits/compare/3.1.1...3.2.0) (2018-03-08) | ||
<a name="3.1.1"></a> | ||
@@ -2,0 +14,0 @@ ## [3.1.1](https://github.com/dollarshaveclub/stickybits/compare/3.1.0...3.1.1) (2018-02-26) |
/** | ||
stickybits - Stickybits is a lightweight alternative to `position: sticky` polyfills | ||
@version v3.2.3 | ||
@version v3.2.4 | ||
@link https://github.com/dollarshaveclub/stickybits#readme | ||
@@ -8,2 +8,2 @@ @author Jeff Wainwright <yowainwright@gmail.com> (https://jeffry.in) | ||
**/ | ||
!function(t,s){"object"==typeof exports&&"undefined"!=typeof module?s():"function"==typeof define&&define.amd?define(s):s()}(0,function(){"use strict";function t(t,s){var e=void 0!==s?s:{};this.version="3.2.3",this.userAgent=window.navigator.userAgent||"no `userAgent` provided by the browser",this.props={customStickyChangeNumber:e.customStickyChangeNumber||null,noStyles:e.noStyles||!1,stickyBitStickyOffset:e.stickyBitStickyOffset||0,parentClass:e.parentClass||"js-stickybit-parent",scrollEl:document.querySelector(e.scrollEl)||window,stickyClass:e.stickyClass||"js-is-sticky",stuckClass:e.stuckClass||"js-is-stuck",stickyChangeClass:e.stickyChangeClass||"js-is-sticky--change",useStickyClasses:e.useStickyClasses||!1,verticalPosition:e.verticalPosition||"top"};var i=this.props;i.positionVal=this.definePosition()||"fixed";var n=i.verticalPosition,o=i.noStyles,a=i.positionVal;this.els="string"==typeof t?document.querySelectorAll(t):t,"length"in this.els||(this.els=[this.els]),this.instances=[];for(var r=0;r<this.els.length;r+=1){var l=this.els[r],c=l.style;if(c[n]="top"!==n||o?"":i.stickyBitStickyOffset+"px",c.position="fixed"!==a?a:"","fixed"===a||i.useStickyClasses){var p=this.addInstance(l,i);this.instances.push(p)}}return this}if(t.prototype.definePosition=function(){for(var t=["","-o-","-webkit-","-moz-","-ms-"],s=document.head.style,e=0;e<t.length;e+=1)s.position=t[e]+"sticky";var i=s.position?s.position:"fixed";return s.position="",i},t.prototype.addInstance=function(t,s){var e=this,i={el:t,parent:t.parentNode,props:s};this.isWin=this.props.scrollEl===window;var n=this.isWin?window:this.getClosestParent(i.el,i.props.scrollEl);return this.computeScrollOffsets(i),i.parent.className+=" "+s.parentClass,i.state="default",i.stateContainer=function(){return e.manageState(i)},n.addEventListener("scroll",i.stateContainer),i},t.prototype.getClosestParent=function(t,s){var e=s,i=t;if(i.parentElement===e)return e;for(;i.parentElement!==e;)i=i.parentElement;return e},t.prototype.computeScrollOffsets=function(t){var s=t,e=s.props,i=s.el,n=s.parent,o=!this.isWin&&"fixed"===e.positionVal,a="bottom"!==e.verticalPosition,r=o?e.scrollEl.getBoundingClientRect().top:0,l=o?n.getBoundingClientRect().top-r:n.getBoundingClientRect().top,c=null!==e.customStickyChangeNumber?e.customStickyChangeNumber:i.offsetHeight;return s.offset=r+e.stickyBitStickyOffset,s.stickyStart=a?l-s.offset:0,s.stickyChange=s.stickyStart+c,s.stickyStop=a?l+n.offsetHeight-(s.el.offsetHeight+s.offset):l+n.offsetHeight,s},t.prototype.toggleClasses=function(t,s,e){var i=t,n=i.className.split(" ");e&&-1===n.indexOf(e)&&n.push(e);var o=n.indexOf(s);-1!==o&&n.splice(o,1),i.className=n.join(" ")},t.prototype.manageState=function(t){var s=t,e=s.el,i=s.props,n=s.state,o=s.stickyStart,a=s.stickyChange,r=s.stickyStop,l=e.style,c=i.noStyles,p=i.positionVal,f=i.scrollEl,u=i.stickyClass,y=i.stickyChangeClass,d=i.stuckClass,h=i.verticalPosition,k=function(t){t()},m=this.isWin&&(window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame)||k,g=this.toggleClasses,C=this.isWin?window.scrollY||window.pageYOffset:f.scrollTop,v=C<=o&&"sticky"===n,w=C>=r&&"sticky"===n;C>o&&C<r&&("default"===n||"stuck"===n)?(s.state="sticky",m(function(){g(e,d,u),l.position=p,c||(l.bottom="",l[h]=i.stickyBitStickyOffset+"px")})):v?(s.state="default",m(function(){g(e,u),"fixed"===p&&(l.position="")})):w&&(s.state="stuck",m(function(){g(e,u,d),"fixed"!==p||c||(l.top="",l.bottom="0",l.position="absolute")}));var S=C>=a&&C<=r;return C<a||C>r?m(function(){g(e,y)}):S&&m(function(){g(e,"stub",y)}),s},t.prototype.removeInstance=function(t){var s=t.el,e=t.props,i=this.toggleClasses;s.style.position="",s.style[e.verticalPosition]="",i(s,e.stickyClass),i(s,e.stuckClass),i(s.parentNode,e.parentClass)},t.prototype.cleanup=function(){for(var t=0;t<this.instances.length;t+=1){var s=this.instances[t];s.props.scrollEl.removeEventListener("scroll",s.stateContainer),this.removeInstance(s)}this.manageState=!1,this.instances=[]},"undefined"!=typeof window){var s=window.$||window.jQuery||window.Zepto;s&&(s.fn.stickybits=function(s){new t(this,s)})}}); | ||
!function(t,s){"object"==typeof exports&&"undefined"!=typeof module?s():"function"==typeof define&&define.amd?define(s):s()}(0,function(){"use strict";var t=function(){function t(t,s){var e=void 0!==s?s:{};this.version="3.2.4",this.userAgent=window.navigator.userAgent||"no `userAgent` provided by the browser",this.props={customStickyChangeNumber:e.customStickyChangeNumber||null,noStyles:e.noStyles||!1,stickyBitStickyOffset:e.stickyBitStickyOffset||0,parentClass:e.parentClass||"js-stickybit-parent",scrollEl:document.querySelector(e.scrollEl)||window,stickyClass:e.stickyClass||"js-is-sticky",stuckClass:e.stuckClass||"js-is-stuck",stickyChangeClass:e.stickyChangeClass||"js-is-sticky--change",useStickyClasses:e.useStickyClasses||!1,verticalPosition:e.verticalPosition||"top"};var i=this.props;i.positionVal=this.definePosition()||"fixed";var n=i.verticalPosition,o=i.noStyles,a=i.positionVal;this.els="string"==typeof t?document.querySelectorAll(t):t,"length"in this.els||(this.els=[this.els]),this.instances=[];for(var r=0;r<this.els.length;r+=1){var l=this.els[r],c=l.style;if(c[n]="top"!==n||o?"":i.stickyBitStickyOffset+"px",c.position="fixed"!==a?a:"","fixed"===a||i.useStickyClasses){var f=this.addInstance(l,i);this.instances.push(f)}}return this}var s=t.prototype;return s.definePosition=function(){for(var t=["","-o-","-webkit-","-moz-","-ms-"],s=document.head.style,e=0;e<t.length;e+=1)s.position=t[e]+"sticky";var i=s.position?s.position:"fixed";return s.position="",i},s.addInstance=function(t,s){var e=this,i={el:t,parent:t.parentNode,props:s};this.isWin=this.props.scrollEl===window;var n=this.isWin?window:this.getClosestParent(i.el,i.props.scrollEl);return this.computeScrollOffsets(i),i.parent.className+=" "+s.parentClass,i.state="default",i.stateContainer=function(){return e.manageState(i)},n.addEventListener("scroll",i.stateContainer),i},s.getClosestParent=function(t,s){var e=s,i=t;if(i.parentElement===e)return e;for(;i.parentElement!==e;)i=i.parentElement;return e},s.computeScrollOffsets=function(t){var s=t,e=s.props,i=s.el,n=s.parent,o=!this.isWin&&"fixed"===e.positionVal,a="bottom"!==e.verticalPosition,r=o?e.scrollEl.getBoundingClientRect().top:0,l=o?n.getBoundingClientRect().top-r:n.getBoundingClientRect().top,c=null!==e.customStickyChangeNumber?e.customStickyChangeNumber:i.offsetHeight;return s.offset=r+e.stickyBitStickyOffset,s.stickyStart=a?l-s.offset:0,s.stickyChange=s.stickyStart+c,s.stickyStop=a?l+n.offsetHeight-(s.el.offsetHeight+s.offset):l+n.offsetHeight,s},s.toggleClasses=function(t,s,e){var i=t,n=i.className.split(" ");e&&-1===n.indexOf(e)&&n.push(e);var o=n.indexOf(s);-1!==o&&n.splice(o,1),i.className=n.join(" ")},s.manageState=function(t){var s=t,e=s.el,i=s.props,n=s.state,o=s.stickyStart,a=s.stickyChange,r=s.stickyStop,l=e.style,c=i.noStyles,f=i.positionVal,u=i.scrollEl,p=i.stickyClass,y=i.stickyChangeClass,d=i.stuckClass,h=i.verticalPosition,k=function(t){t()},m=this.isWin&&(window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame)||k,g=this.toggleClasses,C=this.isWin?window.scrollY||window.pageYOffset:u.scrollTop,v=C<=o&&"sticky"===n,w=C>=r&&"sticky"===n;C>o&&C<r&&("default"===n||"stuck"===n)?(s.state="sticky",m(function(){g(e,d,p),l.position=f,c||(l.bottom="",l[h]=i.stickyBitStickyOffset+"px")})):v?(s.state="default",m(function(){g(e,p),"fixed"===f&&(l.position="")})):w&&(s.state="stuck",m(function(){g(e,p,d),"fixed"!==f||c||(l.top="",l.bottom="0",l.position="absolute")}));var S=C>=a&&C<=r;return C<a||C>r?m(function(){g(e,y)}):S&&m(function(){g(e,"stub",y)}),s},s.removeInstance=function(t){var s=t.el,e=t.props,i=this.toggleClasses;s.style.position="",s.style[e.verticalPosition]="",i(s,e.stickyClass),i(s,e.stuckClass),i(s.parentNode,e.parentClass)},s.cleanup=function(){for(var t=0;t<this.instances.length;t+=1){var s=this.instances[t];s.props.scrollEl.removeEventListener("scroll",s.stateContainer),this.removeInstance(s)}this.manageState=!1,this.instances=[]},t}();if("undefined"!=typeof window){var s=window.$||window.jQuery||window.Zepto;s&&(s.fn.stickybits=function(s){new t(this,s)})}}); |
/** | ||
stickybits - Stickybits is a lightweight alternative to `position: sticky` polyfills | ||
@version v3.2.3 | ||
@version v3.2.4 | ||
@link https://github.com/dollarshaveclub/stickybits#readme | ||
@@ -60,325 +60,333 @@ @author Jeff Wainwright <yowainwright@gmail.com> (https://jeffry.in) | ||
*/ | ||
function Stickybits(target, obj) { | ||
var o = typeof obj !== 'undefined' ? obj : {}; | ||
this.version = '3.2.3'; | ||
this.userAgent = window.navigator.userAgent || 'no `userAgent` provided by the browser'; | ||
this.props = { | ||
customStickyChangeNumber: o.customStickyChangeNumber || null, | ||
noStyles: o.noStyles || false, | ||
stickyBitStickyOffset: o.stickyBitStickyOffset || 0, | ||
parentClass: o.parentClass || 'js-stickybit-parent', | ||
scrollEl: document.querySelector(o.scrollEl) || window, | ||
stickyClass: o.stickyClass || 'js-is-sticky', | ||
stuckClass: o.stuckClass || 'js-is-stuck', | ||
stickyChangeClass: o.stickyChangeClass || 'js-is-sticky--change', | ||
useStickyClasses: o.useStickyClasses || false, | ||
verticalPosition: o.verticalPosition || 'top' | ||
}; | ||
var p = this.props; | ||
/* | ||
define positionVal | ||
---- | ||
- uses a computed (`.definePosition()`) | ||
- defined the position | ||
*/ | ||
var Stickybits = | ||
/*#__PURE__*/ | ||
function () { | ||
function Stickybits(target, obj) { | ||
var o = typeof obj !== 'undefined' ? obj : {}; | ||
this.version = '3.2.4'; | ||
this.userAgent = window.navigator.userAgent || 'no `userAgent` provided by the browser'; | ||
this.props = { | ||
customStickyChangeNumber: o.customStickyChangeNumber || null, | ||
noStyles: o.noStyles || false, | ||
stickyBitStickyOffset: o.stickyBitStickyOffset || 0, | ||
parentClass: o.parentClass || 'js-stickybit-parent', | ||
scrollEl: document.querySelector(o.scrollEl) || window, | ||
stickyClass: o.stickyClass || 'js-is-sticky', | ||
stuckClass: o.stuckClass || 'js-is-stuck', | ||
stickyChangeClass: o.stickyChangeClass || 'js-is-sticky--change', | ||
useStickyClasses: o.useStickyClasses || false, | ||
verticalPosition: o.verticalPosition || 'top' | ||
}; | ||
var p = this.props; | ||
/* | ||
define positionVal | ||
---- | ||
- uses a computed (`.definePosition()`) | ||
- defined the position | ||
*/ | ||
p.positionVal = this.definePosition() || 'fixed'; | ||
var vp = p.verticalPosition; | ||
var ns = p.noStyles; | ||
var pv = p.positionVal; | ||
this.els = typeof target === 'string' ? document.querySelectorAll(target) : target; | ||
if (!('length' in this.els)) this.els = [this.els]; | ||
this.instances = []; | ||
p.positionVal = this.definePosition() || 'fixed'; | ||
var vp = p.verticalPosition; | ||
var ns = p.noStyles; | ||
var pv = p.positionVal; | ||
this.els = typeof target === 'string' ? document.querySelectorAll(target) : target; | ||
if (!('length' in this.els)) this.els = [this.els]; | ||
this.instances = []; | ||
for (var i = 0; i < this.els.length; i += 1) { | ||
var el = this.els[i]; | ||
var styles = el.style; // set vertical position | ||
for (var i = 0; i < this.els.length; i += 1) { | ||
var el = this.els[i]; | ||
var styles = el.style; // set vertical position | ||
styles[vp] = vp === 'top' && !ns ? p.stickyBitStickyOffset + "px" : ''; | ||
styles.position = pv !== 'fixed' ? pv : ''; | ||
styles[vp] = vp === 'top' && !ns ? p.stickyBitStickyOffset + "px" : ''; | ||
styles.position = pv !== 'fixed' ? pv : ''; | ||
if (pv === 'fixed' || p.useStickyClasses) { | ||
var instance = this.addInstance(el, p); // instances are an array of objects | ||
if (pv === 'fixed' || p.useStickyClasses) { | ||
var instance = this.addInstance(el, p); // instances are an array of objects | ||
this.instances.push(instance); | ||
this.instances.push(instance); | ||
} | ||
} | ||
} | ||
return this; | ||
} | ||
/* | ||
setStickyPosition βοΈ | ||
-------- | ||
β most basic thing stickybits does | ||
=> checks to see if position sticky is supported | ||
=> defined the position to be used | ||
=> stickybits works accordingly | ||
*/ | ||
Stickybits.prototype.definePosition = function () { | ||
var prefix = ['', '-o-', '-webkit-', '-moz-', '-ms-']; | ||
var test = document.head.style; | ||
for (var i = 0; i < prefix.length; i += 1) { | ||
test.position = prefix[i] + "sticky"; | ||
return this; | ||
} | ||
/* | ||
setStickyPosition βοΈ | ||
-------- | ||
β most basic thing stickybits does | ||
=> checks to see if position sticky is supported | ||
=> defined the position to be used | ||
=> stickybits works accordingly | ||
*/ | ||
var stickyProp = test.position ? test.position : 'fixed'; | ||
test.position = ''; | ||
return stickyProp; | ||
}; | ||
/* | ||
addInstance βοΈ | ||
-------- | ||
β manages instances of items | ||
- takes in an el and props | ||
- returns an item object | ||
--- | ||
- target = el | ||
- o = {object} = props | ||
- scrollEl = 'string' | ||
- verticalPosition = number | ||
- off = boolean | ||
- parentClass = 'string' | ||
- stickyClass = 'string' | ||
- stuckClass = 'string' | ||
--- | ||
- defined later | ||
- parent = dom element | ||
- state = 'string' | ||
- offset = number | ||
- stickyStart = number | ||
- stickyStop = number | ||
- returns an instance object | ||
*/ | ||
var _proto = Stickybits.prototype; | ||
Stickybits.prototype.addInstance = function addInstance(el, props) { | ||
var _this = this; | ||
_proto.definePosition = function definePosition() { | ||
var prefix = ['', '-o-', '-webkit-', '-moz-', '-ms-']; | ||
var test = document.head.style; | ||
var item = { | ||
el: el, | ||
parent: el.parentNode, | ||
props: props | ||
}; | ||
this.isWin = this.props.scrollEl === window; | ||
var se = this.isWin ? window : this.getClosestParent(item.el, item.props.scrollEl); | ||
this.computeScrollOffsets(item); | ||
item.parent.className += " " + props.parentClass; | ||
item.state = 'default'; | ||
for (var i = 0; i < prefix.length; i += 1) { | ||
test.position = prefix[i] + "sticky"; | ||
} | ||
item.stateContainer = function () { | ||
return _this.manageState(item); | ||
var stickyProp = test.position ? test.position : 'fixed'; | ||
test.position = ''; | ||
return stickyProp; | ||
}; | ||
/* | ||
addInstance βοΈ | ||
-------- | ||
β manages instances of items | ||
- takes in an el and props | ||
- returns an item object | ||
--- | ||
- target = el | ||
- o = {object} = props | ||
- scrollEl = 'string' | ||
- verticalPosition = number | ||
- off = boolean | ||
- parentClass = 'string' | ||
- stickyClass = 'string' | ||
- stuckClass = 'string' | ||
--- | ||
- defined later | ||
- parent = dom element | ||
- state = 'string' | ||
- offset = number | ||
- stickyStart = number | ||
- stickyStop = number | ||
- returns an instance object | ||
*/ | ||
se.addEventListener('scroll', item.stateContainer); | ||
return item; | ||
}; | ||
/* | ||
-------- | ||
getParent π¨β | ||
-------- | ||
- a helper function that gets the target element's parent selected el | ||
- only used for non `window` scroll elements | ||
- supports older browsers | ||
*/ | ||
_proto.addInstance = function addInstance(el, props) { | ||
var _this = this; | ||
Stickybits.prototype.getClosestParent = function (el, match) { | ||
// p = parent element | ||
var p = match; | ||
var e = el; | ||
if (e.parentElement === p) return p; // traverse up the dom tree until we get to the parent | ||
var item = { | ||
el: el, | ||
parent: el.parentNode, | ||
props: props | ||
}; | ||
this.isWin = this.props.scrollEl === window; | ||
var se = this.isWin ? window : this.getClosestParent(item.el, item.props.scrollEl); | ||
this.computeScrollOffsets(item); | ||
item.parent.className += " " + props.parentClass; | ||
item.state = 'default'; | ||
while (e.parentElement !== p) { | ||
e = e.parentElement; | ||
} // return parent element | ||
item.stateContainer = function () { | ||
return _this.manageState(item); | ||
}; | ||
se.addEventListener('scroll', item.stateContainer); | ||
return item; | ||
}; | ||
/* | ||
-------- | ||
getParent π¨β | ||
-------- | ||
- a helper function that gets the target element's parent selected el | ||
- only used for non `window` scroll elements | ||
- supports older browsers | ||
*/ | ||
return p; | ||
}; | ||
/* | ||
computeScrollOffsets π | ||
--- | ||
computeScrollOffsets for Stickybits | ||
- defines | ||
- offset | ||
- start | ||
- stop | ||
*/ | ||
_proto.getClosestParent = function getClosestParent(el, match) { | ||
// p = parent element | ||
var p = match; | ||
var e = el; | ||
if (e.parentElement === p) return p; // traverse up the dom tree until we get to the parent | ||
Stickybits.prototype.computeScrollOffsets = function computeScrollOffsets(item) { | ||
var it = item; | ||
var p = it.props; | ||
var el = it.el; | ||
var parent = it.parent; | ||
var isCustom = !this.isWin && p.positionVal === 'fixed'; | ||
var isBottom = p.verticalPosition !== 'bottom'; | ||
var scrollElOffset = isCustom ? p.scrollEl.getBoundingClientRect().top : 0; | ||
var stickyStart = isCustom ? parent.getBoundingClientRect().top - scrollElOffset : parent.getBoundingClientRect().top; | ||
var stickyChangeOffset = p.customStickyChangeNumber !== null ? p.customStickyChangeNumber : el.offsetHeight; | ||
it.offset = scrollElOffset + p.stickyBitStickyOffset; | ||
it.stickyStart = isBottom ? stickyStart - it.offset : 0; | ||
it.stickyChange = it.stickyStart + stickyChangeOffset; | ||
it.stickyStop = isBottom ? stickyStart + parent.offsetHeight - (it.el.offsetHeight + it.offset) : stickyStart + parent.offsetHeight; | ||
return it; | ||
}; | ||
/* | ||
toggleClasses βοΈ | ||
--- | ||
toggles classes (for older browser support) | ||
r = removed class | ||
a = added class | ||
*/ | ||
while (e.parentElement !== p) { | ||
e = e.parentElement; | ||
} // return parent element | ||
Stickybits.prototype.toggleClasses = function (el, r, a) { | ||
var e = el; | ||
var cArray = e.className.split(' '); | ||
if (a && cArray.indexOf(a) === -1) cArray.push(a); | ||
var rItem = cArray.indexOf(r); | ||
if (rItem !== -1) cArray.splice(rItem, 1); | ||
e.className = cArray.join(' '); | ||
}; | ||
/* | ||
manageState π | ||
--- | ||
- defines the state | ||
- normal | ||
- sticky | ||
- stuck | ||
*/ | ||
Stickybits.prototype.manageState = function manageState(item) { | ||
// cache object | ||
var it = item; | ||
var e = it.el; | ||
var p = it.props; | ||
var state = it.state; | ||
var start = it.stickyStart; | ||
var change = it.stickyChange; | ||
var stop = it.stickyStop; | ||
var stl = e.style; // cache props | ||
var ns = p.noStyles; | ||
var pv = p.positionVal; | ||
var se = p.scrollEl; | ||
var sticky = p.stickyClass; | ||
var stickyChange = p.stickyChangeClass; | ||
var stuck = p.stuckClass; | ||
var vp = p.verticalPosition; | ||
return p; | ||
}; | ||
/* | ||
requestAnimationFrame | ||
computeScrollOffsets π | ||
--- | ||
- use rAF | ||
- or stub rAF | ||
computeScrollOffsets for Stickybits | ||
- defines | ||
- offset | ||
- start | ||
- stop | ||
*/ | ||
var rAFStub = function rAFDummy(f) { | ||
f(); | ||
_proto.computeScrollOffsets = function computeScrollOffsets(item) { | ||
var it = item; | ||
var p = it.props; | ||
var el = it.el; | ||
var parent = it.parent; | ||
var isCustom = !this.isWin && p.positionVal === 'fixed'; | ||
var isBottom = p.verticalPosition !== 'bottom'; | ||
var scrollElOffset = isCustom ? p.scrollEl.getBoundingClientRect().top : 0; | ||
var stickyStart = isCustom ? parent.getBoundingClientRect().top - scrollElOffset : parent.getBoundingClientRect().top; | ||
var stickyChangeOffset = p.customStickyChangeNumber !== null ? p.customStickyChangeNumber : el.offsetHeight; | ||
it.offset = scrollElOffset + p.stickyBitStickyOffset; | ||
it.stickyStart = isBottom ? stickyStart - it.offset : 0; | ||
it.stickyChange = it.stickyStart + stickyChangeOffset; | ||
it.stickyStop = isBottom ? stickyStart + parent.offsetHeight - (it.el.offsetHeight + it.offset) : stickyStart + parent.offsetHeight; | ||
return it; | ||
}; | ||
var rAF = !this.isWin ? rAFStub : window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || rAFStub; | ||
/* | ||
define scroll vars | ||
toggleClasses βοΈ | ||
--- | ||
- scroll | ||
- notSticky | ||
- isSticky | ||
- isStuck | ||
toggles classes (for older browser support) | ||
r = removed class | ||
a = added class | ||
*/ | ||
var tC = this.toggleClasses; | ||
var scroll = this.isWin ? window.scrollY || window.pageYOffset : se.scrollTop; | ||
var notSticky = scroll > start && scroll < stop && (state === 'default' || state === 'stuck'); | ||
var isSticky = scroll <= start && state === 'sticky'; | ||
var isStuck = scroll >= stop && state === 'sticky'; | ||
_proto.toggleClasses = function toggleClasses(el, r, a) { | ||
var e = el; | ||
var cArray = e.className.split(' '); | ||
if (a && cArray.indexOf(a) === -1) cArray.push(a); | ||
var rItem = cArray.indexOf(r); | ||
if (rItem !== -1) cArray.splice(rItem, 1); | ||
e.className = cArray.join(' '); | ||
}; | ||
/* | ||
Unnamed arrow functions within this block | ||
manageState π | ||
--- | ||
- help wanted or discussion | ||
- view test.stickybits.js | ||
- `stickybits .manageState `position: fixed` interface` for more awareness π | ||
- defines the state | ||
- normal | ||
- sticky | ||
- stuck | ||
*/ | ||
if (notSticky) { | ||
it.state = 'sticky'; | ||
rAF(function () { | ||
tC(e, stuck, sticky); | ||
stl.position = pv; | ||
if (ns) return; | ||
stl.bottom = ''; | ||
stl[vp] = p.stickyBitStickyOffset + "px"; | ||
}); | ||
} else if (isSticky) { | ||
it.state = 'default'; | ||
rAF(function () { | ||
tC(e, sticky); | ||
if (pv === 'fixed') stl.position = ''; | ||
}); | ||
} else if (isStuck) { | ||
it.state = 'stuck'; | ||
rAF(function () { | ||
tC(e, sticky, stuck); | ||
if (pv !== 'fixed' || ns) return; | ||
stl.top = ''; | ||
stl.bottom = '0'; | ||
stl.position = 'absolute'; | ||
}); | ||
} | ||
var isStickyChange = scroll >= change && scroll <= stop; | ||
var isNotStickyChange = scroll < change || scroll > stop; | ||
var stub = 'stub'; // a stub css class to remove | ||
_proto.manageState = function manageState(item) { | ||
// cache object | ||
var it = item; | ||
var e = it.el; | ||
var p = it.props; | ||
var state = it.state; | ||
var start = it.stickyStart; | ||
var change = it.stickyChange; | ||
var stop = it.stickyStop; | ||
var stl = e.style; // cache props | ||
if (isNotStickyChange) { | ||
rAF(function () { | ||
tC(e, stickyChange); | ||
}); | ||
} else if (isStickyChange) { | ||
rAF(function () { | ||
tC(e, stub, stickyChange); | ||
}); | ||
} | ||
var ns = p.noStyles; | ||
var pv = p.positionVal; | ||
var se = p.scrollEl; | ||
var sticky = p.stickyClass; | ||
var stickyChange = p.stickyChangeClass; | ||
var stuck = p.stuckClass; | ||
var vp = p.verticalPosition; | ||
/* | ||
requestAnimationFrame | ||
--- | ||
- use rAF | ||
- or stub rAF | ||
*/ | ||
return it; | ||
}; | ||
/* | ||
removes an instance π | ||
-------- | ||
- cleanup instance | ||
*/ | ||
var rAFStub = function rAFDummy(f) { | ||
f(); | ||
}; | ||
var rAF = !this.isWin ? rAFStub : window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || rAFStub; | ||
/* | ||
define scroll vars | ||
--- | ||
- scroll | ||
- notSticky | ||
- isSticky | ||
- isStuck | ||
*/ | ||
Stickybits.prototype.removeInstance = function removeInstance(instance) { | ||
var e = instance.el; | ||
var p = instance.props; | ||
var tC = this.toggleClasses; | ||
e.style.position = ''; | ||
e.style[p.verticalPosition] = ''; | ||
tC(e, p.stickyClass); | ||
tC(e, p.stuckClass); | ||
tC(e.parentNode, p.parentClass); | ||
}; | ||
/* | ||
cleanup π | ||
-------- | ||
- cleans up each instance | ||
- clears instance | ||
*/ | ||
var tC = this.toggleClasses; | ||
var scroll = this.isWin ? window.scrollY || window.pageYOffset : se.scrollTop; | ||
var notSticky = scroll > start && scroll < stop && (state === 'default' || state === 'stuck'); | ||
var isSticky = scroll <= start && state === 'sticky'; | ||
var isStuck = scroll >= stop && state === 'sticky'; | ||
/* | ||
Unnamed arrow functions within this block | ||
--- | ||
- help wanted or discussion | ||
- view test.stickybits.js | ||
- `stickybits .manageState `position: fixed` interface` for more awareness π | ||
*/ | ||
if (notSticky) { | ||
it.state = 'sticky'; | ||
rAF(function () { | ||
tC(e, stuck, sticky); | ||
stl.position = pv; | ||
if (ns) return; | ||
stl.bottom = ''; | ||
stl[vp] = p.stickyBitStickyOffset + "px"; | ||
}); | ||
} else if (isSticky) { | ||
it.state = 'default'; | ||
rAF(function () { | ||
tC(e, sticky); | ||
if (pv === 'fixed') stl.position = ''; | ||
}); | ||
} else if (isStuck) { | ||
it.state = 'stuck'; | ||
rAF(function () { | ||
tC(e, sticky, stuck); | ||
if (pv !== 'fixed' || ns) return; | ||
stl.top = ''; | ||
stl.bottom = '0'; | ||
stl.position = 'absolute'; | ||
}); | ||
} | ||
Stickybits.prototype.cleanup = function cleanup() { | ||
for (var i = 0; i < this.instances.length; i += 1) { | ||
var instance = this.instances[i]; | ||
instance.props.scrollEl.removeEventListener('scroll', instance.stateContainer); | ||
this.removeInstance(instance); | ||
} | ||
var isStickyChange = scroll >= change && scroll <= stop; | ||
var isNotStickyChange = scroll < change || scroll > stop; | ||
var stub = 'stub'; // a stub css class to remove | ||
this.manageState = false; | ||
this.instances = []; | ||
}; | ||
if (isNotStickyChange) { | ||
rAF(function () { | ||
tC(e, stickyChange); | ||
}); | ||
} else if (isStickyChange) { | ||
rAF(function () { | ||
tC(e, stub, stickyChange); | ||
}); | ||
} | ||
return it; | ||
}; | ||
/* | ||
removes an instance π | ||
-------- | ||
- cleanup instance | ||
*/ | ||
_proto.removeInstance = function removeInstance(instance) { | ||
var e = instance.el; | ||
var p = instance.props; | ||
var tC = this.toggleClasses; | ||
e.style.position = ''; | ||
e.style[p.verticalPosition] = ''; | ||
tC(e, p.stickyClass); | ||
tC(e, p.stuckClass); | ||
tC(e.parentNode, p.parentClass); | ||
}; | ||
/* | ||
cleanup π | ||
-------- | ||
- cleans up each instance | ||
- clears instance | ||
*/ | ||
_proto.cleanup = function cleanup() { | ||
for (var i = 0; i < this.instances.length; i += 1) { | ||
var instance = this.instances[i]; | ||
instance.props.scrollEl.removeEventListener('scroll', instance.stateContainer); | ||
this.removeInstance(instance); | ||
} | ||
this.manageState = false; | ||
this.instances = []; | ||
}; | ||
return Stickybits; | ||
}(); | ||
/* | ||
@@ -385,0 +393,0 @@ export |
/** | ||
stickybits - Stickybits is a lightweight alternative to `position: sticky` polyfills | ||
@version v3.2.3 | ||
@version v3.2.4 | ||
@link https://github.com/dollarshaveclub/stickybits#readme | ||
@@ -66,325 +66,333 @@ @author Jeff Wainwright <yowainwright@gmail.com> (https://jeffry.in) | ||
*/ | ||
function Stickybits(target, obj) { | ||
var o = typeof obj !== 'undefined' ? obj : {}; | ||
this.version = '3.2.3'; | ||
this.userAgent = window.navigator.userAgent || 'no `userAgent` provided by the browser'; | ||
this.props = { | ||
customStickyChangeNumber: o.customStickyChangeNumber || null, | ||
noStyles: o.noStyles || false, | ||
stickyBitStickyOffset: o.stickyBitStickyOffset || 0, | ||
parentClass: o.parentClass || 'js-stickybit-parent', | ||
scrollEl: document.querySelector(o.scrollEl) || window, | ||
stickyClass: o.stickyClass || 'js-is-sticky', | ||
stuckClass: o.stuckClass || 'js-is-stuck', | ||
stickyChangeClass: o.stickyChangeClass || 'js-is-sticky--change', | ||
useStickyClasses: o.useStickyClasses || false, | ||
verticalPosition: o.verticalPosition || 'top' | ||
}; | ||
var p = this.props; | ||
/* | ||
define positionVal | ||
---- | ||
- uses a computed (`.definePosition()`) | ||
- defined the position | ||
*/ | ||
var Stickybits = | ||
/*#__PURE__*/ | ||
function () { | ||
function Stickybits(target, obj) { | ||
var o = typeof obj !== 'undefined' ? obj : {}; | ||
this.version = '3.2.4'; | ||
this.userAgent = window.navigator.userAgent || 'no `userAgent` provided by the browser'; | ||
this.props = { | ||
customStickyChangeNumber: o.customStickyChangeNumber || null, | ||
noStyles: o.noStyles || false, | ||
stickyBitStickyOffset: o.stickyBitStickyOffset || 0, | ||
parentClass: o.parentClass || 'js-stickybit-parent', | ||
scrollEl: document.querySelector(o.scrollEl) || window, | ||
stickyClass: o.stickyClass || 'js-is-sticky', | ||
stuckClass: o.stuckClass || 'js-is-stuck', | ||
stickyChangeClass: o.stickyChangeClass || 'js-is-sticky--change', | ||
useStickyClasses: o.useStickyClasses || false, | ||
verticalPosition: o.verticalPosition || 'top' | ||
}; | ||
var p = this.props; | ||
/* | ||
define positionVal | ||
---- | ||
- uses a computed (`.definePosition()`) | ||
- defined the position | ||
*/ | ||
p.positionVal = this.definePosition() || 'fixed'; | ||
var vp = p.verticalPosition; | ||
var ns = p.noStyles; | ||
var pv = p.positionVal; | ||
this.els = typeof target === 'string' ? document.querySelectorAll(target) : target; | ||
if (!('length' in this.els)) this.els = [this.els]; | ||
this.instances = []; | ||
p.positionVal = this.definePosition() || 'fixed'; | ||
var vp = p.verticalPosition; | ||
var ns = p.noStyles; | ||
var pv = p.positionVal; | ||
this.els = typeof target === 'string' ? document.querySelectorAll(target) : target; | ||
if (!('length' in this.els)) this.els = [this.els]; | ||
this.instances = []; | ||
for (var i = 0; i < this.els.length; i += 1) { | ||
var el = this.els[i]; | ||
var styles = el.style; // set vertical position | ||
for (var i = 0; i < this.els.length; i += 1) { | ||
var el = this.els[i]; | ||
var styles = el.style; // set vertical position | ||
styles[vp] = vp === 'top' && !ns ? p.stickyBitStickyOffset + "px" : ''; | ||
styles.position = pv !== 'fixed' ? pv : ''; | ||
styles[vp] = vp === 'top' && !ns ? p.stickyBitStickyOffset + "px" : ''; | ||
styles.position = pv !== 'fixed' ? pv : ''; | ||
if (pv === 'fixed' || p.useStickyClasses) { | ||
var instance = this.addInstance(el, p); // instances are an array of objects | ||
if (pv === 'fixed' || p.useStickyClasses) { | ||
var instance = this.addInstance(el, p); // instances are an array of objects | ||
this.instances.push(instance); | ||
this.instances.push(instance); | ||
} | ||
} | ||
} | ||
return this; | ||
} | ||
/* | ||
setStickyPosition βοΈ | ||
-------- | ||
β most basic thing stickybits does | ||
=> checks to see if position sticky is supported | ||
=> defined the position to be used | ||
=> stickybits works accordingly | ||
*/ | ||
Stickybits.prototype.definePosition = function () { | ||
var prefix = ['', '-o-', '-webkit-', '-moz-', '-ms-']; | ||
var test = document.head.style; | ||
for (var i = 0; i < prefix.length; i += 1) { | ||
test.position = prefix[i] + "sticky"; | ||
return this; | ||
} | ||
/* | ||
setStickyPosition βοΈ | ||
-------- | ||
β most basic thing stickybits does | ||
=> checks to see if position sticky is supported | ||
=> defined the position to be used | ||
=> stickybits works accordingly | ||
*/ | ||
var stickyProp = test.position ? test.position : 'fixed'; | ||
test.position = ''; | ||
return stickyProp; | ||
}; | ||
/* | ||
addInstance βοΈ | ||
-------- | ||
β manages instances of items | ||
- takes in an el and props | ||
- returns an item object | ||
--- | ||
- target = el | ||
- o = {object} = props | ||
- scrollEl = 'string' | ||
- verticalPosition = number | ||
- off = boolean | ||
- parentClass = 'string' | ||
- stickyClass = 'string' | ||
- stuckClass = 'string' | ||
--- | ||
- defined later | ||
- parent = dom element | ||
- state = 'string' | ||
- offset = number | ||
- stickyStart = number | ||
- stickyStop = number | ||
- returns an instance object | ||
*/ | ||
var _proto = Stickybits.prototype; | ||
Stickybits.prototype.addInstance = function addInstance(el, props) { | ||
var _this = this; | ||
_proto.definePosition = function definePosition() { | ||
var prefix = ['', '-o-', '-webkit-', '-moz-', '-ms-']; | ||
var test = document.head.style; | ||
var item = { | ||
el: el, | ||
parent: el.parentNode, | ||
props: props | ||
}; | ||
this.isWin = this.props.scrollEl === window; | ||
var se = this.isWin ? window : this.getClosestParent(item.el, item.props.scrollEl); | ||
this.computeScrollOffsets(item); | ||
item.parent.className += " " + props.parentClass; | ||
item.state = 'default'; | ||
for (var i = 0; i < prefix.length; i += 1) { | ||
test.position = prefix[i] + "sticky"; | ||
} | ||
item.stateContainer = function () { | ||
return _this.manageState(item); | ||
var stickyProp = test.position ? test.position : 'fixed'; | ||
test.position = ''; | ||
return stickyProp; | ||
}; | ||
/* | ||
addInstance βοΈ | ||
-------- | ||
β manages instances of items | ||
- takes in an el and props | ||
- returns an item object | ||
--- | ||
- target = el | ||
- o = {object} = props | ||
- scrollEl = 'string' | ||
- verticalPosition = number | ||
- off = boolean | ||
- parentClass = 'string' | ||
- stickyClass = 'string' | ||
- stuckClass = 'string' | ||
--- | ||
- defined later | ||
- parent = dom element | ||
- state = 'string' | ||
- offset = number | ||
- stickyStart = number | ||
- stickyStop = number | ||
- returns an instance object | ||
*/ | ||
se.addEventListener('scroll', item.stateContainer); | ||
return item; | ||
}; | ||
/* | ||
-------- | ||
getParent π¨β | ||
-------- | ||
- a helper function that gets the target element's parent selected el | ||
- only used for non `window` scroll elements | ||
- supports older browsers | ||
*/ | ||
_proto.addInstance = function addInstance(el, props) { | ||
var _this = this; | ||
Stickybits.prototype.getClosestParent = function (el, match) { | ||
// p = parent element | ||
var p = match; | ||
var e = el; | ||
if (e.parentElement === p) return p; // traverse up the dom tree until we get to the parent | ||
var item = { | ||
el: el, | ||
parent: el.parentNode, | ||
props: props | ||
}; | ||
this.isWin = this.props.scrollEl === window; | ||
var se = this.isWin ? window : this.getClosestParent(item.el, item.props.scrollEl); | ||
this.computeScrollOffsets(item); | ||
item.parent.className += " " + props.parentClass; | ||
item.state = 'default'; | ||
while (e.parentElement !== p) { | ||
e = e.parentElement; | ||
} // return parent element | ||
item.stateContainer = function () { | ||
return _this.manageState(item); | ||
}; | ||
se.addEventListener('scroll', item.stateContainer); | ||
return item; | ||
}; | ||
/* | ||
-------- | ||
getParent π¨β | ||
-------- | ||
- a helper function that gets the target element's parent selected el | ||
- only used for non `window` scroll elements | ||
- supports older browsers | ||
*/ | ||
return p; | ||
}; | ||
/* | ||
computeScrollOffsets π | ||
--- | ||
computeScrollOffsets for Stickybits | ||
- defines | ||
- offset | ||
- start | ||
- stop | ||
*/ | ||
_proto.getClosestParent = function getClosestParent(el, match) { | ||
// p = parent element | ||
var p = match; | ||
var e = el; | ||
if (e.parentElement === p) return p; // traverse up the dom tree until we get to the parent | ||
Stickybits.prototype.computeScrollOffsets = function computeScrollOffsets(item) { | ||
var it = item; | ||
var p = it.props; | ||
var el = it.el; | ||
var parent = it.parent; | ||
var isCustom = !this.isWin && p.positionVal === 'fixed'; | ||
var isBottom = p.verticalPosition !== 'bottom'; | ||
var scrollElOffset = isCustom ? p.scrollEl.getBoundingClientRect().top : 0; | ||
var stickyStart = isCustom ? parent.getBoundingClientRect().top - scrollElOffset : parent.getBoundingClientRect().top; | ||
var stickyChangeOffset = p.customStickyChangeNumber !== null ? p.customStickyChangeNumber : el.offsetHeight; | ||
it.offset = scrollElOffset + p.stickyBitStickyOffset; | ||
it.stickyStart = isBottom ? stickyStart - it.offset : 0; | ||
it.stickyChange = it.stickyStart + stickyChangeOffset; | ||
it.stickyStop = isBottom ? stickyStart + parent.offsetHeight - (it.el.offsetHeight + it.offset) : stickyStart + parent.offsetHeight; | ||
return it; | ||
}; | ||
/* | ||
toggleClasses βοΈ | ||
--- | ||
toggles classes (for older browser support) | ||
r = removed class | ||
a = added class | ||
*/ | ||
while (e.parentElement !== p) { | ||
e = e.parentElement; | ||
} // return parent element | ||
Stickybits.prototype.toggleClasses = function (el, r, a) { | ||
var e = el; | ||
var cArray = e.className.split(' '); | ||
if (a && cArray.indexOf(a) === -1) cArray.push(a); | ||
var rItem = cArray.indexOf(r); | ||
if (rItem !== -1) cArray.splice(rItem, 1); | ||
e.className = cArray.join(' '); | ||
}; | ||
/* | ||
manageState π | ||
--- | ||
- defines the state | ||
- normal | ||
- sticky | ||
- stuck | ||
*/ | ||
Stickybits.prototype.manageState = function manageState(item) { | ||
// cache object | ||
var it = item; | ||
var e = it.el; | ||
var p = it.props; | ||
var state = it.state; | ||
var start = it.stickyStart; | ||
var change = it.stickyChange; | ||
var stop = it.stickyStop; | ||
var stl = e.style; // cache props | ||
var ns = p.noStyles; | ||
var pv = p.positionVal; | ||
var se = p.scrollEl; | ||
var sticky = p.stickyClass; | ||
var stickyChange = p.stickyChangeClass; | ||
var stuck = p.stuckClass; | ||
var vp = p.verticalPosition; | ||
return p; | ||
}; | ||
/* | ||
requestAnimationFrame | ||
computeScrollOffsets π | ||
--- | ||
- use rAF | ||
- or stub rAF | ||
computeScrollOffsets for Stickybits | ||
- defines | ||
- offset | ||
- start | ||
- stop | ||
*/ | ||
var rAFStub = function rAFDummy(f) { | ||
f(); | ||
_proto.computeScrollOffsets = function computeScrollOffsets(item) { | ||
var it = item; | ||
var p = it.props; | ||
var el = it.el; | ||
var parent = it.parent; | ||
var isCustom = !this.isWin && p.positionVal === 'fixed'; | ||
var isBottom = p.verticalPosition !== 'bottom'; | ||
var scrollElOffset = isCustom ? p.scrollEl.getBoundingClientRect().top : 0; | ||
var stickyStart = isCustom ? parent.getBoundingClientRect().top - scrollElOffset : parent.getBoundingClientRect().top; | ||
var stickyChangeOffset = p.customStickyChangeNumber !== null ? p.customStickyChangeNumber : el.offsetHeight; | ||
it.offset = scrollElOffset + p.stickyBitStickyOffset; | ||
it.stickyStart = isBottom ? stickyStart - it.offset : 0; | ||
it.stickyChange = it.stickyStart + stickyChangeOffset; | ||
it.stickyStop = isBottom ? stickyStart + parent.offsetHeight - (it.el.offsetHeight + it.offset) : stickyStart + parent.offsetHeight; | ||
return it; | ||
}; | ||
var rAF = !this.isWin ? rAFStub : window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || rAFStub; | ||
/* | ||
define scroll vars | ||
toggleClasses βοΈ | ||
--- | ||
- scroll | ||
- notSticky | ||
- isSticky | ||
- isStuck | ||
toggles classes (for older browser support) | ||
r = removed class | ||
a = added class | ||
*/ | ||
var tC = this.toggleClasses; | ||
var scroll = this.isWin ? window.scrollY || window.pageYOffset : se.scrollTop; | ||
var notSticky = scroll > start && scroll < stop && (state === 'default' || state === 'stuck'); | ||
var isSticky = scroll <= start && state === 'sticky'; | ||
var isStuck = scroll >= stop && state === 'sticky'; | ||
_proto.toggleClasses = function toggleClasses(el, r, a) { | ||
var e = el; | ||
var cArray = e.className.split(' '); | ||
if (a && cArray.indexOf(a) === -1) cArray.push(a); | ||
var rItem = cArray.indexOf(r); | ||
if (rItem !== -1) cArray.splice(rItem, 1); | ||
e.className = cArray.join(' '); | ||
}; | ||
/* | ||
Unnamed arrow functions within this block | ||
manageState π | ||
--- | ||
- help wanted or discussion | ||
- view test.stickybits.js | ||
- `stickybits .manageState `position: fixed` interface` for more awareness π | ||
- defines the state | ||
- normal | ||
- sticky | ||
- stuck | ||
*/ | ||
if (notSticky) { | ||
it.state = 'sticky'; | ||
rAF(function () { | ||
tC(e, stuck, sticky); | ||
stl.position = pv; | ||
if (ns) return; | ||
stl.bottom = ''; | ||
stl[vp] = p.stickyBitStickyOffset + "px"; | ||
}); | ||
} else if (isSticky) { | ||
it.state = 'default'; | ||
rAF(function () { | ||
tC(e, sticky); | ||
if (pv === 'fixed') stl.position = ''; | ||
}); | ||
} else if (isStuck) { | ||
it.state = 'stuck'; | ||
rAF(function () { | ||
tC(e, sticky, stuck); | ||
if (pv !== 'fixed' || ns) return; | ||
stl.top = ''; | ||
stl.bottom = '0'; | ||
stl.position = 'absolute'; | ||
}); | ||
} | ||
var isStickyChange = scroll >= change && scroll <= stop; | ||
var isNotStickyChange = scroll < change || scroll > stop; | ||
var stub = 'stub'; // a stub css class to remove | ||
_proto.manageState = function manageState(item) { | ||
// cache object | ||
var it = item; | ||
var e = it.el; | ||
var p = it.props; | ||
var state = it.state; | ||
var start = it.stickyStart; | ||
var change = it.stickyChange; | ||
var stop = it.stickyStop; | ||
var stl = e.style; // cache props | ||
if (isNotStickyChange) { | ||
rAF(function () { | ||
tC(e, stickyChange); | ||
}); | ||
} else if (isStickyChange) { | ||
rAF(function () { | ||
tC(e, stub, stickyChange); | ||
}); | ||
} | ||
var ns = p.noStyles; | ||
var pv = p.positionVal; | ||
var se = p.scrollEl; | ||
var sticky = p.stickyClass; | ||
var stickyChange = p.stickyChangeClass; | ||
var stuck = p.stuckClass; | ||
var vp = p.verticalPosition; | ||
/* | ||
requestAnimationFrame | ||
--- | ||
- use rAF | ||
- or stub rAF | ||
*/ | ||
return it; | ||
}; | ||
/* | ||
removes an instance π | ||
-------- | ||
- cleanup instance | ||
*/ | ||
var rAFStub = function rAFDummy(f) { | ||
f(); | ||
}; | ||
var rAF = !this.isWin ? rAFStub : window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || rAFStub; | ||
/* | ||
define scroll vars | ||
--- | ||
- scroll | ||
- notSticky | ||
- isSticky | ||
- isStuck | ||
*/ | ||
Stickybits.prototype.removeInstance = function removeInstance(instance) { | ||
var e = instance.el; | ||
var p = instance.props; | ||
var tC = this.toggleClasses; | ||
e.style.position = ''; | ||
e.style[p.verticalPosition] = ''; | ||
tC(e, p.stickyClass); | ||
tC(e, p.stuckClass); | ||
tC(e.parentNode, p.parentClass); | ||
}; | ||
/* | ||
cleanup π | ||
-------- | ||
- cleans up each instance | ||
- clears instance | ||
*/ | ||
var tC = this.toggleClasses; | ||
var scroll = this.isWin ? window.scrollY || window.pageYOffset : se.scrollTop; | ||
var notSticky = scroll > start && scroll < stop && (state === 'default' || state === 'stuck'); | ||
var isSticky = scroll <= start && state === 'sticky'; | ||
var isStuck = scroll >= stop && state === 'sticky'; | ||
/* | ||
Unnamed arrow functions within this block | ||
--- | ||
- help wanted or discussion | ||
- view test.stickybits.js | ||
- `stickybits .manageState `position: fixed` interface` for more awareness π | ||
*/ | ||
if (notSticky) { | ||
it.state = 'sticky'; | ||
rAF(function () { | ||
tC(e, stuck, sticky); | ||
stl.position = pv; | ||
if (ns) return; | ||
stl.bottom = ''; | ||
stl[vp] = p.stickyBitStickyOffset + "px"; | ||
}); | ||
} else if (isSticky) { | ||
it.state = 'default'; | ||
rAF(function () { | ||
tC(e, sticky); | ||
if (pv === 'fixed') stl.position = ''; | ||
}); | ||
} else if (isStuck) { | ||
it.state = 'stuck'; | ||
rAF(function () { | ||
tC(e, sticky, stuck); | ||
if (pv !== 'fixed' || ns) return; | ||
stl.top = ''; | ||
stl.bottom = '0'; | ||
stl.position = 'absolute'; | ||
}); | ||
} | ||
Stickybits.prototype.cleanup = function cleanup() { | ||
for (var i = 0; i < this.instances.length; i += 1) { | ||
var instance = this.instances[i]; | ||
instance.props.scrollEl.removeEventListener('scroll', instance.stateContainer); | ||
this.removeInstance(instance); | ||
} | ||
var isStickyChange = scroll >= change && scroll <= stop; | ||
var isNotStickyChange = scroll < change || scroll > stop; | ||
var stub = 'stub'; // a stub css class to remove | ||
this.manageState = false; | ||
this.instances = []; | ||
}; | ||
if (isNotStickyChange) { | ||
rAF(function () { | ||
tC(e, stickyChange); | ||
}); | ||
} else if (isStickyChange) { | ||
rAF(function () { | ||
tC(e, stub, stickyChange); | ||
}); | ||
} | ||
return it; | ||
}; | ||
/* | ||
removes an instance π | ||
-------- | ||
- cleanup instance | ||
*/ | ||
_proto.removeInstance = function removeInstance(instance) { | ||
var e = instance.el; | ||
var p = instance.props; | ||
var tC = this.toggleClasses; | ||
e.style.position = ''; | ||
e.style[p.verticalPosition] = ''; | ||
tC(e, p.stickyClass); | ||
tC(e, p.stuckClass); | ||
tC(e.parentNode, p.parentClass); | ||
}; | ||
/* | ||
cleanup π | ||
-------- | ||
- cleans up each instance | ||
- clears instance | ||
*/ | ||
_proto.cleanup = function cleanup() { | ||
for (var i = 0; i < this.instances.length; i += 1) { | ||
var instance = this.instances[i]; | ||
instance.props.scrollEl.removeEventListener('scroll', instance.stateContainer); | ||
this.removeInstance(instance); | ||
} | ||
this.manageState = false; | ||
this.instances = []; | ||
}; | ||
return Stickybits; | ||
}(); | ||
/* | ||
@@ -391,0 +399,0 @@ export |
/** | ||
stickybits - Stickybits is a lightweight alternative to `position: sticky` polyfills | ||
@version v3.2.3 | ||
@version v3.2.4 | ||
@link https://github.com/dollarshaveclub/stickybits#readme | ||
@@ -8,2 +8,2 @@ @author Jeff Wainwright <yowainwright@gmail.com> (https://jeffry.in) | ||
**/ | ||
!function(t,s){"object"==typeof exports&&"undefined"!=typeof module?module.exports=s():"function"==typeof define&&define.amd?define(s):t.stickybits=s()}(this,function(){"use strict";function t(t,s){var e=void 0!==s?s:{};this.version="3.2.3",this.userAgent=window.navigator.userAgent||"no `userAgent` provided by the browser",this.props={customStickyChangeNumber:e.customStickyChangeNumber||null,noStyles:e.noStyles||!1,stickyBitStickyOffset:e.stickyBitStickyOffset||0,parentClass:e.parentClass||"js-stickybit-parent",scrollEl:document.querySelector(e.scrollEl)||window,stickyClass:e.stickyClass||"js-is-sticky",stuckClass:e.stuckClass||"js-is-stuck",stickyChangeClass:e.stickyChangeClass||"js-is-sticky--change",useStickyClasses:e.useStickyClasses||!1,verticalPosition:e.verticalPosition||"top"};var i=this.props;i.positionVal=this.definePosition()||"fixed";var n=i.verticalPosition,o=i.noStyles,a=i.positionVal;this.els="string"==typeof t?document.querySelectorAll(t):t,"length"in this.els||(this.els=[this.els]),this.instances=[];for(var r=0;r<this.els.length;r+=1){var l=this.els[r],c=l.style;if(c[n]="top"!==n||o?"":i.stickyBitStickyOffset+"px",c.position="fixed"!==a?a:"","fixed"===a||i.useStickyClasses){var p=this.addInstance(l,i);this.instances.push(p)}}return this}return t.prototype.definePosition=function(){for(var t=["","-o-","-webkit-","-moz-","-ms-"],s=document.head.style,e=0;e<t.length;e+=1)s.position=t[e]+"sticky";var i=s.position?s.position:"fixed";return s.position="",i},t.prototype.addInstance=function(t,s){var e=this,i={el:t,parent:t.parentNode,props:s};this.isWin=this.props.scrollEl===window;var n=this.isWin?window:this.getClosestParent(i.el,i.props.scrollEl);return this.computeScrollOffsets(i),i.parent.className+=" "+s.parentClass,i.state="default",i.stateContainer=function(){return e.manageState(i)},n.addEventListener("scroll",i.stateContainer),i},t.prototype.getClosestParent=function(t,s){var e=s,i=t;if(i.parentElement===e)return e;for(;i.parentElement!==e;)i=i.parentElement;return e},t.prototype.computeScrollOffsets=function(t){var s=t,e=s.props,i=s.el,n=s.parent,o=!this.isWin&&"fixed"===e.positionVal,a="bottom"!==e.verticalPosition,r=o?e.scrollEl.getBoundingClientRect().top:0,l=o?n.getBoundingClientRect().top-r:n.getBoundingClientRect().top,c=null!==e.customStickyChangeNumber?e.customStickyChangeNumber:i.offsetHeight;return s.offset=r+e.stickyBitStickyOffset,s.stickyStart=a?l-s.offset:0,s.stickyChange=s.stickyStart+c,s.stickyStop=a?l+n.offsetHeight-(s.el.offsetHeight+s.offset):l+n.offsetHeight,s},t.prototype.toggleClasses=function(t,s,e){var i=t,n=i.className.split(" ");e&&-1===n.indexOf(e)&&n.push(e);var o=n.indexOf(s);-1!==o&&n.splice(o,1),i.className=n.join(" ")},t.prototype.manageState=function(t){var s=t,e=s.el,i=s.props,n=s.state,o=s.stickyStart,a=s.stickyChange,r=s.stickyStop,l=e.style,c=i.noStyles,p=i.positionVal,u=i.scrollEl,f=i.stickyClass,y=i.stickyChangeClass,h=i.stuckClass,d=i.verticalPosition,k=function(t){t()},m=this.isWin&&(window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame)||k,g=this.toggleClasses,C=this.isWin?window.scrollY||window.pageYOffset:u.scrollTop,v=C<=o&&"sticky"===n,S=C>=r&&"sticky"===n;C>o&&C<r&&("default"===n||"stuck"===n)?(s.state="sticky",m(function(){g(e,h,f),l.position=p,c||(l.bottom="",l[d]=i.stickyBitStickyOffset+"px")})):v?(s.state="default",m(function(){g(e,f),"fixed"===p&&(l.position="")})):S&&(s.state="stuck",m(function(){g(e,f,h),"fixed"!==p||c||(l.top="",l.bottom="0",l.position="absolute")}));var w=C>=a&&C<=r;return C<a||C>r?m(function(){g(e,y)}):w&&m(function(){g(e,"stub",y)}),s},t.prototype.removeInstance=function(t){var s=t.el,e=t.props,i=this.toggleClasses;s.style.position="",s.style[e.verticalPosition]="",i(s,e.stickyClass),i(s,e.stuckClass),i(s.parentNode,e.parentClass)},t.prototype.cleanup=function(){for(var t=0;t<this.instances.length;t+=1){var s=this.instances[t];s.props.scrollEl.removeEventListener("scroll",s.stateContainer),this.removeInstance(s)}this.manageState=!1,this.instances=[]},function(s,e){return new t(s,e)}}); | ||
!function(t,s){"object"==typeof exports&&"undefined"!=typeof module?module.exports=s():"function"==typeof define&&define.amd?define(s):t.stickybits=s()}(this,function(){"use strict";var t=function(){function t(t,s){var e=void 0!==s?s:{};this.version="3.2.4",this.userAgent=window.navigator.userAgent||"no `userAgent` provided by the browser",this.props={customStickyChangeNumber:e.customStickyChangeNumber||null,noStyles:e.noStyles||!1,stickyBitStickyOffset:e.stickyBitStickyOffset||0,parentClass:e.parentClass||"js-stickybit-parent",scrollEl:document.querySelector(e.scrollEl)||window,stickyClass:e.stickyClass||"js-is-sticky",stuckClass:e.stuckClass||"js-is-stuck",stickyChangeClass:e.stickyChangeClass||"js-is-sticky--change",useStickyClasses:e.useStickyClasses||!1,verticalPosition:e.verticalPosition||"top"};var i=this.props;i.positionVal=this.definePosition()||"fixed";var n=i.verticalPosition,o=i.noStyles,a=i.positionVal;this.els="string"==typeof t?document.querySelectorAll(t):t,"length"in this.els||(this.els=[this.els]),this.instances=[];for(var r=0;r<this.els.length;r+=1){var l=this.els[r],c=l.style;if(c[n]="top"!==n||o?"":i.stickyBitStickyOffset+"px",c.position="fixed"!==a?a:"","fixed"===a||i.useStickyClasses){var u=this.addInstance(l,i);this.instances.push(u)}}return this}var s=t.prototype;return s.definePosition=function(){for(var t=["","-o-","-webkit-","-moz-","-ms-"],s=document.head.style,e=0;e<t.length;e+=1)s.position=t[e]+"sticky";var i=s.position?s.position:"fixed";return s.position="",i},s.addInstance=function(t,s){var e=this,i={el:t,parent:t.parentNode,props:s};this.isWin=this.props.scrollEl===window;var n=this.isWin?window:this.getClosestParent(i.el,i.props.scrollEl);return this.computeScrollOffsets(i),i.parent.className+=" "+s.parentClass,i.state="default",i.stateContainer=function(){return e.manageState(i)},n.addEventListener("scroll",i.stateContainer),i},s.getClosestParent=function(t,s){var e=s,i=t;if(i.parentElement===e)return e;for(;i.parentElement!==e;)i=i.parentElement;return e},s.computeScrollOffsets=function(t){var s=t,e=s.props,i=s.el,n=s.parent,o=!this.isWin&&"fixed"===e.positionVal,a="bottom"!==e.verticalPosition,r=o?e.scrollEl.getBoundingClientRect().top:0,l=o?n.getBoundingClientRect().top-r:n.getBoundingClientRect().top,c=null!==e.customStickyChangeNumber?e.customStickyChangeNumber:i.offsetHeight;return s.offset=r+e.stickyBitStickyOffset,s.stickyStart=a?l-s.offset:0,s.stickyChange=s.stickyStart+c,s.stickyStop=a?l+n.offsetHeight-(s.el.offsetHeight+s.offset):l+n.offsetHeight,s},s.toggleClasses=function(t,s,e){var i=t,n=i.className.split(" ");e&&-1===n.indexOf(e)&&n.push(e);var o=n.indexOf(s);-1!==o&&n.splice(o,1),i.className=n.join(" ")},s.manageState=function(t){var s=t,e=s.el,i=s.props,n=s.state,o=s.stickyStart,a=s.stickyChange,r=s.stickyStop,l=e.style,c=i.noStyles,u=i.positionVal,f=i.scrollEl,p=i.stickyClass,y=i.stickyChangeClass,h=i.stuckClass,d=i.verticalPosition,k=function(t){t()},m=this.isWin&&(window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame)||k,g=this.toggleClasses,C=this.isWin?window.scrollY||window.pageYOffset:f.scrollTop,v=C<=o&&"sticky"===n,S=C>=r&&"sticky"===n;C>o&&C<r&&("default"===n||"stuck"===n)?(s.state="sticky",m(function(){g(e,h,p),l.position=u,c||(l.bottom="",l[d]=i.stickyBitStickyOffset+"px")})):v?(s.state="default",m(function(){g(e,p),"fixed"===u&&(l.position="")})):S&&(s.state="stuck",m(function(){g(e,p,h),"fixed"!==u||c||(l.top="",l.bottom="0",l.position="absolute")}));var w=C>=a&&C<=r;return C<a||C>r?m(function(){g(e,y)}):w&&m(function(){g(e,"stub",y)}),s},s.removeInstance=function(t){var s=t.el,e=t.props,i=this.toggleClasses;s.style.position="",s.style[e.verticalPosition]="",i(s,e.stickyClass),i(s,e.stuckClass),i(s.parentNode,e.parentClass)},s.cleanup=function(){for(var t=0;t<this.instances.length;t+=1){var s=this.instances[t];s.props.scrollEl.removeEventListener("scroll",s.stateContainer),this.removeInstance(s)}this.manageState=!1,this.instances=[]},t}();return function(s,e){return new t(s,e)}}); |
/** | ||
stickybits - Stickybits is a lightweight alternative to `position: sticky` polyfills | ||
@version v3.2.3 | ||
@version v3.2.4 | ||
@link https://github.com/dollarshaveclub/stickybits#readme | ||
@@ -66,325 +66,333 @@ @author Jeff Wainwright <yowainwright@gmail.com> (https://jeffry.in) | ||
*/ | ||
function Stickybits(target, obj) { | ||
var o = typeof obj !== 'undefined' ? obj : {}; | ||
this.version = '3.2.3'; | ||
this.userAgent = window.navigator.userAgent || 'no `userAgent` provided by the browser'; | ||
this.props = { | ||
customStickyChangeNumber: o.customStickyChangeNumber || null, | ||
noStyles: o.noStyles || false, | ||
stickyBitStickyOffset: o.stickyBitStickyOffset || 0, | ||
parentClass: o.parentClass || 'js-stickybit-parent', | ||
scrollEl: document.querySelector(o.scrollEl) || window, | ||
stickyClass: o.stickyClass || 'js-is-sticky', | ||
stuckClass: o.stuckClass || 'js-is-stuck', | ||
stickyChangeClass: o.stickyChangeClass || 'js-is-sticky--change', | ||
useStickyClasses: o.useStickyClasses || false, | ||
verticalPosition: o.verticalPosition || 'top' | ||
}; | ||
var p = this.props; | ||
/* | ||
define positionVal | ||
---- | ||
- uses a computed (`.definePosition()`) | ||
- defined the position | ||
*/ | ||
var Stickybits = | ||
/*#__PURE__*/ | ||
function () { | ||
function Stickybits(target, obj) { | ||
var o = typeof obj !== 'undefined' ? obj : {}; | ||
this.version = '3.2.4'; | ||
this.userAgent = window.navigator.userAgent || 'no `userAgent` provided by the browser'; | ||
this.props = { | ||
customStickyChangeNumber: o.customStickyChangeNumber || null, | ||
noStyles: o.noStyles || false, | ||
stickyBitStickyOffset: o.stickyBitStickyOffset || 0, | ||
parentClass: o.parentClass || 'js-stickybit-parent', | ||
scrollEl: document.querySelector(o.scrollEl) || window, | ||
stickyClass: o.stickyClass || 'js-is-sticky', | ||
stuckClass: o.stuckClass || 'js-is-stuck', | ||
stickyChangeClass: o.stickyChangeClass || 'js-is-sticky--change', | ||
useStickyClasses: o.useStickyClasses || false, | ||
verticalPosition: o.verticalPosition || 'top' | ||
}; | ||
var p = this.props; | ||
/* | ||
define positionVal | ||
---- | ||
- uses a computed (`.definePosition()`) | ||
- defined the position | ||
*/ | ||
p.positionVal = this.definePosition() || 'fixed'; | ||
var vp = p.verticalPosition; | ||
var ns = p.noStyles; | ||
var pv = p.positionVal; | ||
this.els = typeof target === 'string' ? document.querySelectorAll(target) : target; | ||
if (!('length' in this.els)) this.els = [this.els]; | ||
this.instances = []; | ||
p.positionVal = this.definePosition() || 'fixed'; | ||
var vp = p.verticalPosition; | ||
var ns = p.noStyles; | ||
var pv = p.positionVal; | ||
this.els = typeof target === 'string' ? document.querySelectorAll(target) : target; | ||
if (!('length' in this.els)) this.els = [this.els]; | ||
this.instances = []; | ||
for (var i = 0; i < this.els.length; i += 1) { | ||
var el = this.els[i]; | ||
var styles = el.style; // set vertical position | ||
for (var i = 0; i < this.els.length; i += 1) { | ||
var el = this.els[i]; | ||
var styles = el.style; // set vertical position | ||
styles[vp] = vp === 'top' && !ns ? p.stickyBitStickyOffset + "px" : ''; | ||
styles.position = pv !== 'fixed' ? pv : ''; | ||
styles[vp] = vp === 'top' && !ns ? p.stickyBitStickyOffset + "px" : ''; | ||
styles.position = pv !== 'fixed' ? pv : ''; | ||
if (pv === 'fixed' || p.useStickyClasses) { | ||
var instance = this.addInstance(el, p); // instances are an array of objects | ||
if (pv === 'fixed' || p.useStickyClasses) { | ||
var instance = this.addInstance(el, p); // instances are an array of objects | ||
this.instances.push(instance); | ||
this.instances.push(instance); | ||
} | ||
} | ||
} | ||
return this; | ||
} | ||
/* | ||
setStickyPosition βοΈ | ||
-------- | ||
β most basic thing stickybits does | ||
=> checks to see if position sticky is supported | ||
=> defined the position to be used | ||
=> stickybits works accordingly | ||
*/ | ||
Stickybits.prototype.definePosition = function () { | ||
var prefix = ['', '-o-', '-webkit-', '-moz-', '-ms-']; | ||
var test = document.head.style; | ||
for (var i = 0; i < prefix.length; i += 1) { | ||
test.position = prefix[i] + "sticky"; | ||
return this; | ||
} | ||
/* | ||
setStickyPosition βοΈ | ||
-------- | ||
β most basic thing stickybits does | ||
=> checks to see if position sticky is supported | ||
=> defined the position to be used | ||
=> stickybits works accordingly | ||
*/ | ||
var stickyProp = test.position ? test.position : 'fixed'; | ||
test.position = ''; | ||
return stickyProp; | ||
}; | ||
/* | ||
addInstance βοΈ | ||
-------- | ||
β manages instances of items | ||
- takes in an el and props | ||
- returns an item object | ||
--- | ||
- target = el | ||
- o = {object} = props | ||
- scrollEl = 'string' | ||
- verticalPosition = number | ||
- off = boolean | ||
- parentClass = 'string' | ||
- stickyClass = 'string' | ||
- stuckClass = 'string' | ||
--- | ||
- defined later | ||
- parent = dom element | ||
- state = 'string' | ||
- offset = number | ||
- stickyStart = number | ||
- stickyStop = number | ||
- returns an instance object | ||
*/ | ||
var _proto = Stickybits.prototype; | ||
Stickybits.prototype.addInstance = function addInstance(el, props) { | ||
var _this = this; | ||
_proto.definePosition = function definePosition() { | ||
var prefix = ['', '-o-', '-webkit-', '-moz-', '-ms-']; | ||
var test = document.head.style; | ||
var item = { | ||
el: el, | ||
parent: el.parentNode, | ||
props: props | ||
}; | ||
this.isWin = this.props.scrollEl === window; | ||
var se = this.isWin ? window : this.getClosestParent(item.el, item.props.scrollEl); | ||
this.computeScrollOffsets(item); | ||
item.parent.className += " " + props.parentClass; | ||
item.state = 'default'; | ||
for (var i = 0; i < prefix.length; i += 1) { | ||
test.position = prefix[i] + "sticky"; | ||
} | ||
item.stateContainer = function () { | ||
return _this.manageState(item); | ||
var stickyProp = test.position ? test.position : 'fixed'; | ||
test.position = ''; | ||
return stickyProp; | ||
}; | ||
/* | ||
addInstance βοΈ | ||
-------- | ||
β manages instances of items | ||
- takes in an el and props | ||
- returns an item object | ||
--- | ||
- target = el | ||
- o = {object} = props | ||
- scrollEl = 'string' | ||
- verticalPosition = number | ||
- off = boolean | ||
- parentClass = 'string' | ||
- stickyClass = 'string' | ||
- stuckClass = 'string' | ||
--- | ||
- defined later | ||
- parent = dom element | ||
- state = 'string' | ||
- offset = number | ||
- stickyStart = number | ||
- stickyStop = number | ||
- returns an instance object | ||
*/ | ||
se.addEventListener('scroll', item.stateContainer); | ||
return item; | ||
}; | ||
/* | ||
-------- | ||
getParent π¨β | ||
-------- | ||
- a helper function that gets the target element's parent selected el | ||
- only used for non `window` scroll elements | ||
- supports older browsers | ||
*/ | ||
_proto.addInstance = function addInstance(el, props) { | ||
var _this = this; | ||
Stickybits.prototype.getClosestParent = function (el, match) { | ||
// p = parent element | ||
var p = match; | ||
var e = el; | ||
if (e.parentElement === p) return p; // traverse up the dom tree until we get to the parent | ||
var item = { | ||
el: el, | ||
parent: el.parentNode, | ||
props: props | ||
}; | ||
this.isWin = this.props.scrollEl === window; | ||
var se = this.isWin ? window : this.getClosestParent(item.el, item.props.scrollEl); | ||
this.computeScrollOffsets(item); | ||
item.parent.className += " " + props.parentClass; | ||
item.state = 'default'; | ||
while (e.parentElement !== p) { | ||
e = e.parentElement; | ||
} // return parent element | ||
item.stateContainer = function () { | ||
return _this.manageState(item); | ||
}; | ||
se.addEventListener('scroll', item.stateContainer); | ||
return item; | ||
}; | ||
/* | ||
-------- | ||
getParent π¨β | ||
-------- | ||
- a helper function that gets the target element's parent selected el | ||
- only used for non `window` scroll elements | ||
- supports older browsers | ||
*/ | ||
return p; | ||
}; | ||
/* | ||
computeScrollOffsets π | ||
--- | ||
computeScrollOffsets for Stickybits | ||
- defines | ||
- offset | ||
- start | ||
- stop | ||
*/ | ||
_proto.getClosestParent = function getClosestParent(el, match) { | ||
// p = parent element | ||
var p = match; | ||
var e = el; | ||
if (e.parentElement === p) return p; // traverse up the dom tree until we get to the parent | ||
Stickybits.prototype.computeScrollOffsets = function computeScrollOffsets(item) { | ||
var it = item; | ||
var p = it.props; | ||
var el = it.el; | ||
var parent = it.parent; | ||
var isCustom = !this.isWin && p.positionVal === 'fixed'; | ||
var isBottom = p.verticalPosition !== 'bottom'; | ||
var scrollElOffset = isCustom ? p.scrollEl.getBoundingClientRect().top : 0; | ||
var stickyStart = isCustom ? parent.getBoundingClientRect().top - scrollElOffset : parent.getBoundingClientRect().top; | ||
var stickyChangeOffset = p.customStickyChangeNumber !== null ? p.customStickyChangeNumber : el.offsetHeight; | ||
it.offset = scrollElOffset + p.stickyBitStickyOffset; | ||
it.stickyStart = isBottom ? stickyStart - it.offset : 0; | ||
it.stickyChange = it.stickyStart + stickyChangeOffset; | ||
it.stickyStop = isBottom ? stickyStart + parent.offsetHeight - (it.el.offsetHeight + it.offset) : stickyStart + parent.offsetHeight; | ||
return it; | ||
}; | ||
/* | ||
toggleClasses βοΈ | ||
--- | ||
toggles classes (for older browser support) | ||
r = removed class | ||
a = added class | ||
*/ | ||
while (e.parentElement !== p) { | ||
e = e.parentElement; | ||
} // return parent element | ||
Stickybits.prototype.toggleClasses = function (el, r, a) { | ||
var e = el; | ||
var cArray = e.className.split(' '); | ||
if (a && cArray.indexOf(a) === -1) cArray.push(a); | ||
var rItem = cArray.indexOf(r); | ||
if (rItem !== -1) cArray.splice(rItem, 1); | ||
e.className = cArray.join(' '); | ||
}; | ||
/* | ||
manageState π | ||
--- | ||
- defines the state | ||
- normal | ||
- sticky | ||
- stuck | ||
*/ | ||
Stickybits.prototype.manageState = function manageState(item) { | ||
// cache object | ||
var it = item; | ||
var e = it.el; | ||
var p = it.props; | ||
var state = it.state; | ||
var start = it.stickyStart; | ||
var change = it.stickyChange; | ||
var stop = it.stickyStop; | ||
var stl = e.style; // cache props | ||
var ns = p.noStyles; | ||
var pv = p.positionVal; | ||
var se = p.scrollEl; | ||
var sticky = p.stickyClass; | ||
var stickyChange = p.stickyChangeClass; | ||
var stuck = p.stuckClass; | ||
var vp = p.verticalPosition; | ||
return p; | ||
}; | ||
/* | ||
requestAnimationFrame | ||
computeScrollOffsets π | ||
--- | ||
- use rAF | ||
- or stub rAF | ||
computeScrollOffsets for Stickybits | ||
- defines | ||
- offset | ||
- start | ||
- stop | ||
*/ | ||
var rAFStub = function rAFDummy(f) { | ||
f(); | ||
_proto.computeScrollOffsets = function computeScrollOffsets(item) { | ||
var it = item; | ||
var p = it.props; | ||
var el = it.el; | ||
var parent = it.parent; | ||
var isCustom = !this.isWin && p.positionVal === 'fixed'; | ||
var isBottom = p.verticalPosition !== 'bottom'; | ||
var scrollElOffset = isCustom ? p.scrollEl.getBoundingClientRect().top : 0; | ||
var stickyStart = isCustom ? parent.getBoundingClientRect().top - scrollElOffset : parent.getBoundingClientRect().top; | ||
var stickyChangeOffset = p.customStickyChangeNumber !== null ? p.customStickyChangeNumber : el.offsetHeight; | ||
it.offset = scrollElOffset + p.stickyBitStickyOffset; | ||
it.stickyStart = isBottom ? stickyStart - it.offset : 0; | ||
it.stickyChange = it.stickyStart + stickyChangeOffset; | ||
it.stickyStop = isBottom ? stickyStart + parent.offsetHeight - (it.el.offsetHeight + it.offset) : stickyStart + parent.offsetHeight; | ||
return it; | ||
}; | ||
var rAF = !this.isWin ? rAFStub : window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || rAFStub; | ||
/* | ||
define scroll vars | ||
toggleClasses βοΈ | ||
--- | ||
- scroll | ||
- notSticky | ||
- isSticky | ||
- isStuck | ||
toggles classes (for older browser support) | ||
r = removed class | ||
a = added class | ||
*/ | ||
var tC = this.toggleClasses; | ||
var scroll = this.isWin ? window.scrollY || window.pageYOffset : se.scrollTop; | ||
var notSticky = scroll > start && scroll < stop && (state === 'default' || state === 'stuck'); | ||
var isSticky = scroll <= start && state === 'sticky'; | ||
var isStuck = scroll >= stop && state === 'sticky'; | ||
_proto.toggleClasses = function toggleClasses(el, r, a) { | ||
var e = el; | ||
var cArray = e.className.split(' '); | ||
if (a && cArray.indexOf(a) === -1) cArray.push(a); | ||
var rItem = cArray.indexOf(r); | ||
if (rItem !== -1) cArray.splice(rItem, 1); | ||
e.className = cArray.join(' '); | ||
}; | ||
/* | ||
Unnamed arrow functions within this block | ||
manageState π | ||
--- | ||
- help wanted or discussion | ||
- view test.stickybits.js | ||
- `stickybits .manageState `position: fixed` interface` for more awareness π | ||
- defines the state | ||
- normal | ||
- sticky | ||
- stuck | ||
*/ | ||
if (notSticky) { | ||
it.state = 'sticky'; | ||
rAF(function () { | ||
tC(e, stuck, sticky); | ||
stl.position = pv; | ||
if (ns) return; | ||
stl.bottom = ''; | ||
stl[vp] = p.stickyBitStickyOffset + "px"; | ||
}); | ||
} else if (isSticky) { | ||
it.state = 'default'; | ||
rAF(function () { | ||
tC(e, sticky); | ||
if (pv === 'fixed') stl.position = ''; | ||
}); | ||
} else if (isStuck) { | ||
it.state = 'stuck'; | ||
rAF(function () { | ||
tC(e, sticky, stuck); | ||
if (pv !== 'fixed' || ns) return; | ||
stl.top = ''; | ||
stl.bottom = '0'; | ||
stl.position = 'absolute'; | ||
}); | ||
} | ||
var isStickyChange = scroll >= change && scroll <= stop; | ||
var isNotStickyChange = scroll < change || scroll > stop; | ||
var stub = 'stub'; // a stub css class to remove | ||
_proto.manageState = function manageState(item) { | ||
// cache object | ||
var it = item; | ||
var e = it.el; | ||
var p = it.props; | ||
var state = it.state; | ||
var start = it.stickyStart; | ||
var change = it.stickyChange; | ||
var stop = it.stickyStop; | ||
var stl = e.style; // cache props | ||
if (isNotStickyChange) { | ||
rAF(function () { | ||
tC(e, stickyChange); | ||
}); | ||
} else if (isStickyChange) { | ||
rAF(function () { | ||
tC(e, stub, stickyChange); | ||
}); | ||
} | ||
var ns = p.noStyles; | ||
var pv = p.positionVal; | ||
var se = p.scrollEl; | ||
var sticky = p.stickyClass; | ||
var stickyChange = p.stickyChangeClass; | ||
var stuck = p.stuckClass; | ||
var vp = p.verticalPosition; | ||
/* | ||
requestAnimationFrame | ||
--- | ||
- use rAF | ||
- or stub rAF | ||
*/ | ||
return it; | ||
}; | ||
/* | ||
removes an instance π | ||
-------- | ||
- cleanup instance | ||
*/ | ||
var rAFStub = function rAFDummy(f) { | ||
f(); | ||
}; | ||
var rAF = !this.isWin ? rAFStub : window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || rAFStub; | ||
/* | ||
define scroll vars | ||
--- | ||
- scroll | ||
- notSticky | ||
- isSticky | ||
- isStuck | ||
*/ | ||
Stickybits.prototype.removeInstance = function removeInstance(instance) { | ||
var e = instance.el; | ||
var p = instance.props; | ||
var tC = this.toggleClasses; | ||
e.style.position = ''; | ||
e.style[p.verticalPosition] = ''; | ||
tC(e, p.stickyClass); | ||
tC(e, p.stuckClass); | ||
tC(e.parentNode, p.parentClass); | ||
}; | ||
/* | ||
cleanup π | ||
-------- | ||
- cleans up each instance | ||
- clears instance | ||
*/ | ||
var tC = this.toggleClasses; | ||
var scroll = this.isWin ? window.scrollY || window.pageYOffset : se.scrollTop; | ||
var notSticky = scroll > start && scroll < stop && (state === 'default' || state === 'stuck'); | ||
var isSticky = scroll <= start && state === 'sticky'; | ||
var isStuck = scroll >= stop && state === 'sticky'; | ||
/* | ||
Unnamed arrow functions within this block | ||
--- | ||
- help wanted or discussion | ||
- view test.stickybits.js | ||
- `stickybits .manageState `position: fixed` interface` for more awareness π | ||
*/ | ||
if (notSticky) { | ||
it.state = 'sticky'; | ||
rAF(function () { | ||
tC(e, stuck, sticky); | ||
stl.position = pv; | ||
if (ns) return; | ||
stl.bottom = ''; | ||
stl[vp] = p.stickyBitStickyOffset + "px"; | ||
}); | ||
} else if (isSticky) { | ||
it.state = 'default'; | ||
rAF(function () { | ||
tC(e, sticky); | ||
if (pv === 'fixed') stl.position = ''; | ||
}); | ||
} else if (isStuck) { | ||
it.state = 'stuck'; | ||
rAF(function () { | ||
tC(e, sticky, stuck); | ||
if (pv !== 'fixed' || ns) return; | ||
stl.top = ''; | ||
stl.bottom = '0'; | ||
stl.position = 'absolute'; | ||
}); | ||
} | ||
Stickybits.prototype.cleanup = function cleanup() { | ||
for (var i = 0; i < this.instances.length; i += 1) { | ||
var instance = this.instances[i]; | ||
instance.props.scrollEl.removeEventListener('scroll', instance.stateContainer); | ||
this.removeInstance(instance); | ||
} | ||
var isStickyChange = scroll >= change && scroll <= stop; | ||
var isNotStickyChange = scroll < change || scroll > stop; | ||
var stub = 'stub'; // a stub css class to remove | ||
this.manageState = false; | ||
this.instances = []; | ||
}; | ||
if (isNotStickyChange) { | ||
rAF(function () { | ||
tC(e, stickyChange); | ||
}); | ||
} else if (isStickyChange) { | ||
rAF(function () { | ||
tC(e, stub, stickyChange); | ||
}); | ||
} | ||
return it; | ||
}; | ||
/* | ||
removes an instance π | ||
-------- | ||
- cleanup instance | ||
*/ | ||
_proto.removeInstance = function removeInstance(instance) { | ||
var e = instance.el; | ||
var p = instance.props; | ||
var tC = this.toggleClasses; | ||
e.style.position = ''; | ||
e.style[p.verticalPosition] = ''; | ||
tC(e, p.stickyClass); | ||
tC(e, p.stuckClass); | ||
tC(e.parentNode, p.parentClass); | ||
}; | ||
/* | ||
cleanup π | ||
-------- | ||
- cleans up each instance | ||
- clears instance | ||
*/ | ||
_proto.cleanup = function cleanup() { | ||
for (var i = 0; i < this.instances.length; i += 1) { | ||
var instance = this.instances[i]; | ||
instance.props.scrollEl.removeEventListener('scroll', instance.stateContainer); | ||
this.removeInstance(instance); | ||
} | ||
this.manageState = false; | ||
this.instances = []; | ||
}; | ||
return Stickybits; | ||
}(); | ||
/* | ||
@@ -391,0 +399,0 @@ export |
{ | ||
"name": "stickybits", | ||
"version": "3.2.3", | ||
"version": "3.2.4", | ||
"description": "Stickybits is a lightweight alternative to `position: sticky` polyfills", | ||
@@ -8,2 +8,3 @@ "main": "dist/stickybits.js", | ||
"unpkg": "dist/stickybits.min.js", | ||
"types": "types/index.d.ts", | ||
"scripts": { | ||
@@ -50,6 +51,8 @@ "build": "npm run test:unit && npm run build:rollup", | ||
"dist", | ||
"types", | ||
"src" | ||
], | ||
"devDependencies": { | ||
"@babel/core": "^7.0.0-beta.40", | ||
"@babel/core": "^7.0.0-beta.44", | ||
"@babel/plugin-proposal-class-properties": "^7.0.0-beta.44", | ||
"@babel/preset-env": "^7.0.0-beta.40", | ||
@@ -70,3 +73,3 @@ "babel-core": "^7.0.0-bridge.0", | ||
"qunit": "^2.4.1", | ||
"rollup": "0.57.1", | ||
"rollup": "0.58.0", | ||
"rollup-plugin-babel": "^4.0.0-beta.0", | ||
@@ -73,0 +76,0 @@ "rollup-plugin-replace": "^2.0.0", |
@@ -53,302 +53,304 @@ /* | ||
*/ | ||
function Stickybits (target, obj) { | ||
const o = typeof obj !== 'undefined' ? obj : {} | ||
this.version = 'VERSION' | ||
this.userAgent = window.navigator.userAgent || 'no `userAgent` provided by the browser' | ||
this.props = { | ||
customStickyChangeNumber: o.customStickyChangeNumber || null, | ||
noStyles: o.noStyles || false, | ||
stickyBitStickyOffset: o.stickyBitStickyOffset || 0, | ||
parentClass: o.parentClass || 'js-stickybit-parent', | ||
scrollEl: document.querySelector(o.scrollEl) || window, | ||
stickyClass: o.stickyClass || 'js-is-sticky', | ||
stuckClass: o.stuckClass || 'js-is-stuck', | ||
stickyChangeClass: o.stickyChangeClass || 'js-is-sticky--change', | ||
useStickyClasses: o.useStickyClasses || false, | ||
verticalPosition: o.verticalPosition || 'top', | ||
class Stickybits { | ||
constructor (target, obj) { | ||
const o = typeof obj !== 'undefined' ? obj : {} | ||
this.version = 'VERSION' | ||
this.userAgent = window.navigator.userAgent || 'no `userAgent` provided by the browser' | ||
this.props = { | ||
customStickyChangeNumber: o.customStickyChangeNumber || null, | ||
noStyles: o.noStyles || false, | ||
stickyBitStickyOffset: o.stickyBitStickyOffset || 0, | ||
parentClass: o.parentClass || 'js-stickybit-parent', | ||
scrollEl: document.querySelector(o.scrollEl) || window, | ||
stickyClass: o.stickyClass || 'js-is-sticky', | ||
stuckClass: o.stuckClass || 'js-is-stuck', | ||
stickyChangeClass: o.stickyChangeClass || 'js-is-sticky--change', | ||
useStickyClasses: o.useStickyClasses || false, | ||
verticalPosition: o.verticalPosition || 'top', | ||
} | ||
const p = this.props | ||
/* | ||
define positionVal | ||
---- | ||
- uses a computed (`.definePosition()`) | ||
- defined the position | ||
*/ | ||
p.positionVal = this.definePosition() || 'fixed' | ||
const vp = p.verticalPosition | ||
const ns = p.noStyles | ||
const pv = p.positionVal | ||
this.els = typeof target === 'string' ? document.querySelectorAll(target) : target | ||
if (!('length' in this.els)) this.els = [this.els] | ||
this.instances = [] | ||
for (let i = 0; i < this.els.length; i += 1) { | ||
const el = this.els[i] | ||
const styles = el.style | ||
// set vertical position | ||
styles[vp] = vp === 'top' && !ns ? `${p.stickyBitStickyOffset}px` : '' | ||
styles.position = pv !== 'fixed' ? pv : '' | ||
if (pv === 'fixed' || p.useStickyClasses) { | ||
const instance = this.addInstance(el, p) | ||
// instances are an array of objects | ||
this.instances.push(instance) | ||
} | ||
} | ||
return this | ||
} | ||
const p = this.props | ||
/* | ||
define positionVal | ||
---- | ||
- uses a computed (`.definePosition()`) | ||
- defined the position | ||
setStickyPosition βοΈ | ||
-------- | ||
β most basic thing stickybits does | ||
=> checks to see if position sticky is supported | ||
=> defined the position to be used | ||
=> stickybits works accordingly | ||
*/ | ||
p.positionVal = this.definePosition() || 'fixed' | ||
const vp = p.verticalPosition | ||
const ns = p.noStyles | ||
const pv = p.positionVal | ||
this.els = typeof target === 'string' ? document.querySelectorAll(target) : target | ||
if (!('length' in this.els)) this.els = [this.els] | ||
this.instances = [] | ||
for (let i = 0; i < this.els.length; i += 1) { | ||
const el = this.els[i] | ||
const styles = el.style | ||
// set vertical position | ||
styles[vp] = vp === 'top' && !ns ? `${p.stickyBitStickyOffset}px` : '' | ||
styles.position = pv !== 'fixed' ? pv : '' | ||
if (pv === 'fixed' || p.useStickyClasses) { | ||
const instance = this.addInstance(el, p) | ||
// instances are an array of objects | ||
this.instances.push(instance) | ||
definePosition () { | ||
const prefix = ['', '-o-', '-webkit-', '-moz-', '-ms-'] | ||
const test = document.head.style | ||
for (let i = 0; i < prefix.length; i += 1) { | ||
test.position = `${prefix[i]}sticky` | ||
} | ||
const stickyProp = test.position ? test.position : 'fixed' | ||
test.position = '' | ||
return stickyProp | ||
} | ||
return this | ||
} | ||
/* | ||
setStickyPosition βοΈ | ||
-------- | ||
β most basic thing stickybits does | ||
=> checks to see if position sticky is supported | ||
=> defined the position to be used | ||
=> stickybits works accordingly | ||
*/ | ||
Stickybits.prototype.definePosition = () => { | ||
const prefix = ['', '-o-', '-webkit-', '-moz-', '-ms-'] | ||
const test = document.head.style | ||
for (let i = 0; i < prefix.length; i += 1) { | ||
test.position = `${prefix[i]}sticky` | ||
/* | ||
addInstance βοΈ | ||
-------- | ||
β manages instances of items | ||
- takes in an el and props | ||
- returns an item object | ||
--- | ||
- target = el | ||
- o = {object} = props | ||
- scrollEl = 'string' | ||
- verticalPosition = number | ||
- off = boolean | ||
- parentClass = 'string' | ||
- stickyClass = 'string' | ||
- stuckClass = 'string' | ||
--- | ||
- defined later | ||
- parent = dom element | ||
- state = 'string' | ||
- offset = number | ||
- stickyStart = number | ||
- stickyStop = number | ||
- returns an instance object | ||
*/ | ||
addInstance (el, props) { | ||
const item = { | ||
el, | ||
parent: el.parentNode, | ||
props, | ||
} | ||
this.isWin = this.props.scrollEl === window | ||
const se = this.isWin ? window : this.getClosestParent(item.el, item.props.scrollEl) | ||
this.computeScrollOffsets(item) | ||
item.parent.className += ` ${props.parentClass}` | ||
item.state = 'default' | ||
item.stateContainer = () => this.manageState(item) | ||
se.addEventListener('scroll', item.stateContainer) | ||
return item | ||
} | ||
const stickyProp = test.position ? test.position : 'fixed' | ||
test.position = '' | ||
return stickyProp | ||
} | ||
/* | ||
addInstance βοΈ | ||
-------- | ||
β manages instances of items | ||
- takes in an el and props | ||
- returns an item object | ||
--- | ||
- target = el | ||
- o = {object} = props | ||
- scrollEl = 'string' | ||
- verticalPosition = number | ||
- off = boolean | ||
- parentClass = 'string' | ||
- stickyClass = 'string' | ||
- stuckClass = 'string' | ||
--- | ||
- defined later | ||
- parent = dom element | ||
- state = 'string' | ||
- offset = number | ||
- stickyStart = number | ||
- stickyStop = number | ||
- returns an instance object | ||
*/ | ||
Stickybits.prototype.addInstance = function addInstance (el, props) { | ||
const item = { | ||
el, | ||
parent: el.parentNode, | ||
props, | ||
/* | ||
-------- | ||
getParent π¨β | ||
-------- | ||
- a helper function that gets the target element's parent selected el | ||
- only used for non `window` scroll elements | ||
- supports older browsers | ||
*/ | ||
getClosestParent (el, match) { | ||
// p = parent element | ||
const p = match | ||
let e = el | ||
if (e.parentElement === p) return p | ||
// traverse up the dom tree until we get to the parent | ||
while (e.parentElement !== p) e = e.parentElement | ||
// return parent element | ||
return p | ||
} | ||
this.isWin = this.props.scrollEl === window | ||
const se = this.isWin ? window : this.getClosestParent(item.el, item.props.scrollEl) | ||
this.computeScrollOffsets(item) | ||
item.parent.className += ` ${props.parentClass}` | ||
item.state = 'default' | ||
item.stateContainer = () => this.manageState(item) | ||
se.addEventListener('scroll', item.stateContainer) | ||
return item | ||
} | ||
/* | ||
-------- | ||
getParent π¨β | ||
-------- | ||
- a helper function that gets the target element's parent selected el | ||
- only used for non `window` scroll elements | ||
- supports older browsers | ||
*/ | ||
Stickybits.prototype.getClosestParent = (el, match) => { | ||
// p = parent element | ||
const p = match | ||
let e = el | ||
if (e.parentElement === p) return p | ||
// traverse up the dom tree until we get to the parent | ||
while (e.parentElement !== p) e = e.parentElement | ||
// return parent element | ||
return p | ||
} | ||
/* | ||
computeScrollOffsets π | ||
--- | ||
computeScrollOffsets for Stickybits | ||
- defines | ||
- offset | ||
- start | ||
- stop | ||
*/ | ||
Stickybits.prototype.computeScrollOffsets = function computeScrollOffsets (item) { | ||
const it = item | ||
const p = it.props | ||
const el = it.el | ||
const parent = it.parent | ||
const isCustom = !this.isWin && p.positionVal === 'fixed' | ||
const isBottom = p.verticalPosition !== 'bottom' | ||
const scrollElOffset = isCustom ? p.scrollEl.getBoundingClientRect().top : 0 | ||
const stickyStart = isCustom | ||
? parent.getBoundingClientRect().top - scrollElOffset | ||
: parent.getBoundingClientRect().top | ||
const stickyChangeOffset = p.customStickyChangeNumber !== null | ||
? p.customStickyChangeNumber | ||
: el.offsetHeight | ||
it.offset = scrollElOffset + p.stickyBitStickyOffset | ||
it.stickyStart = isBottom ? stickyStart - it.offset : 0 | ||
it.stickyChange = it.stickyStart + stickyChangeOffset | ||
it.stickyStop = isBottom | ||
? (stickyStart + parent.offsetHeight) - (it.el.offsetHeight + it.offset) | ||
: stickyStart + parent.offsetHeight | ||
return it | ||
} | ||
/* | ||
toggleClasses βοΈ | ||
--- | ||
toggles classes (for older browser support) | ||
r = removed class | ||
a = added class | ||
*/ | ||
Stickybits.prototype.toggleClasses = (el, r, a) => { | ||
const e = el | ||
const cArray = e.className.split(' ') | ||
if (a && cArray.indexOf(a) === -1) cArray.push(a) | ||
const rItem = cArray.indexOf(r) | ||
if (rItem !== -1) cArray.splice(rItem, 1) | ||
e.className = cArray.join(' ') | ||
} | ||
/* | ||
manageState π | ||
--- | ||
- defines the state | ||
- normal | ||
- sticky | ||
- stuck | ||
*/ | ||
Stickybits.prototype.manageState = function manageState (item) { | ||
// cache object | ||
const it = item | ||
const e = it.el | ||
const p = it.props | ||
const state = it.state | ||
const start = it.stickyStart | ||
const change = it.stickyChange | ||
const stop = it.stickyStop | ||
const stl = e.style | ||
// cache props | ||
const ns = p.noStyles | ||
const pv = p.positionVal | ||
const se = p.scrollEl | ||
const sticky = p.stickyClass | ||
const stickyChange = p.stickyChangeClass | ||
const stuck = p.stuckClass | ||
const vp = p.verticalPosition | ||
/* | ||
requestAnimationFrame | ||
computeScrollOffsets π | ||
--- | ||
- use rAF | ||
- or stub rAF | ||
computeScrollOffsets for Stickybits | ||
- defines | ||
- offset | ||
- start | ||
- stop | ||
*/ | ||
const rAFStub = function rAFDummy (f) { f() } | ||
const rAF = !this.isWin | ||
? rAFStub | ||
: window.requestAnimationFrame || | ||
window.mozRequestAnimationFrame || | ||
window.webkitRequestAnimationFrame || | ||
window.msRequestAnimationFrame || | ||
rAFStub | ||
computeScrollOffsets (item) { | ||
const it = item | ||
const p = it.props | ||
const el = it.el | ||
const parent = it.parent | ||
const isCustom = !this.isWin && p.positionVal === 'fixed' | ||
const isBottom = p.verticalPosition !== 'bottom' | ||
const scrollElOffset = isCustom ? p.scrollEl.getBoundingClientRect().top : 0 | ||
const stickyStart = isCustom | ||
? parent.getBoundingClientRect().top - scrollElOffset | ||
: parent.getBoundingClientRect().top | ||
const stickyChangeOffset = p.customStickyChangeNumber !== null | ||
? p.customStickyChangeNumber | ||
: el.offsetHeight | ||
it.offset = scrollElOffset + p.stickyBitStickyOffset | ||
it.stickyStart = isBottom ? stickyStart - it.offset : 0 | ||
it.stickyChange = it.stickyStart + stickyChangeOffset | ||
it.stickyStop = isBottom | ||
? (stickyStart + parent.offsetHeight) - (it.el.offsetHeight + it.offset) | ||
: stickyStart + parent.offsetHeight | ||
return it | ||
} | ||
/* | ||
define scroll vars | ||
toggleClasses βοΈ | ||
--- | ||
- scroll | ||
- notSticky | ||
- isSticky | ||
- isStuck | ||
toggles classes (for older browser support) | ||
r = removed class | ||
a = added class | ||
*/ | ||
const tC = this.toggleClasses | ||
const scroll = this.isWin ? (window.scrollY || window.pageYOffset) : se.scrollTop | ||
const notSticky = scroll > start && scroll < stop && (state === 'default' || state === 'stuck') | ||
const isSticky = scroll <= start && state === 'sticky' | ||
const isStuck = scroll >= stop && state === 'sticky' | ||
toggleClasses (el, r, a) { | ||
const e = el | ||
const cArray = e.className.split(' ') | ||
if (a && cArray.indexOf(a) === -1) cArray.push(a) | ||
const rItem = cArray.indexOf(r) | ||
if (rItem !== -1) cArray.splice(rItem, 1) | ||
e.className = cArray.join(' ') | ||
} | ||
/* | ||
Unnamed arrow functions within this block | ||
manageState π | ||
--- | ||
- help wanted or discussion | ||
- view test.stickybits.js | ||
- `stickybits .manageState `position: fixed` interface` for more awareness π | ||
- defines the state | ||
- normal | ||
- sticky | ||
- stuck | ||
*/ | ||
if (notSticky) { | ||
it.state = 'sticky' | ||
rAF(() => { | ||
tC(e, stuck, sticky) | ||
stl.position = pv | ||
if (ns) return | ||
stl.bottom = '' | ||
stl[vp] = `${p.stickyBitStickyOffset}px` | ||
}) | ||
} else if (isSticky) { | ||
it.state = 'default' | ||
rAF(() => { | ||
tC(e, sticky) | ||
if (pv === 'fixed') stl.position = '' | ||
}) | ||
} else if (isStuck) { | ||
it.state = 'stuck' | ||
rAF(() => { | ||
tC(e, sticky, stuck) | ||
if (pv !== 'fixed' || ns) return | ||
stl.top = '' | ||
stl.bottom = '0' | ||
stl.position = 'absolute' | ||
}) | ||
} | ||
manageState (item) { | ||
// cache object | ||
const it = item | ||
const e = it.el | ||
const p = it.props | ||
const state = it.state | ||
const start = it.stickyStart | ||
const change = it.stickyChange | ||
const stop = it.stickyStop | ||
const stl = e.style | ||
// cache props | ||
const ns = p.noStyles | ||
const pv = p.positionVal | ||
const se = p.scrollEl | ||
const sticky = p.stickyClass | ||
const stickyChange = p.stickyChangeClass | ||
const stuck = p.stuckClass | ||
const vp = p.verticalPosition | ||
/* | ||
requestAnimationFrame | ||
--- | ||
- use rAF | ||
- or stub rAF | ||
*/ | ||
const rAFStub = function rAFDummy (f) { f() } | ||
const rAF = !this.isWin | ||
? rAFStub | ||
: window.requestAnimationFrame || | ||
window.mozRequestAnimationFrame || | ||
window.webkitRequestAnimationFrame || | ||
window.msRequestAnimationFrame || | ||
rAFStub | ||
const isStickyChange = scroll >= change && scroll <= stop | ||
const isNotStickyChange = scroll < change || scroll > stop | ||
const stub = 'stub' // a stub css class to remove | ||
if (isNotStickyChange) { | ||
rAF(() => { tC(e, stickyChange) }) | ||
} else if (isStickyChange) { | ||
rAF(() => { tC(e, stub, stickyChange) }) | ||
} | ||
/* | ||
define scroll vars | ||
--- | ||
- scroll | ||
- notSticky | ||
- isSticky | ||
- isStuck | ||
*/ | ||
const tC = this.toggleClasses | ||
const scroll = this.isWin ? (window.scrollY || window.pageYOffset) : se.scrollTop | ||
const notSticky = scroll > start && scroll < stop && (state === 'default' || state === 'stuck') | ||
const isSticky = scroll <= start && state === 'sticky' | ||
const isStuck = scroll >= stop && state === 'sticky' | ||
/* | ||
Unnamed arrow functions within this block | ||
--- | ||
- help wanted or discussion | ||
- view test.stickybits.js | ||
- `stickybits .manageState `position: fixed` interface` for more awareness π | ||
*/ | ||
if (notSticky) { | ||
it.state = 'sticky' | ||
rAF(() => { | ||
tC(e, stuck, sticky) | ||
stl.position = pv | ||
if (ns) return | ||
stl.bottom = '' | ||
stl[vp] = `${p.stickyBitStickyOffset}px` | ||
}) | ||
} else if (isSticky) { | ||
it.state = 'default' | ||
rAF(() => { | ||
tC(e, sticky) | ||
if (pv === 'fixed') stl.position = '' | ||
}) | ||
} else if (isStuck) { | ||
it.state = 'stuck' | ||
rAF(() => { | ||
tC(e, sticky, stuck) | ||
if (pv !== 'fixed' || ns) return | ||
stl.top = '' | ||
stl.bottom = '0' | ||
stl.position = 'absolute' | ||
}) | ||
} | ||
return it | ||
} | ||
const isStickyChange = scroll >= change && scroll <= stop | ||
const isNotStickyChange = scroll < change || scroll > stop | ||
const stub = 'stub' // a stub css class to remove | ||
if (isNotStickyChange) { | ||
rAF(() => { tC(e, stickyChange) }) | ||
} else if (isStickyChange) { | ||
rAF(() => { tC(e, stub, stickyChange) }) | ||
} | ||
/* | ||
removes an instance π | ||
-------- | ||
- cleanup instance | ||
*/ | ||
Stickybits.prototype.removeInstance = function removeInstance (instance) { | ||
const e = instance.el | ||
const p = instance.props | ||
const tC = this.toggleClasses | ||
e.style.position = '' | ||
e.style[p.verticalPosition] = '' | ||
tC(e, p.stickyClass) | ||
tC(e, p.stuckClass) | ||
tC(e.parentNode, p.parentClass) | ||
} | ||
return it | ||
} | ||
/* | ||
cleanup π | ||
-------- | ||
- cleans up each instance | ||
- clears instance | ||
*/ | ||
Stickybits.prototype.cleanup = function cleanup () { | ||
for (let i = 0; i < this.instances.length; i += 1) { | ||
const instance = this.instances[i] | ||
instance.props.scrollEl.removeEventListener('scroll', instance.stateContainer) | ||
this.removeInstance(instance) | ||
/* | ||
removes an instance π | ||
-------- | ||
- cleanup instance | ||
*/ | ||
removeInstance (instance) { | ||
const e = instance.el | ||
const p = instance.props | ||
const tC = this.toggleClasses | ||
e.style.position = '' | ||
e.style[p.verticalPosition] = '' | ||
tC(e, p.stickyClass) | ||
tC(e, p.stuckClass) | ||
tC(e.parentNode, p.parentClass) | ||
} | ||
this.manageState = false | ||
this.instances = [] | ||
/* | ||
cleanup π | ||
-------- | ||
- cleans up each instance | ||
- clears instance | ||
*/ | ||
cleanup () { | ||
for (let i = 0; i < this.instances.length; i += 1) { | ||
const instance = this.instances[i] | ||
instance.props.scrollEl.removeEventListener('scroll', instance.stateContainer) | ||
this.removeInstance(instance) | ||
} | ||
this.manageState = false | ||
this.instances = [] | ||
} | ||
} | ||
@@ -355,0 +357,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
95983
15
1896
21