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