avvo-styleguide
Version:
Avvo styleguide
89 lines (67 loc) • 1.73 kB
JavaScript
import throttle from 'lodash/function/throttle'
import isAccelerating from './is-accelerating'
const ACTIVE_CLASS = 'is-active'
const COORD_MAX = 5
const HOVER_DELAY = 250
const $ = global.jQuery
class SmarterHover {
constructor(el) {
this.$el = $(el)
this.enterId = null
this.exitId = null
this.coordinates = []
this.bindEvents(el)
}
bindEvents(el) {
this.$el.on('mouseenter', (e) => {
this.exitId = null
this.enterId = setTimeout(this.makeActive.bind(this), HOVER_DELAY)
this.$el.on('mousemove', throttle(this.handleMove.bind(this), HOVER_DELAY / 4))
})
this.$el.on('mouseleave', (e) => {
clearTimeout(this.enterId)
clearTimeout(this.exitId)
this.enterId = null
this.exitId = setTimeout(this.makeInactive.bind(this), HOVER_DELAY / 2)
})
this.$el.on('click', (e) => {
if (e.target === el) {
this.makeActiveNow()
}
})
}
makeActiveNow() {
this.resetCoordinates()
this.$el.addClass(ACTIVE_CLASS)
}
makeActive() {
if (!this.exitId) {
this.makeActiveNow.call(this)
}
this.enterId = null
}
makeInactive() {
this.$el.removeClass(ACTIVE_CLASS)
this.$el.off('mousemove')
this.exitId = null
}
addCoordinate(x, y) {
this.coordinates.push({ x, y })
if (this.coordinates.length > COORD_MAX) {
this.coordinates.shift()
}
}
resetCoordinates() {
this.coordinates = []
}
handleMove(move) {
this.addCoordinate(move.pageX, move.pageY)
if (!this.exitId && !isAccelerating(this.coordinates)) {
this.makeActiveNow()
}
}
}
export { SmarterHover }
export default function (el) {
return new SmarterHover(el)
}