| /* |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| const vueSticky = {} |
| let listenAction |
| vueSticky.install = Vue => { |
| Vue.directive('sticky', { |
| inserted(el, binding) { |
| const params = binding.value || {} |
| const stickyTop = params.stickyTop || 0 |
| const zIndex = params.zIndex || 1000 |
| const 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) |
| } |
| }) |
| } |
| |
| export default vueSticky |
| |