PageSourceSearch

https://www.nsu.ru/local/templates/nsu_ru/js/detect.js?167402672750736

js nsu.ru collected 2026-10-01 10:19:25 UTC 50,736 bytes, 1,196 lines download raw bytes

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.