l3lue
l3lue

Reputation: 541

How would I prevent redirecting of a href during touchmove and mousemove?

I've got an issue while I'm trying to combine touchstart and mousedown in 1 function. I've used an a tag as the target element of the function for going to the link directly when I touched or clicked the tag.

The issue is when I touch the middle of a tag, link doesn't respond. it only works when I click the element or touch the edge of the a tag, and the output fires mousedown.

enter image description here

In the mobile mode, try to click the edge of a tag as much as you would possible like a grey dot in the picture above. I've created an CodePen example for looking, testing and understanding better.

How would I fix this issue?

class Slider {
  constructor($el, paragraph) {
    this.$el = $el;
    this.paragraph = paragraph;
  }
  start(e) {
    e.preventDefault();
    var type = e.type;
    if (type === 'touchstart' || type === 'mousedown') this.paragraph.text(this.paragraph.text() + ' ' + type);
    return false;
  }
  apply() {
    this.$el.bind('touchstart mousedown', (e) => this.start(e));
  }
}
const setSlider = new Slider($('#anchor'), $('.textbox'), {passive: false});
setSlider.apply();
  a {
    display: block;
    width: 100px;
    height: 100px;
    background-color: orange;
  }
<a id="anchor" href="https://google.co.uk">Tap or Click Me</a>
<p class="textbox"></p>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

========= Progress Update ==========

I've just added move & end function then I have to click twice for moving on to the linked website. It keeps getting worse and have no idea how to solve this issue.

class Slider {
  constructor($el, paragraph) {
    this.$el = $el;
    this.paragraph = paragraph;
  }
  start(e) {
    e.preventDefault();
    var type = e.type;
    if (type === 'touchstart' || type === 'mousedown') this.paragraph.text(this.paragraph.text() + ' ' + type);
    this.$el.bind('touchmove mousemove', (e) => this.move(e));
    this.$el.bind('touchend mouseup', (e) => this.end(e));
    return false;
  }
  move(e) {
    var type = e.type;
    if (type === 'touchstart' || type === 'mousedown') this.paragraph.text(this.paragraph.text() + ' ' + type);
    return false;
  }
  end(e) {
    console.log('test');
    this.$el.on('click');
    this.$el.off('touchstart touchend');
    return false;
  }
  apply() {
    this.$el.bind('touchstart || mousedown', (e) => this.start(e));

  }
}
const setSlider = new Slider($('#anchor'), $('.textbox'));
setSlider.apply(); 


======== Progress Updated After Bounty (Latest) ========

After dozens of tried, I've finally figured out and solve the previous problem but I've faced up a new issue that can't draggable and redirecting instantly.

When I use the preventDefault in the start function, all of the events work fine. The only issue of this case is dragging doesn't prevent redirecting link from the a tag. It always send me to the website no matter which ways to call the functions, clicked or dragged.

when I don't use the preventDefault, dragging doesn't work. it only works clicking the elements.

My final goal is to prevent redirecting link of the a tag from the both events, touchmove and mousemove. I've been searched about on google so many times but haven't got any of the clues.

I've written an example in Codepen and this is what I've done so far:

class Slider {
  constructor($el, paragraph) {
    this.$el = $el;
    this.paragraph = paragraph;
  }
  start(e) {
    var type = e.type;
    if (type === 'touchstart') {
      this.paragraph.text(this.paragraph.text() + ' ' + type);
    } else if (type === 'mousedown') {
      this.paragraph.text(this.paragraph.text() + ' ' + type);
    }
  }
  move(e) {
    var type = e.type;
  }
  end(e) {
    var type = e.type;
    if (type === 'touchend') {
      console.log('touchstart enabled');
    } else if (type === 'mouseup') {
      console.log('mousedown enabled');
    }
  }
  apply() {
    this.$el.bind({
      touchstart: (e) => this.start(e),
      touchmove: (e) => this.move(e),
      touchend: (e) => this.end(e),
      mousedown:(e) => this.start(e),
      onmousemove: (e) => this.move(e),
      mouseup:  (e) => this.end(e)
    });
  }
}
const setSlider = new Slider($('#anchor'), $('.textbox'));
setSlider.apply();
    a {
      display: block;
      width: 100px;
      height: 100px;
      background-color: orange; 
    }
    <a id="anchor" href="https://google.co.uk">Tap or Click Me</a>
    <p class="textbox"></p>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Upvotes: 7

Views: 1528

Answers (2)

l3lue
l3lue

Reputation: 541

I think I found the solution about this. I add this code for some people in the future who are trying hard to search the same problem such as me.

    function start(event, etype, condition) {
      console.log(etype); // track the type of event
      if (!condition) event.preventDefault(); // compare etype(eventType). Set preventDefault if condition is falsy.
      items.off('click');
      items.on({
        ['touchmove mousemove']: (event) => move(event, etype, condition),
        ['touchend mouseup']: end
      });
    }

    function move(event, etype, cnd) {
      if (cnd) event.preventDefault();
      console.log(cnd); // track the type of event from the condition
      items.on('click', function(event) {event.preventDefault();});
    }

    function end(event) {
      items.off('touchmove mousemove touchend mouseup');
    }
    var items = $('.item a');
    items.on('touchstart mousedown', function() {
      var eventType = event.type;
      var condition = (eventType === 'touchstart' || eventType === 'mousedown');
      start(event, eventType, condition);
    });
    #anchor {
      display: block;
      width: 100px;
      height: 100px;
      background-color: orange;
    }
    .item {
    background-color: gray;
    }

    .item + .item {
        margin-top: 10px;
    }

    .item a {
        cursor: pointer;
        display: inline-block;
        background-color: blue;
        color: white;
        padding: 9px;
        width: 100%;
        height: 100%;
    }
    <div id="items" class="items">
      <div class="item">
          <a target="_blank" href="https://google.com">Anchor</a>
      </div>
      <div class="item">
          <a target="_blank" href="https://google.com">Anchor</a>
      </div>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Upvotes: 6

Galzor
Galzor

Reputation: 845

i think i figured out little solution for you. enable the preventDefault and afterwards enable the draggable for the a tag. Let me know if this works for you.

 start(e) {
  e.preventDefault();
  ...//rest of the code
 apply() {
  $el.draggable("enable");
  ...//rest of the code

Upvotes: 4

Related Questions