bowser.js 19 KB

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