UNPKG

quasar

Version:

Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time

266 lines (214 loc) 7.89 kB
import { client } from '../plugins/Platform.js' import { createDirective } from '../utils/private/create.js' import { addEvt, cleanEvt, position, leftClick, stopAndPrevent, noop } from '../utils/event.js' import { clearSelection } from '../utils/private/selection.js' import { isKeyCode } from '../utils/private/key-composition.js' import getSSRProps from '../utils/private/noop-ssr-directive-transform.js' const keyCodes = { esc: 27, tab: 9, enter: 13, space: 32, up: 38, left: 37, right: 39, down: 40, delete: [ 8, 46 ] }, keyRegex = new RegExp(`^([\\d+]+|${ Object.keys(keyCodes).join('|') })$`, 'i') function shouldEnd (evt, origin) { const { top, left } = position(evt) return Math.abs(left - origin.left) >= 7 || Math.abs(top - origin.top) >= 7 } export default createDirective(__QUASAR_SSR_SERVER__ ? { name: 'touch-repeat', getSSRProps } : { name: 'touch-repeat', beforeMount (el, { modifiers, value, arg }) { const keyboard = Object.keys(modifiers).reduce((acc, key) => { if (keyRegex.test(key) === true) { const keyCode = isNaN(parseInt(key, 10)) ? keyCodes[ key.toLowerCase() ] : parseInt(key, 10) keyCode >= 0 && acc.push(keyCode) } return acc }, []) // early return, we don't need to do anything if ( modifiers.mouse !== true && client.has.touch !== true && keyboard.length === 0 ) { return } const durations = typeof arg === 'string' && arg.length > 0 ? arg.split(':').map(val => parseInt(val, 10)) : [ 0, 600, 300 ] const durationsLast = durations.length - 1 const ctx = { keyboard, handler: value, noop, mouseStart (evt) { if (ctx.event === void 0 && typeof ctx.handler === 'function' && leftClick(evt) === true) { addEvt(ctx, 'temp', [ [ document, 'mousemove', 'move', 'passiveCapture' ], [ document, 'click', 'end', 'notPassiveCapture' ] ]) ctx.start(evt, true) } }, keyboardStart (evt) { if (typeof ctx.handler === 'function' && isKeyCode(evt, keyboard) === true) { if (durations[ 0 ] === 0 || ctx.event !== void 0) { stopAndPrevent(evt) el.focus() if (ctx.event !== void 0) { return } } addEvt(ctx, 'temp', [ [ document, 'keyup', 'end', 'notPassiveCapture' ], [ document, 'click', 'end', 'notPassiveCapture' ] ]) ctx.start(evt, false, true) } }, touchStart (evt) { if (evt.target !== void 0 && typeof ctx.handler === 'function') { const target = evt.target addEvt(ctx, 'temp', [ [ target, 'touchmove', 'move', 'passiveCapture' ], [ target, 'touchcancel', 'end', 'notPassiveCapture' ], [ target, 'touchend', 'end', 'notPassiveCapture' ] ]) ctx.start(evt) } }, start (evt, mouseEvent, keyboardEvent) { if (keyboardEvent !== true) { ctx.origin = position(evt) } function styleCleanup (withDelay) { ctx.styleCleanup = void 0 document.documentElement.style.cursor = '' const remove = () => { document.body.classList.remove('non-selectable') } if (withDelay === true) { clearSelection() setTimeout(remove, 10) } else { remove() } } if (client.is.mobile === true) { document.body.classList.add('non-selectable') clearSelection() ctx.styleCleanup = styleCleanup } ctx.event = { touch: mouseEvent !== true && keyboardEvent !== true, mouse: mouseEvent === true, keyboard: keyboardEvent === true, startTime: Date.now(), repeatCount: 0 } const fn = () => { ctx.timer = void 0 if (ctx.event === void 0) { return } if (ctx.event.repeatCount === 0) { ctx.event.evt = evt if (keyboardEvent === true) { ctx.event.keyCode = evt.keyCode } else { ctx.event.position = position(evt) } if (client.is.mobile !== true) { document.documentElement.style.cursor = 'pointer' document.body.classList.add('non-selectable') clearSelection() ctx.styleCleanup = styleCleanup } } ctx.event.duration = Date.now() - ctx.event.startTime ctx.event.repeatCount += 1 ctx.handler(ctx.event) const index = durationsLast < ctx.event.repeatCount ? durationsLast : ctx.event.repeatCount ctx.timer = setTimeout(fn, durations[ index ]) } if (durations[ 0 ] === 0) { fn() } else { ctx.timer = setTimeout(fn, durations[ 0 ]) } }, move (evt) { if (ctx.event !== void 0 && ctx.timer !== void 0 && shouldEnd(evt, ctx.origin) === true) { clearTimeout(ctx.timer) ctx.timer = void 0 } }, end (evt) { if (ctx.event === void 0) { return } ctx.styleCleanup !== void 0 && ctx.styleCleanup(true) evt !== void 0 && ctx.event.repeatCount > 0 && stopAndPrevent(evt) cleanEvt(ctx, 'temp') if (ctx.timer !== void 0) { clearTimeout(ctx.timer) ctx.timer = void 0 } ctx.event = void 0 } } el.__qtouchrepeat = ctx if (modifiers.mouse === true) { // account for UMD too where modifiers will be lowercased to work const capture = modifiers.mouseCapture === true || modifiers.mousecapture === true ? 'Capture' : '' addEvt(ctx, 'main', [ [ el, 'mousedown', 'mouseStart', `passive${ capture }` ] ]) } client.has.touch === true && addEvt(ctx, 'main', [ [ el, 'touchstart', 'touchStart', `passive${ modifiers.capture === true ? 'Capture' : '' }` ], [ el, 'touchend', 'noop', 'passiveCapture' ] ]) if (keyboard.length !== 0) { // account for UMD too where modifiers will be lowercased to work const capture = modifiers.keyCapture === true || modifiers.keycapture === true ? 'Capture' : '' addEvt(ctx, 'main', [ [ el, 'keydown', 'keyboardStart', `notPassive${ capture }` ] ]) } }, updated (el, { oldValue, value }) { const ctx = el.__qtouchrepeat if (ctx !== void 0 && oldValue !== value) { typeof value !== 'function' && ctx.end() ctx.handler = value } }, beforeUnmount (el) { const ctx = el.__qtouchrepeat if (ctx !== void 0) { ctx.timer !== void 0 && clearTimeout(ctx.timer) cleanEvt(ctx, 'main') cleanEvt(ctx, 'temp') ctx.styleCleanup !== void 0 && ctx.styleCleanup() delete el.__qtouchrepeat } } } )