From d077b1b9c9f7d3086fc96476516db047183472f8 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Thu, 31 Mar 2022 15:49:59 +0100 Subject: [PATCH] :sparkles: Custom directive for long-press events (#586) --- src/directives/LongPress.js | 51 +++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/directives/LongPress.js diff --git a/src/directives/LongPress.js b/src/directives/LongPress.js new file mode 100644 index 00000000..02c8c9e8 --- /dev/null +++ b/src/directives/LongPress.js @@ -0,0 +1,51 @@ +/** + * A Vue directive to call event when element is long-pressed + * Used to open context menus on touch-enabled devices + * Inspired by: FeliciousX/vue-directive-long-press + * Dashy: Licensed under MIT - (C) Alicia Sykes 2022 + */ + +const LONG_PRESS_DEFAULT_DELAY = 750; +const longPressEvent = new CustomEvent('long-press'); + +export default { + bind(element, binding, vnode) { + const el = element; + el.dataset.longPressTimeout = null; + + const swallowClick = (e) => { + el.removeEventListener('click', swallowClick); + if (!el.dataset.elapsed) return true; + e.preventDefault(); + e.stopPropagation(); + return false; + }; + + const complete = () => { + if (vnode.componentInstance) vnode.componentInstance.$emit('long-press'); + else el.dispatchEvent(longPressEvent); + el.dataset.elapsed = true; + }; + + const onPointerUp = () => { + clearTimeout(parseInt(el.dataset.longPressTimeout, 10)); + document.removeEventListener('pointerup', onPointerUp); + }; + + const onPointerDown = () => { + document.addEventListener('pointerup', onPointerUp); + el.addEventListener('click', swallowClick); + const timeoutDuration = binding.value || LONG_PRESS_DEFAULT_DELAY; + const timeout = setTimeout(complete, timeoutDuration); + el.dataset.elapsed = false; + el.dataset.longPressTimeout = timeout; + }; + + el.$longPressHandler = onPointerDown; + el.addEventListener('pointerdown', onPointerDown); + }, + unbind(el) { + clearTimeout(parseInt(el.dataset.longPressTimeout, 10)); + el.removeEventListener('pointerdown', el.$longPressHandler); + }, +};