7

How can I detect if the device is ONLY tablet? This script below is not working properly.

var ua = navigator.userAgent, tablet = /Tablet|iPad/i.test(ua);
alert("Tablet? " + tablet);

I don't want check if is mobile and use else to show tablet. I want only a function to confirm if is tablet. How can I do that? Thanks

Strepk
  • 111
  • 1
  • 2
  • 6

2 Answers2

21

If you want to just use vanilla javascript you can use the navigator API

const userAgent = navigator.userAgent.toLowerCase();
const isTablet = /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/.test(userAgent);
console.log(isTablet)

https://developer.mozilla.org/en-US/docs/Web/API/Window/navigator

But i'd suggest using a librray such as wurfl.io

https://web.wurfl.io/#wurfl-js

if (WURFL.is_mobile === true && WURFL.form_factor === "Tablet") {
    // targetSmartPhoneDevices();
}

Joe Warner
  • 3,335
  • 1
  • 14
  • 41
  • 4
    There are plenty of ways to spoof user agents, like [this extension](https://chrome.google.com/webstore/detail/user-agent-switcher-for-c/djflhoibgkdhkhhcedjiklpkjnoahfmg?hl=en) for example. `navigator.userAgent` is essentially worthless as it's untrustworthy. Better to check device width with CSS media queries for dynamic styling, or modernizr for support if using modern or experimental APIs with fallbacks for legacy browsers. And OP explicitly stated they do not want to use external libraries. – Patrick Roberts May 06 '18 at 01:54
  • I know i'd suggest using a library but OP said he doesnt want to if you dont want to use a library and want a light solution i don't think it can get better than this? – Joe Warner May 06 '18 at 01:56
  • 1
    just FYI, navigator.userAgent solution does not detect new ipad pro ;) But for the most of the tablets forks ok for me. – strix25 Jul 02 '20 at 09:33
  • 3
    Old comments, but just want to argue against @PatrickRoberts assertion that userAgent is "worthless". The fact that is can be spoofed is irrelevant. It is a way of informing which useragent I would like to be represented for. In other words, spoofing is a feature, not a bug. If a user wants to see a desktop version on a mobile, then it should be up to them. If device type trustworthiness is a problem for you, then I would suspect design flaws in your project. – Matt Way Jun 01 '21 at 05:29
  • @MattWay if you're checking the user agent to distinguish desktop from mobile users for styling purposes then your project is already flawed. There are CSS media queries specifically for that purpose. – Patrick Roberts Jun 01 '21 at 13:03
  • @PatrickRoberts I agree (but I don't think styling is mentioned anywhere in this thread). There are plenty of other use cases for the user agent. – Matt Way Jun 02 '21 at 04:26
  • @PatrickRoberts if a user wants to spoof their user agent string to break the website then you should let them and not worry about it. 99.9% of users won't do this, and the users that do do it are literally breaking their browser on purpose, so why in the world should the developer make an effort to accommodate them?. User agent strings are completely fine to use and are a useful tool. – ICW Jan 26 '22 at 17:56
  • @ICW a better question would be why in the world a developer would make an effort to misuse an API for feature detection when there are better purpose-built APIs made available for the specific purpose of feature detection? The point is that the only valid reason to distinguish a tablet from another device is to treat it differently. Why treat it differently? Render a different UI because of screen space (again, see CSS media queries), or to enable touch events (which you should test for directly). There is no good reason to smoke test for features indirectly by checking the user agent string. – Patrick Roberts Jan 27 '22 at 03:40
  • @ICW and where on earth did you come up with that statistic? I suspect it would be inappropriate for me to guess. – Patrick Roberts Jan 27 '22 at 03:41
  • 1
    Hey fellas, current answer was updated in 2019 last, since that time we have news from apple, new iPadOS returns MacOS type userAgent so it won't work anymore, I think, from now we can test on touch availability only. – K. Yurii Feb 14 '22 at 23:41
2

Here is an example of working script :

/**
 * @constructor
 */
function DeviceMeta() {}

DeviceMeta.prototype.name = 'DeviceMeta';

/**
 * @return {boolean}
 * @throws {Error}
 */
DeviceMeta.isMobile = function () {
    var userAgent = this.getUserAgent();

    var userAgentPart = userAgent.substr(0, 4);

    return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(userAgent)
        || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(userAgentPart);
};

/**
 * @return {boolean}
 * @throws {Error}
 */
DeviceMeta.isMobileOrTablet = function () {
    var userAgent = this.getUserAgent();

    var userAgentPart = userAgent.substr(0, 4);

    return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(userAgent)
        || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(userAgentPart);
};

/**
 * @return {string|null}
 * @throws {Error}
 */
DeviceMeta.getUserAgent = function () {
    var userAgent = navigator.userAgent
        || navigator.vendor
        || window.opera
        || null;
    
    if (!userAgent)
        throw new Error('Failed to look for user agent information.');

    return userAgent;
};
B. Bohdan
  • 480
  • 4
  • 12