jquery preventing hover function on touch

强颜欢笑 提交于 2020-06-27 07:04:22

问题


I have a hover function, if it's a touch device I'd like the hover event to NOT happen. The problem is when you tap the link with a touch device it does the hover event before doing the click event, so you have to tap it twice for it to work.

this is the hover function:

$("#close").hover( 
    function () { 
        $("#close_2").css({
            display: "none"
        });
        $("#close_1").css({
            display: "block"
        });
    }, 
    function () {
        $("#close_1").css({
            display: "none"
        });
        $("#close_2").css({
            display: "block"
        });;
    }
); 

and then I have this set up as the click function:

$('#close').click(function() {
    var id = $(this).attr('id');
    $('#full_image').animate({
        height: 0
    }, 300, function() {
        $('#full_image img').attr('src','#');
    });
    $("#close_1").css({
        display: "none"
    });
    $("#close_2").css({
        display: "none"
    });
    $("#close").css({
        display: "none"
    });
});

回答1:


Make the .hover() method more explicit and combine it with .on():

var $close1 = $('#close_1'),
    $close2 = $('#close_2');

$('#close').on({
    mouseenter: function(){
        $close2.css({display:'none'});
        $close1.css({display:'block'});
    },
    mouseleave: function(){
        $close1.css({display:'none'});
        $close2.css({display:'block'});
    }
});

Then combine that with .off().

$('#close').on('touchstart',function(){
    $(this).off('mouseenter,mouseleave');
});

If you want the event to fire on click with touch devices, but on hover on desktop devices, then put the functions as a separate function you call within those actions respectively.

EDIT

Been a while since I did this answer, here is a better way:

$(function(){
    var isTouchDevice = ('ontouchstart' in window || 'onmsgesturechange' in window),
        $close = $('#close'),
        $close1 = $('#close_1'),
        $close2 = $('#close_2');

    if(!isTouchDevice){
        $close.on({
            mouseenter: function(){
                $close2.hide();
                $close1.show();
            },
            mouseleave: function(){
                $close1.hide();
                $close2.show();
            }
        });
    }

    $close.on('click',function(){
        $('#full_image').animate({height:0},300,function(){
            $(this).find('img').attr('src','#');
        });

        $close.hide();
        $close1.hide();
        $close2.hide();
    });
});

This doesn't require a "hover prevention" event to fire with each touch, basically sets capabilities on page load while not affecting the click event.




回答2:


I think a clear approach would be to:

  1. Detect if the browser supports touch events
  2. Add the hover event handler accordingly

If you're using something like Modernizr already:

if(!Modernizr.touch){
    // only if the browser doesn't support touch events,
    // add the hover handler here.
}
//add the click handler here, as you want it bound no matter what

See What's the best way to detect a 'touch screen' device using JavaScript? and What's the best way to detect a 'touch screen' device using JavaScript? for other options to detect touch capabilities.




回答3:


On mobile side calling preventDefault in touchstart event prevents mouseover, mouseenter, mousedown and affiliated events. Detail: https://patrickhlauke.github.io/touch/tests/results/

    $('#close').on('touchstart',function(e){
        console.log('touchstart');
        e.preventDefault();
        //Do touch stuff
    });



回答4:


Because of Windows 8 and Ultrabooks, I expect to see a lot of devices that support both touch and pointer events. As a result, I avoid disabling the hover event outright since it could potentially break the site for an touch enabled user with a mouse.

To solve this problem I ended up using two different classes for displaying menus, .hover and .touch, as well as separate events for hover and tap.

I'm using jquery.finger for capturing tap events, though any plug-in should work, this was just the smallest one.

The HTML Would be something like:

<li>
    <a>Some Link</a>
    <div>Some Content</div>
</li>

The CSS would be something like:

li div {display:none;}
li.hover div, li.touch div {display:block;}

And the Javascript using JQuery:

// Caching whatever elements I'm using for the navigation
a = $("a");
li = $("li");

// Set hover events
li.hover(

    // Both hover in and out fire whenever the user taps, aggravating!
    function(e) {
        // Close unused menus
        li.not(this).removeClass("hover").removeClass("touch");

        // Show this menu
        $(this).addClass( "hover" );
    }, function(e) {
        // Only closes if the menu doesn't have .touch, hell yeah!
        li.removeClass("hover");
    }

);

// Set the tap event
a.on('tap',function(e,data){
    e.stopPropagation();
    var thisParent = $(this.parentNode);

    // Close unused menus
    li.not(thisParent).removeClass("touch");

    // Toggle the current menu
    thisParent.toggleClass("touch");

    // The menu is open, so we don't need this class anymore
    li.removeClass("hover");
});

// Prevent the list items when being tapped from closing the drop down
li.on('tap',function(e){e.stopPropagation();});

// Close drop downs when tapping outside the menus
$(document).on('tap',function(e){
   li.removeClass("touch");
});

The important take away here is how I'm adding a seperate .hover or .touch class depending on the event, as well as removing the unused classes. The order is important so the menus don't blink.




回答5:


ended up using touch detection:

var deviceAgent = navigator.userAgent.toLowerCase();
var agentID = deviceAgent.match(/(iphone|ipod|ipad)/);

if(agentID) { 
    $('#close').click(function() {
        var id = $(this).attr('id');
        $('#full_image').animate({
            height: 0
        }, 300, function() {
            $('#full_image img').attr('src','#');
        });
        $("#close_1").css({
            display: "none"
        });
        $("#close_2").css({
            display: "none"
        });
        $("#close").css({
            display: "none"
        });
    });
}
else {
    $('#close').hover(
        function() {
            $("#close_2").css({
                display: "none"
            });
            $("#close_1").css({
                display: "block"
            });
        }, function() {
            $("#close_1").css({
                display: "none"
            });
            $("#close_2").css({
                display: "block"
            });
        }
    ); 
    $('#close').click(function() {
        var id = $(this).attr('id');
        $('#full_image').animate({
            height: 0
        }, 300, function() {
            $('#full_image img').attr('src','#');
        });
        $("#close_1").css({
            display: "none"
        });
        $("#close_2").css({
            display: "none"
        });
        $("#close").css({
            display: "none"
        });
    });
}


来源:https://stackoverflow.com/questions/14388813/jquery-preventing-hover-function-on-touch

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!