- 1 :
/**
- 2 :
* @file browser.js
- 3 :
* @module browser
- 4 :
*/
- 5 :
import * as Dom from './dom';
- 6 :
import window from 'global/window';
- 7 :
- 8 :
const USER_AGENT = window.navigator && window.navigator.userAgent || '';
- 9 :
const webkitVersionMap = (/AppleWebKit\/([\d.]+)/i).exec(USER_AGENT);
- 10 :
const appleWebkitVersion = webkitVersionMap ? parseFloat(webkitVersionMap.pop()) : null;
- 11 :
- 12 :
/**
- 13 :
* Whether or not this device is an iPod.
- 14 :
*
- 15 :
* @static
- 16 :
* @const
- 17 :
* @type {Boolean}
- 18 :
*/
- 19 :
export const IS_IPOD = (/iPod/i).test(USER_AGENT);
- 20 :
- 21 :
/**
- 22 :
* The detected iOS version - or `null`.
- 23 :
*
- 24 :
* @static
- 25 :
* @const
- 26 :
* @type {string|null}
- 27 :
*/
- 28 :
export const IOS_VERSION = (function() {
- 29 :
const match = USER_AGENT.match(/OS (\d+)_/i);
- 30 :
- 31 :
if (match && match[1]) {
- 32 :
return match[1];
- 33 :
}
- 34 :
return null;
- 35 :
}());
- 36 :
- 37 :
/**
- 38 :
* Whether or not this is an Android device.
- 39 :
*
- 40 :
* @static
- 41 :
* @const
- 42 :
* @type {Boolean}
- 43 :
*/
- 44 :
export const IS_ANDROID = (/Android/i).test(USER_AGENT);
- 45 :
- 46 :
/**
- 47 :
* The detected Android version - or `null`.
- 48 :
*
- 49 :
* @static
- 50 :
* @const
- 51 :
* @type {number|string|null}
- 52 :
*/
- 53 :
export const ANDROID_VERSION = (function() {
- 54 :
// This matches Android Major.Minor.Patch versions
- 55 :
// ANDROID_VERSION is Major.Minor as a Number, if Minor isn't available, then only Major is returned
- 56 :
const match = USER_AGENT.match(/Android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i);
- 57 :
- 58 :
if (!match) {
- 59 :
return null;
- 60 :
}
- 61 :
- 62 :
const major = match[1] && parseFloat(match[1]);
- 63 :
const minor = match[2] && parseFloat(match[2]);
- 64 :
- 65 :
if (major && minor) {
- 66 :
return parseFloat(match[1] + '.' + match[2]);
- 67 :
} else if (major) {
- 68 :
return major;
- 69 :
}
- 70 :
return null;
- 71 :
}());
- 72 :
- 73 :
/**
- 74 :
* Whether or not this is a native Android browser.
- 75 :
*
- 76 :
* @static
- 77 :
* @const
- 78 :
* @type {Boolean}
- 79 :
*/
- 80 :
export const IS_NATIVE_ANDROID = IS_ANDROID && ANDROID_VERSION < 5 && appleWebkitVersion < 537;
- 81 :
- 82 :
/**
- 83 :
* Whether or not this is Mozilla Firefox.
- 84 :
*
- 85 :
* @static
- 86 :
* @const
- 87 :
* @type {Boolean}
- 88 :
*/
- 89 :
export const IS_FIREFOX = (/Firefox/i).test(USER_AGENT);
- 90 :
- 91 :
/**
- 92 :
* Whether or not this is Microsoft Edge.
- 93 :
*
- 94 :
* @static
- 95 :
* @const
- 96 :
* @type {Boolean}
- 97 :
*/
- 98 :
export const IS_EDGE = (/Edg/i).test(USER_AGENT);
- 99 :
- 100 :
/**
- 101 :
* Whether or not this is Google Chrome.
- 102 :
*
- 103 :
* This will also be `true` for Chrome on iOS, which will have different support
- 104 :
* as it is actually Safari under the hood.
- 105 :
*
- 106 :
* @static
- 107 :
* @const
- 108 :
* @type {Boolean}
- 109 :
*/
- 110 :
export const IS_CHROME = !IS_EDGE && ((/Chrome/i).test(USER_AGENT) || (/CriOS/i).test(USER_AGENT));
- 111 :
- 112 :
/**
- 113 :
* The detected Google Chrome version - or `null`.
- 114 :
*
- 115 :
* @static
- 116 :
* @const
- 117 :
* @type {number|null}
- 118 :
*/
- 119 :
export const CHROME_VERSION = (function() {
- 120 :
const match = USER_AGENT.match(/(Chrome|CriOS)\/(\d+)/);
- 121 :
- 122 :
if (match && match[2]) {
- 123 :
return parseFloat(match[2]);
- 124 :
}
- 125 :
return null;
- 126 :
}());
- 127 :
- 128 :
/**
- 129 :
* The detected Internet Explorer version - or `null`.
- 130 :
*
- 131 :
* @static
- 132 :
* @const
- 133 :
* @type {number|null}
- 134 :
*/
- 135 :
export const IE_VERSION = (function() {
- 136 :
const result = (/MSIE\s(\d+)\.\d/).exec(USER_AGENT);
- 137 :
let version = result && parseFloat(result[1]);
- 138 :
- 139 :
if (!version && (/Trident\/7.0/i).test(USER_AGENT) && (/rv:11.0/).test(USER_AGENT)) {
- 140 :
// IE 11 has a different user agent string than other IE versions
- 141 :
version = 11.0;
- 142 :
}
- 143 :
- 144 :
return version;
- 145 :
}());
- 146 :
- 147 :
/**
- 148 :
* Whether or not this is desktop Safari.
- 149 :
*
- 150 :
* @static
- 151 :
* @const
- 152 :
* @type {Boolean}
- 153 :
*/
- 154 :
export const IS_SAFARI = (/Safari/i).test(USER_AGENT) && !IS_CHROME && !IS_ANDROID && !IS_EDGE;
- 155 :
- 156 :
/**
- 157 :
* Whether or not this is a Windows machine.
- 158 :
*
- 159 :
* @static
- 160 :
* @const
- 161 :
* @type {Boolean}
- 162 :
*/
- 163 :
export const IS_WINDOWS = (/Windows/i).test(USER_AGENT);
- 164 :
- 165 :
/**
- 166 :
* Whether or not this device is touch-enabled.
- 167 :
*
- 168 :
* @static
- 169 :
* @const
- 170 :
* @type {Boolean}
- 171 :
*/
- 172 :
export const TOUCH_ENABLED = Boolean(Dom.isReal() && (
- 173 :
'ontouchstart' in window ||
- 174 :
window.navigator.maxTouchPoints ||
- 175 :
window.DocumentTouch && window.document instanceof window.DocumentTouch));
- 176 :
- 177 :
/**
- 178 :
* Whether or not this device is an iPad.
- 179 :
*
- 180 :
* @static
- 181 :
* @const
- 182 :
* @type {Boolean}
- 183 :
*/
- 184 :
export const IS_IPAD = (/iPad/i).test(USER_AGENT) ||
- 185 :
(IS_SAFARI && TOUCH_ENABLED && !(/iPhone/i).test(USER_AGENT));
- 186 :
- 187 :
/**
- 188 :
* Whether or not this device is an iPhone.
- 189 :
*
- 190 :
* @static
- 191 :
* @const
- 192 :
* @type {Boolean}
- 193 :
*/
- 194 :
// The Facebook app's UIWebView identifies as both an iPhone and iPad, so
- 195 :
// to identify iPhones, we need to exclude iPads.
- 196 :
// http://artsy.github.io/blog/2012/10/18/the-perils-of-ios-user-agent-sniffing/
- 197 :
export const IS_IPHONE = (/iPhone/i).test(USER_AGENT) && !IS_IPAD;
- 198 :
- 199 :
/**
- 200 :
* Whether or not this is an iOS device.
- 201 :
*
- 202 :
* @static
- 203 :
* @const
- 204 :
* @type {Boolean}
- 205 :
*/
- 206 :
export const IS_IOS = IS_IPHONE || IS_IPAD || IS_IPOD;
- 207 :
- 208 :
/**
- 209 :
* Whether or not this is any flavor of Safari - including iOS.
- 210 :
*
- 211 :
* @static
- 212 :
* @const
- 213 :
* @type {Boolean}
- 214 :
*/
- 215 :
export const IS_ANY_SAFARI = (IS_SAFARI || IS_IOS) && !IS_CHROME;