1. Firefox
Gecko是firefox的呈现引擎。当初的Gecko是作为通用Mozilla浏览器一部分开发的,而第一个采用Gecko引擎的浏览器是Netscape6;
我们可以使用用户代理检测下:如下JS代码:
1
2
|
var
ua
=
navigator
.
userAgent
;
console
.
log
(
ua
)
;
|
在windows下firefox下打印如下:
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0
上述是为Netscape6编写的代理字符串一些构成:如下:
Mozilla/Mozilla版本号(平台;加密类型;操作系统或CPU;预先发行的版本;Gecko/Gecko版本号;应用程序或产品/应用程序或产品版本号);
2. Safari
Safari的呈现引擎是WebKit;是Linux平台中Konqueror浏览器的呈现引擎KHTML的一个分支;几年后,webkit独立出来成为一个开源项目,专注于呈现引擎开发;
如下代码:
1
2
|
var
ua
=
navigator
.
userAgent
;
console
.
log
(
ua
)
;
|
在windows下safari下打印如下:
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2
Webkit的用户代理字符串具备如下格式:
Mozilla/5.0 (平台;加密类型;操作系统或cpu) AppleWebkit/AppleWebkit版本号(KHTML,like Gecko) safari/safari版本号;
3. Chrome
谷歌公司的chrome浏览器以webkit作为呈现引擎,使用了不同的javascript引擎;
如下JS代码:
1
2
|
var
ua
=
navigator
.
userAgent
;
console
.
log
(
ua
)
;
|
在windows下chrome下打印如下:
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36
用户代理字符串完全自取webkit,只添加了一段表示chrome版本号信息;格式如下:
Mozilla/5.0 (平台;加密类型;操作系统或cpu) AppleWebKit/AppleWebKit版本号(KHTML,like Gecko) chrome/chrome版本号 safari/safari版本号
4. Opera
Opera默认的用户代理字符串是所有现代浏览器中最合理的—正确地标识了自身极其版本号,在Opera8.0之前;其用户代理字符串采用如下格式:
Opera/ 版本号 (操作系统或CPU;加密类型) [语言]
Opera8发布后,用户代理字符串的 “语言”部分被移到圆括号内,以便更好地与其他浏览器匹配;如下所示:
Opera/版本号 (操作系统或CPU;加密类型;语言)
在现在的最新的版本opera29,
如下JS代码:
1
2
|
var
ua
=
navigator
.
userAgent
;
console
.
log
(
ua
)
;
|
通过代理检测如下:
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36 OPR/29.0.1795.60;
5. IE
自从IE3以来,微软已经将IE的用户代理字符串修改成兼容Netscape的形式,结构如下:
Mozilla/版本号(平台;加密类型;操作系统或CPU);
但是IE8+的用户代理字符串添加了呈现引擎的(Trident)的版本号;
JS代码如下:
1
2
|
var
ua
=
navigator
.
userAgent
.
toLowerCase
(
)
;
console
.
log
(
ua
)
;
|
比如在window下 IE7的如下:
mozilla/4.0 (compatible; msie 7.0; windows nt 6.1; wow64; trident/7.0; slcc2; .net clr 2.0.50727; .net clr 3.5.30729; .net clr 3.0.30729; media center pc 6.0; infopath.3; .net4.0c; .net4.0e)
IE8的如下:
mozilla/4.0 (compatible; msie 8.0; windows nt 6.1; wow64; trident/7.0; slcc2; .net clr 2.0.50727; .net clr 3.5.30729; .net clr 3.0.30729; media center pc 6.0; infopath.3; .net4.0c; .net4.0e)
但是IE9+ 对字符串的格式做了一点调整;mozilla的版本号增加到5.0;
IE9的如下:
mozilla/5.0 (compatible; msie 9.0; windows nt 6.1; wow64; trident/7.0; slcc2; .net clr 2.0.50727; .net clr 3.5.30729; .net clr 3.0.30729; media center pc 6.0; infopath.3; .net4.0c; .net4.0e)
IE10的如下:
mozilla/5.0 (compatible; msie 10.0; windows nt 6.1; wow64; trident/7.0; slcc2; .net clr 2.0.50727; .net clr 3.5.30729; .net clr 3.0.30729; media center pc 6.0; infopath.3; .net4.0c; .net4.0e)
IE11的如下:
mozilla/5.0 (windows nt 6.1; wow64; trident/7.0; slcc2; .net clr 2.0.50727; .net clr 3.5.30729; .net clr 3.0.30729; media center pc 6.0; infopath.3; .net4.0c; .net4.0e; rv:11.0) like gecko
6. IOS和Android
移动操作系统IOS和Android默认的浏览器都是基于webkit;而且都像桌面版一样;共享相同的基本用户代理字符串格式;ios设备的基本格式如下:
Mozilla/5.0 (平台;加密类型;操作系统或CPU like Mac OS x;语言)
AppleWebKit/ AppleWebKit版本号(KHTML,like Gecko) Version/浏览器版本号
Mobile/移动版本号 Safari/Safari版本号
Android浏览器中默认格式与IOS格式相似,没有移动版本号(但有Mobile记号):
Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91)
AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
7. Konqueror
与KDE Linux 集成的Konqueror,是一款基于KHTML 开源呈现引擎的浏览器。尽管Konqueror 只
能在Linux 中使用,但它也有数量可观的用户。为确保最大限度的兼容性,Konqueror 效仿IE 选择了如
下用户代理字符串格式:
Mozilla/5.0 (compatible; Konqueror/ 版本号; 操作系统或CPU )
不过,为了与WebKit 的用户代理字符串的变化保持一致,Konqueror 3.2 又有了变化,以如下格式
将自己标识为KHTML:
Mozilla/5.0 (compatible; Konqueror/ 版本号; 操作系统或CPU) KHTML/ KHTML 版本号 (like Gecko)
下面是一个例子:
Mozilla/5.0 (compatible; Konqueror/3.5; SunOS) KHTML/3.5.0 (like Gecko)
用户代理字符串检测技术
识别呈现引擎;
下面我们主要检测五大呈现引擎:IE,Gecko,WebKit,KHTML和Opera
如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
var
client
=
function
(
)
{
var
engine
=
{
// 呈现引擎
ie
:
0
,
gecko
:
0
,
webkit
:
0
,
khtml
:
0
,
opera
:
0
,
//其他版本号
ver
:
null
}
;
// 在此检测呈现引擎,平台和设备
return
{
engine
:
engine
}
;
}
(
)
;
|
在如上client对象字面量中,每个呈现引擎都对应着一个属性,属性值默认为0;如果检测到了那个呈现引擎,那么将以浮点数值形式将引擎的版本号写入相应的属性。而呈现引擎的完整版本被写入变量ver属性中;
要正确识别呈现引擎,关键是检测顺序要正确,用户代理字符串存在诸多不一致的地方,如果检测顺序不对,很可能会导致检测结果不正确,因此,第一步就是识别Opera,因为它的用户代理字符串有可能模仿其他浏览器;目前最新的opera浏览器版本是29,所以如下:
1
2
3
|
var
ua
=
navigator
.
userAgent
.
toLowerCase
(
)
;
console
.
log
(
ua
)
;
|
打印如下:
mozilla/5.0 (windows nt 6.1; wow64) applewebkit/537.36 (khtml, like gecko) chrome/42.0.2311.152 safari/537.36 opr/29.0.1795.60
因此可以这样判断代码;如下:
1
2
3
4
5
6
|
var
ua
=
navigator
.
userAgent
.
toLowerCase
(
)
;
if
(
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
)
{
var
result
=
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
;
console
.
log
(
result
)
console
.
log
(
result
[
1
]
)
}
|
执行如下:
console.log(result);打印如下:
[“opr/29.0.1795.60”, “29.0.1795.60”, index: 110, input: “mozilla/5.0 (windows nt 6.1; wow64) applewebkit/53…rome/42.0.2311.152 safari/537.36 opr/29.0.1795.60”];
console.log(result[1])打印如下:
29.0.1795.60
由此;我们可以这样编写代码;如下:
1
2
3
4
5
6
|
var
ua
=
navigator
.
userAgent
.
toLowerCase
(
)
;
if
(
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
)
{
var
result
=
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
;
engine
.
ver
=
result
[
1
]
;
engine
.
opera
=
parseFloat
(
engine
.
ver
)
;
}
|
现在我们来打印下console.log(engine);如下所示:
但是呢opera29之前的版本, Opera5+也有window.opera对象,所以我们也必须检测window.opera对象,我们可以调用version()方法可以返回一个表示浏览器版本的字符串;如下代码:
1
2
3
4
|
if
(
window
.
opera
)
{
engine
.
ver
=
window
.
opera
.
version
(
)
;
engine
.
opera
=
parseFloat
(
engine
.
ver
)
;
}
|
现在我们为了兼容之前及之后的opera浏览器,我们可以综合一下;如下:
1
2
3
4
5
6
7
8
9
10
11
|
var
engine
=
client
;
var
ua
=
navigator
.
userAgent
.
toLowerCase
(
)
;
if
(
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
||
window
.
opera
)
{
var
result
=
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
;
engine
.
ver
=
result
[
1
]
;
engine
.
opera
=
parseFloat
(
engine
.
ver
)
;
if
(
window
.
opera
)
{
engine
.
ver
=
window
.
opera
.
version
(
)
;
engine
.
opera
=
parseFloat
(
engine
.
ver
)
;
}
}
|
现在第二步需要检测的是引擎是WebKit,因为WebKit的用户代理字符串中包含”Gecko”和”KHTML”这两个字符串,如果检测这两个,可能会有误差,但是WebKit的用户代理字符串中的”AppleWebKit”是独一无二的,因此可以根据这个来检测;
1
2
3
4
5
6
|
var
engine
=
client
;
var
ua
=
navigator
.
userAgent
.
toLowerCase
(
)
;
if
(
/
applewebkit
\
/
(
\
S
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
webkit
=
parseFloat
(
engine
.
ver
)
;
}
|
因此综合以上的所有代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
var
engine
=
client
;
var
ua
=
navigator
.
userAgent
.
toLowerCase
(
)
;
if
(
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
||
window
.
opera
)
{
var
result
=
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
;
engine
.
ver
=
result
[
1
]
;
engine
.
opera
=
parseFloat
(
engine
.
ver
)
;
if
(
window
.
opera
)
{
engine
.
ver
=
window
.
opera
.
version
(
)
;
engine
.
opera
=
parseFloat
(
engine
.
ver
)
;
}
}
else
if
(
/
applewebkit
\
/
(
\
S
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
webkit
=
parseFloat
(
engine
.
ver
)
;
}
|
接下来要测试的呈现引擎是KHTML,同样,KHTML的用户代理字符串中也包含”Gecko”,因此在排除KHTML之前,我们无法准确检测基于Gecko浏览器。KHTML的版本号与WebKit的版本号在用户代理字符串中的格式差不多,因此也可以使用正则表达式,此外,由于Konqueror 3.1 及更早版本中不包含KHTML 的版本,故而就要使用Konqueror 的版本来代替。下面就是相应的检测代码。
1
2
3
4
|
if
(
/
KHTML
\
/
(
\
S
+
)
/
.
test
(
ua
)
||
/
Konqueror
\
/
(
[
^
;
]
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
khtml
=
parseFloat
(
engine
.
ver
)
;
}
|
下面是所有的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
var
engine
=
client
;
var
ua
=
navigator
.
userAgent
.
toLowerCase
(
)
;
if
(
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
||
window
.
opera
)
{
var
result
=
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
;
engine
.
ver
=
result
[
1
]
;
engine
.
opera
=
parseFloat
(
engine
.
ver
)
;
if
(
window
.
opera
)
{
engine
.
ver
=
window
.
opera
.
version
(
)
;
engine
.
opera
=
parseFloat
(
engine
.
ver
)
;
}
}
else
if
(
/
applewebkit
\
/
(
\
S
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
webkit
=
parseFloat
(
engine
.
ver
)
;
}
else
if
(
/
khtml
\
/
(
\
S
+
)
/
.
test
(
ua
)
||
/
konqueror
\
/
(
[
^
;
]
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
khtml
=
parseFloat
(
engine
.
ver
)
;
}
|
在排除WebKit和KHTML后,就可以准确检测Gecko了,但是在用户代理字符串中,Gecko的版本号不会出现在字符串”Gecko”的后面,而是会出现在字符串”rv:”的后面。因此必须使用一个更复杂的正则表达式;
比如 firefox下的用户代理如下:
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0
如下JS代码检测:
1
2
3
4
5
6
|
var
engine
=
client
;
var
ua
=
navigator
.
userAgent
.
toLowerCase
(
)
;
if
(
/
rv
:
(
[
^
\
)
]
+
)
\
)
gecko
\
/
\
d
{
8
}
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
gecko
=
parseFloat
(
engine
.
ver
)
;
}
|
所以所有的JS代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
var
engine
=
client
;
var
ua
=
navigator
.
userAgent
.
toLowerCase
(
)
;
if
(
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
||
window
.
opera
)
{
var
result
=
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
;
engine
.
ver
=
result
[
1
]
;
engine
.
opera
=
parseFloat
(
engine
.
ver
)
;
if
(
window
.
opera
)
{
engine
.
ver
=
window
.
opera
.
version
(
)
;
engine
.
opera
=
parseFloat
(
engine
.
ver
)
;
}
}
else
if
(
/
applewebkit
\
/
(
\
S
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
webkit
=
parseFloat
(
engine
.
ver
)
;
}
else
if
(
/
khtml
\
/
(
\
S
+
)
/
.
test
(
ua
)
||
/
konqueror
\
/
(
[
^
;
]
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
khtml
=
parseFloat
(
engine
.
ver
)
;
}
else
if
(
/
rv
:
(
[
^
\
)
]
+
)
\
)
gecko
\
/
\
d
{
8
}
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
gecko
=
parseFloat
(
engine
.
ver
)
;
}
|
最后一个检测就是IE浏览器了,IE的版本号位于字符串”msie”的后面,一个分号的前面;如下:
mozilla/5.0 (compatible; msie 9.0; windows nt 6.1; wow64; trident/7.0; slcc2; .net clr 2.0.50727; .net clr 3.5.30729; .net clr 3.0.30729; media center pc 6.0; infopath.3; .net4.0c; .net4.0e)
如下JS代码检测:
1
2
3
4
|
if
(
/
msie
(
[
^
;
]
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
ie
=
parseFloat
(
engine
.
ver
)
;
}
|
如上;所有的代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
var
client
=
function
(
)
{
var
engine
=
{
// 呈现引擎
ie
:
0
,
gecko
:
0
,
webkit
:
0
,
khtml
:
0
,
opera
:
0
,
//其他版本号
ver
:
null
}
;
// 在此检测呈现引擎,平台和设备
return
{
engine
:
engine
}
;
}
(
)
;
var
engine
=
client
;
var
ua
=
navigator
.
userAgent
.
toLowerCase
(
)
;
if
(
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
||
window
.
opera
)
{
var
result
=
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
;
engine
.
ver
=
result
[
1
]
;
engine
.
opera
=
parseFloat
(
engine
.
ver
)
;
if
(
window
.
opera
)
{
engine
.
ver
=
window
.
opera
.
version
(
)
;
engine
.
opera
=
parseFloat
(
engine
.
ver
)
;
}
}
else
if
(
/
applewebkit
\
/
(
\
S
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
webkit
=
parseFloat
(
engine
.
ver
)
;
}
else
if
(
/
khtml
\
/
(
\
S
+
)
/
.
test
(
ua
)
||
/
konqueror
\
/
(
[
^
;
]
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
khtml
=
parseFloat
(
engine
.
ver
)
;
}
else
if
(
/
rv
:
(
[
^
\
)
]
+
)
\
)
gecko
\
/
\
d
{
8
}
/.test(ua)){
engine.ver = RegExp["$1"];
engine.gecko = parseFloat(engine.ver);
}else if (/msie
(
[
^
;
]
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
ie
=
parseFloat
(
engine
.
ver
)
;
}
|
2. 识别浏览器
大多数情况下,如上面识别了引擎还不能满足我们的需求,比如苹果公司的safari浏览器和谷歌的chrome浏览器都使用了webkit作为呈现引擎;但他们的javascript引擎且不一样,在这两个浏览器中,client.webkit都会返回非0值,无法区别,因此我们还需要识别下浏览器;
如下增加代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
var
client
=
function
(
)
{
var
engine
=
{
// 呈现引擎
ie
:
0
,
gecko
:
0
,
webkit
:
0
,
khtml
:
0
,
opera
:
0
,
//其他版本号
ver
:
null
}
;
var
browser
=
{
// 浏览器
ie
:
0
,
firefox
:
0
,
safari
:
0
,
konq
:
0
,
opera
:
0
,
chrome
:
0
,
// 其他的版本
ver
:
null
}
;
// 在此检测呈现引擎,平台和设备
return
{
engine
:
engine
,
browser
:
browser
}
;
}
(
)
;
|
如上代码增加了私有变量browser,用于保存每个主要浏览器的属性,与engine变量一样,除了当前使用的浏览器,其他属性值将保持为0;如果是当前使用的浏览器,则这个属性中保存的是浮点数值形式的版本号,同样browser中的ver属性中在必要时将包含字符串形式的浏览器完整版本号;
因此封装后的所有JS代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
var
client
=
function
(
)
{
var
engine
=
{
// 呈现引擎
ie
:
0
,
gecko
:
0
,
webkit
:
0
,
khtml
:
0
,
opera
:
0
,
//其他版本号
ver
:
null
}
;
var
browser
=
{
// 浏览器
ie
:
0
,
firefox
:
0
,
safari
:
0
,
konq
:
0
,
opera
:
0
,
chrome
:
0
,
// 其他的版本
ver
:
null
}
;
// 在此检测呈现引擎,平台和设备
return
{
engine
:
engine
,
browser
:
browser
}
;
}
(
)
;
var
engine
=
client
;
var
browser
=
client
;
var
ua
=
navigator
.
userAgent
.
toLowerCase
(
)
;
if
(
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
||
window
.
opera
)
{
var
result
=
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
;
engine
.
ver
=
browser
.
ver
=
result
[
1
]
;
engine
.
opera
=
browser
.
opera
=
parseFloat
(
engine
.
ver
)
;
if
(
window
.
opera
)
{
engine
.
ver
=
browser
.
ver
=
window
.
opera
.
version
(
)
;
engine
.
opera
=
browser
.
opera
=
parseFloat
(
engine
.
ver
)
;
}
}
else
if
(
/
applewebkit
\
/
(
\
S
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
webkit
=
parseFloat
(
engine
.
ver
)
;
// 确定是chrome还是safari
/*
* chrome用户代理字符串
* Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)
* Chrome/42.0.2311.152 Safari/537.36
*/
if
(
/
chrome
\
/
(
\
S
+
)
/
.
test
(
ua
)
)
{
browser
.
ver
=
RegExp
[
"$1"
]
;
browser
.
chrome
=
parseFloat
(
browser
.
ver
)
;
}
else
if
(
/
version
\
/
(
\
S
+
)
/
.
test
(
ua
)
)
{
/*
* safari用户代理字符串
* Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko)
* Version/5.1.7 Safari/534.57.2
*/
browser
.
ver
=
RegExp
[
"$1"
]
;
browser
.
safari
=
parseFloat
(
browser
.
ver
)
;
}
else
{
//近似地确定版本号
var
safariVersion
=
1
;
if
(
engine
.
webkit
<
100
)
{
safariVersion
=
1
;
}
else
if
(
engine
.
webkit
<
312
)
{
safariVersion
=
1.2
;
}
else
if
(
engine
.
webkit
<
412
)
{
safariVersion
=
1.3
;
}
else
{
safariVersion
=
2
;
}
browser
.
safari
=
browser
.
ver
=
safariVersion
;
}
}
else
if
(
/
khtml
\
/
(
\
S
+
)
/
.
test
(
ua
)
||
/
konqueror
\
/
(
[
^
;
]
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
browser
.
ver
=
RegExp
[
"$1"
]
;
engine
.
khtml
=
browser
.
konq
=
parseFloat
(
engine
.
ver
)
;
}
else
if
(
/
rv
:
(
[
^
\
)
]
+
)
\
)
gecko
\
/
\
d
{
8
}
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
gecko
=
parseFloat
(
engine
.
ver
)
;
/*
* firefox的用户代理的字符串
* Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0)
* Gecko/20100101 Firefox/38.0
*/
// 确定是不是firefox
if
(
/
firefox
\
/
(
\
S
+
)
/.test(ua)) {
browser.ver = RegExp["$1"];
browser.firefox = parseFloat(browser.ver);
}
}else if (/msie
(
[
^
;
]
+
)
/.test(ua) || "ActiveXObject" in window){
if("ActiveXObject" in window) {
if(/msie
(
[
^
;
]
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
browser
.
ver
=
RegExp
[
"1"
]
;
engine
.
ie
=
browser
.
ie
=
parseFloat
(
engine
.
ver
)
;
}
else
{
// ie11+ if(/rv:([^\)]+)\)/.test(ua)) { engine.ver = browser.ver = RegExp["1"];
engine
.
ie
=
browser
.
ie
=
parseFloat
(
engine
.
ver
)
;
}
}
}
}
// 可以打印下
console
.
log
(
browser
)
;
|
对opera和IE而言,browser对象中的值等于engine对象中值,对Konqueror 而言,browser.
konq 和browser.ver 属性分别等于engine.khtml 和engine.ver 属性。为了检测Chrome 和Safari,我们在检测引擎的代码中添加了if 语句。提取Chrome 的版本号时,需要查找字符串”chrome/”并取得该字符串后面的数值。而提取Safari 的版本号时,则需要查找字符串”version/”并取得其后的数值。由于这种方式仅适用于Safari 3 及更高版本,因此需要一些备用的代码,将WebKit 的版本号近似地映射为Safari 的版本号(至于else后面的就不多讲)。在检测Firefox 的版本时,首先要找到字符串”firefox/”,然后提取出该字符串后面的数值。
有了上面的代码,我们就可以编写下面的代码判断了,如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
if
(
client
.
engine
.
webkit
)
{
//if it’s WebKit
if
(
client
.
browser
.
chrome
)
{
//执行针对Chrome 的代码
}
else
if
(
client
.
browser
.
safari
)
{
//执行针对Safari 的代码
}
}
else
if
(
client
.
engine
.
gecko
)
{
if
(
client
.
browser
.
firefox
)
{
//执行针对Firefox 的代码
}
else
{
//执行针对其他Gecko 浏览器的代码
}
}
|
识别平台
目前有三大主流平台(windows,Mac,Unix(包括各种linux));因为那些浏览器(safari,opera,firefox)在不同的平台可能会有不同的问题;为了检测这些平台,还需要像下面这样再添加一个新对象;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
var
client
=
function
(
)
{
var
engine
=
{
// 呈现引擎
ie
:
0
,
gecko
:
0
,
webkit
:
0
,
khtml
:
0
,
opera
:
0
,
//其他版本号
ver
:
null
}
;
var
browser
=
{
// 浏览器
ie
:
0
,
firefox
:
0
,
safari
:
0
,
konq
:
0
,
opera
:
0
,
chrome
:
0
,
// 其他的版本
ver
:
null
}
;
var
system
=
{
win
:
false
,
mac
:
false
,
xll
:
false
}
;
// 在此检测呈现引擎,平台和设备
return
{
engine
:
engine
,
browser
:
browser
,
system
:
system
}
;
}
(
)
;
|
如上的代码添加了一个包含3个属性的新变量system,其中,win属性表示是否为windows平台,mac代表Mac,xll代表是Unix,system的对象的属性默认都为false,在确定平台时,检测navigator.platform要比检测用户代理字符串更简单,检测用户代理字符串在不同的浏览器中会给出不同的平台信息,而navigator.platform属性可能的值包括”Win32”,”Win64”,”MacPPC”,”MacIntel”,”Xll”和”Linux i686”,这些值在不同的浏览器中都是一致的,检测代码非常直观;如下代码:
1
2
3
4
5
|
var
system
=
client
;
var
platform
=
navigator
.
platform
;
system
.
win
=
platform
.
indexOf
(
"Win"
)
==
0
;
system
.
mac
=
platform
.
indexOf
(
"Mac"
)
==
0
;
system
.
x11
=
(
platform
.
indexOf
(
"X11"
)
==
0
)
||
(
platform
.
indexOf
(
"Linux"
)
==
0
)
;
|
比如我现在在chrome浏览器下打印如下:
console.log(system)
截图如下:
如果我想知道是win32或者是win64的话,我们可以使用这句代码打印即可
Console.log(navigator.platform);
识别移动设备
可以通过简单地检测字符串”iPhone”,”iPod”,”iPad”,就可以分别设置响应属性的值了。
1
2
3
|
system
.
iphone
=
ua
.
indexOf
(“
iphone”
)
>
-
1
;
system
.
ipod
=
ua
.
indexOf
(“
ipod”
)
>
-
1
;
system
.
ipad
=
ua
.
indexOf
(“
ipad”
)
>
-
1
;
|
除了知道iOS 设备,最好还能知道iOS 的版本号。在iOS 3 之前,用户代理字符串中只包含”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
2
3
4
5
6
7
8
|
//检测iOS 版本
if
(
system
.
mac
&&
ua
.
indexOf
(
"mobile"
)
>
-
1
)
{
if
(
/
cpu
(
?
:
iphone
)
?
os
(
\
d
+
_
\
d
+
)
/
.
test
(
ua
)
)
{
system
.
ios
=
parseFloat
(
RegExp
.
$
1.replace
(
"_"
,
"."
)
)
;
}
else
{
system
.
ios
=
2
;
//不能真正检测出来,所以只能猜测
}
}
|
检查系统是不是Mac OS、字符串中是否存在”Mobile”,可以保证无论是什么版本,system.ios
中都不会是0。然后,再使用正则表达式确定是否存在iOS 的版本号。如果有,将system.ios 设置为
表示版本号的浮点值;否则,将版本设置为2。(因为没有办法确定到底是什么版本,所以设置为更早的
版本比较稳妥。)
检测Android 操作系统也很简单,也就是搜索字符串”Android”并取得紧随其后的版本号。
1
2
3
4
|
//检测Android 版本
if
(
/
android
(
\
d
+
\
.
\
d
+
)
/
.
test
(
ua
)
)
{
system
.
android
=
parseFloat
(
RegExp
.
$
1
)
;
}
|
由于所有版本的Android 都有版本值,因此这个正则表达式可以精确地检测所有版本,并将
system.android 设置为正确的值。
在了解这些设备信息的基础上,就可以通过下列代码来确定用户使用的是什么设备中的WebKit 来
访问网页:
1
2
3
4
5
6
7
|
if
(
client
.
engine
.
webkit
)
{
if
(
client
.
system
.
ios
)
{
//iOS 手机的内容
}
else
if
(
client
.
system
.
android
)
{
//Android 手机的内容
}
}
|
因此所有的JS代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
var
client
=
function
(
)
{
var
engine
=
{
// 呈现引擎
ie
:
0
,
gecko
:
0
,
webkit
:
0
,
khtml
:
0
,
opera
:
0
,
//其他版本号
ver
:
null
}
;
var
browser
=
{
// 浏览器
ie
:
0
,
firefox
:
0
,
safari
:
0
,
konq
:
0
,
opera
:
0
,
chrome
:
0
,
// 其他的版本
ver
:
null
}
;
var
system
=
{
win
:
false
,
mac
:
false
,
xll
:
false
,
// 移动设备
iphone
:
false
,
ipod
:
false
,
ipad
:
false
,
ios
:
false
,
android
:
false
}
;
// 在此检测呈现引擎,平台和设备
return
{
engine
:
engine
,
browser
:
browser
,
system
:
system
}
;
}
(
)
;
var
engine
=
client
;
var
browser
=
client
;
var
ua
=
navigator
.
userAgent
.
toLowerCase
(
)
;
if
(
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
||
window
.
opera
)
{
var
result
=
ua
.
match
(
/
opr
\
/
(
[
\
d
\
.
]
+
)
/
)
;
engine
.
ver
=
browser
.
ver
=
result
[
1
]
;
engine
.
opera
=
browser
.
opera
=
parseFloat
(
engine
.
ver
)
;
if
(
window
.
opera
)
{
engine
.
ver
=
browser
.
ver
=
window
.
opera
.
version
(
)
;
engine
.
opera
=
browser
.
opera
=
parseFloat
(
engine
.
ver
)
;
}
}
else
if
(
/
applewebkit
\
/
(
\
S
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
webkit
=
parseFloat
(
engine
.
ver
)
;
// 确定是chrome还是safari
/*
* chrome用户代理字符串
* Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)
* Chrome/42.0.2311.152 Safari/537.36
*/
if
(
/
chrome
\
/
(
\
S
+
)
/
.
test
(
ua
)
)
{
browser
.
ver
=
RegExp
[
"$1"
]
;
browser
.
chrome
=
parseFloat
(
browser
.
ver
)
;
}
else
if
(
/
version
\
/
(
\
S
+
)
/
.
test
(
ua
)
)
{
/*
* safari用户代理字符串
* Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko)
* Version/5.1.7 Safari/534.57.2
*/
browser
.
ver
=
RegExp
[
"$1"
]
;
browser
.
safari
=
parseFloat
(
browser
.
ver
)
;
}
else
{
//近似地确定版本号
var
safariVersion
=
1
;
if
(
engine
.
webkit
<
100
)
{
safariVersion
=
1
;
}
else
if
(
engine
.
webkit
<
312
)
{
safariVersion
=
1.2
;
}
else
if
(
engine
.
webkit
<
412
)
{
safariVersion
=
1.3
;
}
else
{
safariVersion
=
2
;
}
browser
.
safari
=
browser
.
ver
=
safariVersion
;
}
}
else
if
(
/
khtml
\
/
(
\
S
+
)
/
.
test
(
ua
)
||
/
konqueror
\
/
(
[
^
;
]
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
browser
.
ver
=
RegExp
[
"$1"
]
;
engine
.
khtml
=
browser
.
konq
=
parseFloat
(
engine
.
ver
)
;
}
else
if
(
/
rv
:
(
[
^
\
)
]
+
)
\
)
gecko
\
/
\
d
{
8
}
/
.
test
(
ua
)
)
{
engine
.
ver
=
RegExp
[
"$1"
]
;
engine
.
gecko
=
parseFloat
(
engine
.
ver
)
;
/*
* firefox的用户代理的字符串
* Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0)
* Gecko/20100101 Firefox/38.0
*/
// 确定是不是firefox
if
(
/
firefox
\
/
(
\
S
+
)
/.test(ua)) {
browser.ver = RegExp["$1"];
browser.firefox = parseFloat(browser.ver);
}
}else if (/msie
(
[
^
;
]
+
)
/.test(ua) || "ActiveXObject" in window){
if("ActiveXObject" in window) {
if(/msie
(
[
^
;
]
+
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
browser
.
ver
=
RegExp
[
"$1"
]
;
engine
.
ie
=
browser
.
ie
=
parseFloat
(
engine
.
ver
)
;
}
else
{
if
(
/
rv
:
(
[
^
\
)
]
+
)
\
)
/
.
test
(
ua
)
)
{
engine
.
ver
=
browser
.
ver
=
RegExp
[
"$1"
]
;
engine
.
ie
=
browser
.
ie
=
parseFloat
(
engine
.
ver
)
;
}
}
}
}
// 检测平台
var
system
=
client
;
var
platform
=
navigator
.
platform
;
system
.
win
=
platform
.
indexOf
(
"Win"
)
==
0
;
system
.
mac
=
platform
.
indexOf
(
"Mac"
)
==
0
;
system
.
x11
=
(
platform
.
indexOf
(
"X11"
)
==
0
)
||
(
platform
.
indexOf
(
"Linux"
)
==
0
)
;
// 移动设备
system
.
iphone
=
ua
.
indexOf
(
"iphone"
)
>
-
1
;
system
.
ipod
=
ua
.
indexOf
(
"ipod"
)
>
-
1
;
system
.
ipad
=
ua
.
indexOf
(
"ipad"
)
>
-
1
;
//检测iOS 版本
if
(
system
.
mac
&&
ua
.
indexOf
(
"mobile"
)
>
-
1
)
{
if
(
/
cpu
(
?
:
iphone
)
?
os
(
\
d
+
_
\
d
+
)
/
.
test
(
ua
)
)
{
system
.
ios
=
parseFloat
(
RegExp
.
$
1.replace
(
"_"
,
"."
)
)
;
}
else
{
system
.
ios
=
2
;
//不能真正检测出来,所以只能猜测
}
}
//检测Android 版本
if
(
/
android
(
\
d
+
\
.
\
d
+
)
/
.
test
(
ua
)
)
{
system
.
android
=
parseFloat
(
RegExp
.
$
1
)
;
}
|