Detecting touch screen devices with Javascript
Asked Answered
E

16

132

In Javascript/jQuery, how can I detect if the client device has a mouse?

I've got a site that slides up a little info panel when the user hovers their mouse over an item. I'm using jQuery.hoverIntent to detect the hover, but this obviously doesn't work on touchscreen devices like iPhone/iPad/Android. So on those devices I'd like to revert to tap to show the info panel.

Expellant answered 20/10, 2010 at 4:44 Comment(5)
Why can't you do both? Is the tap functionality undesirable in non-touchscreen devices?Hurlee
Since some newer devices don't support :hover, it's probably better (when coding one stylesheet for multiple devices) to use :hover for purely cosmetic purposes.Hemminger
@empraptor: good point - yes I could do that. However... we were also thinking of always showing the panel on touchscreen devices - in which case I would need to be able to detect support.Expellant
If you can always show the panel on touchscreen devices, couldn't you show it on other devices too? How large is the panel and why is it desirable to show it only on hover/tap?Hurlee
possible duplicate of What's the best way to detect a 'touch screen' device using JavaScript?Ephraimite
D
12

+1 for doing hover and click both. One other way could be using CSS media queries and using some styles only for smaller screens / mobile devices, which are the ones most likely to have touch / tap functionality. So if you have some specific styles via CSS, and from jQuery you check those elements for the mobile device style properties you could hook into them to write you mobile specific code.

See here: http://www.forabeautifulweb.com/blog/about/hardboiled_css3_media_queries/

Domineca answered 20/10, 2010 at 4:53 Comment(2)
Good solution, you could probably do something like a hover check with a one() bind so it only fires the first time around.Shuttlecock
The problem is that if you target by screen width then when you rotate your device (let's take iphone 6+ 736x414) it won't have the same style. So not the best solution :/Guayule
I
268
var isTouchDevice = 'ontouchstart' in document.documentElement;

Note: Just because a device supports touch events doesn't necessarily mean that it is exclusively a touch screen device. Many devices (such as my Asus Zenbook) support both click and touch events, even when they doen't have any actual touch input mechanisms. When designing for touch support, always include click event support and never assume any device is exclusively one or the other.

Ichabod answered 22/6, 2011 at 23:57 Comment(9)
As described in the Modernizr docs, this only detects browser capability, not device capability... you'll get a false positive result on devices with no touch input running a touch-capable browser. I don't know of a way to detect device touch capability natively, without just waiting for a touch event to occur.Pinon
In order to also detect IE 10 touch I'm using: (window.navigator.msMaxTouchPoints || ('ontouchstart' in document.documentElement));Ultraism
Returns false positives on Win 8 PC with FF 23 and Chrome 28. Is this always the case or is it because I've once had a touch screen attached to this computer - probably before installing FF and Chrome - but not anymore? Finally Alexander Kellett's method manages to return a false positive on IE10 on the same PC. I think that the answer needs to be improved and that Stu Cox's comment is important.Cernuous
'ontouchstart' in document.documentElement incorrectly returns true on BlackBerry 9300Barrator
@typhon if the software (Win 8, modern browsers) supports touch, this will always be true – even if you're on hardware (desktop, standard monitor, mouse and keyboard) that doesn't support touch. Therefore this solution is out of date.Sunshade
funnyItsNotCamelCaseAsJsIsThroughout. I mean people will now need to copy, paste AND edit the code.. . :)Pollaiuolo
The use of this ugly hack is actually what breaks certain browsers, and is the reason clicking the tinyscrollbar is broken in Ubuntu 14.x Firefox: bugs.launchpad.net/ubuntu/+source/firefox/+bug/1477815Caddric
I've seen similar bugs in projects I've worked on professionally. This is not an ugly hack, it's just a simple feature detection that can easily be misused. I added a note to the original answer warning about the pitfalls of assuming mutual exclusivity of device input mechanisms. The bug you linked is a product of the assumption that devices can't have multiple input mechanisms which they often do.Ichabod
very good but not perfect for some weird Windows cases. (Chrome)Unduly
T
20

Found testing for window.Touch didn't work on android but this does:

function is_touch_device() {
  return !!('ontouchstart' in window);
}

See article: What's the best way to detect a 'touch screen' device using JavaScript?

Truditrudie answered 8/6, 2012 at 18:16 Comment(1)
This does detect touch screens but be careful because it returns TRUE for laptops with touch screens too. This could be a problem if you are trying to distinguish if the user is from phone/tablet OR computer/laptop because for laptops with touch screen it returns TRUE.Hilel
D
12

+1 for doing hover and click both. One other way could be using CSS media queries and using some styles only for smaller screens / mobile devices, which are the ones most likely to have touch / tap functionality. So if you have some specific styles via CSS, and from jQuery you check those elements for the mobile device style properties you could hook into them to write you mobile specific code.

See here: http://www.forabeautifulweb.com/blog/about/hardboiled_css3_media_queries/

Domineca answered 20/10, 2010 at 4:53 Comment(2)
Good solution, you could probably do something like a hover check with a one() bind so it only fires the first time around.Shuttlecock
The problem is that if you target by screen width then when you rotate your device (let's take iphone 6+ 736x414) it won't have the same style. So not the best solution :/Guayule
C
10
if ("ontouchstart" in window || navigator.msMaxTouchPoints) {
    isTouch = true;
} else {
    isTouch = false;
}

Works every where !!

Cottony answered 18/12, 2013 at 8:50 Comment(2)
And what does that have to do with a mouse? (the actual question)Scullery
It would be simpler to do isTouch = "ontouchstart" in window || navigator.msMaxTouchPoints;Dorren
P
8
return (('ontouchstart' in window)
      || (navigator.maxTouchPoints > 0)
      || (navigator.msMaxTouchPoints > 0));

Reason for using maxTouchPoints alongwith msMaxTouchPoints:

Microsoft has stated that starting with Internet Explorer 11, Microsoft vendor prefixed version of this property (msMaxTouchPoints) may be removed and recommends using maxTouchPoints instead.

Source : http://ctrlq.org/code/19616-detect-touch-screen-javascript

Piety answered 9/11, 2015 at 7:39 Comment(1)
this worked and worked in google chrome developer tools simulate device thank youRoundly
E
4

I use:

if(jQuery.support.touch){
    alert('Touch enabled');
}

in jQuery mobile 1.0.1

Eisenstein answered 19/3, 2012 at 14:16 Comment(1)
jQuery recommends against using jQuery.support in favor of Modernizr (modernizr.com): reference - api.jquery.com/jQuery.support -Frontlet
V
4

Google Chrome seems to return false positives on this one:

var isTouch = 'ontouchstart' in document.documentElement;

I suppose it has something to do with its ability to "emulate touch events" (F12 -> settings at lower right corner -> "overrides" tab -> last checkbox). I know it's turned off by default but that's what I connect the change in results with (the "in" method used to work in Chrome). However, this seems to be working, as far as I have tested:

var isTouch = !!("undefined" != typeof document.documentElement.ontouchstart);

All browsers I've run that code on state the typeof is "object" but I feel more certain knowing that it's whatever but undefined :-)

Tested on IE7, IE8, IE9, IE10, Chrome 23.0.1271.64, Chrome for iPad 21.0.1180.80 and iPad Safari. It would be cool if someone made some more tests and shared the results.

Vegetative answered 25/11, 2012 at 0:14 Comment(3)
Both methods return false positives on Win 8 PC with FF 23 and Chrome 28. Is this always the case or is it because I've once had a touch screen attached to this computer - probably before installing FF and Chrome - but not anymore? I don't have "emulate touch events" option set.Cernuous
Uh, it's always a struggle with new hardware. Browsers have to work with the OS abstraction layers... which don't always implement everything... in short, with JS you have to rely on the browser :) There is never an universal way.Vegetative
Both of those return true on Ubuntu Firefox on a non-touch laptop.Caddric
S
4

Wrote this for one of my sites and probably is the most foolproof solution. Especially since even Modernizr can get false positives on touch detection.

If you're using jQuery

$(window).one({
  mouseover : function(){
    Modernizr.touch = false; // Add this line if you have Modernizr
    $('html').removeClass('touch').addClass('mouse');
  } 
});

or just pure JS...

window.onmouseover = function(){ 
    window.onmouseover = null;
    document.getElementsByTagName("html")[0].className += " mouse";
}
Shuttlecock answered 23/1, 2013 at 4:25 Comment(4)
Be careful though: at least iPads throw onmouseovers tooObvert
And people using IE on a Windows tablet may want to use both touch and mouse.Kaohsiung
This post was made before the Windows Tablet came into existence.Shuttlecock
@s427 - Fecking IE... just do a check for IE8. I don't think there are any mobile devices with <= IE8.Shuttlecock
E
4

For my first post/comment: We all know that 'touchstart' is triggered before click. We also know that when user open your page he or she will: 1) move the mouse 2) click 3) touch the screen (for scrolling, or ... :) )

Let's try something :

//--> Start: jQuery

var hasTouchCapabilities = 'ontouchstart' in window && (navigator.maxTouchPoints || navigator.msMaxTouchPoints);
var isTouchDevice = hasTouchCapabilities ? 'maybe':'nope';

//attach a once called event handler to window

$(window).one('touchstart mousemove click',function(e){

    if ( isTouchDevice === 'maybe' && e.type === 'touchstart' )
        isTouchDevice = 'yes';
});

//<-- End: jQuery

Have a nice day!

Ephemeris answered 13/7, 2016 at 15:5 Comment(0)
D
3

I have tested following code mentioned above in the discussion

 function is_touch_device() {
    return !!('ontouchstart' in window);
 }

works on android Mozilla, chrome, Opera, android default browser and safari on iphone... all positive ...

seems solid for me :)

Declaration answered 8/4, 2014 at 0:22 Comment(2)
Super simple and works fine for me. Tested on Android (old Galaxy Note) and with emulators (Chrome) and on iPad.Fortification
Returns a false positive for me on Chrome.Maybellmaybelle
L
3

A helpful blog post on the subject, linked to from within the Modernizr source for detecting touch events. Conclusion: it's not possible to reliably detect touchscreen devices from Javascript.

http://www.stucox.com/blog/you-cant-detect-a-touchscreen/

Lanny answered 25/8, 2014 at 3:1 Comment(0)
A
2

This works for me:

function isTouchDevice(){
    return true == ("ontouchstart" in window || window.DocumentTouch && document instanceof DocumentTouch);
}
Alternation answered 11/11, 2012 at 12:6 Comment(6)
how many platforms, browsere, OS', devices have you tested on?Undermanned
FF, Chrome, Safari on Android and iOS (iPad)Alternation
Nice enough. I just tested on desktop and got a lot of "undefined" which makes the IF structure a bit hacky. If you ajust your return value just a little, like this: return true == ("ontouchstart" in window || window.DocumentTouch && document instanceof DocumentTouch); Then you have true or false :-)Undermanned
In Chrome, "ontouchstart" in window is true on my PC without a touch screen, so this does not work. As remarked earlier, this tests if the browser is touch-capable. Also, true == doesn't do anything and should be omitted.Integumentary
When I try this in Chrome with the built in emulator, it will detect touch when it is switched on in the emulator, and will not detect touch when it is switched off. So works fine for me. But: I use the short version by Prasad (below) which does not use the || in Turtletrail's code. And: I don't care if it works for 100% of devices. 99% will do for me.Fortification
Why are you comparing a boolean to true? õ.O Just return the boolean or !!bool to make sure it returns booleanJune
S
1

If you use Modernizr, it is very easy to use Modernizr.touch as mentioned earlier.

However, I prefer using a combination of Modernizr.touch and user agent testing, just to be safe.

var deviceAgent = navigator.userAgent.toLowerCase();

var isTouchDevice = Modernizr.touch || 
(deviceAgent.match(/(iphone|ipod|ipad)/) ||
deviceAgent.match(/(android)/)  || 
deviceAgent.match(/(iemobile)/) || 
deviceAgent.match(/iphone/i) || 
deviceAgent.match(/ipad/i) || 
deviceAgent.match(/ipod/i) || 
deviceAgent.match(/blackberry/i) || 
deviceAgent.match(/bada/i));

if (isTouchDevice) {
        //Do something touchy
    } else {
        //Can't touch this
    }

If you don't use Modernizr, you can simply replace the Modernizr.touch function above with ('ontouchstart' in document.documentElement)

Also note that testing the user agent iemobile will give you broader range of detected Microsoft mobile devices than Windows Phone.

Also see this SO question

Stenophagous answered 26/6, 2013 at 17:38 Comment(3)
Is the same response for 4 questions now... and this is not a solution for the question he is asking.Delatorre
I believe it does answer the question hereStenophagous
it is not the answer but it is a hint i think for whom who want to detect if the device is touchable before user touch itGallegos
M
1

In jQuery Mobile you can simply do:

$.support.touch

Don't know why this is so undocumented.. but it is crossbrowser safe (latest 2 versions of current browsers).

Mononucleosis answered 20/4, 2016 at 7:35 Comment(0)
Y
0

As already mentioned, a device may support both mouse and touch input. Very often, the question is not "what is supported" but "what is currently used".

For this case, you can simply register mouse events (including the hover listener) and touch events alike.

element.addEventListener('touchstart',onTouchStartCallback,false);

element.addEventListener('onmousedown',onMouseDownCallback,false);

...

JavaScript should automatically call the correct listener based on user input. So, in case of a touch event, onTouchStartCallback will be fired, emulating your hover code.

Note that a touch may fire both kinds of listeners, touch and mouse. However, the touch listener goes first and can prevent subsequent mouse listeners from firing by calling event.preventDefault().

function onTouchStartCallback(ev) {
    // Call preventDefault() to prevent any further handling
    ev.preventDefault();
    your code...
}

Further reading here.

Yugoslavia answered 9/7, 2020 at 7:34 Comment(0)
S
-3

For iPad development I am using:

  if (window.Touch)
  {
    alert("touchy touchy");
  }
  else
  {
    alert("no touchy touchy");
  }

I can then selectively bind to the touch based events (eg ontouchstart) or mouse based events (eg onmousedown). I haven't yet tested on android.

Stabilize answered 22/10, 2010 at 12:47 Comment(2)
This doesn't work with Opera Mobile 10 or Internet Explorer Mobile 6 (Windows Mobile 6.5).Sulfide
bad crossbrowser/cross OS/cross platform advice.Undermanned

© 2022 - 2024 — McMap. All rights reserved.