javascript客户端检测技术
1. Firefox
Gecko是firefox的呈现引擎。当初的Gecko是作为通用Mozilla浏览器一部分开发的,而第一个采用Gecko引擎的浏览器是Netscape6;
我们可以使用用户代理检测下:如下JS代码:
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独立出来成为一个开源项目,专注于呈现引擎开发;
如下代码:
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代码:
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代码:
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代码如下:
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
如下代码:
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,所以如下:
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
因此可以这样判断代码;如下:
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
由此;我们可以这样编写代码;如下:
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()方法可以返回一个表示浏览器版本的字符串;如下代码:
if(window.opera) {
    engine.ver = window.opera.version();
    engine.opera = parseFloat(engine.ver);
}
现在我们为了兼容之前及之后的opera浏览器,我们可以综合一下;如下:
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”是独一无二的,因此可以根据这个来检测;
var engine = client;
var ua = navigator.userAgent.toLowerCase();
if(/applewebkit\/(\S+)/.test(ua)) {
engine.ver = RegExp["$1"];
engine.webkit = parseFloat(engine.ver);
}
因此综合以上的所有代码如下:
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 的版本来代替。下面就是相应的检测代码。
if (/KHTML\/(\S+)/.test(ua) || /Konqueror\/([^;]+)/.test(ua)){
    engine.ver = RegExp["$1"];
    engine.khtml = parseFloat(engine.ver);
}
下面是所有的代码:
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代码检测:
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代码如下:
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代码检测:
if (/msie ([^;]+)/.test(ua)){
    engine.ver = RegExp["$1"];
    engine.ie = parseFloat(engine.ver);
}
如上;所有的代码如下:
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);
}
识别浏览器
大多数情况下,如上面识别了引擎还不能满足我们的需求,比如苹果公司的safari浏览器和谷歌的chrome浏览器都使用了webkit作为呈现引擎;但他们的javascript引擎且不一样,在这两个浏览器中,client.webkit都会返回非0值,无法区别,因此我们还需要识别下浏览器;
如下增加代码如下:
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代码如下:
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);         }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/",然后提取出该字符串后面的数值。
有了上面的代码,我们就可以编写下面的代码判断了,如下代码:
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)在不同的平台可能会有不同的问题;为了检测这些平台,还需要像下面这样再添加一个新对象;
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”,这些值在不同的浏览器中都是一致的,检测代码非常直观;如下代码:
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”,就可以分别设置响应属性的值了。
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 需要正则表达式反映这些变化。
//检测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"并取得紧随其后的版本号。
//检测Android 版本
if (/android (\d+\.\d+)/.test(ua)){
system.android = parseFloat(RegExp.$1);
}
由于所有版本的Android 都有版本值,因此这个正则表达式可以精确地检测所有版本,并将
system.android 设置为正确的值。
在了解这些设备信息的基础上,就可以通过下列代码来确定用户使用的是什么设备中的WebKit 来
访问网页:
if (client.engine.webkit){
if (client.system.ios){
//iOS 手机的内容
} else if (client.system.android){
//Android 手机的内容
}
}
因此所有的JS代码如下:
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);
          }												
											javascript客户端检测技术的更多相关文章
- [Javascript]客户端检测
		客户端检测是一种行之有效的开发策略.但不到万不得已,就不要使用客户端检测.先设计通用的方案,然后根据浏览器之间的差异和各自的怪癖quirky,再使用特定于浏览器的技术增强该方案. 能力检测 Featu ... 
- JavaScript功能检测技术和函数构造
		Javascript与很多编程语言不同,它不能够控制其运行环境.再写php代码时,只要在服务器端部署了正确的版本,那么程序就绝对能够运行,对于其他python或ruby后端语言来说,也不存在什么灰色区 ... 
- JavaScript高级程序设计学习笔记第九章--客户端检测
		1.能力检测:能力检测的目标不是识别特定的浏览器,而是识别浏览器的能力.(我的理解就是识别浏览器能做什么不能做什么) 2.怪癖检测:目标是识别浏览器的特殊行为.但与能力检测确认浏览器支持什么能力不同, ... 
- 《JAVASCRIPT高级程序设计》客户端检测
		web开发的理想状态之一是浏览器支持一组最常用的功能,但是在现实情况下,浏览器间的差异非常大,因此,为了兼容大部分的了浏览器,开发人员首先需要设计最通用的方案,然后再使用客户端检测的技术增强该方案.客 ... 
- MVC下的客户端模板技术
		1.引言 在Web编程中,我们有时经常需要使用Ajax来访问服务端的接口,然后使用这些返回的数据(一般格式都是JSON)来展示客户端的相关信息.例如:在一个商品列表,我们点击某一样的商品,查看该商品的 ... 
- Javascript高级程序设计——客户端检测
		ECMAScript虽然是Javascript的核心,但是要在web中使用Javascript,那么BOM才是核心,BOM为我们提供了操作访问浏览器对象的借口, 但是由于BOM没有标准规范,导致存在不 ... 
- 读书时间《JavaScript高级程序设计》四:BOM,客户端检测
		隔了一段时间,现在开始看第8章. 第8章:BOM BOM提供了很多对象,用于访问浏览器的功能.BOM的核心对象是window,它表示浏览器的一个实例. window对象是通过javascript访问浏 ... 
- JavaScript浏览器检测之客户端检测
		客户端检测一共分为三种,分别为:能力检测.怪癖检测和用户代理检测,通过这三种检测方案,我们可以充分的了解当前浏览器所处系统.所支持的语法.所具有的特殊性能. 一.能力检测: 能力检测又称作为特性检测, ... 
- Javascript高级编程学习笔记(34)—— 客户端检测(3)用户代理检测
		用户代理检测 前面的文章介绍的是如何检测浏览器对某一功能的支持情况 但是在实践中我们有些时候免不了需要知道用户到底是用的什么浏览器对我们的站点进行访问 这也是统计用户行为的一部分 用户代理检测这种方式 ... 
随机推荐
- BZOJ2440 [中山市选2011]完全平方数
			本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ... 
- 帝国备份王(Empirebak) \class\functions.php、\class\combakfun.php GETSHELL vul
			catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 EmpireBak是一款完全免费.专门为Mysql大数据的备份与导入而设 ... 
- Subime学习记录
			一.快捷键 注:快捷键这种东西没有必要刻意去记,自己需要就去查查,经常用的自然熟了,关键是时刻保持提高效率的意识,才会主动去发现快捷键. 1.Ctrl + F:查找 2.F12:根据函数定位函数声明( ... 
- ubuntu常见错误--could not get lock /var/lib/dpkg/lock -open
			最近研究ubuntu,用apt-get命令安装一些软件包时,总报错:E:could not get lock /var/lib/dpkg/lock -open等 出现这个问题的原因可能是有另外一个程序 ... 
- [JavaEE] NIO与IO的区别
			nio是new io的简称,从jdk1.4就被引入了.现在的jdk已经到了1.6了,可以说不是什么新东西了.但其中的一些思想值得我来研究.这两天,我研究了下其中的套接字部分,有一些心得,在此分享. 首 ... 
- 【Alpha阶段】第二次Scrum例会
			燃尽图软件存在bug,正在排查修复:(已修复)由于时区设置到了美国,图表显示有问题. 会议信息 时间:2016.10.18 22:00 时长:1h 地点:大运村1号公寓5楼楼道 类型:设计阶段阶段性会 ... 
- HDU5671Matrix(矩阵行列交换)
			有一个nn行mm列的矩阵(1 \leq n \leq 1000 ,1 \leq m \leq 1000 )(1≤n≤1000,1≤m≤1000),在这个矩阵上进行qq (1 \leq q \leq 1 ... 
- JAVA通过md5方法进行加密
			import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /* * MD5 算法 * */ ... 
- IEquatable 的Equals 代替 object 的Equals
			struct Point2 : IEquatable<Point2> { public int X { get; set; } public int Y { get; set; } pub ... 
- CSS学习笔记——CSS选择器样式总结
			<style type="text/css"> * { padding:0; margin:0; } .box h2 { //内边距左边的距离 padding-left ... 
