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