<template>
  <div :class="classes" :style="styles">
    <slot>
      <el-tooltip class="item" effect="dark" content="回到顶部" placement="left">
        <el-button type="text" @click="back">
          <i class="fa fa-arrow-up f20"></i>
        </el-button>
      </el-tooltip>
    </slot>
  </div>
</template>
<script>
const prefixCls = 'back-top'
export default {
  props: {
    height: { // 页面滚动高度达到该值时才显示BackTop组件
      type: Number,
      default: 400
    },
    bottom: { // 组件距离底部的距离
      type: Number,
      default: 100
    },
    right: { // 组件距离右部的距离
      type: Number,
      default: 10
    },
    duration: { // 滚动动画持续时间，单位 毫秒
      type: Number,
      default: 1000
    }
  },
  data () {
    return {
      backTop: false
    }
  },
  mounted () {
    this.on(window, 'scroll', this.handleScroll)
    this.on(window, 'resize', this.handleScroll)
  },
  beforeDestroy () {
    this.off(window, 'scroll', this.handleScroll)
    this.off(window, 'resize', this.handleScroll)
  },
  computed: {
    classes () {
      return [
        `${prefixCls}`,
        {
          [`${prefixCls}-show`]: this.backTop
        }
      ]
    },
    styles () {
      return {
        bottom: `${this.bottom}px`,
        right: `${this.right}px`
      }
    }
  },
  methods: {
    handleScroll () {
      this.backTop = window.pageYOffset >= this.height
    },
    back () {
      const sTop = document.documentElement.scrollTop || document.body.scrollTop
      this.scrollTop(window, sTop, 0, this.duration)
      this.$emit('on-click')
    },
    scrollTop(el, from = 0, to, duration = 500, endCallback) {
      if (!window.requestAnimationFrame) {
        window.requestAnimationFrame = (
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame ||
          window.msRequestAnimationFrame ||
          function (callback) {
            return window.setTimeout(callback, 1000 / 60)
          }
        )
      }
      const difference = Math.abs(from - to)
      const step = Math.ceil(difference / duration * 50)
      function scroll(start, end, step) {
        if (start === end) {
          endCallback && endCallback()
          return
        }
        let d = (start + step > end) ? end : start + step
        if (start > end) {
          d = (start - step < end) ? end : start - step
        }
        if (el === window) {
          window.scrollTo(d, d)
        } else {
          el.scrollTop = d
        }
        window.requestAnimationFrame(() => scroll(d, end, step))
      }
      scroll(from, to, step)
    },
    on (element, event, handler) {
      if (document.addEventListener) {
        if (element && event && handler) {
          element.addEventListener(event, handler, false)
        }
      } else {
        if (element && event && handler) {
          element.attachEvent('on' + event, handler)
        }
      }
    },
    off (element, event, handler) {
      if (document.addEventListener) {
        if (element && event && handler) {
          element.removeEventListener(event, handler, false)
        }
      } else {
        if (element && event && handler) {
          element.detachEvent('on' + event, handler)
        }
      }
    }
  }
}
</script>
<style scoped>
  .back-top {
    cursor: pointer;
    display: none;
    position: fixed;
    z-index: 10;
  }
  .back-top.back-top-show {
    display: block;
  }
</style>
