Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

tooltip does not work on mobile browsers after upgrading to 0.13.4 from 0.13.3 and is still broken #4731

Closed
gae123 opened this issue Oct 26, 2015 · 35 comments

Comments

@gae123
Copy link

gae123 commented Oct 26, 2015

I have a responsive app that uses tooltip extensively. Tooltips work fine until 0.13.3 but they suddenly stopped working for iOS and Android with 0.13.4 and is still broken with 0.14.3 the latest release I tried. In all these releases work fine with desktop browsers.

@RobJacobs
Copy link
Contributor

I viewed the demo page using Chromes device emulator, tooltips are appearing when I click on the elements with the tooltip directive.

@gae123
Copy link
Author

gae123 commented Oct 26, 2015

Chrome's desktop "device emulator" just emulates the device sizes not the engines. Find an iPad, Android or iPhone and try it out, it does not work any more. It also fails in the real iOS xcode emulator.

@icfantv
Copy link
Contributor

icfantv commented Oct 26, 2015

I just tried our demo page in Chrome on my iPhone and it's working. Can you please post a plunker where it is not working and I will check again?

@RobJacobs
Copy link
Contributor

@gae123 In my experience, the Chrome desktop emulator does a pretty good job of emulating touch events which I suspected was the problem you are having.

@gae123
Copy link
Author

gae123 commented Oct 26, 2015

What is the version of your iPhone and what is the demo page you refer to? I just tried your page https://angular-ui.github.io/bootstrap/ with both iOS 9.0.2 and 9.1 on both iPad and iPhone and does not work.

@icfantv
Copy link
Contributor

icfantv commented Oct 26, 2015

@gae123, I'm on an iPhone 6 running iOS 9.1. I've sent an email to my team asking if folks would please check our demo page as well and if it didn't work to respond with their iOS version and phone/tablet model number.

@gae123
Copy link
Author

gae123 commented Oct 26, 2015

Mystery. I am also on iPhone 6 running iOS 9.1 As a side note, maybe related, do you see the page render as it should, here is what I see on my iPhone:
angular-ui-bootstrap-iphone

As another side note, I see quite a few tooltip changes between 0.13.3 and 0.13.4: 0.13.3...0.13.4

@gae123
Copy link
Author

gae123 commented Oct 26, 2015

I am also experimenting with the Xcode simulator. Mostly popups do not come up, once in a while I get one to come up but that's it. Then I reload the page and the same routine, keep clicking and randomly one comes up. This is consistent with what I see with my app. Then I go back to 0.13.3 and toolitps work fine and consistently everywhere.

image

@icfantv
Copy link
Contributor

icfantv commented Oct 26, 2015

I believe that's my view as well.

It is not working on iOS 9.1 on an iPhone 6+ (via a co-worker)

@gae123
Copy link
Author

gae123 commented Oct 26, 2015

Preliminary finding with my app: Changing the element that is hosting the tooltip attributes from <span> to <a> seems to fix the problem. This might be a good work around for me, I will experiment more in a couple of hours.

@PerfectPixel
Copy link

The tooltip is not completely broken. On https://angular-ui.github.io/bootstrap/#/tooltip the tooltip on the input field with the label "Or use custom triggers, like focus:" is working on my iPhone 5 and iPad Air 2 (both iOS 9.1). All other tooltips are not working, well at least not 95% of the time, sometimes they work all of a sudden.

I stumbled upon this issue today, the easy fix was giving the span-element a cursor: pointer CSS property (see http://www.shdon.com/blog/2013/06/07/why-your-click-events-don-t-work-on-mobile-safari).

For extra confusion:
Open the tooltip plunker at https://angular-ui.github.io/bootstrap/#/tooltip and all tooltips are working both on my iPhone and iPad.

@icfantv
Copy link
Contributor

icfantv commented Oct 26, 2015

Guys, I don't know that there's going to be much we can do here. We just use the same CSS classes as core Bootstrap. It's possible we've missed some cases but we haven't heard anything from anyone until now that there may be an issue.

Can you guys check Bootstrap's site to see if they're working?

It would be really helpful if you could create something that was reproducible and broken - otherwise, we're all just thrashing.

@RobJacobs
Copy link
Contributor

Seems like this may be related to iOS v9, I was not seeing this problem on an iPad running v7. Interesting thing is if you hold on the tooltip link long enough, the Open, Open in New Tab, etc... menu appears and choosing open will show the tooltip. TWBS tooltips do work fine.

@PerfectPixel
Copy link

Bootstrap itself works fine.

Using jQuery's element.bind instead of element[0].addEventListener at https://github.com/angular-ui/bootstrap/blob/master/src/tooltip/tooltip.js#L464-L472 fixes the issue for me. This is related to #4060.

@RobJacobs it does not seem to work on iOS 8.3 either

@icfantv
Copy link
Contributor

icfantv commented Oct 26, 2015

Hmm. Why aren't we using the on/off methods? @wesleycho, any ramifications of changing this to use .on(...) and .off(...)?

@wesleycho
Copy link
Contributor

jqLite/jQuery bug with mouseleave

@icfantv
Copy link
Contributor

icfantv commented Oct 26, 2015

@PerfectPixel, see @wesleycho's comment - so while your .bind may fix it on mobile devices, it will break it for mouseleave events on desktop browsers.

@RobJacobs
Copy link
Contributor

I've tested this:

<div uib-tooltip="I am a tooltip" style="padding: 10px;" tooltip-trigger="click" tooltip-placement=">Some tooltip</div>

And it works. I remember a discussion we had recently with regards to click/focus triggers and the specifics on what's needed for iOS with implementation guidance from TWBS but I can't seem to find it?

@PerfectPixel
Copy link

@icfantv merely pointing out the origin of the bug, that this one is caused by another bugfix is unfortunate. Any ideas for a robust solution that neither breaks desktops nor mobile devices?

@icfantv
Copy link
Contributor

icfantv commented Oct 26, 2015

@PerfectPixel, I'm still not convinced this is a bug in our library.

If I had a solution, I'd have mentioned it - I wouldn't hold out on you guys. :-)

@PerfectPixel
Copy link

@icfantv, I agree and I love your library. I guess it's an issue with Safari. Setting that cursor property works for me so far.

@PerfectPixel
Copy link

plunker: http://plnkr.co/edit/4E1YiqqgMsUWiu0CBDoD?p=preview
For some odd reason, the css cursor property does not work here. I give up and head to bed, happy hunting ;-)

@RobJacobs
Copy link
Contributor

Probably related to #3687

@icfantv
Copy link
Contributor

icfantv commented Oct 27, 2015

@gae123, that change from <span> to <a> is interesting because <span> is not a focusable element by default. You can get around this by adding tabindex="-1" to prevent it from also being tabbable (not an issue on mobile, however). What were the event triggers you were using?

@gae123
Copy link
Author

gae123 commented Oct 27, 2015

@icfantv I am using whatever is the default. My typical tooltip is inside a directive template and after I replaced <span> with <a> looks like:

<a tooltip-html="swNgTooltipHtml"
    tooltip-append-to-body="true"
    tooltip-placement="right"><i class="fa fa-question-circle"></i></a>

@RobJacobs
Copy link
Contributor

@icfantv @gae123 I want to make sure I understand the issue clearly - this is related to touch events only, mouse events are working fine. Please correct me if I am wrong.

Going on the assumption that we are trouble shooting touch events, the default triggers on a tooltip are mouseenter, mouseleave. The touch equivalent are touchstart and touchend. So we would need something like so:

element[0].addEventListener('mouseenter', showTooltipBind);
element[0].addEventListener('touchstart', showTooltipBind);

element[0].addEventListener('mouseleave', hideTooltipBind);
element[0].addEventListener('touchend', hideTooltipBind);

to support this properly (tested on an iPad v9 iOS). This approach works on any element and does not need a tabindex="-1" There are ways to translate touch events to mouse events, touchpunch is one which I re-wrote to remove jQuery dependencies.

_Disclaimer_
I am not advocating for adding this to the angular-ui-library.

function touchToMouseEvents {
  if (angular.isUndefined($window.ontouchstart)) {
    return;
  }

  var evts = {
    'touchstart': 'mousedown',
    'touchmove': 'mousemove',
    'touchend': 'mouseup',
    'touchcancel': 'mouseup'
  };

  angular.forEach(evts, function(val, key) {
    $window.document.addEventListener(
      key,
      function(evt) {
        var e = evt.originalEvent || evt;
        if (e.touches.length > 1) {
          return;
        }

        var touchEvent = e.changedTouches[0];
        var mouseEvent = $window.document.createEvent('MouseEvent');
        // Preventing event kills scrolling
        //evt.preventDefault();
        mouseEvent.initMouseEvent(
          val,                  // type
          true,                 // bubbles
          true,                 // cancelable
          window,               // view
          1,                    // detail
          touchEvent.screenX,   // screenX
          touchEvent.screenY,   // screenY
          touchEvent.clientX,   // clientX
          touchEvent.clientY,   // clientY
          false,                // ctrlKey
          false,                // altKey
          false,                // shiftKey
          false,                // metaKey
          0,                    // button
          null                  // relatedTarget
        );
        touchEvent.target.dispatchEvent(mouseEvent);
      },
      true);
  });
};

I have not researched why using the jQuery/jqLite 'on' method works, but I suspect they may be doing something similar and it only works for the mouseenter. My testing shows the tooltip is not getting dismissed with the 'on' method.

@gae123
Copy link
Author

gae123 commented Oct 27, 2015

@RobJacobs on a touch platform you want a tap on the element with the tooltip attributes to open the tooltip. However, at that point the finger most likely covers part of the tooltip. So the user should be able to take the finger off the screen while the tooltip is still on. Then (1) either on a timeout or (2) when the user taps the tooltip or somewhere else in the screen again the tooltip goes away. For now, something close to (2) seems to be working when using <a> and this is an OK workaround.

@RobJacobs
Copy link
Contributor

There is the tooltip-popup-close-delay. Tooltips on a touch device are a losing endeavor IMO...

@wesleycho
Copy link
Contributor

Agreed with @RobJacobs - tooltips don't make sense on mobile.

@gae123
Copy link
Author

gae123 commented Oct 28, 2015

@wesleycho let's leave it up to the UX experts to decide that and not open that can of worms here. The focus of this issue should be fixing the regression introduced in 0.13.3 and make the behavior again the same as it is in bootstrap 3 that this library tracks

@wesleycho
Copy link
Contributor

When it affects technical decisions, we have to take a stance - that fact alone makes this a low priority issue given that there are workarounds for (questionable) requested behavior, including creating custom triggers. In addition, I just spoke to a UX professional and he agreed with me 100% on this.

Personally, I'd think what the heck is (whoever is speccing/planning a product) doing if I had to interact with a tooltip on mobile - it makes absolutely no sense in a mobile UI, and makes no sense from a user perspective.

@gae123
Copy link
Author

gae123 commented Oct 28, 2015

@wesleycho this is a regression of something that was working for a very long time and good software is software without regressions. IMHO the rest of the argument is irrelevant. I have a work around for now and I am OK but I want to make sure this is tested as well.

@wesleycho
Copy link
Contributor

And the maintainers (at least 4 of us so far) are in universal agreement so far that we should not officially support this, and any prior support was incidental. That much is very relevant.

@PerfectPixel
Copy link

A note for those how absolutely must have this:
Add mouseover / mouseout to the triggers if the mouseenter trigger is used. jQuery substitutes mouseover for mouseenter. Mouseover / mouseout do not fire events for disabled elements (seems like mozilla recently resolved this 12 year old bug) but they do fire on all elements on iOS Safari.

@BonzaiThePenguin
Copy link

Agreed with @RobJacobs - tooltips don't make sense on mobile.

Tooltips have always been mapped to touch-and-hold on mobile and it makes perfect sense. Try clicking on the "switch tabs" button in Chrome, for example. Once a tooltip for a button is displayed, the button action won't trigger when you let go with your finger.

Here are the guidelines for Android and mobile Safari mentioning this behavior:

https://material.io/guidelines/components/tooltips.html#tooltips-interaction

A tooltip is triggered by tapping and holding an item. Keep the tooltip displayed as long as the user continues to hold the element.

https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/CreatingContentforSafarioniPhone/CreatingContentforSafarioniPhone.html#//apple_ref/doc/uid/TP40006482-SW1

Similar to hover styles, tooltips are not displayed unless the user touches and holds a clickable element with a tooltip.

It's certainly harder to implement consistently on mobile since touch-and-hold is also an actionable gesture for things like rearranging list items or opening links in new tabs, but the onus is on the developer to only use tooltips where they make sense, like buttons.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants