detectizr.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. /*!
  2. * Detectizr v2.0.0
  3. * http://barisaydinoglu.github.com/Detectizr/
  4. *
  5. * Written by Baris Aydinoglu (http://baris.aydinoglu.info) - Copyright 2012
  6. * Released under the MIT license
  7. *
  8. * Date: 2014-03-21
  9. */
  10. window.Detectizr = (function(window, navigator, document, undefined) {
  11. var Detectizr = {},
  12. Modernizr = window.Modernizr,
  13. deviceTypes = [ "tv", "tablet", "mobile", "desktop" ],
  14. options = {
  15. // option for enabling HTML classes of all features (not only the true features) to be added
  16. addAllFeaturesAsClass: false,
  17. // option for enabling detection of device
  18. detectDevice: true,
  19. // option for enabling detection of device model
  20. detectDeviceModel: true,
  21. // option for enabling detection of screen size
  22. detectScreen: true,
  23. // option for enabling detection of operating system type and version
  24. detectOS: true,
  25. // option for enabling detection of browser type and version
  26. detectBrowser: true,
  27. // option for enabling detection of common browser plugins
  28. detectPlugins: true
  29. },
  30. plugins2detect = [ {
  31. name: "adobereader",
  32. substrs: [ "Adobe", "Acrobat" ],
  33. // AcroPDF.PDF is used by version 7 and later
  34. // PDF.PdfCtrl is used by version 6 and earlier
  35. progIds: [ "AcroPDF.PDF", "PDF.PDFCtrl.5" ]
  36. }, {
  37. name: "flash",
  38. substrs: [ "Shockwave Flash" ],
  39. progIds: [ "ShockwaveFlash.ShockwaveFlash.1" ]
  40. }, {
  41. name: "wmplayer",
  42. substrs: [ "Windows Media" ],
  43. progIds: [ "wmplayer.ocx" ]
  44. }, {
  45. name: "silverlight",
  46. substrs: [ "Silverlight" ],
  47. progIds: [ "AgControl.AgControl" ]
  48. }, {
  49. name: "quicktime",
  50. substrs: [ "QuickTime" ],
  51. progIds: [ "QuickTime.QuickTime" ]
  52. } ],
  53. rclass = /[\t\r\n]/g,
  54. docElement = document.documentElement,
  55. resizeTimeoutId,
  56. oldOrientation;
  57. function extend(obj, extObj) {
  58. var a, b, i;
  59. if (arguments.length > 2) {
  60. for (a = 1, b = arguments.length; a < b; a += 1) {
  61. extend(obj, arguments[a]);
  62. }
  63. } else {
  64. for (i in extObj) {
  65. if (extObj.hasOwnProperty(i)) {
  66. obj[i] = extObj[i];
  67. }
  68. }
  69. }
  70. return obj;
  71. }
  72. // simplified and localized indexOf method as one parameter fixed as useragent
  73. function is(key) {
  74. return Detectizr.browser.userAgent.indexOf(key) > -1;
  75. }
  76. // simplified and localized regex test method as one parameter fixed as useragent
  77. function test(regex) {
  78. return regex.test(Detectizr.browser.userAgent);
  79. }
  80. // simplified and localized regex exec method as one parameter fixed as useragent
  81. function exec(regex) {
  82. return regex.exec(Detectizr.browser.userAgent);
  83. }
  84. // localized string trim method
  85. function trim(value) {
  86. return value.replace(/^\s+|\s+$/g, "");
  87. }
  88. // convert string to camelcase
  89. function toCamel(string) {
  90. if (string === null || string === undefined) {
  91. return "";
  92. }
  93. return String(string).replace(/((\s|\-|\.)+[a-z0-9])/g, function($1) {
  94. return $1.toUpperCase().replace(/(\s|\-|\.)/g, "");
  95. });
  96. }
  97. // removeClass function inspired from jQuery.removeClass
  98. function removeClass(element, value) {
  99. var class2remove = value || "",
  100. cur = element.nodeType === 1 && (element.className ? (" " + element.className + " ").replace(rclass, " ") : "");
  101. if (cur) {
  102. while (cur.indexOf(" " + class2remove + " ") >= 0) {
  103. cur = cur.replace(" " + class2remove + " ", " ");
  104. }
  105. element.className = value ? trim(cur) : "";
  106. }
  107. }
  108. // add version test to Modernizr
  109. function addVersionTest(version, major, minor) {
  110. if ( !!version) {
  111. version = toCamel(version);
  112. if ( !!major) {
  113. major = toCamel(major);
  114. addConditionalTest(version + major, true);
  115. if ( !!minor) {
  116. addConditionalTest(version + major + "_" + minor, true);
  117. }
  118. }
  119. }
  120. }
  121. function checkOrientation() {
  122. //timeout wrapper points with doResizeCode as callback
  123. window.clearTimeout(resizeTimeoutId);
  124. resizeTimeoutId = window.setTimeout(function() {
  125. oldOrientation = Detectizr.device.orientation;
  126. //wrapper for height/width check
  127. if (window.innerHeight > window.innerWidth) {
  128. Detectizr.device.orientation = "portrait";
  129. } else {
  130. Detectizr.device.orientation = "landscape";
  131. }
  132. addConditionalTest(Detectizr.device.orientation, true);
  133. if (oldOrientation !== Detectizr.device.orientation) {
  134. addConditionalTest(oldOrientation, false);
  135. }
  136. }, 10);
  137. }
  138. // add test to Modernizr based on a condition
  139. function addConditionalTest(feature, test) {
  140. if ( !!feature && !!Modernizr) {
  141. if (options.addAllFeaturesAsClass) {
  142. Modernizr.addTest(feature, test);
  143. } else {
  144. test = typeof test === "function" ? test() : test;
  145. if (test) {
  146. Modernizr.addTest(feature, true);
  147. } else {
  148. delete Modernizr[feature];
  149. removeClass(docElement, feature);
  150. }
  151. }
  152. }
  153. }
  154. // set version based on versionFull
  155. function setVersion(versionType, versionFull) {
  156. versionType.version = versionFull;
  157. var versionArray = versionFull.split(".");
  158. if (versionArray.length > 0) {
  159. versionArray = versionArray.reverse();
  160. versionType.major = versionArray.pop();
  161. if (versionArray.length > 0) {
  162. versionType.minor = versionArray.pop();
  163. if (versionArray.length > 0) {
  164. versionArray = versionArray.reverse();
  165. versionType.patch = versionArray.join(".");
  166. } else {
  167. versionType.patch = "0";
  168. }
  169. } else {
  170. versionType.minor = "0";
  171. }
  172. } else {
  173. versionType.major = "0";
  174. }
  175. }
  176. function detect(opt) {
  177. // Create Global "extend" method, so Detectizr does not need jQuery.extend
  178. var that = this,
  179. i, j, k, device, os, browser, plugin2detect, pluginFound;
  180. options = extend({}, options, opt || {});
  181. /** Device detection **/
  182. if (options.detectDevice) {
  183. Detectizr.device = {
  184. type: "",
  185. model: "",
  186. orientation: ""
  187. };
  188. device = Detectizr.device;
  189. if (test(/googletv|smarttv|internet.tv|netcast|nettv|appletv|boxee|kylo|roku|dlnadoc|ce\-html/)) {
  190. // Check if user agent is a smart tv
  191. device.type = deviceTypes[0];
  192. device.model = "smartTv";
  193. } else if (test(/xbox|playstation.3|wii/)) {
  194. // Check if user agent is a game console
  195. device.type = deviceTypes[0];
  196. device.model = "gameConsole";
  197. } else if (test(/ip(a|ro)d/)) {
  198. // Check if user agent is a iPad
  199. device.type = deviceTypes[1];
  200. device.model = "ipad";
  201. } else if ((test(/tablet/) && !test(/rx-34/)) || test(/folio/)) {
  202. // Check if user agent is a Tablet
  203. device.type = deviceTypes[1];
  204. device.model = String(exec(/playbook/) || "");
  205. } else if (test(/linux/) && test(/android/) && !test(/fennec|mobi|htc.magic|htcX06ht|nexus.one|sc-02b|fone.945/)) {
  206. // Check if user agent is an Android Tablet
  207. device.type = deviceTypes[1];
  208. device.model = "android";
  209. } else if (test(/kindle/) || (test(/mac.os/) && test(/silk/))) {
  210. // Check if user agent is a Kindle or Kindle Fire
  211. device.type = deviceTypes[1];
  212. device.model = "kindle";
  213. } else if (test(/gt-p10|sc-01c|shw-m180s|sgh-t849|sch-i800|shw-m180l|sph-p100|sgh-i987|zt180|htc(.flyer|\_flyer)|sprint.atp51|viewpad7|pandigital(sprnova|nova)|ideos.s7|dell.streak.7|advent.vega|a101it|a70bht|mid7015|next2|nook/) || (test(/mb511/) && test(/rutem/))) {
  214. // Check if user agent is a pre Android 3.0 Tablet
  215. device.type = deviceTypes[1];
  216. device.model = "android";
  217. } else if (test(/bb10/)) {
  218. // Check if user agent is a BB10 device
  219. device.type = deviceTypes[1];
  220. device.model = "blackberry";
  221. } else {
  222. // Check if user agent is one of common mobile types
  223. device.model = exec(/iphone|ipod|android|blackberry|opera mini|opera mobi|skyfire|maemo|windows phone|palm|iemobile|symbian|symbianos|fennec|j2me/);
  224. if (device.model !== null) {
  225. device.type = deviceTypes[2];
  226. device.model = String(device.model);
  227. } else {
  228. device.model = "";
  229. if (test(/bolt|fennec|iris|maemo|minimo|mobi|mowser|netfront|novarra|prism|rx-34|skyfire|tear|xv6875|xv6975|google.wireless.transcoder/)) {
  230. // Check if user agent is unique Mobile User Agent
  231. device.type = deviceTypes[2];
  232. } else if (test(/opera/) && test(/windows.nt.5/) && test(/htc|xda|mini|vario|samsung\-gt\-i8000|samsung\-sgh\-i9/)) {
  233. // Check if user agent is an odd Opera User Agent - http://goo.gl/nK90K
  234. device.type = deviceTypes[2];
  235. } else if ((test(/windows.(nt|xp|me|9)/) && !test(/phone/)) || test(/win(9|.9|nt)/) || test(/\(windows 8\)/)) {
  236. // Check if user agent is Windows Desktop, "(Windows 8)" Chrome extra exception
  237. device.type = deviceTypes[3];
  238. } else if (test(/macintosh|powerpc/) && !test(/silk/)) {
  239. // Check if agent is Mac Desktop
  240. device.type = deviceTypes[3];
  241. device.model = "mac";
  242. } else if (test(/linux/) && test(/x11/)) {
  243. // Check if user agent is a Linux Desktop
  244. device.type = deviceTypes[3];
  245. } else if (test(/solaris|sunos|bsd/)) {
  246. // Check if user agent is a Solaris, SunOS, BSD Desktop
  247. device.type = deviceTypes[3];
  248. } else if (test(/bot|crawler|spider|yahoo|ia_archiver|covario-ids|findlinks|dataparksearch|larbin|mediapartners-google|ng-search|snappy|teoma|jeeves|tineye/) && !test(/mobile/)) {
  249. // Check if user agent is a Desktop BOT/Crawler/Spider
  250. device.type = deviceTypes[3];
  251. device.model = "crawler";
  252. } else {
  253. // Otherwise assume it is a Mobile Device
  254. device.type = deviceTypes[2];
  255. }
  256. }
  257. }
  258. for (i = 0, j = deviceTypes.length; i < j; i += 1) {
  259. addConditionalTest(deviceTypes[i], (device.type === deviceTypes[i]));
  260. }
  261. if (options.detectDeviceModel) {
  262. addConditionalTest(toCamel(device.model), true);
  263. }
  264. }
  265. /** Screen detection **/
  266. if (options.detectScreen) {
  267. if ( !!Modernizr && !!Modernizr.mq) {
  268. addConditionalTest("smallScreen", Modernizr.mq("only screen and (max-width: 480px)"));
  269. addConditionalTest("verySmallScreen", Modernizr.mq("only screen and (max-width: 320px)"));
  270. addConditionalTest("veryVerySmallScreen", Modernizr.mq("only screen and (max-width: 240px)"));
  271. }
  272. if (device.type === deviceTypes[1] || device.type === deviceTypes[2]) {
  273. window.onresize = function(event) {
  274. checkOrientation(event);
  275. };
  276. checkOrientation();
  277. } else {
  278. device.orientation = "landscape";
  279. addConditionalTest(device.orientation, true);
  280. }
  281. }
  282. /** OS detection **/
  283. if (options.detectOS) {
  284. Detectizr.os = {};
  285. os = Detectizr.os;
  286. if (device.model !== "") {
  287. if (device.model === "ipad" || device.model === "iphone" || device.model === "ipod") {
  288. os.name = "ios";
  289. setVersion(os, (test(/os\s([\d_]+)/) ? RegExp.$1 : "").replace(/_/g, "."));
  290. } else if (device.model === "android") {
  291. os.name = "android";
  292. setVersion(os, (test(/android\s([\d\.]+)/) ? RegExp.$1 : ""));
  293. } else if (device.model === "blackberry") {
  294. os.name = "blackberry";
  295. setVersion(os, (test(/version\/([^\s]+)/) ? RegExp.$1 : ""));
  296. } else if (device.model === "playbook") {
  297. os.name = "blackberry";
  298. setVersion(os, (test(/os ([^\s]+)/) ? RegExp.$1.replace(";", "") : ""));
  299. }
  300. }
  301. if (!os.name) {
  302. if (is("win") || is("16bit")) {
  303. os.name = "windows";
  304. if (is("windows nt 6.3")) {
  305. setVersion(os, "8.1");
  306. } else if (is("windows nt 6.2") || test(/\(windows 8\)/)) { //windows 8 chrome mac fix
  307. setVersion(os, "8");
  308. } else if (is("windows nt 6.1")) {
  309. setVersion(os, "7");
  310. } else if (is("windows nt 6.0")) {
  311. setVersion(os, "vista");
  312. } else if (is("windows nt 5.2") || is("windows nt 5.1") || is("windows xp")) {
  313. setVersion(os, "xp");
  314. } else if (is("windows nt 5.0") || is("windows 2000")) {
  315. setVersion(os, "2k");
  316. } else if (is("winnt") || is("windows nt")) {
  317. setVersion(os, "nt");
  318. } else if (is("win98") || is("windows 98")) {
  319. setVersion(os, "98");
  320. } else if (is("win95") || is("windows 95")) {
  321. setVersion(os, "95");
  322. }
  323. } else if (is("mac") || is("darwin")) {
  324. os.name = "mac os";
  325. if (is("68k") || is("68000")) {
  326. setVersion(os, "68k");
  327. } else if (is("ppc") || is("powerpc")) {
  328. setVersion(os, "ppc");
  329. } else if (is("os x")) {
  330. setVersion(os, (test(/os\sx\s([\d_]+)/) ? RegExp.$1 : "os x").replace(/_/g, "."));
  331. }
  332. } else if (is("webtv")) {
  333. os.name = "webtv";
  334. } else if (is("x11") || is("inux")) {
  335. os.name = "linux";
  336. } else if (is("sunos")) {
  337. os.name = "sun";
  338. } else if (is("irix")) {
  339. os.name = "irix";
  340. } else if (is("freebsd")) {
  341. os.name = "freebsd";
  342. } else if (is("bsd")) {
  343. os.name = "bsd";
  344. }
  345. }
  346. if ( !!os.name) {
  347. addConditionalTest(os.name, true);
  348. if ( !!os.major) {
  349. addVersionTest(os.name, os.major);
  350. if ( !!os.minor) {
  351. addVersionTest(os.name, os.major, os.minor);
  352. }
  353. }
  354. }
  355. if (test(/\sx64|\sx86|\swin64|\swow64|\samd64/)) {
  356. os.addressRegisterSize = "64bit";
  357. } else {
  358. os.addressRegisterSize = "32bit";
  359. }
  360. addConditionalTest(os.addressRegisterSize, true);
  361. }
  362. /** Browser detection **/
  363. if (options.detectBrowser) {
  364. browser = Detectizr.browser;
  365. if (!test(/opera|webtv/) && (test(/msie\s([\d\w\.]+)/) || is("trident"))) {
  366. browser.engine = "trident";
  367. browser.name = "ie";
  368. if (!window.addEventListener && document.documentMode && document.documentMode === 7) {
  369. setVersion(browser, "8.compat");
  370. } else if (test(/trident.*rv[ :](\d+)\./)) {
  371. setVersion(browser, RegExp.$1);
  372. } else {
  373. setVersion(browser, (test(/trident\/4\.0/) ? "8" : RegExp.$1));
  374. }
  375. } else if (is("firefox")) {
  376. browser.engine = "gecko";
  377. browser.name = "firefox";
  378. setVersion(browser, (test(/firefox\/([\d\w\.]+)/) ? RegExp.$1 : ""));
  379. } else if (is("gecko/")) {
  380. browser.engine = "gecko";
  381. } else if (is("opera")) {
  382. browser.name = "opera";
  383. browser.engine = "presto";
  384. setVersion(browser, (test(/version\/([\d\.]+)/) ? RegExp.$1 : (test(/opera(\s|\/)([\d\.]+)/) ? RegExp.$2 : "")));
  385. } else if (is("konqueror")) {
  386. browser.name = "konqueror";
  387. } else if (is("chrome")) {
  388. browser.engine = "webkit";
  389. browser.name = "chrome";
  390. setVersion(browser, (test(/chrome\/([\d\.]+)/) ? RegExp.$1 : ""));
  391. } else if (is("iron")) {
  392. browser.engine = "webkit";
  393. browser.name = "iron";
  394. } else if (is("crios")) {
  395. browser.name = "chrome";
  396. browser.engine = "webkit";
  397. setVersion(browser, (test(/crios\/([\d\.]+)/) ? RegExp.$1 : ""));
  398. } else if (is("applewebkit/")) {
  399. browser.name = "safari";
  400. browser.engine = "webkit";
  401. setVersion(browser, (test(/version\/([\d\.]+)/) ? RegExp.$1 : ""));
  402. } else if (is("mozilla/")) {
  403. browser.engine = "gecko";
  404. }
  405. if ( !!browser.name) {
  406. addConditionalTest(browser.name, true);
  407. if ( !!browser.major) {
  408. addVersionTest(browser.name, browser.major);
  409. if ( !!browser.minor) {
  410. addVersionTest(browser.name, browser.major, browser.minor);
  411. }
  412. }
  413. }
  414. addConditionalTest(browser.engine, true);
  415. // Browser Language
  416. browser.language = navigator.userLanguage || navigator.language;
  417. addConditionalTest(browser.language, true);
  418. }
  419. /** Plugin detection **/
  420. if (options.detectPlugins) {
  421. browser.plugins = [];
  422. that.detectPlugin = function(substrs) {
  423. var plugins = navigator.plugins,
  424. plugin, haystack, pluginFoundText;
  425. for (j = plugins.length - 1; j >= 0; j--) {
  426. plugin = plugins[j];
  427. haystack = plugin.name + plugin.description;
  428. pluginFoundText = 0;
  429. for (k = substrs.length; k >= 0; k--) {
  430. if (haystack.indexOf(substrs[k]) !== -1) {
  431. pluginFoundText += 1;
  432. }
  433. }
  434. if (pluginFoundText === substrs.length) {
  435. return true;
  436. }
  437. }
  438. return false;
  439. };
  440. that.detectObject = function(progIds) {
  441. for (j = progIds.length - 1; j >= 0; j--) {
  442. try {
  443. new ActiveXObject(progIds[j]);
  444. } catch (e) {
  445. // Ignore
  446. }
  447. }
  448. return false;
  449. };
  450. for (i = plugins2detect.length - 1; i >= 0; i--) {
  451. plugin2detect = plugins2detect[i];
  452. pluginFound = false;
  453. if (window.ActiveXObject) {
  454. pluginFound = that.detectObject(plugin2detect.progIds);
  455. } else if (navigator.plugins) {
  456. pluginFound = that.detectPlugin(plugin2detect.substrs);
  457. }
  458. if (pluginFound) {
  459. browser.plugins.push(plugin2detect.name);
  460. addConditionalTest(plugin2detect.name, true);
  461. }
  462. }
  463. if (navigator.javaEnabled()) {
  464. browser.plugins.push("java");
  465. addConditionalTest("java", true);
  466. }
  467. }
  468. }
  469. Detectizr.detect = function(settings) {
  470. return detect(settings);
  471. };
  472. Detectizr.init = function() {
  473. if (Detectizr !== undefined) {
  474. Detectizr.browser = {
  475. userAgent: (navigator.userAgent || navigator.vendor || window.opera).toLowerCase()
  476. };
  477. Detectizr.detect();
  478. }
  479. };
  480. Detectizr.init();
  481. return Detectizr;
  482. }(this, this.navigator, this.document));