16

Is there a jQuery plugin or JavaScript script that automagically loops through each CSS hover (found in an external stylesheet) and binds it with a double touchdown event?

  • Touchdown 1 - CSS :hover is triggered
  • Touchdown 2 - Click (link following or form action)

If there isn't something like this yet, can it be made and how (guidelines)?

EDIT:

To be clear, I am not in search of a double tap. Touchdown 1 is a single tab just like Touchdown 2 is. There can be as less as 0 seconds between both or as much as 3 minutes, that's the user's choice.

No touch:

  • :hover -> element becomes visible
  • click -> following link or other action

Touch (iOS):

  • touchdown 1 -> element becomes visible
  • touchdown 2 -> following link or other action
DADU
  • 6,482
  • 7
  • 42
  • 64
  • 2
    That would break the consistency of the UI, particularly requiring a double-tap for navigation (double-tap is already overloaded, it can mean zoom in/out or bring up a context menu). There is no hover for iOS devices, there are only clicks and drags. – RobG Apr 01 '11 at 00:33
  • Yes, but sometimes you have important information that appears on hover. Example: http://html5awesome.com/. Go over one of the screenshots and you will see two actions: love and visit. Don't get those on iOS. You go directly to another page. – DADU Apr 01 '11 at 00:45
  • But what? As stated, that's just how it works. The concept of over doesn't exist on a touch device. If you want to expose that same information somehow, you need to come up with an alternative means. As stated, a double-tap is already taken by the OS itself. The typical suggestion is to add a separate visual to access said info such a help icon (?) – DA. Apr 05 '11 at 21:35
  • Off course. But :hover does exist in the stylesheet. And the touchdown event does exist. By the way, my example doesn't show a double tap. It is a single tap that triggers action 1 and another single tap that triggers action 2. I've seen this many times while visiting websites on iPad and it is possible. I am just asking for some guidelines or something that can automate this. – DADU Apr 05 '11 at 21:49

8 Answers8

13

Try this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <title>iPad Experiment</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            if(navigator.platform == "iPad") {
                $("a").each(function() { // have to use an `each` here - either a jQuery `each` or a `for(...)` loop
                    var onClick; // this will be a function
                    var firstClick = function() {
                        onClick = secondClick;
                        return false;
                    };
                    var secondClick = function() {
                        onClick = firstClick;
                        return true;
                    };
                    onClick = firstClick;
                    $(this).click(function() {
                        return onClick();
                    });
                });
            }
        });
    </script>
    <style type="text/css">
        a:hover {
            color:white;
            background:#FF00FF;
        }
    </style>
<body>
    <a href="http://google.ca">Google</a>
    <a href="http://stackoverflow.com">stackoverflow.com</a>
</body>
</html>

... or check out the demo on my web site. Note that it's set up to only work its magic on the iPad - detecting all versions of the iOS is another question in my books ;)

It works on the basis of the fact that...

After you click a link on the iphone or ipad, it leaves a simulated mouse hover that triggers the a:hover css styling on that link. If the link has a javascript handler that keeps you on same page, the hover state will not change until you click on another link.

Citation: Safari iphone/ipad “mouse hover” on new link after prior one is replaced with javascript

Community
  • 1
  • 1
Richard JP Le Guen
  • 28,364
  • 7
  • 89
  • 119
  • Thanks! Gonna check that out. – DADU Apr 05 '11 at 21:50
  • Magically working! Is there a way to remove the hover state when you click anywhere else on the page (not only anchor elements)? – DADU Apr 05 '11 at 22:35
  • @DADU - Sorry, I don't know how to do that :( but I'll think about it. – Richard JP Le Guen Apr 06 '11 at 02:51
  • For html click use: var navigationActive = $("#mainNavigation > li");function htmlClick () { if ($(navigationActive).hasClass("hover")) { $(navigationActive).removeClass("hover"); $(navigationActive).attr("aria-expanded", "false"); } } if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) { $("html").click(htmlClick); } – Jamie Paterson Mar 05 '15 at 14:28
6

I've used this:

$(document).ready(function() {
    $('.hover').bind('touchstart touchend', function(e) {
        e.preventDefault();
        $(this).toggleClass('hover_effect');
    });
});

Before, to allow hover on certain elements. Obviously you'll need to tweak it for your own use, but it's a nice way to allow a touch and hold hover effect.

Rich Bradshaw
  • 71,795
  • 44
  • 182
  • 241
  • It looks like you need to add the .hover_effect classname to every :hover in the CSS stylesheet. – DADU Apr 06 '11 at 14:37
  • 2
    In the site I was using, this is what I did, as I didn't want every hover to act in this way. You could add the event to every element, but that seems wasteful, and will preventDefault on too much. In the end I settled on this as it seemed a happy compromise. – Rich Bradshaw Apr 06 '11 at 18:07
3

I created this update apon Richard JP Le Guens solution. It works GREAT, but my version fixes the issue recognized by DADU.

Also I fixed his workaround to detect iPads. My solution detects any other touch devices too (except IE10 on MS surface, I didn't remember the MS special treatment).

My fix is not a 100% perfect solution, but it resets the hover fix at least when hovering another link.

<!DOCTYPE html>
<html>
<head>
    <title>TouchDevice Experiment</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            if(document.createEvent("TouchEvent")) { // using document.createEvent is more reliable than navigator (Modernizr uses this practice)
                $("a").each(function() { // have to use an `each` here - either a jQuery `each` or a `for(...)` loop
                    var onClick; // this will be a function
                    var firstClick = function() {
                        $("a").trigger("JWUnhover"); // triggering hoverfix reset if any link gets touched

                        onClick = secondClick;
                        return false;
                    };
                    secondClick = function() {
                        onClick = firstClick;
                        return true;
                    };
                    onClick = firstClick;
                    $(this).click(function() {
                        return onClick();
                    });
                    $(this).bind('JWUnhover', function(){ onClick = firstClick; });
                });
            }
        });
    </script>
    <style type="text/css">
        a:hover {
            color:white;
            background:#FF00FF;
        }
    </style>
</head>
<body>
    <a href="http://google.ca">Google</a>
    <a href="http://stackoverflow.com">stackoverflow.com</a>
</body>
</html>
Julian F. Weinert
  • 7,474
  • 7
  • 59
  • 107
3

Here is a further optimized version that also handles closing the :hover

You'll have to encapsulate your site with a

<div id="container"></div>

for it to work. Just putting the closing event on the body did nothing

var bodyBound = false;
var container;

if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/iPad/i))
{
    container = $("#container");

     // Provoke iOS :hover event
    $("a.someLink").on("mouseover", handleHoverClick);
}

function handleClose(event)
{
    container.off("click", handleClose);

    bodyBound = false;
}

function handleHoverClick(event)
{
    if (!bodyBound)
    {
        bodyBound = true;

        // Somehow, just calling this function—even if empty—closes the :hover
        container.on("click", handleClose);
    }
}
kotyy
  • 167
  • 1
  • 3
  • 11
Steven Vachon
  • 3,814
  • 1
  • 30
  • 30
1

This worked for me!

// Ipad Navigation Hover Support
    $('#header .nav li a').bind('touchstart touchend', function(e) {
        if( $(this).attr("href") != "" ){
            window.location = $(this).attr("href");
        }

    });
crivers
  • 41
  • 2
1

There is no jQuery plugin that I know of to do such a thing.

You cannot trigger a css psuedo class such as ":hover". You can however loop through the anchor elements and add a css class ".hover" on touchstart and touchend events as follows:

    var pageLinks = document.getElementsByTagName('a');
for(var i = 0; i < pageLinks.length; i++){
    pageLinks[i].addEventListener('touchstart', function(){this.className = "hover";}, false);
    pageLinks[i].addEventListener('touchend', function(){this.className = "";}, false);
}

To add a double finger tap gesture recognizer, you can use a plugin such as: http://plugins.jquery.com/project/multiswipe

Willster
  • 2,526
  • 1
  • 32
  • 32
0

There is a more simpler way to fix the issue with iOS and hover states, using CSS. For the link you have an issue with set the cursor property to pointer and the hover state will be ignored on iOS. For all links to function as expected, see below:

a
{cursor: pointer;}
0

Here's an optimized version of the jQuery code provided by Richard JP Le Guen:

$(document).ready(function() {

    $('a').each(function() {

        var clicked = false;

        $(this).bind('click', function() {

            if(!clicked) return !(clicked = true);
        });
    });
});
DADU
  • 6,482
  • 7
  • 42
  • 64