Search code examples
javascriptclicktouchswipedrag

How would I cancel a specific event in javascript?


I added 2 different events each called touchstart and mousedown in the on method like this:

this.$el.on('touchstart mousedown', (e) => { this.start(e); })

My main goal is to cancel a mousedown event only which belongs to the on method at the end of called end function.

If I run a touchstart event 2 different events are always firing together. See this picture:

enter image description here

This problem causes undesired event block at Firefox. And also the code runs twice which is unnecessary. I want to redirect the website when I click or touch the element, prevent when I drag or swipe.

I searched about how to prevent a specific event on google but haven't found any of info so I've tried few ways by myself. However, all of the cases didn't work.

  1. Add return false; line

    • Sadly, return false makes stop all of the remained events after end function has ended. My goal is to cancel the mousedown only, not the entire of the events. Therefore I can't just put the line into the function.
  2. Add mousedown event into the off method

    • This also doesn't work. The events which belongs to the off method still remains as it's turned off. So if I try to drag after I swiped the element, nothing happens because mousedown event is now turned off.
  3. Add preventDefault() or stopPropagation()

    • Those can't use as the same reason of case 1.
  4. Using RegExp to separate and make a new function for Firefox

    • The problem was firing the undesired event, not the browser.

Are there any ways to cancel a specific event in this code?

class Evt {
  constructor($el) {
    this.$el = $el;
  }
  start(e) {
    console.log('start Function');
    this.$el.off('click');
    this.$el.on({
      ['touchmove mousemove']: (e) => this.eventmove(e),
      ['touchend mouseup']: (e) => this.end(e)
    });
  }
  eventmove(e) {
    e.preventDefault();
    console.log('move function');
    this.$el.on('click', (e) => {e.preventDefault();});
    return false;
  }
  end(e) {
    console.log('end function');
    this.$el.on('click');
    this.$el.off('touchmove touchend mousemove mouseup');
  }
  apply() {
    this.$el.on('touchstart mousedown', (e) => {
      this.start(e);
    })
  }
}
var thatEvt = new Evt($('#link'));
thatEvt.apply();
      a {
        width: 100%;
        height: 200px;
        border-radius: 10px;
        background-color: brown;
        font-family: Helvetica;
      }
    <a id="link" href="https://google.co.uk">
      Click/Touch and Drag/Swipe
    </a>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


Solution

  • As I hear it, your intention is to have the link not redirect when the mouse is moved within a click.

    Firstly, I assume you do not want the link to be draggable, so add the draggable="false" tag. This will prevent events that may effect code outside what you have sent (such as redirecting/dropping links).

    <a id="link" href="https://google.co.uk" draggable="false">
      Click/Touch and Drag/Swipe
    </a>
    

    If that does not solve your issue I have put together this code below, it may be more complicated, but it should be a little more robust.

    class Evt {
      constructor($el) {
        this.$el = $el;
        this.active = false;
        this.preventRedirect = false;
      }
      start(e) {
        console.log('start Function');
        this.active = true;
        this.preventRedirect = false;
      }
      eventmove(e) {
        if (this.active) {
          console.log('move function');
          this.preventRedirect = true;
        }
      }
      end(e) {
        if (this.active) {
          console.log('end function');
          this.active = false;
        }
      }
      apply() {
        this.$el.on({
          ['touchstart mousedown']: (e) => this.start(e),
          ['click']: (e) => { //preventing onclick only if preventRedirect is set
            if (this.preventRedirect) {
              e.preventDefault();
              return false;
            }
          }
        });
        $("html").on({ //so that the mouse can move outside the element and still work.
          ['touchmove mousemove']: (e) => this.eventmove(e),
          ['touchend mouseup']: (e) => this.end(e)
        });
      }
    }
    var thatEvt = new Evt($('#link'));
    thatEvt.apply();