1!function (root, name, definition) { 2 if (typeof module != 'undefined' && module.exports) module.exports = definition() 3 else if (typeof define == 'function' && define.amd) define(name, definition) 4 else root[name] = definition() 5}(this, 'bowser', function () { 6 /** 7 * See useragents.js for examples of navigator.userAgent 8 */ 9 10 var t = true 11 12 function detect(ua) { 13 14 function getFirstMatch(regex) { 15 var match = ua.match(regex); 16 return (match && match.length > 1 && match[1]) || ''; 17 } 18 19 function getSecondMatch(regex) { 20 var match = ua.match(regex); 21 return (match && match.length > 1 && match[2]) || ''; 22 } 23 24 var iosdevice = getFirstMatch(/(ipod|iphone|ipad)/i).toLowerCase() 25 , likeAndroid = /like android/i.test(ua) 26 , android = !likeAndroid && /android/i.test(ua) 27 , nexusMobile = /nexus\s*[0-6]\s*/i.test(ua) 28 , nexusTablet = !nexusMobile && /nexus\s*[0-9]+/i.test(ua) 29 , chromeos = /CrOS/.test(ua) 30 , silk = /silk/i.test(ua) 31 , sailfish = /sailfish/i.test(ua) 32 , tizen = /tizen/i.test(ua) 33 , webos = /(web|hpw)(o|0)s/i.test(ua) 34 , windowsphone = /windows phone/i.test(ua) 35 , samsungBrowser = /SamsungBrowser/i.test(ua) 36 , windows = !windowsphone && /windows/i.test(ua) 37 , mac = !iosdevice && !silk && /macintosh/i.test(ua) 38 , linux = !android && !sailfish && !tizen && !webos && /linux/i.test(ua) 39 , edgeVersion = getSecondMatch(/edg([ea]|ios)\/(\d+(\.\d+)?)/i) 40 , versionIdentifier = getFirstMatch(/version\/(\d+(\.\d+)?)/i) 41 , tablet = /tablet/i.test(ua) && !/tablet pc/i.test(ua) 42 , mobile = !tablet && /[^-]mobi/i.test(ua) 43 , xbox = /xbox/i.test(ua) 44 , result 45 46 if (/opera/i.test(ua)) { 47 // an old Opera 48 result = { 49 name: 'Opera' 50 , opera: t 51 , version: versionIdentifier || getFirstMatch(/(?:opera|opr|opios)[\s\/](\d+(\.\d+)?)/i) 52 } 53 } else if (/opr\/|opios/i.test(ua)) { 54 // a new Opera 55 result = { 56 name: 'Opera' 57 , opera: t 58 , version: getFirstMatch(/(?:opr|opios)[\s\/](\d+(\.\d+)?)/i) || versionIdentifier 59 } 60 } 61 else if (/SamsungBrowser/i.test(ua)) { 62 result = { 63 name: 'Samsung Internet for Android' 64 , samsungBrowser: t 65 , version: versionIdentifier || getFirstMatch(/(?:SamsungBrowser)[\s\/](\d+(\.\d+)?)/i) 66 } 67 } 68 else if (/Whale/i.test(ua)) { 69 result = { 70 name: 'NAVER Whale browser' 71 , whale: t 72 , version: getFirstMatch(/(?:whale)[\s\/](\d+(?:\.\d+)+)/i) 73 } 74 } 75 else if (/MZBrowser/i.test(ua)) { 76 result = { 77 name: 'MZ Browser' 78 , mzbrowser: t 79 , version: getFirstMatch(/(?:MZBrowser)[\s\/](\d+(?:\.\d+)+)/i) 80 } 81 } 82 else if (/coast/i.test(ua)) { 83 result = { 84 name: 'Opera Coast' 85 , coast: t 86 , version: versionIdentifier || getFirstMatch(/(?:coast)[\s\/](\d+(\.\d+)?)/i) 87 } 88 } 89 else if (/focus/i.test(ua)) { 90 result = { 91 name: 'Focus' 92 , focus: t 93 , version: getFirstMatch(/(?:focus)[\s\/](\d+(?:\.\d+)+)/i) 94 } 95 } 96 else if (/yabrowser/i.test(ua)) { 97 result = { 98 name: 'Yandex Browser' 99 , yandexbrowser: t 100 , version: versionIdentifier || getFirstMatch(/(?:yabrowser)[\s\/](\d+(\.\d+)?)/i) 101 } 102 } 103 else if (/ucbrowser/i.test(ua)) { 104 result = { 105 name: 'UC Browser' 106 , ucbrowser: t 107 , version: getFirstMatch(/(?:ucbrowser)[\s\/](\d+(?:\.\d+)+)/i) 108 } 109 } 110 else if (/mxios/i.test(ua)) { 111 result = { 112 name: 'Maxthon' 113 , maxthon: t 114 , version: getFirstMatch(/(?:mxios)[\s\/](\d+(?:\.\d+)+)/i) 115 } 116 } 117 else if (/epiphany/i.test(ua)) { 118 result = { 119 name: 'Epiphany' 120 , epiphany: t 121 , version: getFirstMatch(/(?:epiphany)[\s\/](\d+(?:\.\d+)+)/i) 122 } 123 } 124 else if (/puffin/i.test(ua)) { 125 result = { 126 name: 'Puffin' 127 , puffin: t 128 , version: getFirstMatch(/(?:puffin)[\s\/](\d+(?:\.\d+)?)/i) 129 } 130 } 131 else if (/sleipnir/i.test(ua)) { 132 result = { 133 name: 'Sleipnir'
134 , sleipnir: t 135 , version: getFirstMatch(/(?:sleipnir)[\s\/](\d+(?:\.\d+)+)/i) 136 } 137 } 138 else if (/k-meleon/i.test(ua)) { 139 result = { 140 name: 'K-Meleon' 141 , kMeleon: t 142 , version: getFirstMatch(/(?:k-meleon)[\s\/](\d+(?:\.\d+)+)/i) 143 } 144 } 145 else if (windowsphone) { 146 result = { 147 name: 'Windows Phone' 148 , osname: 'Windows Phone' 149 , windowsphone: t 150 } 151 if (edgeVersion) { 152 result.msedge = t 153 result.version = edgeVersion 154 } 155 else { 156 result.msie = t 157 result.version = getFirstMatch(/iemobile\/(\d+(\.\d+)?)/i) 158 } 159 } 160 else if (/msie|trident/i.test(ua)) { 161 result = { 162 name: 'Internet Explorer' 163 , msie: t 164 , version: getFirstMatch(/(?:msie |rv:)(\d+(\.\d+)?)/i) 165 } 166 } else if (chromeos) { 167 result = { 168 name: 'Chrome' 169 , osname: 'Chrome OS' 170 , chromeos: t 171 , chromeBook: t 172 , chrome: t 173 , version: getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i) 174 } 175 } else if (/edg([ea]|ios)/i.test(ua)) { 176 result = { 177 name: 'Microsoft Edge' 178 , msedge: t 179 , version: edgeVersion 180 } 181 } 182 else if (/vivaldi/i.test(ua)) { 183 result = { 184 name: 'Vivaldi' 185 , vivaldi: t 186 , version: getFirstMatch(/vivaldi\/(\d+(\.\d+)?)/i) || versionIdentifier 187 } 188 } 189 else if (sailfish) { 190 result = { 191 name: 'Sailfish' 192 , osname: 'Sailfish OS' 193 , sailfish: t 194 , version: getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i) 195 } 196 } 197 else if (/seamonkey\//i.test(ua)) { 198 result = { 199 name: 'SeaMonkey' 200 , seamonkey: t 201 , version: getFirstMatch(/seamonkey\/(\d+(\.\d+)?)/i) 202 } 203 } 204 else if (/firefox|iceweasel|fxios/i.test(ua)) { 205 result = { 206 name: 'Firefox' 207 , firefox: t 208 , version: getFirstMatch(/(?:firefox|iceweasel|fxios)[ \/](\d+(\.\d+)?)/i) 209 } 210 if (/\((mobile|tablet);[^\)]*rv:[\d\.]+\)/i.test(ua)) { 211 result.firefoxos = t 212 result.osname = 'Firefox OS' 213 } 214 } 215 else if (silk) { 216 result = { 217 name: 'Amazon Silk' 218 , silk: t 219 , version : getFirstMatch(/silk\/(\d+(\.\d+)?)/i) 220 } 221 } 222 else if (/phantom/i.test(ua)) { 223 result = { 224 name: 'PhantomJS' 225 , phantom: t 226 , version: getFirstMatch(/phantomjs\/(\d+(\.\d+)?)/i) 227 } 228 } 229 else if (/slimerjs/i.test(ua)) { 230 result = { 231 name: 'SlimerJS' 232 , slimer: t 233 , version: getFirstMatch(/slimerjs\/(\d+(\.\d+)?)/i) 234 } 235 } 236 else if (/blackberry|\bbb\d+/i.test(ua) || /rim\stablet/i.test(ua)) { 237 result = { 238 name: 'BlackBerry' 239 , osname: 'BlackBerry OS' 240 , blackberry: t 241 , version: versionIdentifier || getFirstMatch(/blackberry[\d]+\/(\d+(\.\d+)?)/i) 242 } 243 } 244 else if (webos) { 245 result = { 246 name: 'WebOS' 247 , osname: 'WebOS' 248 , webos: t 249 , version: versionIdentifier || getFirstMatch(/w(?:eb)?osbrowser\/(\d+(\.\d+)?)/i) 250 }; 251 /touchpad\//i.test(ua) && (result.touchpad = t) 252 } 253 else if (/bada/i.test(ua)) { 254 result = { 255 name: 'Bada' 256 , osname: 'Bada' 257 , bada: t 258 , version: getFirstMatch(/dolfin\/(\d+(\.\d+)?)/i) 259 }; 260 } 261 else if (tizen) { 262 result = { 263 name: 'Tizen' 264 , osname: 'Tizen' 265 , tizen: t 266 , version: getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.\d+)?)/i) || versionIdentifier 267 }; 268 } 269 else if (/qupzilla/i.test(ua)) { 270 result = { 271 name: 'QupZilla' 272 , qupzilla: t 273 , version: getFirstMatch(/(?:qupzilla)[\s\/](\d+(?:\.\d+)+)/i) || versionIdentifier 274 } 275 } 276 else if (/chromium/i.test(ua)) { 277 result = { 278 name: 'Chromium' 279 , chromium: t 280 , version: getFirstMatch(/(?:chromium)[\s\/](\d+(?:\.\d+)?)/i) || versionIdentifier 281 } 282 } 283 else if (/chrome|crios|crmo/i.test(ua)) { 284 result = { 285 name: 'Chrome' 286 , chrome: t 287 , version: getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i) 288 } 289 } 290 else if (android) { 291 result = { 292 name: 'Android' 293 , version: versionIdentifier 294 } 295 } 296 else if (/safari|applewebkit/i.test(ua)) { 297 result = { 298 name: 'Safari' 299 , safari: t 300 } 301 if (versionIdentifier) { 302 result.version = versionIdentifier 303 } 304 } 305 else if (iosdevice) { 306 result = { 307 name : iosdevice == 'iphone' ? 'iPhone' : iosdevice == 'ipad' ? 'iPad' : 'iPod' 308 } 309 // WTF: version is not part of user agent in web apps 310 if (versionIdentifier) { 311 result.version = versionIdentifier 312 } 313 } 314 else if(/googlebot/i.test(ua)) { 315 result = { 316 name: 'Googlebot' 317 , googlebot: t 318 , version: getFirstMatch(/googlebot\/(\d+(\.\d+))/i) || versionIdentifier 319 } 320 } 321 else { 322 result = { 323 name: getFirstMatch(/^(.*)\/(.*) /), 324 version: getSecondMatch(/^(.*)\/(.*) /) 325 }; 326 } 327 328 // set webkit or gecko flag for browsers based on these engines 329 if (!result.msedge && /(apple)?webkit/i.test(ua)) { 330 if (/(apple)?webkit\/537\.36/i.test(ua)) { 331 result.name = result.name || "Blink" 332 result.blink = t 333 } else { 334 result.name = result.name || "Webkit" 335 result.webkit = t 336 } 337 if (!result.version && versionIdentifier) { 338 result.version = versionIdentifier 339 } 340 } else if (!result.opera && /gecko\//i.test(ua)) { 341 result.name = result.name || "Gecko" 342 result.gecko = t 343 result.version = result.version || getFirstMatch(/gecko\/(\d+(\.\d+)?)/i) 344 } 345 346 // set OS flags for platforms that have multiple browsers 347 if (!result.windowsphone && (android || result.silk)) { 348 result.android = t 349 result.osname = 'Android' 350 } else if (!result.windowsphone && iosdevice) { 351 result[iosdevice] = t 352 result.ios = t 353 result.osname = 'iOS' 354 } else if (mac) { 355 result.mac = t 356 result.osname = 'macOS' 357 } else if (xbox) { 358 result.xbox = t 359 result.osname = 'Xbox' 360 } else if (windows) { 361 result.windows = t 362 result.osname = 'Windows' 363 } else if (linux) { 364 result.linux = t 365 result.osname = 'Linux' 366 } 367 368 function getWindowsVersion (s) { 369 switch (s) { 370 case 'NT': return 'NT' 371 case 'XP': return 'XP' 372 case 'NT 5.0': return '2000' 373 case 'NT 5.1': return 'XP' 374 case 'NT 5.2': return '2003' 375 case 'NT 6.0': return 'Vista' 376 case 'NT 6.1': return '7' 377 case 'NT 6.2': return '8' 378 case 'NT 6.3': return '8.1' 379 case 'NT 10.0': return '10' 380 default: return undefined 381 } 382 } 383 384 // OS version extraction 385 var osVersion = ''; 386 if (result.windows) { 387 osVersion = getWindowsVersion(getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i)) 388 } else if (result.windowsphone) { 389 osVersion = getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i); 390 } else if (result.mac) { 391 osVersion = getFirstMatch(/Mac OS X (\d+([_\.\s]\d+)*)/i); 392 osVersion = osVersion.replace(/[_\s]/g, '.'); 393 } else if (iosdevice) { 394 osVersion = getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i); 395 osVersion = osVersion.replace(/[_\s]/g, '.'); 396 } else if (android) { 397 osVersion = getFirstMatch(/android[ \/-](\d+(\.\d+)*)/i); 398 } else if (result.webos) { 399 osVersion = getFirstMatch(/(?:web|hpw)os\/(\d+(\.\d+)*)/i); 400 } else if (result.blackberry) { 401 osVersion = getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i); 402 } else if (result.bada) { 403 osVersion = getFirstMatch(/bada\/(\d+(\.\d+)*)/i); 404 } else if (result.tizen) { 405 osVersion = getFirstMatch(/tizen[\/\s](\d+(\.\d+)*)/i); 406 } 407 if (osVersion) { 408 result.osversion = osVersion; 409 } 410 411 // device type extraction 412 var osMajorVersion = !result.windows && osVersion.split('.')[0]; 413 if ( 414 tablet 415 || nexusTablet 416 || iosdevice == 'ipad' 417 || (android && (osMajorVersion == 3 || (osMajorVersion >= 4 && !mobile))) 418 || result.silk 419 ) { 420 result.tablet = t 421 } else if ( 422 mobile 423 || iosdevice == 'iphone' 424 || iosdevice == 'ipod' 425 || android 426 || nexusMobile 427 || result.blackberry 428 || result.webos 429 || result.bada 430 ) { 431 result.mobile = t 432 } 433 434 // Graded Browser Support
435 // http://developer.yahoo.com/yui/articles/gbs 436 if (result.msedge || 437 (result.msie && result.version >= 10) || 438 (result.yandexbrowser && result.version >= 15) || 439 (result.vivaldi && result.version >= 1.0) || 440 (result.chrome && result.version >= 20) || 441 (result.samsungBrowser && result.version >= 4) || 442 (result.whale && compareVersions([result.version, '1.0']) === 1) || 443 (result.mzbrowser && compareVersions([result.version, '6.0']) === 1) || 444 (result.focus && compareVersions([result.version, '1.0']) === 1) || 445 (result.firefox && result.version >= 20.0) || 446 (result.safari && result.version >= 6) || 447 (result.opera && result.version >= 10.0) || 448 (result.ios && result.osversion && result.osversion.split(".")[0] >= 6) || 449 (result.blackberry && result.version >= 10.1) 450 || (result.chromium && result.version >= 20) 451 ) { 452 result.a = t; 453 } 454 else if ((result.msie && result.version < 10) || 455 (result.chrome && result.version < 20) || 456 (result.firefox && result.version < 20.0) || 457 (result.safari && result.version < 6) || 458 (result.opera && result.version < 10.0) || 459 (result.ios && result.osversion && result.osversion.split(".")[0] < 6) 460 || (result.chromium && result.version < 20) 461 ) { 462 result.c = t 463 } else result.x = t 464 465 return result 466 } 467 468 var bowser = detect(typeof navigator !== 'undefined' ? navigator.userAgent || '' : '') 469 470 bowser.test = function (browserList) { 471 for (var i = 0; i < browserList.length; ++i) { 472 var browserItem = browserList[i]; 473 if (typeof browserItem=== 'string') { 474 if (browserItem in bowser) { 475 return true; 476 } 477 } 478 } 479 return false; 480 } 481 482 /** 483 * Get version precisions count 484 * 485 * @example 486 * getVersionPrecision("1.10.3") // 3 487 * 488 * @param {string} version 489 * @return {number} 490 */ 491 function getVersionPrecision(version) { 492 return version.split(".").length; 493 } 494 495 /** 496 * Array::map polyfill 497 * 498 * @param {Array} arr 499 * @param {Function} iterator 500 * @return {Array} 501 */ 502 function map(arr, iterator) { 503 var result = [], i; 504 if (Array.prototype.map) { 505 return Array.prototype.map.call(arr, iterator); 506 } 507 for (i = 0; i < arr.length; i++) { 508 result.push(iterator(arr[i])); 509 } 510 return result; 511 } 512 513 /** 514 * Calculate browser version weight 515 * 516 * @example 517 * compareVersions(['1.10.2.1', '1.8.2.1.90']) // 1 518 * compareVersions(['1.010.2.1', '1.09.2.1.90']); // 1 519 * compareVersions(['1.10.2.1', '1.10.2.1']); // 0 520 * compareVersions(['1.10.2.1', '1.0800.2']); // -1 521 * 522 * @param {Array<String>} versions versions to compare 523 * @return {Number} comparison result 524 */ 525 function compareVersions(versions) { 526 // 1) get common precision for both versions, for example for "10.0" and "9" it should be 2 527 var precision = Math.max(getVersionPrecision(versions[0]), getVersionPrecision(versions[1])); 528 var chunks = map(versions, function (version) { 529 var delta = precision - getVersionPrecision(version); 530 531 // 2) "9" -> "9.0" (for precision = 2) 532 version = version + new Array(delta + 1).join(".0"); 533 534 // 3) "9.0" -> ["000000000"", "000000009"] 535 return map(version.split("."), function (chunk) { 536 return new Array(20 - chunk.length).join("0") + chunk; 537 }).reverse(); 538 }); 539 540 // iterate in reverse order by reversed chunks array 541 while (--precision >= 0) { 542 // 4) compare: "000000009" > "000000010" = false (but "9" > "10" = true) 543 if (chunks[0][precision] > chunks[1][precision]) { 544 return 1; 545 } 546 else if (chunks[0][precision] === chunks[1][precision]) { 547 if (precision === 0) { 548 // all version chunks are same 549 return 0; 550 } 551 } 552 else { 553 return -1; 554 } 555 } 556 } 557 558 /** 559 * Check if browser is unsupported 560 * 561 * @example 562 * bowser.isUnsupportedBrowser({ 563 * msie: "10", 564 * firefox: "23", 565 * chrome: "29", 566 * safari: "5.1", 567 * opera: "16", 568 * phantom: "534" 569 * }); 570 * 571 * @param {Object} minVersions map of minimal version to browser 572 * @param {Boolean} [strictMode = false] flag to return false if browser wasn't found in map 573 * @param {String} [ua] user agent string 574 * @return {Boolean} 575 */ 576 function isUnsupportedBrowser(minVersions, strictMode, ua) { 577 var _bowser = bowser; 578 579 // make strictMode param optional with ua param usage 580 if (typeof strictMode === 'string') { 581 ua = strictMode;
582 strictMode = void(0); 583 } 584 585 if (strictMode === void(0)) { 586 strictMode = false; 587 } 588 if (ua) { 589 _bowser = detect(ua); 590 } 591 592 var version = "" + _bowser.version; 593 for (var browser in minVersions) { 594 if (minVersions.hasOwnProperty(browser)) { 595 if (_bowser[browser]) { 596 if (typeof minVersions[browser] !== 'string') { 597 throw new Error('Browser version in the minVersion map should be a string: ' + browser + ': ' + String(minVersions)); 598 } 599 600 // browser version and min supported version. 601 return compareVersions([version, minVersions[browser]]) < 0; 602 } 603 } 604 } 605 606 return strictMode; // not found 607 } 608 609 /** 610 * Check if browser is supported 611 * 612 * @param {Object} minVersions map of minimal version to browser 613 * @param {Boolean} [strictMode = false] flag to return false if browser wasn't found in map 614 * @param {String} [ua] user agent string 615 * @return {Boolean} 616 */ 617 function check(minVersions, strictMode, ua) { 618 return !isUnsupportedBrowser(minVersions, strictMode, ua); 619 } 620 621 bowser.isUnsupportedBrowser = isUnsupportedBrowser; 622 bowser.compareVersions = compareVersions; 623 bowser.check = check; 624 625 /* 626 * Set our detect method to the main bowser object so we can 627 * reuse it to test other user agents. 628 * This is needed to implement future tests. 629 */ 630 bowser._detect = detect; 631 632 /* 633 * Set our detect public method to the main bowser object 634 * This is needed to implement bowser in server side 635 */ 636 bowser.detect = detect; 637 return bowser 638});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.