1/** 2 * Detect.js: User-Agent Parser 3 * https://github.com/darcyclarke/Detect.js 4 * Dual licensed under the MIT and GPL licenses. 5 * 6 * @version 2.2.2 7 * @author Darcy Clarke 8 * @url http://darcyclarke.me 9 * @createdat Mon Oct 26 2015 08:21:54 GMT-0200 (Horário brasileiro de verão) 10 * 11 * Based on UA-Parser (https://github.com/tobie/ua-parser) by Tobie Langel 12 * 13 * Example Usage: 14 * var agentInfo = detect.parse(navigator.userAgent); 15 * console.log(agentInfo.browser.family); // Chrome 16 * 17 */ 18(function(root, undefined) { 19 // Shim Array.prototype.map if necessary 20 // Production steps of ECMA-262, Edition 5, 15.4.4.19 21 // Reference: http://es5.github.com/#x15.4.4.19 22 if (!Array.prototype.map) { 23 Array.prototype.map = function(callback, thisArg) { 24 var T, A, k; 25 if (this == null) { 26 throw new TypeError(" this is null or not defined"); 27 } 28 // 1. Let O be the result of calling ToObject passing the |this| value as the argument. 29 var O = Object(this); 30 // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length". 31 // 3. Let len be ToUint32(lenValue). 32 var len = O.length >>> 0; 33 // 4. If IsCallable(callback) is false, throw a TypeError exception. 34 // See: http://es5.github.com/#x9.11 35 if (typeof callback !== "function") { 36 throw new TypeError(callback + " is not a function"); 37 } 38 // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. 39 if (thisArg) { 40 T = thisArg; 41 } 42 // 6. Let A be a new array created as if by the expression new Array(len) where Array is 43 // the standard built-in constructor with that name and len is the value of len. 44 A = new Array(len); 45 // 7. Let k be 0 46 k = 0; 47 // 8. Repeat, while k < len 48 while (k < len) { 49 var kValue, mappedValue; 50 // a. Let Pk be ToString(k). 51 // This is implicit for LHS operands of the in operator 52 // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk. 53 // This step can be combined with c 54 // c. If kPresent is true, then 55 if (k in O) { 56 // i. Let kValue be the result of calling the Get internal method of O with argument Pk. 57 kValue = O[k]; 58 // ii. Let mappedValue be the result of calling the Call internal method of callback 59 // with T as the this value and argument list containing kValue, k, and O. 60 mappedValue = callback.call(T, kValue, k, O); 61 // iii. Call the DefineOwnProperty internal method of A with arguments 62 // Pk, Property Descriptor {Value: mappedValue, : true, Enumerable: true, Configurable: true}, 63 // and false. 64 // In browsers that support Object.defineProperty, use the following: 65 // Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true }); 66 // For best browser support, use the following: 67 A[k] = mappedValue; 68 } 69 // d. Increase k by 1. 70 k++; 71 } 72 // 9. return A 73 return A; 74 }; 75 } 76 // Detect 77 var detect = root.detect = function() { 78 // Context 79 var _this = function() {}; 80 // Regexes 81 var regexes = { 82 browser_parsers: [ { 83 regex: "^(Opera)/(\\d+)\\.(\\d+) \\(Nintendo Wii", 84 family_replacement: "Wii", 85 manufacturer: "Nintendo" 86 }, { 87 regex: "(SeaMonkey|Camino)/(\\d+)\\.(\\d+)\\.?([ab]?\\d+[a-z]*)", 88 family_replacement: "Camino", 89 other: true 90 }, { 91 regex: "(Pale[Mm]oon)/(\\d+)\\.(\\d+)\\.?(\\d+)?", 92 family_replacement: "Pale Moon (Firefox Variant)", 93 other: true 94 }, { 95 regex: "(Fennec)/(\\d+)\\.(\\d+)\\.?([ab]?\\d+[a-z]*)", 96 family_replacement: "Firefox Mobile" 97 }, { 98 regex: "(Fennec)/(\\d+)\\.(\\d+)(pre)", 99 family_replacment: "Firefox Mobile" 100 }, { 101 regex: "(Fennec)/(\\d+)\\.(\\d+)", 102 family_replacement: "Firefox Mobile" 103 }, { 104 regex: "Mobile.*(Firefox)/(\\d+)\\.(\\d+)", 105 family_replacement: "Firefox Mobile" 106 }, { 107 regex: "(Namoroka|Shiretoko|Minefield)/(\\d+)\\.(\\d+)\\.(\\d+(?:pre)?)", 108 family_replacement: "Firefox ($1)" 109 }, { 110 regex: "(Firefox)/(\\d+)\\.(\\d+)(a\\d+[a-z]*)", 111 family_replacement: "Firefox Alpha" 112 }, { 113 regex: "(Firefox)/(\\d+)\\.(\\d+)(b\\d+[a-z]*)", 114 family_replacement: "Firefox Beta" 115 }, { 116 regex: "(Firefox)-(?:\\d+\\.\\d+)?/(\\d+)\\.(\\d+)(a\\d+[a-z]*)", 117 family_replacement: "Firefox Alpha" 118 }, { 119 regex: "(Firefox)-(?:\\d+\\.\\d+)?/(\\d+)\\.(\\d+)(b\\d+[a-z]*)", 120 family_replacement: "Firefox Beta" 121 }, { 122 regex: "(Namoroka|Shiretoko|Minefield)/(\\d+)\\.(\\d+)([ab]\\d+[a-z]*)?", 123 family_replacement: "Firefox ($1)" 124 }, { 125 regex: "(Firefox).*Tablet browser (\\d+)\\.(\\d+)\\.(\\d+)", 126 family_replacement: "MicroB", 127 tablet: true 128 }, { 129 regex: "(MozillaDeveloperPreview)/(\\d+)\\.(\\d+)([ab]\\d+[a-z]*)?" 130 }, { 131 regex: "(Flock)/(\\d+)\\.(\\d+)(b\\d+?)", 132 family_replacement: "Flock", 133 other: true 134 }, { 135 regex: "(RockMelt)/(\\d+)\\.(\\d+)\\.(\\d+)", 136 family_replacement: "Rockmelt", 137 other: true 138 }, { 139 regex: "(Navigator)/(\\d+)\\.(\\d+)\\.(\\d+)", 140 family_replacement: "Netscape" 141 }, { 142 regex: "(Navigator)/(\\d+)\\.(\\d+)([ab]\\d+)", 143 family_replacement: "Netscape" 144 }, { 145 regex: "(Netscape6)/(\\d+)\\.(\\d+)\\.(\\d+)", 146 family_replacement: "Netscape" 147 }, { 148 regex: "(MyIBrow)/(\\d+)\\.(\\d+)", 149 family_replacement: "My Internet Browser", 150 other: true 151 }, { 152 regex: "(Opera Tablet).*Version/(\\d+)\\.(\\d+)(?:\\.(\\d+))?", 153 family_replacement: "Opera Tablet", 154 tablet: true 155 }, { 156 regex: "(Opera)/.+Opera Mobi.+Version/(\\d+)\\.(\\d+)", 157 family_replacement: "Opera Mobile" 158 }, { 159 regex: "Opera Mobi", 160 family_replacement: "Opera Mobile" 161 }, { 162 regex: "(Opera Mini)/(\\d+)\\.(\\d+)", 163 family_replacement: "Opera Mini" 164 }, { 165 regex: "(Opera Mini)/att/(\\d+)\\.(\\d+)", 166 family_replacement: "Opera Mini" 167 }, { 168 regex: "(Opera)/9.80.*Version/(\\d+)\\.(\\d+)(?:\\.(\\d+))?", 169 family_replacement: "Opera" 170 }, { 171 regex: "(OPR)/(\\d+)\\.(\\d+)(?:\\.(\\d+))?", 172 family_replacement: "Opera" 173 }, { 174 regex: "(webOSBrowser)/(\\d+)\\.(\\d+)", 175 family_replacement: "webOS" 176 }, { 177 regex: "(webOS)/(\\d+)\\.(\\d+)", 178 family_replacement: "webOS" 179 }, { 180 regex: "(wOSBrowser).+TouchPad/(\\d+)\\.(\\d+)", 181 family_replacement: "webOS TouchPad" 182 }, { 183 regex: "(luakit)", 184 family_replacement: "LuaKit", 185 other: true 186 }, { 187 regex: "(Lightning)/(\\d+)\\.(\\d+)([ab]?\\d+[a-z]*)", 188 family_replacement: "Lightning", 189 other: true 190 }, { 191 regex: "(Firefox)/(\\d+)\\.(\\d+)\\.(\\d+(?:pre)?) \\(Swiftfox\\)", 192 family_replacement: "Swiftfox", 193 other: true 194 }, { 195 regex: "(Firefox)/(\\d+)\\.(\\d+)([ab]\\d+[a-z]*)? \\(Swiftfox\\)", 196 family_replacement: "Swiftfox", 197 other: true 198 }, { 199 regex: "rekonq", 200 family_replacement: "Rekonq", 201 other: true 202 }, { 203 regex: "(conkeror|Conkeror)/(\\d+)\\.(\\d+)\\.?(\\d+)?", 204 family_replacement: "Conkeror", 205 other: true 206 }, { 207 regex: "(konqueror)/(\\d+)\\.(\\d+)\\.(\\d+)", 208 family_replacement: "Konqueror", 209 other: true 210 }, { 211 regex: "(WeTab)-Browser", 212 family_replacement: "WeTab", 213 other: true 214 }, { 215 regex: "(Comodo_Dragon)/(\\d+)\\.(\\d+)\\.(\\d+)", 216 family_replacement: "Comodo Dragon", 217 other: true 218 }, { 219 regex: "(YottaaMonitor)", 220 family_replacement: "Yottaa Monitor", 221 other: true 222 }, { 223 regex: "(Kindle)/(\\d+)\\.(\\d+)", 224 family_replacement: "Kindle" 225 }, { 226 regex: "(Symphony) (\\d+).(\\d+)", 227 family_replacement: "Symphony", 228 other: true 229 }, { 230 regex: "Minimo", 231 family_replacement: "Minimo", 232 other: true 233 }, { 234 regex: "(Edge)/(\\d+)\\.(\\d+)", 235 family_replacement: "Edge" 236 }, { 237 regex: "(CrMo)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)", 238 family_replacement: "Chrome Mobile" 239 }, { 240 regex: "(CriOS)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)", 241 family_replacement: "Chrome Mobile iOS" 242 }, { 243 regex: "(Chrome)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+) Mobile", 244 family_replacement: "Chrome Mobile" 245 }, { 246 regex: "(chromeframe)/(\\d+)\\.(\\d+)\\.(\\d+)", 247 family_replacement: "Chrome Frame" 248 }, { 249 regex: "(UC Browser)(\\d+)\\.(\\d+)\\.(\\d+)", 250 family_replacement: "UC Browser", 251 other: true 252 }, { 253 regex: "(SLP Browser)/(\\d+)\\.(\\d+)", 254 family_replacement: "Tizen Browser", 255 other: true 256 }, { 257 regex: "(Epiphany)/(\\d+)\\.(\\d+).(\\d+)", 258 family_replacement: "Epiphany", 259 other: true 260 }, { 261 regex: "(SE 2\\.X) MetaSr (\\d+)\\.(\\d+)", 262 family_replacement: "Sogou Explorer", 263 other: true 264 }, { 265 regex: "(Pingdom.com_bot_version_)(\\d+)\\.(\\d+)", 266 family_replacement: "PingdomBot", 267 other: true 268 }, { 269 regex: "(facebookexternalhit)/(\\d+)\\.(\\d+)", 270 family_replacement: "FacebookBot" 271 }, { 272 regex: "(Twitterbot)/(\\d+)\\.(\\d+)", 273 family_replacement: "TwitterBot" 274 }, { 275 regex: "(AdobeAIR|Chromium|FireWeb|Jasmine|ANTGalio|Midori|Fresco|Lobo|PaleMoon|Maxthon|Lynx|OmniWeb|Dillo|Camino|Demeter|Fluid|Fennec|Shiira|Sunrise|Chrome|Flock|Netscape|Lunascape|WebPilot|NetFront|Netfront|Konqueror|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|Opera Mini|iCab|NetNewsWire|ThunderBrowse|Iron|Iris|UP\\.Browser|Bunjaloo|Google Earth|Raven for Mac)/(\\d+)\\.(\\d+)\\.(\\d+)" 276 }, { 277 regex: "(Bolt|Jasmine|IceCat|Skyfire|Midori|Maxthon|Lynx|Arora|IBrowse|Dillo|Camino|Shiira|Fennec|Phoenix|Chrome|Flock|Netscape|Lunascape|Epiphany|WebPilot|Opera Mini|Opera|NetFront|Netfront|Konqueror|Googlebot|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|iCab|NetNewsWire|Iron|Space Bison|Stainless|Orca|Dolfin|BOLT|Minimo|Tizen Browser|Polaris)/(\\d+)\\.(\\d+)" 278 }, { 279 regex: "(iRider|Crazy Browser|SkipStone|iCab|Lunascape|Sleipnir|Maemo Browser) (\\d+)\\.(\\d+)\\.(\\d+)" 280 }, { 281 regex: "(iCab|Lunascape|Opera|Android|Jasmine|Polaris|BREW) (\\d+)\\.(\\d+)\\.?(\\d+)?" 282 }, { 283 regex: "(Android) Donut", 284 v2_replacement: "2", 285 v1_replacement: "1" 286 }, { 287 regex: "(Android) Eclair", 288 v2_replacement: "1", 289 v1_replacement: "2" 290 }, { 291 regex: "(Android) Froyo", 292 v2_replacement: "2", 293 v1_replacement: "2" 294 }, { 295 regex: "(Android) Gingerbread", 296 v2_replacement: "3", 297 v1_replacement: "2" 298 }, { 299 regex: "(Android) Honeycomb", 300 v1_replacement: "3" 301 }, { 302 regex: "(IEMobile)[ /](\\d+)\\.(\\d+)", 303 family_replacement: "IE Mobile" 304 }, { 305 regex: "(MSIE) (\\d+)\\.(\\d+).*XBLWP7", 306 family_replacement: "IE Large Screen" 307 }, { 308 regex: "(Firefox)/(\\d+)\\.(\\d+)\\.(\\d+)" 309 }, { 310 regex: "(Firefox)/(\\d+)\\.(\\d+)(pre|[ab]\\d+[a-z]*)?" 311 }, { 312 regex: "(Obigo)InternetBrowser", 313 other: true 314 }, { 315 regex: "(Obigo)\\-Browser", 316 other: true 317 }, { 318 regex: "(Obigo|OBIGO)[^\\d]*(\\d+)(?:.(\\d+))?", 319 other: true 320 }, { 321 regex: "(MAXTHON|Maxthon) (\\d+)\\.(\\d+)", 322 family_replacement: "Maxthon", 323 other: true 324 }, { 325 regex: "(Maxthon|MyIE2|Uzbl|Shiira)", 326 v1_replacement: "0", 327 other: true 328 }, { 329 regex: "(PLAYSTATION) (\\d+)", 330 family_replacement: "PlayStation", 331 manufacturer: "Sony" 332 }, { 333 regex: "(PlayStation Portable)[^\\d]+(\\d+).(\\d+)", 334 manufacturer: "Sony" 335 }, { 336 regex: "(BrowseX) \\((\\d+)\\.(\\d+)\\.(\\d+)", 337 other: true 338 }, { 339 regex: "(POLARIS)/(\\d+)\\.(\\d+)", 340 family_replacement: "Polaris", 341 other: true 342 }, { 343 regex: "(Embider)/(\\d+)\\.(\\d+)", 344 family_replacement: "Polaris", 345 other: true 346 }, { 347 regex: "(BonEcho)/(\\d+)\\.(\\d+)\\.(\\d+)", 348 family_replacement: "Bon Echo", 349 other: true 350 }, { 351 regex: "(iPod).+Version/(\\d+)\\.(\\d+)\\.(\\d+)", 352 family_replacement: "Mobile Safari", 353 manufacturer: "Apple" 354 }, { 355 regex: "(iPod).*Version/(\\d+)\\.(\\d+)", 356 family_replacement: "Mobile Safari", 357 manufacturer: "Apple" 358 }, { 359 regex: "(iPod)", 360 family_replacement: "Mobile Safari", 361 manufacturer: "Apple" 362 }, { 363 regex: "(iPhone).*Version/(\\d+)\\.(\\d+)\\.(\\d+)", 364 family_replacement: "Mobile Safari", 365 manufacturer: "Apple" 366 }, { 367 regex: "(iPhone).*Version/(\\d+)\\.(\\d+)", 368 family_replacement: "Mobile Safari", 369 manufacturer: "Apple" 370 }, { 371 regex: "(iPhone)", 372 family_replacement: "Mobile Safari", 373 manufacturer: "Apple" 374 }, { 375 regex: "(iPad).*Version/(\\d+)\\.(\\d+)\\.(\\d+)", 376 fami
376ly_replacement: "Mobile Safari", 377 tablet: true, 378 manufacturer: "Apple" 379 }, { 380 regex: "(iPad).*Version/(\\d+)\\.(\\d+)", 381 family_replacement: "Mobile Safari", 382 tablet: true, 383 manufacturer: "Apple" 384 }, { 385 regex: "(iPad)", 386 family_replacement: "Mobile Safari", 387 tablet: true, 388 manufacturer: "Apple" 389 }, { 390 regex: "(AvantGo) (\\d+).(\\d+)", 391 other: true 392 }, { 393 regex: "(Avant)", 394 v1_replacement: "1", 395 other: true 396 }, { 397 regex: "^(Nokia)", 398 family_replacement: "Nokia Services (WAP) Browser", 399 manufacturer: "Nokia" 400 }, { 401 regex: "(NokiaBrowser)/(\\d+)\\.(\\d+).(\\d+)\\.(\\d+)", 402 manufacturer: "Nokia" 403 }, { 404 regex: "(NokiaBrowser)/(\\d+)\\.(\\d+).(\\d+)", 405 manufacturer: "Nokia" 406 }, { 407 regex: "(NokiaBrowser)/(\\d+)\\.(\\d+)", 408 manufacturer: "Nokia" 409 }, { 410 regex: "(BrowserNG)/(\\d+)\\.(\\d+).(\\d+)", 411 family_replacement: "NokiaBrowser", 412 manufacturer: "Nokia" 413 }, { 414 regex: "(Series60)/5\\.0", 415 v2_replacement: "0", 416 v1_replacement: "7", 417 family_replacement: "NokiaBrowser", 418 manufacturer: "Nokia" 419 }, { 420 regex: "(Series60)/(\\d+)\\.(\\d+)", 421 family_replacement: "Nokia OSS Browser", 422 manufacturer: "Nokia" 423 }, { 424 regex: "(S40OviBrowser)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)", 425 family_replacement: "Nokia Series 40 Ovi Browser", 426 manufacturer: "Nokia" 427 }, { 428 regex: "(Nokia)[EN]?(\\d+)", 429 manufacturer: "Nokia" 430 }, { 431 regex: "(PlayBook).+RIM Tablet OS (\\d+)\\.(\\d+)\\.(\\d+)", 432 family_replacement: "Blackberry WebKit", 433 tablet: true, 434 manufacturer: "Nokia" 435 }, { 436 regex: "(Black[bB]erry).+Version/(\\d+)\\.(\\d+)\\.(\\d+)", 437 family_replacement: "Blackberry WebKit", 438 manufacturer: "RIM" 439 }, { 440 regex: "(Black[bB]erry)\\s?(\\d+)", 441 family_replacement: "Blackberry", 442 manufacturer: "RIM" 443 }, { 444 regex: "(OmniWeb)/v(\\d+)\\.(\\d+)", 445 other: true 446 }, { 447 regex: "(Blazer)/(\\d+)\\.(\\d+)", 448 family_replacement: "Palm Blazer", 449 manufacturer: "Palm" 450 }, { 451 regex: "(Pre)/(\\d+)\\.(\\d+)", 452 family_replacement: "Palm Pre", 453 manufacturer: "Palm" 454 }, { 455 regex: "(Links) \\((\\d+)\\.(\\d+)", 456 other: true 457 }, { 458 regex: "(QtWeb) Internet Browser/(\\d+)\\.(\\d+)", 459 other: true 460 }, { 461 regex: "(Silk)/(\\d+)\\.(\\d+)(?:\\.([0-9\\-]+))?", 462 other: true, 463 tablet: true 464 }, {
465 regex: "(AppleWebKit)/(\\d+)\\.?(\\d+)?\\+ .* Version/\\d+\\.\\d+.\\d+ Safari/", 466 family_replacement: "WebKit Nightly" 467 }, { 468 regex: "(Version)/(\\d+)\\.(\\d+)(?:\\.(\\d+))?.*Safari/", 469 family_replacement: "Safari" 470 }, { 471 regex: "(Safari)/\\d+" 472 }, { 473 regex: "(OLPC)/Update(\\d+)\\.(\\d+)", 474 other: true 475 }, { 476 regex: "(OLPC)/Update()\\.(\\d+)", 477 v1_replacement: "0", 478 other: true 479 }, { 480 regex: "(SEMC\\-Browser)/(\\d+)\\.(\\d+)", 481 other: true 482 }, { 483 regex: "(Teleca)", 484 family_replacement: "Teleca Browser", 485 other: true 486 }, { 487 regex: "Trident(.*)rv.(\\d+)\\.(\\d+)", 488 family_replacement: "IE" 489 }, { 490 regex: "(MSIE) (\\d+)\\.(\\d+)", 491 family_replacement: "IE" 492 } ], 493 os_parsers: [ { 494 regex: "(Android) (\\d+)\\.(\\d+)(?:[.\\-]([a-z0-9]+))?" 495 }, { 496 regex: "(Android)\\-(\\d+)\\.(\\d+)(?:[.\\-]([a-z0-9]+))?" 497 }, { 498 regex: "(Android) Donut", 499 os_v2_replacement: "2", 500 os_v1_replacement: "1" 501 }, { 502 regex: "(Android) Eclair", 503 os_v2_replacement: "1", 504 os_v1_replacement: "2" 505 }, { 506 regex: "(Android) Froyo", 507 os_v2_replacement: "2", 508 os_v1_replacement: "2" 509 }, { 510 regex: "(Android) Gingerbread", 511 os_v2_replacement: "3", 512 os_v1_replacement: "2" 513 }, { 514 regex: "(Android) Honeycomb", 515 os_v1_replacement: "3" 516 }, { 517 regex: "(Silk-Accelerated=[a-z]{4,5})", 518 os_replacement: "Android" 519 }, { 520 regex: "(Windows Phone 6\\.5)" 521 }, { 522 regex: "(Windows (?:NT 5\\.2|NT 5\\.1))", 523 os_replacement: "Windows XP" 524 }, { 525 regex: "(XBLWP7)", 526 os_replacement: "Windows Phone OS" 527 }, { 528 regex: "(Windows NT 6\\.1)", 529 os_replacement: "Windows 7" 530 }, { 531 regex: "(Windows NT 6\\.0)", 532 os_replacement: "Windows Vista" 533 }, { 534 regex: "(Windows 98|Windows XP|Windows ME|Windows 95|Windows CE|Windows 7|Windows NT 4\\.0|Windows Vista|Windows 2000)" 535 }, { 536 regex: "(Windows NT 6\\.4|Windows NT 10\\.0)", 537 os_replacement: "Windows 10" 538 }, { 539 regex: "(Windows NT 6\\.2)", 540 os_replacement: "Windows 8" 541 }, { 542 regex: "(Windows Phone 8)", 543 os_replacement: "Windows Phone 8" 544 }, { 545 regex: "(Windows NT 5\\.0)", 546 os_replacement: "Windows 2000" 547 }, { 548 regex: "(Windows Phone OS) (\\d+)\\.(\\d+)" 549 }, { 550 regex: "(Windows ?Mobile)", 551 os_replacement: "Windows Mobile" 552 }, { 553 regex: "(WinNT4.0)", 554 os_replacement: "Windows NT 4.0" 555 }, { 556 regex: "(Win98)", 557 os_replacement: "Windows 98" 558 }, { 559 regex: "(Tizen)/(\\d+)\\.(\\d+)", 560 other: true 561 }, { 562 regex: "(Mac OS X) (\\d+)[_.](\\d+)(?:[_.](\\d+))?", 563 manufacturer: "Apple" 564 }, { 565 regex: "(?:PPC|Intel) (Mac OS X)", 566 manufacturer: "Apple" 567 }, { 568 regex: "(CPU OS|iPhone OS) (\\d+)_(\\d+)(?:_(\\d+))?", 569 os_replacement: "iOS", 570 manufacturer: "Apple" 571 }, { 572 regex: "(iPhone|iPad|iPod); Opera", 573 os_replacement: "iOS", 574 manufacturer: "Apple" 575 }, { 576 regex: "(iPad); Opera", 577 tablet: true, 578 manufacturer: "Apple" 579 }, { 580 regex: "(iPhone|iPad|iPod).*Mac OS X.*Version/(\\d+)\\.(\\d+)", 581 os_replacement: "iOS", 582 manufacturer: "Apple" 583 }, { 584 regex: "(CrOS) [a-z0-9_]+ (\\d+)\\.(\\d+)(?:\\.(\\d+))?", 585 os_replacement: "Chrome OS" 586 }, { 587 regex: "(Debian)-(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?", 588 other: true 589 }, { 590 regex: "(Linux Mint)(?:/(\\d+))?", 591 other: true 592 }, { 593 regex: "(Mandriva)(?: Linux)?/(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?", 594 other: true 595 }, { 596 regex: "(Symbian[Oo][Ss])/(\\d+)\\.(\\d+)", 597 os_replacement: "Symbian OS" 598 }, { 599 regex: "(Symbian/3).+NokiaBrowser/7\\.3", 600 os_replacement: "Symbian^3 Anna" 601 }, { 602 regex: "(Symbian/3).+NokiaBrowser/7\\.4", 603 os_replacement: "Symbian^3 Belle" 604 }, { 605 regex: "(Symbian/3)", 606 os_replacement: "Symbian^3" 607 }, { 608 regex: "(Series 60|SymbOS|S60)", 609 os_replacement: "Symbian OS" 610 }, { 611 regex: "(MeeGo)", 612 other: true 613 }, { 614 regex: "Symbian [Oo][Ss]", 615 os_replacement: "Symbian OS" 616 }, { 617 regex: "(Black[Bb]erry)[0-9a-z]+/(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?", 618 os_replacement: "BlackBerry OS", 619 manufacturer: "RIM" 620 }, { 621 regex: "(Black[Bb]erry).+Version/(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?", 622 os_replacement: "BlackBerry OS", 623 manufacturer: "RIM" 624 }, { 625 regex: "(RIM Tablet OS) (\\d+)\\.(\\d+)\\.(\\d+)", 626 os_replacement: "BlackBerry Tablet OS", 627 tablet: true, 628 manufacturer: "RIM" 629 }, { 630 regex: "(Play[Bb]ook)", 631 os_replacement: "BlackBerry Tablet OS", 632 tablet: true, 633 manufacturer: "RIM" 634 }, { 635 regex: "(Black[Bb]erry)", 636 os_replacement: "Blackberry OS", 637 manufacturer: "RIM" 638 }, { 639 regex: "(webOS|hpwOS)/(\\d+)\\.(\\d+)(?:\\.(\\d+))?", 640 os_replacement: "webOS" 641 }, { 642 regex: "(SUSE|Fedora|Red Hat|PCLinuxOS)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)", 643 other: true 644 }, { 645 regex: "(SUSE|Fedora|Red Hat|Puppy|PCLinuxOS|CentOS)/(\\d+)\\.(\\d+)\\.(\\d+)", 646 other: true 647 }, { 648 regex: "(Ubuntu|Kindle|Bada|Lubuntu|BackTrack|Red Hat|Slackware)/(\\d+)\\.(\\d+)" 649 }, { 650 regex: "(Windows|OpenBSD|FreeBSD|NetBSD|Ubuntu|Kubuntu|Android|Arch Linux|CentOS|WeTab|Slackware)" 651 }, { 652 regex: "(Linux|BSD)", 653 other: true 654 } ], 655 mobile_os_families: [ "Windows Phone 6.5", "Windows CE", "Symbian OS" ], 656 device_parsers: [ { 657 regex: "HTC ([A-Z][a-z0-9]+) Build", 658 device_replacement: "HTC $1", 659 manufacturer: "HTC" 660 }, { 661 regex: "HTC ([A-Z][a-z0-9 ]+) \\d+\\.\\d+\\.\\d+\\.\\d+", 662 device_replacement: "HTC $1", 663 manufacturer: "HTC" 664 }, { 665 regex: "HTC_Touch_([A-Za-z0-9]+)", 666 device_replacement: "HTC Touch ($1)", 667 manufacturer: "HTC" 668 }, { 669 regex: "USCCHTC(\\d+)", 670 device_replacement: "HTC $1 (US Cellular)", 671 manufacturer: "HTC" 672 }, { 673 regex: "Sprint APA(9292)", 674 device_replacement: "HTC $1 (Sprint)", 675 manufacturer: "HTC" 676 }, { 677 regex: "HTC ([A-Za-z0-9]+ [A-Z])", 678 device_replacement: "HTC $1", 679 manufacturer: "HTC" 680 }, { 681 regex: "HTC-([A-Za-z0-9]+)", 682 device_replacement: "HTC $1", 683 manufacturer: "HTC" 684 }, { 685 regex: "HTC_([A-Za-z0-9]+)", 686 device_replacement: "HTC $1", 687 manufacturer: "HTC" 688 }, { 689 regex: "HTC ([A-Za-z0-9]+)", 690 device_replacement: "HTC $1", 691 manufacturer: "HTC" 692 }, { 693 regex: "(ADR[A-Za-z0-9]+)", 694 device_replacement: "HTC $1", 695 manufacturer: "HTC" 696 }, { 697 regex: "(HTC)", 698 manufacturer: "HTC" 699 }, { 700 regex: "SonyEricsson([A-Za-z0-9]+)/", 701 device_replacement: "Ericsson $1", 702 other: true, 703 manufacturer: "Sony" 704 }, { 705 regex: "Android[\\- ][\\d]+\\.[\\d]+\\; [A-Za-z]{2}\\-[A-Za-z]{2}\\; WOWMobile (.+) Build" 706 }, { 707 regex: "Android[\\- ][\\d]+\\.[\\d]+\\.[\\d]+; [A-Za-z]{2}\\-[A-Za-z]{2}\\; (.+) Build" 708 }, { 709 regex: "Android[\\- ][\\d]+\\.[\\d]+\\-update1\\; [A-Za-z]{2}\\-[A-Za-z]{2}\\; (.+) Build" 710 }, { 711 regex: "Android[\\- ][\\d]+\\.[\\d]+\\; [A-Za-z]{2}\\-[A-Za-z]{2}\\; (.+) Build" 712 }, { 713 regex: "Android[\\- ][\\d]+\\.[\\d]+\\.[\\d]+; (.+) Build" 714 }, { 715 regex: "NokiaN([0-9]+)", 716 device_replacement: "Nokia N$1", 717 manufacturer: "Nokia" 718 }, { 719 regex: "Nokia([A-Za-z0-9\\v-]+)", 720 device_replacement: "Nokia $1", 721 manufacturer: "Nokia" 722 }, { 723 regex: "NOKIA ([A-Za-z0-9\\-]+)", 724 device_replacement: "Nokia $1", 725 manufacturer: "Nokia" 726 }, { 727 regex: "Nokia ([A-Za-z0-9\\-]+)", 728 device_replacement: "Nokia $1", 729 manufacturer: "Nokia" 730 }, { 731 regex: "Lumia ([A-Za-z0-9\\-]+)", 732 device_replacement: "Lumia $1", 733 manufacturer: "Nokia" 734 }, { 735 regex: "Symbian", 736 device_replacement: "Nokia", 737 manufacturer: "Nokia" 738 }, { 739 regex: "(PlayBook).+RIM Tablet OS", 740 device_replacement: "Blackberry Playbook", 741 tablet: true, 742 manufacturer: "RIM" 743 }, { 744 regex: "(Black[Bb]erry [0-9]+);", 745 manufacturer: "RIM" 746 }, { 747 regex: "Black[Bb]erry([0-9]+)", 748 device_replacement: "BlackBerry $1", 749 manufacturer: "RIM" 750 }, { 751 regex: "(Pre)/(\\d+)\\.(\\d+)", 752 device_replacement: "Palm Pre", 753 manufacturer: "Palm" 754 }, { 755 regex: "(Pixi)/(\\d+)\\.(\\d+)", 756 device_replacement: "Palm Pixi", 757 manufacturer: "Palm" 758 }, { 759 regex: "(Touchpad)/(\\d+)\\.(\\d+)", 760 device_replacement: "HP Touchpad", 761 manufacturer: "HP" 762 }, { 763 regex: "HPiPAQ([A-Za-z0-9]+)/(\\d+).(\\d+)", 764 device_replacement: "HP iPAQ $1", 765 manufacturer: "HP" 766 }, { 767 regex: "Palm([A-Za-z0-9]+)", 768 device_replacement: "Palm $1", 769 manufacturer: "Palm" 770 }, { 771 regex: "Treo([A-Za-z0-9]+)", 772 device_replacement: "Palm Treo $1", 773 manufacturer: "Palm" 774 }, { 775 regex: "webOS.*(P160UNA)/(\\d+).(\\d+)", 776 device_replacement: "HP Veer", 777 manufacturer: "HP" 778 }, { 779 regex: "(Kindle Fire)", 780 manufacturer: "Amazon" 781 }, { 782 regex: "(Kindle)", 783 manufacturer: "Amazon" 784 }, { 785 regex: "(Silk)/(\\d+)\\.(\\d+)(?:\\.([0-9\\-]+))?", 786 device_replacement: "Kindle Fire", 787 tablet: true, 788 manufacturer: "Amazon" 789 }, { 790 regex: "(iPad) Simulator;", 791 manufacturer: "Apple" 792 }, { 793 regex: "(iPad);", 794 manufacturer: "Apple" 795 }, { 796 regex: "(iPod);", 797 manufacturer: "Apple" 798 }, { 799 regex: "(iPhone) Simulator;", 800 manufacturer: "Apple" 801 }, { 802 regex: "(iPhone);", 803 manufacturer: "Apple" 804 }, { 805 regex: "Nexus\\ ([A-Za-z0-9\\-]+)", 806 device_replacement: "Nexus $1" 807 }, { 808 regex: "acer_([A-Za-z0-9]+)_", 809 device_replacement: "Acer $1", 810 manufacturer: "Acer" 811 }, { 812 regex: "acer_([A-Za-z0-9]+)_", 813 device_replacement: "Acer $1", 814 manufacturer: "Acer" 815 }, { 816 regex: "Amoi\\-([A-Za-z0-9]+)", 817 device_replacement: "Amoi $1", 818 other: true, 819 manufacturer: "Amoi" 820 }, { 821 regex: "AMOI\\-([A-Za-z0-9]+)", 822 device_replacement: "Amoi $1", 823 other: true, 824 manufacturer: "Amoi" 825 }, { 826 regex: "Asus\\-([A-Za-z0-9]+)", 827 device_replacement: "Asus $1", 828 manufacturer: "Asus" 829 }, { 830 regex: "ASUS\\-([A-Za-z0-9]+)", 831 device_replacement: "Asus $1", 832 manufacturer: "Asus" 833 }, { 834 regex: "BIRD\\-([A-Za-z0-9]+)", 835 device_replacement: "Bird $1", 836 other: true 837 }, { 838 regex: "BIRD\\.([A-Za-z0-9]+)", 839 device_replacement: "Bird $1", 840 other: true 841 }, { 842 regex: "BIRD ([A-Za-z0-9]+)", 843 device_replacement: "Bird $1", 844 other: true 845 }, { 846 regex: "Dell ([A-Za-z0-9]+)", 847 device_replacement: "Dell $1", 848 manufacturer: "Dell" 849 }, { 850 regex: "DoCoMo/2\\.0 ([A-Za-z0-9]+)", 851 device_replacement: "DoCoMo $1", 852 other: true 853 }, { 854 regex: "([A-Za-z0-9]+)\\_W\\;FOMA", 855 device_replacement: "DoCoMo $1", 856 other: true 857 }, { 858 regex: "([A-Za-z0-9]+)\\;FOMA", 859 device_replacement: "DoCoMo $1", 860 other: true 861 }, { 862 regex: "vodafone([A-Za-z0-9]+)", 863 device_replacement: "Huawei Vodafone $1", 864 other: true 865 }, { 866 regex: "i\\-mate ([A-Za-z0-9]+)", 867 device_replacement: "i-mate $1", 868 other: true 869 }, { 870 regex: "Kyocera\\-([A-Za-z0-9]+)", 871 device_replacement: "Kyocera $1", 872 other: true 873 }, { 874 regex: "KWC\\-([A-Za-z0-9]+)", 875 device_replacement: "Kyocera $1", 876 other: true 877 }, { 878 regex: "Lenovo\\-([A-Za-z0-9]+)", 879 device_replacement: "Lenovo $1", 880 manufacturer: "Lenovo" 881 }, { 882 regex: "Lenovo\\_([A-Za-z0-9]+)", 883 device_replacement: "Lenovo $1", 884 manufacturer: "Levovo" 885 }, { 886 regex: "LG/([A-Za-z0-9]+)", 887 device_replacement: "LG $1", 888 manufacturer: "LG" 889 }, { 890 regex: "LG-LG([A-Za-z0-9]+)", 891 device_replacement: "LG $1", 892 manufacturer: "LG" 893 }, { 894 regex: "
894LGE-LG([A-Za-z0-9]+)", 895 device_replacement: "LG $1", 896 manufacturer: "LG" 897 }, { 898 regex: "LGE VX([A-Za-z0-9]+)", 899 device_replacement: "LG $1", 900 manufacturer: "LG" 901 }, { 902 regex: "LG ([A-Za-z0-9]+)", 903 device_replacement: "LG $1", 904 manufacturer: "LG" 905 }, { 906 regex: "LGE LG\\-AX([A-Za-z0-9]+)", 907 device_replacement: "LG $1", 908 manufacturer: "LG" 909 }, { 910 regex: "LG\\-([A-Za-z0-9]+)", 911 device_replacement: "LG $1", 912 manufacturer: "LG" 913 }, { 914 regex: "LGE\\-([A-Za-z0-9]+)", 915 device_replacement: "LG $1", 916 manufacturer: "LG" 917 }, { 918 regex: "LG([A-Za-z0-9]+)", 919 device_replacement: "LG $1", 920 manufacturer: "LG" 921 }, { 922 regex: "(KIN)\\.One (\\d+)\\.(\\d+)", 923 device_replacement: "Microsoft $1" 924 }, { 925 regex: "(KIN)\\.Two (\\d+)\\.(\\d+)", 926 device_replacement: "Microsoft $1" 927 }, { 928 regex: "(Motorola)\\-([A-Za-z0-9]+)", 929 manufacturer: "Motorola" 930 }, { 931 regex: "MOTO\\-([A-Za-z0-9]+)", 932 device_replacement: "Motorola $1", 933 manufacturer: "Motorola" 934 }, { 935 regex: "MOT\\-([A-Za-z0-9]+)", 936 device_replacement: "Motorola $1", 937 manufacturer: "Motorola" 938 }, { 939 regex: "Philips([A-Za-z0-9]+)", 940 device_replacement: "Philips $1", 941 manufacturer: "Philips" 942 }, { 943 regex: "Philips ([A-Za-z0-9]+)", 944 device_replacement: "Philips $1", 945 manufacturer: "Philips" 946 }, { 947 regex: "SAMSUNG-([A-Za-z0-9\\-]+)", 948 device_replacement: "Samsung $1", 949 manufacturer: "Samsung" 950 }, { 951 regex: "SAMSUNG\\; ([A-Za-z0-9\\-]+)", 952 device_replacement: "Samsung $1", 953 manufacturer: "Samsung" 954 }, { 955 regex: "Softbank/1\\.0/([A-Za-z0-9]+)", 956 device_replacement: "Softbank $1", 957 other: true 958 }, { 959 regex: "Softbank/2\\.0/([A-Za-z0-9]+)", 960 device_replacement: "Softbank $1", 961 other: true 962 }, { 963 regex: "(hiptop|avantgo|plucker|xiino|blazer|elaine|up.browser|up.link|mmp|smartphone|midp|wap|vodafone|o2|pocket|mobile|pda)", 964 device_replacement: "Generic Smartphone" 965 }, { 966 regex: "^(1207|3gso|4thp|501i|502i|503i|504i|505i|506i|6310|6590|770s|802s|a wa|acer|acs\\-|airn|alav|asus|attw|au\\-m|aur |aus |abac|acoo|aiko|alco|alca|amoi|anex|anny|anyw|aptu|arch|argo|bell|bird|bw\\-n|bw\\-u|beck|benq|bilb|blac|c55/|cdm\\-|chtm|capi|comp|cond|craw|dall|dbte|dc\\-s|dica|ds\\-d|ds12|dait|devi|dmob|doco|dopo|el49|erk0|esl8|ez40|ez60|ez70|ezos|ezze|elai|emul|eric|ezwa|fake|fly\\-|fly\\_|g\\-mo|g1 u|g560|gf\\-5|grun|gene|go.w|good|grad|hcit|hd\\-m|hd\\-p|hd\\-t|hei\\-|hp i|hpip|hs\\-c|htc |htc\\-|htca|htcg)", 967 device_replacement: "Generic Feature Phone" 968 }, { 969 regex: "^(htcp|htcs|htct|htc\\_|haie|hita|huaw|hutc|i\\-20|i\\-go|i\\-ma|i230|iac|iac\\-|iac/|ig01|im1k|inno|iris|jata|java|kddi|kgt|kgt/|kpt |kwc\\-|klon|lexi|lg g|lg\\-a|lg\\-b|lg\\-c|lg\\-d|lg\\-f|lg\\-g|lg\\-k|lg\\-l|lg\\-m|lg\\-o|lg\\-p|lg\\-s|lg\\-t|lg\\-u|lg\\-w|lg/k|lg/l|lg/u|lg50|lg54|lge\\-|lge/|lynx|leno|m1\\-w|m3ga|m50/|maui|mc01|mc21|mcca|medi|meri|mio8|mioa|mo01|mo02|mode|modo|mot |mot\\-|mt50|mtp1|mtv |mate|maxo|merc|mits|mobi|motv|mozz|n100|n101|n102|n202|n203|n300|n302|n500|n502|n505|n700|n701|n710|nec\\-|nem\\-|newg|neon)", 970 device_replacement: "Generic Feature Phone" 971 }, { 972 regex: "^(netf|noki|nzph|o2 x|o2\\-x|opwv|owg1|opti|oran|ot\\-s|p800|pand|pg\\-1|pg\\-2|pg\\-3|pg\\
972-6|pg\\-8|pg\\-c|pg13|phil|pn\\-2|pt\\-g|palm|pana|pire|pock|pose|psio|qa\\-a|qc\\-2|qc\\-3|qc\\-5|qc\\-7|qc07|qc12|qc21|qc32|qc60|qci\\-|qwap|qtek|r380|r600|raks|rim9|rove|s55/|sage|sams|sc01|sch\\-|scp\\-|sdk/|se47|sec\\-|sec0|sec1|semc|sgh\\-|shar|sie\\-|sk\\-0|sl45|slid|smb3|smt5|sp01|sph\\-|spv |spv\\-|sy01|samm|sany|sava|scoo|send|siem|smar|smit|soft|sony|t\\-mo|t218|t250|t600|t610|t618|tcl\\-|tdg\\-|telm|tim\\-|ts70|tsm\\-|tsm3|tsm5|tx\\-9|tagt)", 973 device_replacement: "Generic Feature Phone" 974 }, { 975 regex: "^(talk|teli|topl|tosh|up.b|upg1|utst|v400|v750|veri|vk\\-v|vk40|vk50|vk52|vk53|vm40|vx98|virg|vite|voda|vulc|w3c |w3c\\-|wapj|wapp|wapu|wapm|wig |wapi|wapr|wapv|wapy|wapa|waps|wapt|winc|winw|wonu|x700|xda2|xdag|yas\\-|your|zte\\-|zeto|aste|audi|avan|blaz|brew|brvw|bumb|ccwa|cell|cldc|cmd\\-|dang|eml2|fetc|hipt|http|ibro|idea|ikom|ipaq|jbro|jemu|jigs|keji|kyoc|kyok|libw|m\\-cr|midp|mmef|moto|mwbp|mywa|newt|nok6|o2im|pant|pdxg|play|pluc|port|prox|rozo|sama|seri|smal|symb|treo|upsi|vx52|vx53|vx60|vx61|vx70|vx80|vx81|vx83|vx85|wap\\-|webc|whit|wmlb|xda\\-|xda\\_)", 976 device_replacement: "Generic Feature Phone" 977 }, { 978 regex: "(bot|borg|google(^tv)|yahoo|slurp|msnbot|msrbot|openbot|archiver|netresearch|lycos|scooter|altavista|teoma|gigabot|baiduspider|blitzbot|oegp|charlotte|furlbot|http%20client|polybot|htdig|ichiro|mogimogi|larbin|pompos|scrubby|searchsight|seekbot|semanticdiscovery|silk|snappy|speedy|spider|voila|vortex|voyager|zao|zeal|fast\\-webcrawler|converacrawler|dataparksearch|findlinks)", 979 device_replacement: "Spider" 980 } ], 981 mobile_browser_families: [ "Firefox Mobile", "Opera Mobile", "Opera Mini", "Mobile Safari", "webOS", "IE Mobile", "Playstation Portable", "Nokia", "Blackberry", "Palm", "Silk", "Android", "Maemo", "Obigo", "Netfront", "AvantGo", "Teleca", "SEMC-Browser", "Bolt", "Iris", "UP.Browser", "Symphony", "Minimo", "Bunjaloo", "Jasmine", "Dolfin", "Polaris", "BREW", "Chrome Mobile", "Chrome Mobile iOS", "UC Browser", "Tizen Browser" ] 982 }; 983 // Parsers 984 _this.parsers = [ "device_parsers", "browser_parsers", "os_parsers", "mobile_os_families", "mobile_browser_families" ]; 985 // Types 986 _this.types = [ "browser", "os", "device" ]; 987 // Regular Expressions 988 _this.regexes = regexes || function() { 989 var results = {}; 990 _this.parsers.map(function(parser) { 991 results[parser] = []; 992 }); 993 return results; 994 }(); 995 // Families 996 _this.families = function() { 997 var results = {}; 998 _this.types.map(function(type) { 999 results[type] = []; 1000 }); 1001 return results; 1002 }(); 1003 // Utility Variables 1004 var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype, nativeForEach = ArrayProto.forEach, nativeIndexOf = ArrayProto.indexOf; 1005 // Find Utility 1006 var find = function(ua, obj) { 1007 var ret = {}; 1008 for (var i = 0; i < obj.length; i++) { 1009 ret = obj[i](ua); 1010 if (ret) { 1011 break; 1012 } 1013 } 1014 return ret; 1015 }; 1016 // Remove Utility 1017 var remove = function(arr, props) { 1018 each(arr, function(obj) { 1019 each(props, function(prop) { 1020 delete obj[prop]; 1021 }); 1022 }); 1023 }; 1024 // Contains Utility 1025 var contains = function(obj, target) { 1026 var found = false; 1027 if (obj == null) return found; 1028 if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; 1029 found = any(obj, function(value) { 1030 return value === target; 1031 }); 1032 return found; 1033 }; 1034 // Each Utility 1035 var each = forEach = function(obj, iterator, context) { 1036 if (obj == null) return;
1037 if (nativeForEach && obj.forEach === nativeForEach) { 1038 obj.forEach(iterator, context); 1039 } else if (obj.length === +obj.length) { 1040 for (var i = 0, l = obj.length; i < l; i++) { 1041 iterator.call(context, obj[i], i, obj); 1042 } 1043 } else { 1044 for (var key in obj) { 1045 if (_.has(obj, key)) { 1046 iterator.call(context, obj[key], key, obj); 1047 } 1048 } 1049 } 1050 }; 1051 // Extend Utiltiy 1052 var extend = function(obj) { 1053 each(slice.call(arguments, 1), function(source) { 1054 for (var prop in source) { 1055 obj[prop] = source[prop]; 1056 } 1057 }); 1058 return obj; 1059 }; 1060 // Check String Utility 1061 var check = function(str) { 1062 return !!(str && typeof str != "undefined" && str != null); 1063 }; 1064 // To Version String Utility 1065 var toVersionString = function(obj) { 1066 var output = ""; 1067 obj = obj || {}; 1068 if (check(obj)) { 1069 if (check(obj.major)) { 1070 output += obj.major; 1071 if (check(obj.minor)) { 1072 output += "." + obj.minor; 1073 if (check(obj.patch)) { 1074 output += "." + obj.patch; 1075 } 1076 } 1077 } 1078 } 1079 return output; 1080 }; 1081 // To String Utility 1082 var toString = function(obj) { 1083 obj = obj || {}; 1084 var suffix = toVersionString(obj); 1085 if (suffix) suffix = " " + suffix; 1086 return obj && check(obj.family) ? obj.family + suffix : ""; 1087 }; 1088 // Parse User-Agent String 1089 _this.parse = function(ua) { 1090 // Parsers Utility 1091 var parsers = function(type) { 1092 return _this.regexes[type + "_parsers"].map(function(obj) { 1093 var regexp = new RegExp(obj.regex), rep = obj[(type === "browser" ? "family" : type) + "_replacement"], major_rep = obj.major_version_replacement; 1094 function parser(ua) { 1095 var m = ua.match(regexp); 1096 if (!m) return null; 1097 var ret = {}; 1098 ret.family = (rep ? rep.replace("$1", m[1]) : m[1]) || "other"; 1099 ret.major = parseInt(major_rep ? major_rep : m[2]) || null; 1100 ret.minor = m[3] ? parseInt(m[3]) : null; 1101 ret.patch = m[4] ? parseInt(m[4]) : null; 1102 ret.tablet = obj.tablet; 1103 ret.man = obj.manufacturer || null; 1104 return ret; 1105 } 1106 return parser; 1107 }); 1108 }; 1109 // User Agent 1110 var UserAgent = function() {}; 1111 // Browsers Parsed 1112 var browser_parsers = parsers("browser"); 1113 // Operating Systems Parsed 1114 var os_parsers = parsers("os"); 1115 // Devices Parsed 1116 var device_parsers = parsers("device"); 1117 // Set Agent 1118 var a = new UserAgent(); 1119 // Remember the original user agent string 1120 a.source = ua; 1121 // Set Browser 1122 a.browser = find(ua, browser_parsers); 1123 if (check(a.browser)) { 1124 a.browser.name = toString(a.browser); 1125 a.browser.version = toVersionString(a.browser); 1126 } else { 1127 a.browser = {}; 1128 } 1129 // Set OS 1130 a.os = find(ua, os_parsers); 1131 if (check(a.os)) { 1132 a.os.name = toString(a.os); 1133 a.os.version = toVersionString(a.os); 1134 } else { 1135 a.os = {}; 1136 } 1137 // Set Device 1138 a.device = find(ua, device_parsers); 1139 if (check(a.device)) { 1140 a.device.name = toString(a.device); 1141 a.device.version = toVersionString(a.device); 1142 } else { 1143 a.device = { 1144 tablet: false, 1145 family: "Other" 1146 }; 1147 } 1148 // Determine Device Type 1149 var mobile_agents = {}; 1150 var mobile_browser_families = _this.regexes.mobile_browser_families.map(function(str) { 1151 mobile_agents[str] = true; 1152 }); 1153 var mobile_os_families = _this.regexes.mobile_os_families.map(function(str) { 1154 mobile_agents[str] = true; 1155 }); 1156 // Is Spider 1157 if (a.browser.family === "Spider") { 1158 a.device.type = "Spider"; 1159 } else if (a.browser.tablet || a.os.tablet || a.device.tablet) { 1160 a.device.type = "Tablet"; 1161 } else if (mobile_agents.hasOwnProperty(a.browser.family)) { 1162 a.device.type = "Mobile"; 1163 } else { 1164 a.device.type = "Desktop"; 1165 } 1166 // Determine Device Manufacturer 1167 a.device.manufacturer = a.browser.man || a.os.man || a.device.man || null; 1168 // Cleanup Objects 1169 remove([ a.browser, a.os, a.device ], [ "tablet", "man" ]); 1170 // Return Agent 1171 return a; 1172 }; 1173 // Return context 1174 return _this; 1175 }(); 1176 // Export the Underscore object for **Node.js** and **"CommonJS"**, 1177 // backwards-compatibility for the old `require()` API. If we're not 1178 // CommonJS, add `_` to the global object via a string identifier 1179 // the Closure Compiler "advanced" mode. Registration as an AMD 1180 // via define() happens at the end of this file 1181 if (typeof exports !== "undefined") { 1182 if (typeof module !== "undefined" && module.exports) { 1183 exports = module.exports = detect; 1184 } 1185 exports.detect = detect; 1186 } else { 1187 root["detect"] = detect; 1188 } 1189 // AMD define happens at the end for compatibility with AMD 1190 // that don't enforce next-turn semantics on modules 1191 if (typeof define === "function" && define.amd) { 1192 define(function(require) { 1193 return detect; 1194 }); 1195 } 1196})(window);
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.