javascript - JQuery .on("click") triggers "mouseover" on touch device - Stack Overflow

I'm encountering unwanted behavior when using JQuery's $.on("click", function(){});

I'm encountering unwanted behavior when using JQuery's $.on("click", function(){}); on touch devices. This is my code below:

Code:

$(".team").on("mouseover", teamMouseOver);
$(".team").on("mouseout", teamMouseOut);
$(".team").on("click", teamThumbClicked);

function teamMouseOver(event){
    console.log(event.type);
}

function teamMouseOut(event){
    // Do something
}

function teamThumbClicked(event){
    console.log("Clicked!");
}

Problem:

With the code above, tapping on a .team element on a touch device simultaneously triggers both listeners, giving me the following console log:

mouseover
Clicked!

Question Why is mouseover being triggered on a touch device? This is not the behavior that I would expect from a device that doesn't have a mouse. Is this a bug? What event should I be using so "mouseover" only gets fired when it's an actual mouse pointer that's entering?

My JQuery version is 2.2.4.

I'm encountering unwanted behavior when using JQuery's $.on("click", function(){}); on touch devices. This is my code below:

Code:

$(".team").on("mouseover", teamMouseOver);
$(".team").on("mouseout", teamMouseOut);
$(".team").on("click", teamThumbClicked);

function teamMouseOver(event){
    console.log(event.type);
}

function teamMouseOut(event){
    // Do something
}

function teamThumbClicked(event){
    console.log("Clicked!");
}

Problem:

With the code above, tapping on a .team element on a touch device simultaneously triggers both listeners, giving me the following console log:

mouseover
Clicked!

Question Why is mouseover being triggered on a touch device? This is not the behavior that I would expect from a device that doesn't have a mouse. Is this a bug? What event should I be using so "mouseover" only gets fired when it's an actual mouse pointer that's entering?

My JQuery version is 2.2.4.

Share Improve this question edited May 24, 2016 at 18:52 M - asked May 24, 2016 at 3:08 M -M - 28.6k12 gold badges54 silver badges93 bronze badges 5
  • This may be helpful – Guruprasad J Rao Commented May 24, 2016 at 3:40
  • This is the correct behavior. What are you trying to achieve? I just recently ran in to the same problem (unwanted classes being added on mobile 'click') and was able to solve the issue using CSS specificity: developer.mozilla/en-US/docs/Web/CSS/Specificity – Mussser Commented May 24, 2016 at 19:14
  • I display a tooltip on mouseover and I hide it on click. If these two events are triggered simultaneously, the tooltip stays visible, when it should be hidden because you clicked. That's why I don't need mouseover to be triggered when the device doesn't have a mouse. I thought that's what touch events were for. Did JQuery do this on purpose to simulate :hover effects? – M - Commented May 24, 2016 at 19:32
  • @MarcoDelValle Did you eventually solve this? I am trying to solve a similar bug. Thanks! – unsingefou Commented Jul 13, 2017 at 14:19
  • @unsingefou I don't exactly remember, since it was over a year ago, but I think I disabled the "mouseover" event listener if "touchstart" happens before "clicked". It's convoluted, but it was the only way I found to allow for devices that had both mouse and touch inputs. – M - Commented Jul 13, 2017 at 19:17
Add a ment  | 

4 Answers 4

Reset to default 2

The relatedTarget property of MouseEvent is null when the mouseenter or mouseover is triggered by click or touch. https://developer.mozilla/en-US/docs/Web/API/MouseEvent/relatedTarget

someElement.addEventListener("mouseover", (e)=>{
  e.relatedTarget // null if triggered by click or touch, 
                  // otherwise it refers to the element the pointer came from.
})

I just ran into the same issue and this is what I did to solve the problem.

$('#myEl').on('click', myElClickEvent);

$('#myEl').on('mouseenter', myElMouseEnterEvent);

function myElClickEvent (event) {
   $(this).addClass('Clicked');
}

function myElMouseEnterEvent() {
    // Turn off events
    $('#myEl').off();

    // After 100 milliseconds cut on events, notice click event won't trigger
    setTimeout(function() {
       // .off() is used to prevent from adding multiple click events if the user hovers multiple elements too quickly.
       $('#myEl').off().on('click', myElClickEvent);             
       $('#myEl').off().on('mouseenter', myElMouseEnterEvent);
    }, 100);


   // Do some mouseenter stuff, whatever the reqs. are.
}

This is what I did and it worked fine for my use case. Hopefully this helps someone in the future. The idea is to turn off the click event within the mouse enter event and then after 100 milliseconds cut the mouse click event back on. This will prevent both events from triggering on touch.

I ran into the same problem and also felt that it was a bit annoying that we cant separate the two events. My approach to solve this was adding the touchend event and let it flag that it is a touch device first. Since the rest of the events will follow, I can ignore them or do something else with them and they still will still be run if triggered by a non touch device.

var touchEndDetected = false;
var mouseOverDetected = false;

$('#myEl').on('click mouseover touchend', function (e) {
    console.log('Event type: ' + e.type);

    if(mouseOverDetected) {
        console.log('Mouseover event has already run this before');
        touchEndDetected = false;
        mouseOverDetected = false;
        return;
    }

    if(touchEndDetected) {
        touchEndDetected = false;
        mouseOverDetected = true;
        console.log('Touchend event has already run this before');
        return;
    }

    if(e.type === 'touchend') {
        touchEndDetected = true;
        mouseOverDetected = false;
    }

    console.log('This code will only run once when touch');
}

Call .preventDefault() on the original touch event.

The API link actually provides the answer. https://developer.mozilla/en-US/docs/Web/API/Touch_events/Supporting_both_TouchEvent_and_MouseEvent#event_firing.

In your case, you are using jQuery's .on() function, to which you can send multiple events (separated by spaces), so you can add touchstart or ontouchstart to that string and just call preventDeault() right off the bat in your handler function.

$(".team").on("click touchstart", teamThumbClicked);

// and later...

function teamThumbClicked(event){
    event.preventDefault(); // prevent further mouse events from being dispatched
    console.log("Clicked!");
}

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745462263a4628761.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信