userAgent,JS这么屌的用户代理,你造吗?——判断浏览器内核、浏览器、浏览器平台、windows操作系统版本、移动设备、游戏系统
1、识别浏览器呈现引擎
为了不在全局作用域中添加多余变量,这里使用单例模式(什么是单例模式?)来封装检测脚本。检测脚本的基本代码如下所示:
1 var client = function() { 2 var engine = { 3 ie: 0, 4 gecko: 0, 5 webkit: 0, 6 khtml: 0, 7 opera: 0, 8 9 // 具体的版本号 10 ver: null 11 }; 12 13 return { 14 engine: engine 15 } 16 }();
这里声明了一个名为client的全局变量,用于保存相关信息。匿名函数内部定义了一个局部变量engine,它是一个包含默认设置的对象字面量。在这个对象字面量中,每个呈现引擎都对应着一个属性,属性的默认值是0。如果检测到了哪个呈现引擎,那么就以浮点数值形式将该引擎的版本号写入相应属性。
要识别Opera,必须得检测window.opera对象。Opera5及更高版本中都有这个对象,用于保存与浏览器相关的标识信息以及与浏览器直接交互。在Opera7.6及更高版本中,调用version()方法可以返回一个表示浏览器版本的字符串,而这也是确定Opera版本的最佳方式。要检测更早的Opera,可以直接检测用户代理字符串,因为那些版本还不支持隐藏身份。不过2007底Opera的最高版本已经是9.5了,所以不太可能有人还使用7.6之前的版本。那么,检测呈现引擎的代码的第一步,就是编写如下代码:
1 if (window.opera) { 2 engine.ver = window.opera.version(); 3 engine.opra = parseFloat(engine.ver); 4 }
接下来检测的引擎是webkit,因为webkit的用户代理字符串中包含“Gecko”和“KHTML”这两个子字符串,所以如果先检测它们,都可能会得出错误的结论。
不过,Webkit的用户代理字符串中的“AppleWebkit”是独一无二的,因此检测这个字符串是最合适的。下面就是检测该字符串的示例代码:
1 var ua = navigator.userAgent; 2 if (window.opera) { 3 engine.ver = window.opera.version(); 4 engine.opra = parseFloat(engine.ver); 5 } else if (/AppleWebkit\/(\S+)/i.test(ua)) { 6 engine.ver = RegExp['$1']; 7 engine.webkit = parseFloat(engine.ver); 8 }
接下来要测试的引擎是KHTML。同样,KHTML的用户代理字符串中也包含“Gecko”,因此在排除KHTML之前,我们无法准确检测基于Gecko的浏览器。KHTML的版本号与Webkit的版本号在用户代理字符串中的格式差不多,因此可以使用类似的正则表达式。此外,由于Konquerror 3.1及更早版本中不包含KHTML的版本,故而就要使用Konqueror的版本来代替。下面就是相应的检测代码。
1 var ua = navigator.userAgent; 2 if (window.opera) { 3 // 检测opera 4 engine.ver = window.opera.version(); 5 engine.opra = parseFloat(engine.ver); 6 } else if (/AppleWebkit\/(\S+)/i.test(ua)) { 7 // 检测webkit 8 engine.ver = RegExp['$1']; 9 engine.webkit = parseFloat(engine.ver); 10 } else if (/KHTML\/(\S+)/i.test(ua) || /Konqueror\/([^;]+)/i.test(ua)) { 11 // 检测khtml 12 engine.ver = RegExp['$1']; 13 engine.khtml = parseFloat(engine.ver); 14 }
在排除了Webkit和KHTML之后,就可以准确地检测Gecko了。但是,在用户代理字符串中,Gecko的版本号不会出现在字符串“Gecko”的后面,而是会出现在字符串“rv:”的后面。这样,我们就必须使用一个比前面复杂一些的正则表达式,如下所示。
1 var ua = navigator.userAgent; 2 if (window.opera) { 3 // 检测opera 4 engine.ver = window.opera.version(); 5 engine.opra = parseFloat(engine.ver); 6 } else if (/AppleWebkit\/(\S+)/i.test(ua)) { 7 // 检测webkit 8 engine.ver = RegExp['$1']; 9 engine.webkit = parseFloat(engine.ver); 10 } else if (/KHTML\/(\S+)/i.test(ua) || /Konqueror\/([^;]+)/i.test(ua)) { 11 // 检测khtml 12 engine.ver = RegExp['$1']; 13 engine.khtml = parseFloat(engine.ver); 14 } else if (/rv:([^\)]+)\) Gecko\/\d{8}/i.test(ua)) { 15 // 检测gecko 16 engine.ver = RegExp['$1']; 17 engine.gecko = parseFloat(engine.ver); 18 }
最后一个要检测的就是IE了。IE的版本号们于字符串“MSIE”的后面、一个分号的前面,因此相应的正则表达式非常简单,如下所示:
1 var ua = navigator.userAgent; 2 if (window.opera) { 3 // 检测opera 4 engine.ver = window.opera.version(); 5 engine.opra = parseFloat(engine.ver); 6 } else if (/AppleWebkit\/(\S+)/i.test(ua)) { 7 // 检测webkit 8 engine.ver = RegExp['$1']; 9 engine.webkit = parseFloat(engine.ver); 10 } else if (/KHTML\/(\S+)/i.test(ua) || /Konqueror\/([^;]+)/i.test(ua)) { 11 // 检测khtml 12 engine.ver = RegExp['$1']; 13 engine.khtml = parseFloat(engine.ver); 14 } else if (/rv:([^\)]+)\) Gecko\/\d{8}/i.test(ua)) { 15 // 检测gecko 16 engine.ver = RegExp['$1']; 17 engine.gecko = parseFloat(engine.ver); 18 } else if (/MSIE ([^;]+/i.test(ua))/) { 19 // 检测ie 20 engine.ver = RegExp['$1']; 21 engine.ie = parseFloat(engine.ver); 22 }
2、识别浏览器
大多数情况下,识别了浏览器的呈现引擎就足以为我们采取正确的操作提供依据了。可是,只有呈现引擎还不能说明存在所需的JavaScript功能。苹果公司的Safari浏览器和谷歌公司的Chrome浏览器都使用Webkit引擎,但它们的JavaScript引擎却不一样。在这两款浏览器中,client.webkit都会返回非0值,但仅知道这一点恐怕还不够。对于它们,有必要像下面这样为client对象再添加一些新属性。
1 var client = function() { 2 var engine = { 3 ie: 0, 4 gecko: 0, 5 webkit: 0, 6 khtml: 0, 7 opera: 0, 8 9 // 具体的版本号 10 ver: null 11 }; 12 13 var browser = { 14 // 浏览器 15 ie: 0, 16 firefox: 0, 17 safari: 0, 18 konq: 0, 19 opera: 0, 20 chrome: 0, 21 22 // 具体的版本号 23 ver: null 24 }; 25 26 return { 27 engine: engine, 28 browser: browser 29 } 30 }();
代码中又添加了browser,用于保存每个主要浏览器的属性。与engine变量一样,除了当前使用的浏览器,其它属性的值将保持为0。如果是当前使用的浏览器,则这个属性中保存的是浮点数值形式的版本号。同样,ver属性中必要时将会包含字符串形式的浏览器完整版本号。由于大多数浏览器与呈现引擎密切相关,所以下面示例中检测浏览器代码与检测呈现引擎的代码是混合在一起的。
1 var client = function() { 2 var engine = { 3 ie: 0, 4 gecko: 0, 5 webkit: 0, 6 khtml: 0, 7 opera: 0, 8 9 // 具体的版本号 10 ver: null 11 }; 12 13 var browser = { 14 // 浏览器 15 ie: 0, 16 firefox: 0, 17 safari: 0, 18 konq: 0, 19 opera: 0, 20 chrome: 0, 21 22 // 具体的版本号 23 ver: null 24 }; 25 26 var ua = navigator.userAgent; 27 if (window.opera) { 28 // 检测opera 29 engine.ver = browser.ver = window.opera.version(); 30 engine.opra = browser.opera = parseFloat(engine.ver); 31 } else if (/AppleWebkit\/(\S+)/i.test(ua)) { 32 // 检测webkit 33 engine.ver = RegExp['$1']; 34 engine.webkit = parseFloat(engine.ver); 35 36 // 检测Chrome/safari与其对应的版本 37 if (/Chrome\/(\S+)/i.test(ua)) { 38 browser.ver = RegExp['$1']; 39 browser.chrome = parseFloat(browser.ver); 40 } else if (/Version\/(\S+)/i.test(ua)) { 41 browser.ver = RegExp['$1']; 42 browser.safari = parseFloat(browser.ver); 43 } else { 44 // 当检测不出Safari版本时,可大致确定safari的版本 45 var safariVersion = 1; 46 47 if (engine.webkit < 100) { 48 safariVersion = 1; 49 } else if (engine.webkit < 312) { 50 safariVersion = 1.2; 51 } else if (engine.webkit < 412) { 52 safariVersion = 1.3; 53 } else { 54 safariVersion = 2; 55 } 56 57 browser.safari = browser.ver = safariVersion; 58 } 59 } else if (/KHTML\/(\S+)/i.test(ua) || /Konqueror\/([^;]+)/i.test(ua)) { 60 // 检测khtml 61 engine.ver = browser.ver = RegExp['$1']; 62 engine.khtml = browser.konq = parseFloat(engine.ver); 63 } else if (/rv:([^\)]+)\) Gecko\/\d{8}/i.test(ua)) { 64 // 检测gecko 65 engine.ver = RegExp['$1']; 66 engine.gecko = parseFloat(engine.ver); 67 68 // 确定是不是Firefox 69 if (/Firefox\/(\S)+/i.test(ua)) { 70 browser.ver = RegExp['$1']; 71 browser.firefox = parseFloat(browser.ver); 72 } 73 } else if (/MSIE ([^;]+/i.test(ua))/) { 74 // 检测ie 75 engine.ver = browser.ver = RegExp['$1']; 76 engine.ie = browser.ie = parseFloat(engine.ver); 77 } 78 79 return { 80 engine: engine, 81 browser: browser 82 } 83 }();
3、识别浏览器平台——操作系统
很多时候,只要知道呈现引擎足以编写出适当的代码了。但在某些条件下,平台可能是必须关注的问题。那些具有各个平台的浏览器(如Safari、Firefox、Opera)在不同的平台下可能会有不同的问题。目前的三大主流平台是Windows、Mac和Unix(包括各种Linux)。为了检测这些平台,还需要像下面这样添加一个新对象。
1 var client = function() { 2 var engine = { 3 ie: 0, 4 gecko: 0, 5 webkit: 0, 6 khtml: 0, 7 opera: 0, 8 9 // 具体的版本号 10 ver: null 11 }; 12 13 var browser = { 14 // 浏览器 15 ie: 0, 16 firefox: 0, 17 safari: 0, 18 konq: 0, 19 opera: 0, 20 chrome: 0, 21 22 // 具体的版本号 23 ver: null 24 }; 25 26 var system = { 27 win: false, 28 mac: false, 29 xll: false 30 }; 31 32 return { 33 engine: engine, 34 browser: browser 35 } 36 }();
在确定平台时,检测navigator.platform要比检测用户代理字符串更简单,后者在不同浏览器中会给出不同平台的信息。而navigator.platform属性可能的值包括“Win32”、“Win64”、“MacPPC”、“MacIntel”、“Xll”和“Linux i686”,这些值在不同浏览器中都是一致的。检测平台的代码非常直观,如下所示:
1 var p = navigator.platform; 2 system.win = p.indexOf('Win') == 0; 3 system.mac = p.indexOf('Mac') == 0; 4 system.xll = (p.indexOf('Xll') == 0 || p.indexOf('Linux') == 0);
4、识别Window操作系统
在Windows下台下,还可以从用户代理字符串中进一步以得具体的操作系统信息。在WIndows XP之前,Windows有两种版本,分别针对家庭版用户和商业用户。针对家庭用户的版本分别是Windows 95、98和Windows ME。而针对商业用户的版本则一直叫做Windows NT,最后由于市场原因改名为Windows 2000。这两个产品后来又合并成一个由Windows NT发展而来的公共的代码基,代表产品就是Winodws XP。随后,微软在Windows XP基础上又构建Windows Vista。
只有了解这些信息,才能搞清楚用户代理字符串中Winodws操作系统具体版本。下表列出了不同浏览器在表示不同Windows操作系统时给出的不同字符串。
windows版本 | IE4+ | Gecko | Opera | Webkit |
---|---|---|---|---|
95 | “Windows 95” | “Win95” | “Windows 95” | n/a |
98 | “Winodws 98” | “Win98” | “Windows 98” | n/a |
NT 4.0 | “Windows NT” | “WinNT4.0” | “windows NT 4.0” | n/a |
2000 | “Windows NT 5.0” | “Windows NT 5.0” | “Windows NT 5.0” | n/a |
ME | “Win 9x 4.90” | “Win 9x 4.90” | “Win 9x 4.90” | n/a |
XP | “Windows NT 5.1” | “Windows NT 5.1” | “Windows NT 5.1” | “Windows NT 5.1” |
Vista | “Windows NT 6.0” | “Windows NT 6.0” | “Windows NT 6.0” | “Windows NT 6.0” |
7 | “Windows NT 6.1” | “Windows NT 6.1” | “Windows NT 6.1” | “Windows NT 6.1” |
8 | “Windows NT 6.2” | “Windows NT 6.2” | “Windows NT 6.2” | “Windows NT 6.2” |
由于用户代理字符串中的Windows操作系统版本表示方法各异,因此检测代码并不十分直观。好在,从Windows 2000开始,表示操作系统的字符串大部分都还相同,只有版本号有变化。为了检测不同的Windows操作系统,必须使用正则表达式。
第一步就是匹配Winodws 95和Windows 98这两个字符串。对这两个字符串,只有Gecko与其它浏览器不同,即没有"dows",而且"win"与版本号之间没有空格。要匹配这个模式,可以使用下面这个简单的正则表达式:
1 /Win(?:dows )?([^do]{2})/i
这个正则表达式中捕获的数组会返回操作系统的版本。由于版本可能是任何两个字符编码(例如 95、98、9x、NT、ME及XP),因此要使用两个非空空格字符。
Gecko在表示Windows NT时会在末尾添加“4.0”,与其查找实际字符串,不如像现在这样查找小数值更合适。
1 /Win(?:dows )?([^do]{2})(\d+\.\d+)?/i
这样,正则表达式中就包含了第二个捕获组,用于取得NT的版本号。由于该版本号对于Windows 95、98而言是不存在的,所以必须设置为可选。这个模式与Opera表示Windows NT的字符串之间唯一的区别,就是“NT”与“4.0”之间的空格,这在模式中很容易添加。
1 /Win(?:dows )?([^do]{2})\s+(\d+\.\d+)?/i
经过一番修改后,这个正则表达式也可以成功匹配Windows ME、Windows XP和Windows Vista的字符串了。具体来说,第一个捕获数组将会匹配95、98、9x、NT、ME或XP。第二个捕获数组则只针对Windows ME及所有WIndows NT的变体。这个信息作为具体的操作系统信息保存在system.win属性中,如下所示:
1 if (system.win) { 2 if (/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/i.test(ua)) { 3 if (RegExp['$1'] == 'NT') { 4 switch (RegExp['$2']) { 5 case '5.0': system.win = '2000'; break; 6 case '5.1': system.win = 'XP'; break; 7 case '6.0': system.win = 'Vista'; break; 8 case '6.1': system.win = '7'; break; 9 case '6.2': system.win = '8'; break; 10 default: system.win = 'NT'; break; 11 } 12 } else if (RegExp['$1'] == '9x') { 13 system.win = 'ME'; 14 } else { 15 system.win = RegExp['$1']; 16 } 17 } 18 }
5、识别移动设备
2006到2007年,移动设备中Web浏览器的应用呈爆炸式增长。四大主要浏览器都推出了手机版和其它设备中运行的版本。要检测相应的设备,第一步是为要检测的所有移动设备添加属性,如下所示:
1 var client = function() { 2 var engine = { 3 ie: 0, 4 gecko: 0, 5 webkit: 0, 6 khtml: 0, 7 opera: 0, 8 9 // 具体的版本号 10 ver: null 11 }; 12 13 var browser = { 14 // 浏览器 15 ie: 0, 16 firefox: 0, 17 safari: 0, 18 konq: 0, 19 opera: 0, 20 chrome: 0, 21 22 // 具体的版本号 23 ver: null 24 }; 25 26 var system = { 27 win: false, 28 mac: false, 29 xll: false, 30 31 // 移动设备 32 iphone: false, 33 ipod: false, 34 ipad: false, 35 ios: false, 36 android: false, 37 nokiaN: false, 38 winMobile: false 39 }; 40 41 return { 42 engine: engine, 43 browser: browser, 44 system: system 45 } 46 47 }();
然后,通过简单地检测字符串“iPhone”、"iPod"和"iPad"就可以分别设置相应属性的值了。
1 system.iphone = ua.indexOf('iPhone') > -1; 2 system.ipod = ua.indexOf('iPod') > -1; 3 system.ipad = ua.indexOf('iPad') > -1;
除了知道IOS设备,最好还知道IOS的版本号。在IOS之前,用户代理字符串中只包含“CPU like Mac OS”,后来iPhone中又改成“CPU iPhone OS 3_0 like Mac OS X”,iPad又改成“CPU OS 3_2 like Mac OS X”。也就是说,检测IOS需要正则表达式反映这些变化。
1 // 检测ios版本 2 if (system.mac && ua.indexOf('Mobile') > -1) { 3 if (/CPU (?:iPhone )?OS (\d+_\d+)/i.test(ua)) { 4 system.ios = parseFloat(RegExp['$1'].replace('_', '.')); 5 } else { 6 system.ios = 2; // 不能真正检测出来,所以只能猜测 7 } 8 }
检测系统是不是Mac OS、字符串中是否存在“Mobile”,可以保证无论是什么版本,system.ios中都不会是0。然后,再使用正则表达式确定是否存在IOS的版本号。如果有,将system.ios设置为表示版本号的浮点值;否则,将版本号设置为2。(因为没有办法确定到底是什么版本,所以设置为更早的版本比较稳妥)
检测Android版本操作系统也很简单,也就是搜索字符串“Android”并取得紧随其后的版本号。
1 // 检测android版本 2 if (/Android (\d+\.\d+)/i.test(ua)) { 3 system.android = parseFloat(RegExp['$1']); 4 }
由于所有的Android都有版本值,因此使用这个正则表达式可以精确的检测所有版本,并将system.android设置为正确的值。
诺基亚N系统手机使用的也是Webkit,其用户代理字符串与其它基于webkit的手机很相似。虽然诺基亚N系列手机在用户代理字符串中声称使用的是“safari”,但实际上并不是safari,尽管确实是基于webkit引擎。只要使用下面检测一下用户代理字符串中是否存在“NokiaN”,就足以确定是不是该系列的手机了。
1 // 检测nokia 2 system.nokiaN = ua.indexOf('NokiaN') > -1;
最后一种主要的移动设备平台是Windows Mobile(也称Windows CE),用于Pocket PC和Smartphone中。由于从技术上说这些平台都属于Windows平台,因此Windows平台和操作系统都会返回正确的值。对于Windows Mobile 5.0及以前的版本,这两种设备的用户代理字符串非常相似,如下所示:
Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; PPC; 240x320)
Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; Smartphone; 176x220)
这一个来自Pocket PC中的移动Internet Explorer 4.01,第二个来自Smartphone中的同一个浏览器。当Windows操作系统检测脚本检测到这两个字符串时,system.win将被设置成"CE",因此在检测Windows Mobile时可以使用这个值:
1 // 检测Windows Mobile 2 system.winMobile = (system.win == 'CE');
不建议测试字符串中的“PPC”或“Smartphone”,因为在Windows Mobile 5.0以后版本的浏览器中,这些记号已经被移除了。不过,一般情况下,只知道这某个设备使用的是Windows Mobile也就足够了。
Windows Phone 7的用户代理字符串稍有改进,基本格式如下:
Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0) Asus;Galaxy6
其中,Windows操作符的标签符与已往完全不同,因此在这个用户代理中,clinet.system.win等于"ph"。从中可以取得有关系统的更多信息:
1 // 检测Windows Mobile 2 if (system.win == 'CE') { 3 system.winMobile = system.win; 4 } else if (system.win == 'Ph') { 5 if (/Windows Phone OS (\d+.\d+)/i.test(ua)) { 6 system.win = 'Phone'; 7 system.winMobile = parseFloat(RegExp['$1']); 8 } 9 }
如果system.win的值是"CE",就说明是老版本的Windows Mobile,因此system.winMobile会被设置为相同的值(只能知道这个信息)。如果system.win的值是“Ph”,那么这个设置就可能是Windows Phone7或更新版本。因此就用正则表达式来测试格式并提取版本号,将system.win的值重置为"Phone",而将system.winMobile设置为版本号。
6、识别游戏系统
除了移动设备之外,视频游戏系统中的Web浏览器也开始日益普及。Wii中的浏览器实际上是定制版的Opera,是专门为Wii Remote设计的。Playstation的浏览器是自己开发的,没有基于前面提到的任何呈现引擎。这两个中的用户代理字符串如下所示:
Opera/9.10 (Nintendo Wii; U; ; 1621; en)
Mozilla/5.0 (PLAYSTATION 3; 2.00)
在检测这些设置以前,我们必须先为client.system中添加适当的属性,如下所示:
1 var client = function() { 2 var engine = { 3 ie: 0, 4 gecko: 0, 5 webkit: 0, 6 khtml: 0, 7 opera: 0, 8 9 // 具体的版本号 10 ver: null 11 }; 12 13 var browser = { 14 // 浏览器 15 ie: 0, 16 firefox: 0, 17 safari: 0, 18 konq: 0, 19 opera: 0, 20 chrome: 0, 21 22 // 具体的版本号 23 ver: null 24 }; 25 26 var system = { 27 win: false, 28 mac: false, 29 xll: false, 30 31 // 移动设备 32 iphone: false, 33 ipod: false, 34 ipad: false, 35 ios: false, 36 android: false, 37 nokiaN: false, 38 winMobile: false, 39 40 // 游戏系统 41 wii: false, 42 ps: false 43 }; 44 45 return { 46 engine: engine, 47 browser: browser, 48 system: system 49 } 50 51 }();
检测前述游戏系统的代码如下:
1 // 检测游戏系统 2 system.wii = ua.indexOf('Wii') > -1; 3 system.ps = /playstation/i.test(ua);
完整的代码:
1 var client = function() { 2 var engine = { 3 ie: 0, 4 gecko: 0, 5 webkit: 0, 6 khtml: 0, 7 opera: 0, 8 ver: null 9 }; 10 11 var browser = { 12 ie: 0, 13 firefox: 0, 14 safari: 0, 15 konq: 0, 16 opera: 0, 17 chrome: 0, 18 ver: null 19 }; 20 21 var system = { 22 win: false, 23 mac: false, 24 xll: false, 25 iphone: false, 26 ipoad: false, 27 ipad: false, 28 ios: false, 29 android: false, 30 nokiaN: false, 31 winMobile: false, 32 wii: false, 33 ps: false 34 }; 35 36 var ua = navigator.userAgent; 37 // 检测浏览器呈现引擎 38 if (window.opera) { 39 engine.ver = browser.ver = window.opera.version(); 40 engine.opera = browser.opera = parseFloat(engine.ver); 41 } else if (/AppleWebkit\/(\S+)/i.test(ua)) { 42 engine.ver = RegExp['$1']; 43 engine.webkit = parseFloat(engine.ver); 44 45 // 确定是Chrome还是Safari 46 if (/Chrome\/(\S+)/i.test(ua)) { 47 browser.ver = RegExp['$1']; 48 browser.chrome = parseFloat(browser.ver); 49 } else if (/Version\/(\S+)/i.test(ua)) { 50 browser.ver = RegExp['$1']; 51 browser.safari = parseFloat(browser.ver); 52 } else { 53 // 近似地确定版本号 54 var safariVersion = 1; 55 if (engine.webkit < 100) { 56 safariVersion = 1; 57 } else if (engine.webkit < 312) { 58 safariVersion = 1.2; 59 } else if (engine.webkit < 412) { 60 safariVersion = 1.3; 61 } else { 62 safariVersion = 2; 63 } 64 65 browser.safari = browser.safari = safariVersion; 66 } 67 } else if (/KHTML\/(\S+)/i.test(ua) || /Konqueror\/([^;]+)/i.test(ua)) { 68 engine.ver = browser.ver = RegExp['$1']; 69 engine.khtml = browser.konq = parseFloat(engine.ver); 70 } else if (/rv:([^\)]+)\) Gecko\/\d{8}/i.test(ua)) { 71 engine.ver = RegExp['$1']; 72 engine.gecko = parseFloat(engine.ver); 73 74 // 确定是不是Firefox 75 if (/Firefox\/(\S+)/i.test(ua)) { 76 engine.ver = browser.ver = RegExp['$1']; 77 engine.firefox = parseFloat(browser.ver); 78 } 79 } else if (/MSIE ([^;]+)/i.test(ua)) { 80 engine.ver = browser.ver = RegExp['$1']; 81 engine.ie = browser.ie = parseFloat(engine.ver); 82 } 83 84 // 检测平台 85 var p = navigator.platform; 86 system.win = p.indexOf('Win') == 0; 87 system.mac = p.indexOf('Mac') == 0; 88 system.xll = (p.indexOf('Xll') == 0 || p.indexOf('Linux') == 0); 89 90 // 检测Windows操作系统 91 if (system.win) { 92 if (/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/.test(ua)) { 93 if (RegExp['$1'] == 'NT') { 94 switch(RegExp['$2']) { 95 case '5.0': system.win = '2000'; break; 96 case '5.1': system.win = 'XP'; break; 97 case '6.0': system.win = 'Vista'; break; 98 case '6.1': system.win = '7'; break; 99 case '6.2': system.win = '8'; break; 100 default: system.win = 'NT'; break; 101 } 102 } else if (RegExp['$1'] == '9x') { 103 system.win = 'ME'; 104 } else { 105 system.win = RegExp['$1']; 106 } 107 } 108 } 109 110 // 移动设备 111 system.iphone = ua.indexOf('iPhone') > -1; 112 system.ipod = ua.indexOf('iPod') > -1; 113 system.ipad = ua.indexOf('iPad') > -1; 114 system.nokiaN = ua.indexOf('nokiaN') > -1; 115 116 // windows mobile 117 if (system.win == 'CE') { 118 system.winMobile = system.win; 119 } else if (system.win == 'Ph') { 120 if (/Windows Phone OS (\d+.\d)/i.test(ua)) { 121 system.win = 'Phone'; 122 system.winMobile = parseFloat(RegExp['$1']); 123 } 124 } 125 126 // 检测IOS版本 127 if (system.mac && ua.indexOf('Mobile') > -1) { 128 if (/CPU (?:iPhone )?OS (\d+_\d+)/i.test(ua)) { 129 system.ios = parseFloat(RegExp['$1'].replace('_', '.')); 130 } else { 131 system.ios = 2; // 不能真正检测出来,所以只能猜测 132 } 133 } 134 135 // 检测Android版本 136 if (/Android (\d+\.\d+)/i.test(ua)) { 137 system.android = parseFloat(RegExp['$1']); 138 } 139 140 // 游戏系统 141 system.wii = ua.indexOf('Wii') > -1; 142 system.ps = /PlayStation/i.test(ua); 143 144 return { 145 engine: engine, 146 browser: browser, 147 system: system 148 } 149 }();
(注:原文摘自《JavaScript高级程序设计》第3版,第9章 客户端检测,9.3用户代理检测,p221)