isMobile.js 4.18 KB
Newer Older
liang ce committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
(function(global) {
  var apple_phone = /iPhone/i,
    apple_ipod = /iPod/i,
    apple_tablet = /iPad/i,
    android_phone = /\bAndroid(?:.+)Mobile\b/i, // Match 'Android' AND 'Mobile'
    android_tablet = /Android/i,
    amazon_phone = /\bAndroid(?:.+)SD4930UR\b/i,
    amazon_tablet = /\bAndroid(?:.+)(?:KF[A-Z]{2,4})\b/i,
    windows_phone = /Windows Phone/i,
    windows_tablet = /\bWindows(?:.+)ARM\b/i, // Match 'Windows' AND 'ARM'
    other_blackberry = /BlackBerry/i,
    other_blackberry_10 = /BB10/i,
    other_opera = /Opera Mini/i,
    other_chrome = /\b(CriOS|Chrome)(?:.+)Mobile/i,
    other_firefox = /\Mobile(?:.+)Firefox\b/i; // Match 'Mobile' AND 'Firefox'

  function match(regex, userAgent) {
    return regex.test(userAgent);
  }

  function isMobile(userAgent) {
    var ua =
      userAgent ||
      (typeof navigator !== 'undefined' ? navigator.userAgent : '');

    // Facebook mobile app's integrated browser adds a bunch of strings that
    // match everything. Strip it out if it exists.
    var tmp = ua.split('[FBAN');
    if (typeof tmp[1] !== 'undefined') {
      ua = tmp[0];
    }

    // Twitter mobile app's integrated browser on iPad adds a "Twitter for
    // iPhone" string. Same probably happens on other tablet platforms.
    // This will confuse detection so strip it out if it exists.
    tmp = ua.split('Twitter');
    if (typeof tmp[1] !== 'undefined') {
      ua = tmp[0];
    }

    var result = {
      apple: {
        phone: match(apple_phone, ua) && !match(windows_phone, ua),
        ipod: match(apple_ipod, ua),
        tablet:
          !match(apple_phone, ua) &&
          match(apple_tablet, ua) &&
          !match(windows_phone, ua),
        device:
          (match(apple_phone, ua) ||
            match(apple_ipod, ua) ||
            match(apple_tablet, ua)) &&
          !match(windows_phone, ua)
      },
      amazon: {
        phone: match(amazon_phone, ua),
        tablet: !match(amazon_phone, ua) && match(amazon_tablet, ua),
        device: match(amazon_phone, ua) || match(amazon_tablet, ua)
      },
      android: {
        phone:
          (!match(windows_phone, ua) && match(amazon_phone, ua)) ||
          (!match(windows_phone, ua) && match(android_phone, ua)),
        tablet:
          !match(windows_phone, ua) &&
          !match(amazon_phone, ua) &&
          !match(android_phone, ua) &&
          (match(amazon_tablet, ua) || match(android_tablet, ua)),
        device:
          (!match(windows_phone, ua) &&
            (match(amazon_phone, ua) ||
              match(amazon_tablet, ua) ||
              match(android_phone, ua) ||
              match(android_tablet, ua))) ||
          match(/\bokhttp\b/i, ua)
      },
      windows: {
        phone: match(windows_phone, ua),
        tablet: match(windows_tablet, ua),
        device: match(windows_phone, ua) || match(windows_tablet, ua)
      },
      other: {
        blackberry: match(other_blackberry, ua),
        blackberry10: match(other_blackberry_10, ua),
        opera: match(other_opera, ua),
        firefox: match(other_firefox, ua),
        chrome: match(other_chrome, ua),
        device:
          match(other_blackberry, ua) ||
          match(other_blackberry_10, ua) ||
          match(other_opera, ua) ||
          match(other_firefox, ua) ||
          match(other_chrome, ua)
      }
    };
    (result.any =
      result.apple.device ||
      result.android.device ||
      result.windows.device ||
      result.other.device),
      // excludes 'other' devices and ipods, targeting touchscreen phones
      (result.phone =
        result.apple.phone || result.android.phone || result.windows.phone),
      (result.tablet =
        result.apple.tablet || result.android.tablet || result.windows.tablet);

    return result;
  }

  if (
    typeof module !== 'undefined' &&
    module.exports &&
    typeof window === 'undefined'
  ) {
    // Node.js
    module.exports = isMobile;
  } else if (
    typeof module !== 'undefined' &&
    module.exports &&
    typeof window !== 'undefined'
  ) {
    // Browserify
    module.exports = isMobile();
  } else if (typeof define === 'function' && define.amd) {
    // AMD
    define([], (global.isMobile = isMobile()));
  } else {
    global.isMobile = isMobile();
  }
})(this);