mdbootstrap / bootstrap-hover-dropdown

An unofficial Bootstrap plugin to enable Bootstrap dropdowns to activate on hover and provide a nice user experience.
http://cameronspear.com/demos/bootstrap-hover-dropdown/
MIT License
1.26k stars 504 forks source link

Menus automatically closing on Windows Phone 8 #28

Closed theonlysteve closed 10 years ago

theonlysteve commented 11 years ago

Stumbled across a potential issue for Windows phones. When you touch the drop down menu, it will automatically close again after the amount of delay you set.

Thought it may have been just my implementation, but I went to the demo page linked from here and the behaviour is the same. Desktops, iPhone and iPad all seem to be fine.

This is on the Windows Phone 8S produced by HTC.

Any help appreciated, thanks.

CWSpear commented 11 years ago

Oh man. Unless you want to donate a Windows Phone to me... I don't really have a way to test this.

It does seem to work fine on my Android, too. Just Windows, eh? The old version had a bunch of weird hacks for all of this, but it wasn't particularly necessary for most situations and introduced more issues than it really solved. But it sounds like Microsoft just won't let it die... argh.

nesl247 commented 10 years ago

Happens on not just WP8, but IE 10/11 on Windows 8/8.1.

CWSpear commented 10 years ago

I still don't have an Windows Phone to be able to do anything about this, but I finally did get my hands on IE10. I can't resolve this case, but I will keep it open and once again, if anyone with a Windows Phone wants to tackle this, please do.

@nesl247 I cannot reproduce any issues in IE10 on Windows 8. It appears to function just like Chrome does. What exactly are you experiencing?

nesl247 commented 10 years ago

The issue is when you are on a touchscreen enabled device, this plugin seems to cause the dropdowns to only stay on screen for a brief second, and then they close. They aren't staying put. Without this plugin, it behaves properly because it's click to open.

It's almost like this plugin isn't detecting it's a click.

dam-scasi commented 10 years ago

The issue is that when, on desktop browser, you hover a button with dropdown-hover, the dropdown appear and when you click on the button right after that, the dropdown disappear. So on touch screen, when you tap on the button, it first do the hover witch display the dropdown, and then do the click witch hide it with the famous 300ms delay on mobile.

CWSpear commented 10 years ago

I’m not seeing this on my Android phone. What phone do you have?

CWSpear commented 10 years ago

I mean to say, so you have a Windows phone? I still have no way to test this and no one has offered a fix or to buy me a Windows phone. So… still not sure what more I can do.

dam-scasi commented 10 years ago

Yes I have a Windows Phone 8, but my colleagues who have Android have the same problem on the first time they tap on button. They have to tap twice so the dropdown stay displayed. And that make sense with what I said : on first tap it does hover followed by click which display and hide the dropdown, and second tap only do click since it's already on the button, so it just display the dropdown. And if you tap elsewhere between the two tap, the second will redo the hover and click events. They have Android 4.1 and 4.2. I tested it on Android SDK 4.3 and it also does it, so you can test it with that if your version does not do this issue.

On Windows Phone, even two tap doesn't display the dropdown, it always display and directly hide it.

CWSpear commented 10 years ago

Ooook, so I was able to reproduce this Android stuff. Stupidest bug so far all of this.

What I ended up doing is just disable the plugin if the device supports touch events, since it's not even needed on mobile devices, etc. That definitely fixed the Android issues (I tested), but still don't have a way to test the Windows phones, but unless they don't support touch events (which I feel pretty confident they do), it should fix them, too.

So I'm closing the ticket, finally.

Thanks for your help.

nesl247 commented 10 years ago

If you disable the plugin if it supports touch events, you just disabled the plugin on tablets that have a mouse connected. The fix is really not the way to go. Not sure if it's possible, but it would best if you could check to see if the click event was also triggered and if so, ignore your code, and let bootstrap handle it. Sounds almost like hoverIntent is needed instead of hover().

CWSpear commented 10 years ago

Really? Spend another $100 or two (what you probably spent on your special Tablet keyboard and mouse) and get a laptop, already! It'll be 10 times more powerful.

Haha, sorry. Not ranting against you specifically. I just can't really understand tablets... other than Apple has the world in mass hypnosis?

But seriously, I don't think hoverIntent is really the solution here. It does actually alleviate some of this, but it's a bit more complicated... if you want to use hoverIntent, include it in your page and replace any instances of hover with hoverIntent in the plugin.

I've spent a couple hours on it tonight and it's just a rather complicated and time consuming issue for a very small subset of users. And the page is still perfectly usable: Just click on the dropdown!

nesl247 commented 10 years ago

This actually didn't fix the issue with IE. It is still executing the hover(). I believe this is because of IE's use of point events vs the standard ontouchstart.

CWSpear commented 10 years ago

Well, then I'm guess we're back at square one. I don't have a way to test a Windows Phone (assuming that's what you meant by "IE," since IE11 seems to be fine).

nesl247 commented 10 years ago

IE is always fine until you have a touch screen enabled browser. That's where the issue is. IE on WP uses the same pointer events that IE on the desktop uses. So when I say IE, it doesn't matter if it's the desktop or if it's the phone. They behave the same in this particular case.

Rather than hover(), maybe use mouseenter/mouseleave and the correct MSPointer* events ("The events for capturing generic pointer input look a lot like those for mouse: MSPointerDown, MSPointerMove, MSPointerUp, MSPointerOver, MSPointerOut, etc." - http://blogs.msdn.com/b/ie/archive/2011/09/20/touch-input-for-ie10-and-metro-style-apps.aspx).

CWSpear commented 10 years ago

But I still have no way to test it.

nesl247 commented 10 years ago

I can either test it for you, or screen share with you if you'd like?

CWSpear commented 10 years ago

In the IE with a touch screen: what does the following code return when put into the console?

'ontouchstart' in document

(it should say true or false)

While you're at it, confirm that this is true:

'onmspointerout' in document
nesl247 commented 10 years ago

First returns false, second returns true.

CWSpear commented 10 years ago

Ok, go to http://dropdown.staging.matchbooklab.com and see how that works on your Touch IE thing.

nesl247 commented 10 years ago

Still broken. Doesn't appear anything changed.

CWSpear commented 10 years ago

You can see instances of MSPointerOut in http://dropdown.staging.matchbooklab.com/twitter-bootstrap-hover-dropdown.js, right?

nesl247 commented 10 years ago

I can.

nesl247 commented 10 years ago

Might need to take a look at http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx

Looks like IE11 changed some stuff from IE10 when dealing with this.

CWSpear commented 10 years ago

Ok, so here's the events I'm using now:

hoverOverEvents = 'mouseover MSPointerOver pointerover',
hoverOutEvents = 'mouseout MSPointerOut pointerout',

That's nice of MS to add a proprietary prefixed event and then completely remove it in the next release.

At least that's what that link said, but do you have IE10 or IE11? Cuz 'onmspointerout' in document returned true for you. So I'm a little confused.

But see if the new events change anything.

CWSpear commented 10 years ago

Oh, I guess it says

the Microsoft prefixed versions of pointer events APIs are no longer supported and might be removed in a future release.

So I guess it is just deprecated and not removed. Feel like they could have been more clear. Like using the word deprecated.

Whatever.

Anyway, so that means this won't really change anything, other than I used MSPointerOut instead of MSPointerLeave.

nesl247 commented 10 years ago

The reason they had MS prefixed was because the W3C hadn't accepted the spec yet (which was when IE10 was developed). In IE11, W3C accepted it and therefore they removed the prefix. IE11 at the moment supposedly supports both, which is why onmspointerout would have worked. Any random update could eventually disable the prefixed versions, and IE12 whenever it gets released won't have support anymore.

As far as the fix, still not working. Opens it and then closes immediately.

"Because the W3C Pointer Events specification wasn't complete when Internet Explorer 10 was released, vendor prefixes were used for the Pointer Events implementation. Since then, the specification has reached Candidate Recommendation status, and the MS vendor prefix versions of the APIs have been deprecated in favor of the non-prefixed signatures defined in the spec. As of IE11, the Microsoft prefixed versions of pointer events APIs are no longer supported and might be removed in a future release."

CWSpear commented 10 years ago

Right, what you described is called "deprecated." I just thought it was weird that they didn't use that word, making a little harder to uncover the meaning.

So any other ideas for a fix?

nesl247 commented 10 years ago

Updated my reply, they actually do call it deprecated, just not the part you quoted from :)

I did my own testing earlier and it's almost as if the open class is only there on pointerenter, and it automatically knows to remove it when the event ends. I'm really not sure why. I'm going to test tomorrow with just a single element page, and a few of the different events, and have it apply a class and see if it sticks. I have no idea at this point if bootstrap is doing something stupid with their CSS on this or not.

CWSpear commented 10 years ago

lol, yes they do. I'm just trying to do 10 things at once. My bad.

I do think a little bit of the implementation changed in BS 3.0, but the end game (toggling the open class) is more or less the same.

jrchamp commented 10 years ago

Have you tried setting some CSS to prevent the double-tap-to-zoom tap delay? This may be conflicting with the auto-close timer:

* {
    -ms-touch-action: none !important;
}

This idea came from https://github.com/ftlabs/fastclick#when-it-isnt-needed

CWSpear commented 10 years ago

@jrchamp If you look at FastClick's mention of Bootstrap, you'll see that Bootstrap already attempts to solve this issue on their own (assuming this hasn't changed since 2.2.2), and FastClick itself conflicts with that.

Sorry, that's a bit of an off-topic tangent. I do think it's possible that this may help. Do you or @nesl247 want to try it out and see what happens? I think it's really only needed for button and a. I don't know if it would hurt to apply it to * tho?

jrchamp commented 10 years ago

@CWSpear Nice find, I missed that completely. Unfortunately, I don't have a Windows phone to test with. I agree that the more specific css should be sufficient (though applying it to star might tell it you're really really serious! ha!):

button, a {
  -ms-touch-action: none !important;
}
CWSpear commented 10 years ago

@jrchamp As an aside, you should familiarize yourself with Markdown, specifically GitHub Flavored Markdown which is especially developer friendly.

Always helpful to put code and key code words in <code> with code blocks in <pre> and GFM makes it easy to do by just wrapping stuff in a single backtick ` for inline code and three for blocks ``` (with an optional syntax (see above link)).

jrchamp commented 10 years ago

@CWSpear Thanks! I'll keep that in mind.

davidb2002 commented 10 years ago

@jrchamp @CWSpear I've just tried adding that -ms-touch-action css mention above and it still doesn't work.

CWSpear commented 10 years ago

@davidb2002 I still don't have a Windows Phone. Not trying to be unsympathetic, but it's way too much work for me to really be able to reliably test/debug this.

It's good to know what does and doesn't work for future posterity, but I am still open to solutions if anyone with Windows Phones is able to find one. =)

davidb2002 commented 10 years ago

@CWSpear Not sure if this will help as i've not looked at how the plugin actually works...

In a non bootstrap project I had a menu which dropdowns. The parent menu links (top level) also had a url to follow if clicked on. Needless to say, I wanted touch devices to display the drop down first and then require the user to touch the parent menu link again if they wished to follow it. So what I did was add to the parent's onclick a function which event.preventDefault(); and checked to see if the dropdown was visible by way to checking its css display property or class. If it wasn't displayed, the function did javascript:void(); . If the dropdown was visible, I followed the href.

function menu_follow(submenu,link){
    event.preventDefault();
    if($('#'+submenu).css('display') == 'block'){
        window.location.href = link;
    }
    else { 
        javascript: void(0); 
    }
}

This appeared to work for touch devices and desktops acted normally with a normal hover css effect.

jrchamp commented 10 years ago

@davidb2002 You may want to try using jQuery's .is() and the :visible selector in case the display value is changed to a different value, such as inline-block.

 if ($('#'+submenu).is(':visible')) {
CWSpear commented 10 years ago

@davidb2002 That definitely is one approach.

Are you saying that that solves the issue for Windows phones?

To address the "follow parent link" thing: From a user experience standpoint, I don't typically like dropdowns at all, and then when it goes on to expecting the user to know they have to click twice on a top level/parent nav item to visit it (even if only on mobile), I just feel like there is usually a better answer, but it starts at the design level.

davidb2002 commented 10 years ago

@jrchamp thanks i'll keep that in mind

@CWSpear I agree that it's a bit weird. Unfortunately we have to backwards support some old interface issues. I'm not sure if it will work, i'll be doing some work today on it to see.

davidb2002 commented 10 years ago

@CWSpear Still no go.

CWSpear commented 10 years ago

@davidb2002 to be clear, is your issue Windows Phone specific, or are you trying to accomplish something for all mobile devices? (Since the title of this issue is about Windows Phones.)

I guess I'm asking you to re-state your exact issue to make sure I'm on the same page.

binary-scenery commented 10 years ago

I managed to get round this by adding aria-haspopup="true" attribute to elements that include hover functionality, seems to nudge windows phones into making a hover state