forked from AkkomaGang/admin-fe
102 lines
2.9 KiB
JavaScript
102 lines
2.9 KiB
JavaScript
|
(function() {
|
|||
|
const vueSticky = {};
|
|||
|
let listenAction;
|
|||
|
vueSticky.install = Vue => {
|
|||
|
Vue.directive('sticky', {
|
|||
|
inserted(el, binding) {
|
|||
|
const params = binding.value || {},
|
|||
|
stickyTop = params.stickyTop || 0,
|
|||
|
zIndex = params.zIndex || 1000,
|
|||
|
elStyle = el.style;
|
|||
|
|
|||
|
elStyle.position = '-webkit-sticky';
|
|||
|
elStyle.position = 'sticky';
|
|||
|
|
|||
|
// if the browser support css sticky(Currently Safari, Firefox and Chrome Canary)
|
|||
|
// if (~elStyle.position.indexOf('sticky')) {
|
|||
|
// elStyle.top = `${stickyTop}px`;
|
|||
|
// elStyle.zIndex = zIndex;
|
|||
|
// return
|
|||
|
// }
|
|||
|
|
|||
|
const elHeight = el.getBoundingClientRect().height;
|
|||
|
const elWidth = el.getBoundingClientRect().width;
|
|||
|
elStyle.cssText = `top: ${stickyTop}px; z-index: ${zIndex}`;
|
|||
|
|
|||
|
const parentElm = el.parentNode || document.documentElement;
|
|||
|
const placeholder = document.createElement('div');
|
|||
|
placeholder.style.display = 'none';
|
|||
|
placeholder.style.width = `${elWidth}px`;
|
|||
|
placeholder.style.height = `${elHeight}px`;
|
|||
|
parentElm.insertBefore(placeholder, el)
|
|||
|
|
|||
|
let active = false;
|
|||
|
|
|||
|
const getScroll = (target, top) => {
|
|||
|
const prop = top ? 'pageYOffset' : 'pageXOffset';
|
|||
|
const method = top ? 'scrollTop' : 'scrollLeft';
|
|||
|
let ret = target[prop];
|
|||
|
if (typeof ret !== 'number') {
|
|||
|
ret = window.document.documentElement[method];
|
|||
|
}
|
|||
|
return ret;
|
|||
|
};
|
|||
|
|
|||
|
const sticky = () => {
|
|||
|
if (active) {
|
|||
|
return
|
|||
|
}
|
|||
|
if (!elStyle.height) {
|
|||
|
elStyle.height = `${el.offsetHeight}px`
|
|||
|
}
|
|||
|
|
|||
|
elStyle.position = 'fixed';
|
|||
|
elStyle.width = `${elWidth}px`;
|
|||
|
placeholder.style.display = 'inline-block';
|
|||
|
active = true
|
|||
|
};
|
|||
|
|
|||
|
const reset = () => {
|
|||
|
if (!active) {
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
elStyle.position = '';
|
|||
|
placeholder.style.display = 'none';
|
|||
|
active = false;
|
|||
|
};
|
|||
|
|
|||
|
const check = () => {
|
|||
|
const scrollTop = getScroll(window, true);
|
|||
|
const offsetTop = el.getBoundingClientRect().top;
|
|||
|
if (offsetTop < stickyTop) {
|
|||
|
sticky();
|
|||
|
} else {
|
|||
|
if (scrollTop < elHeight + stickyTop) {
|
|||
|
reset()
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
listenAction = () => {
|
|||
|
check()
|
|||
|
};
|
|||
|
|
|||
|
window.addEventListener('scroll', listenAction)
|
|||
|
},
|
|||
|
|
|||
|
unbind() {
|
|||
|
window.removeEventListener('scroll', listenAction)
|
|||
|
}
|
|||
|
})
|
|||
|
};
|
|||
|
if (typeof exports == 'object') {
|
|||
|
module.exports = vueSticky
|
|||
|
} else if (typeof define == 'function' && define.amd) {
|
|||
|
define([], () => vueSticky)
|
|||
|
} else if (window.Vue) {
|
|||
|
window.vueSticky = vueSticky;
|
|||
|
Vue.use(vueSticky)
|
|||
|
}
|
|||
|
}());
|
|||
|
|