Skip to content

Instantly share code, notes, and snippets.

@c0depanda
Last active June 25, 2019 12:23
Show Gist options
  • Save c0depanda/47b1e9a26a80581fd9e0553db68d405c to your computer and use it in GitHub Desktop.
Save c0depanda/47b1e9a26a80581fd9e0553db68d405c to your computer and use it in GitHub Desktop.
Vue.directive('longpress', {
bind: function (el, binding, vNode) {
// Make sure expression provided is a function
if (typeof binding.value !== 'function') {
// Fetch name of component
const compName = vNode.context.name
// pass warning to console
let warn = `[longpress:] provided expression '${binding.expression}' is not a function, but has to be`
if (compName) { warn += `Found in component '${compName}' ` }
console.warn(warn)
}
// Define variable
let pressTimer = null
// Define funtion handlers
// Create timeout ( run function after 1s )
let start = (e) => {
if (e.type === 'click' && e.button !== 0) {
return;
}
if (pressTimer === null) {
pressTimer = setTimeout(() => {
// Run function
handler()
}, 1000)
}
}
// Cancel Timeout
let cancel = (e) => {
// Check if timer has a value or not
if (pressTimer !== null) {
clearTimeout(pressTimer)
pressTimer = null
}
}
// Run Function
const handler = (e) => {
binding.value(e)
}
// Add Event listeners
el.addEventListener("mousedown", start);
el.addEventListener("touchstart", start);
// Cancel timeouts if this events happen
el.addEventListener("click", cancel);
el.addEventListener("mouseout", cancel);
el.addEventListener("touchend", cancel);
el.addEventListener("touchcancel", cancel);
}
})
@aquadk
Copy link

aquadk commented Apr 12, 2019

Handles both click and long click in same directive.
Typescript version:

import {
  DirectiveOptions, VNodeDirective, VNode
} from "vue";
let pressTimer: NodeJS.Timeout | undefined;
const directive: DirectiveOptions = {
  bind: function (el: HTMLElement, binding: VNodeDirective,
    vNode?: VNode): void {
    // make sure expression provided is a function
    if (typeof binding.value !== "function") {
      // fetch name of component
      const compName: string = (vNode && vNode.context) ? vNode.context["name"] : "";
      // pass warning to console
      let warn: string = `[longpress:] provided expression '${binding.expression}' is not a function, but has to be`;
      if (compName) {
        warn += `Found in component '${compName}' `;
      }

      console.warn(warn);
    }

    // define variable
    let StartDate: number = 0;

    // run Function
    const handler: Function = (e: Event, duration: number): void => {
      binding.value(e, duration);
    };

    // define funtion handlers
    // create timeout ( run function after 1s )
    let start: EventListener = (e: Event): void => {
      StartDate = new Date().getTime();
      console.log("start press", e);
      if ((e instanceof MouseEvent) && (e as MouseEvent).button !== 0) {
        return;
      }

      if (!pressTimer) {
        pressTimer = setTimeout(() => {
          // run function
          if (pressTimer) {
            clearTimeout(pressTimer);
            pressTimer = undefined;
          }
          handler(e, (new Date().getTime() - StartDate));
        }, 1000);
      }
    };

    // cancel Timeout
    let cancel: EventListener = (e: Event) => {
      // check if timer has a value or not
      if (pressTimer) {
        clearTimeout(pressTimer);
        pressTimer = undefined;
        handler(e, new Date().getTime() - StartDate);
      }
    }


    // add Event listeners
    el.addEventListener("mousedown", start);
    el.addEventListener("touchstart", start);
    // cancel timeouts if this events happen
    el.addEventListener("click", cancel);
    el.addEventListener("mouseout", cancel);
    el.addEventListener("touchend", cancel);
    el.addEventListener("touchcancel", cancel);
  },
  unbind: function (): void {
    if (pressTimer) {
      clearTimeout(pressTimer);
      pressTimer = undefined;
    }
  }
}

export default directive;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment