vuetify
Version:
Vue.js 2 Semantic Component Framework
126 lines (101 loc) • 3.99 kB
JavaScript
function style (el, value) {
el.style['transform'] = value
el.style['webkitTransform'] = value
}
const RippleDataAttribute = 'data-ripple'
const ripple = {
/**
* @param {Event} e
* @param {Element} el
* @param {{ class?: string, center?: boolean }} [value={}]
*/
show: (e, el, { value = {} }) => {
if (el.getAttribute(RippleDataAttribute) !== 'true') {
return
}
const container = document.createElement('span')
const animation = document.createElement('span')
container.appendChild(animation)
container.className = 'ripple__container'
if (value.class) {
container.className += ` ${value.class}`
}
const size = el.clientWidth > el.clientHeight
? el.clientWidth
: el.clientHeight
animation.className = 'ripple__animation'
animation.style.width = `${size * (value.center ? 1 : 2)}px`
animation.style.height = animation.style.width
el.appendChild(container)
const computed = window.getComputedStyle(el)
if (computed.position !== 'absolute' && computed.position !== 'fixed') el.style.position = 'relative'
const offset = el.getBoundingClientRect()
const x = value.center ? '50%' : `${e.clientX - offset.left}px`
const y = value.center ? '50%' : `${e.clientY - offset.top}px`
animation.classList.add('ripple__animation--enter')
animation.classList.add('ripple__animation--visible')
style(animation, `translate(-50%, -50%) translate(${x}, ${y}) scale3d(0.01,0.01,0.01)`)
animation.dataset.activated = Date.now()
setTimeout(() => {
animation.classList.remove('ripple__animation--enter')
style(animation, `translate(-50%, -50%) translate(${x}, ${y}) scale3d(0.99,0.99,0.99)`)
}, 0)
},
hide: (el) => {
if (el.getAttribute(RippleDataAttribute) !== 'true') {
return
}
const ripples = el.getElementsByClassName('ripple__animation')
if (ripples.length === 0) return
const animation = ripples[ripples.length - 1]
const diff = Date.now() - Number(animation.dataset.activated)
let delay = 400 - diff
delay = delay < 0 ? 0 : delay
setTimeout(() => {
animation.classList.remove('ripple__animation--visible')
setTimeout(() => {
// Need to figure out a new way to do this
try {
if (ripples.length < 1) el.style.position = null
animation.parentNode && el.removeChild(animation.parentNode)
} catch (e) {}
}, 300)
}, delay)
}
}
function isRippleEnabled (binding) {
return typeof binding.value === 'undefined' || !!binding.value
}
function directive (el, binding) {
el.setAttribute(RippleDataAttribute, isRippleEnabled(binding))
if ('ontouchstart' in window) {
el.addEventListener('touchend', () => ripple.hide(el), false)
el.addEventListener('touchcancel', () => ripple.hide(el), false)
}
el.addEventListener('mousedown', e => ripple.show(e, el, binding), false)
el.addEventListener('mouseup', () => ripple.hide(el), false)
el.addEventListener('mouseleave', () => ripple.hide(el), false)
// Anchor tags can be dragged, causes other hides to fail - #1537
el.addEventListener('dragstart', () => ripple.hide(el), false)
}
function unbind (el, binding) {
el.removeEventListener('touchstart', e => ripple.show(e, el, binding), false)
el.removeEventListener('mousedown', e => ripple.show(e, el, binding), false)
el.removeEventListener('touchend', () => ripple.hide(el), false)
el.removeEventListener('touchcancel', () => ripple.hide(el), false)
el.removeEventListener('mouseup', () => ripple.hide(el), false)
el.removeEventListener('mouseleave', () => ripple.hide(el), false)
el.removeEventListener('dragstart', () => ripple.hide(el), false)
}
function update (el, binding) {
if (binding.value === binding.oldValue) {
return
}
el.setAttribute(RippleDataAttribute, isRippleEnabled(binding))
}
export default {
name: 'ripple',
bind: directive,
unbind: unbind,
update: update
}