(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) } }());