1. 程式人生 > >《Javascript 高階程式設計(第三版)》筆記0xE 客戶端檢測

《Javascript 高階程式設計(第三版)》筆記0xE 客戶端檢測

目錄

能力檢測(特性檢測)

     更可靠的能力檢測

     能力檢測,不是瀏覽器檢測

 怪癖檢測(quirks detection)

使用者代理檢測

    使用者代理字串的歷史

    使用者代理字串檢測技術

        1. 識別呈現引擎

        2. 識別瀏覽器

        3.識別平臺

        4.識別 Windows 作業系統

        5. 識別移動裝置

        6. 識別遊戲系統

    完整的程式碼


能力檢測(特性檢測)

        先檢測達成目的的最常用的特性

function getElement(id){
	if (document.getElementById){
		return document.getElementById(id);
	} else if (document.all){
		return document.all[id];
	} else {
		throw new Error("No way to retrieve element!");
	}
}

        必須測試實際要用到的特性

//一個特性存在,不一定意味著另一個特性也存在。
function getWindowWidth(){
	if (document.all){ //假設是 IE
		return document.documentElement.clientWidth; //錯誤的用法!!!
	} else {
		return window.innerWidth;
	}
}

     更可靠的能力檢測

//不要這樣做!這不是能力檢測——只檢測了是否存在相應的方法
function isSortable(object){
	return !!object.sort;
}

//這樣更好:檢查 sort 是不是函式
function isSortable(object){
	return typeof object.sort == "function";
}

        在瀏覽器環境下測試任何物件的某個特性是否存在:

function isHostMethod(object, property) {
	var t = typeof object[property];
	return t=='function' ||
		(!!(t=='object' && object[property])) ||
		t=='unknown';
}

result = isHostMethod(xhr, "open"); //true
result = isHostMethod(xhr, "foo"); //false

     能力檢測,不是瀏覽器檢測

        根據瀏覽器不同將能力組合起來是更可取的方式。如果你知道自己的應用程式需要使用某些特定的瀏覽器特性,那麼最好是一次性檢測所有相關特性,而不要分別檢測。

//確定瀏覽器是否支援 Netscape 風格的外掛
var hasNSPlugins = !!(navigator.plugins && navigator.plugins.length);
//確定瀏覽器是否具有 DOM1 級規定的能力
var hasDOM1 = !!(document.getElementById && document.createElement &&
	document.getElementsByTagName);

 怪癖檢測(quirks detection)

        一般來說,“怪癖”都是個別瀏覽器所獨有的,而且通常被歸為 bug。在相關瀏覽器的新版本中,這些問題可能會也可能不會被修復。

使用者代理檢測

        使用者代理檢測通過檢測使用者代理字串來確定實際使用的瀏覽器。 

    使用者代理字串的歷史

        HTTP 規範(包括 1.0 和 1.1 版)明確規定,使用者代理字串應該以一組產品的形式給出,字串格式為:識別符號/產品版本號。 

    使用者代理字串檢測技術

        1. 識別呈現引擎

        2. 識別瀏覽器

        3.識別平臺

        4.識別 Windows 作業系統

        5. 識別移動裝置

        6. 識別遊戲系統

    完整的程式碼


var client = function(){

    //rendering engines
    var engine = {            
        ie: 0,
        gecko: 0,
        webkit: 0,
        khtml: 0,
        opera: 0,

        //complete version
        ver: null  
    };
    
    //browsers
    var browser = {
        
        //browsers
        ie: 0,
        firefox: 0,
        safari: 0,
        konq: 0,
        opera: 0,
        chrome: 0,

        //specific version
        ver: null
    };

    
    //platform/device/OS
    var system = {
        win: false,
        mac: false,
        x11: false,
        
        //mobile devices
        iphone: false,
        ipod: false,
        ipad: false,
        ios: false,
        android: false,
        nokiaN: false,
        winMobile: false,
        
        //game systems
        wii: false,
        ps: false 
    };    

    //detect rendering engines/browsers
    var ua = navigator.userAgent;    
    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);
        
        //figure out if it's Chrome or Safari
        if (/Chrome\/(\S+)/.test(ua)){
            browser.ver = RegExp["$1"];
            browser.chrome = parseFloat(browser.ver);
        } else if (/Version\/(\S+)/.test(ua)){
            browser.ver = RegExp["$1"];
            browser.safari = parseFloat(browser.ver);
        } else {
            //approximate version
            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);
        
        //determine if it's Firefox
        if (/Firefox\/(\S+)/.test(ua)){
            browser.ver = RegExp["$1"];
            browser.firefox = parseFloat(browser.ver);
        }
    } else if (/MSIE ([^;]+)/.test(ua)){    
        engine.ver = browser.ver = RegExp["$1"];
        engine.ie = browser.ie = parseFloat(engine.ver);
    }
    
    //detect browsers
    browser.ie = engine.ie;
    browser.opera = engine.opera;
    

    //detect platform
    var p = navigator.platform;
    system.win = p.indexOf("Win") == 0;
    system.mac = p.indexOf("Mac") == 0;
    system.x11 = (p == "X11") || (p.indexOf("Linux") == 0);

    //detect windows operating systems
    if (system.win){
        if (/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/.test(ua)){
            if (RegExp["$1"] == "NT"){
                switch(RegExp["$2"]){
                    case "5.0":
                        system.win = "2000";
                        break;
                    case "5.1":
                        system.win = "XP";
                        break;
                    case "6.0":
                        system.win = "Vista";
                        break;
                    case "6.1":
                        system.win = "7";
                        break;
                    default:
                        system.win = "NT";
                        break;                
                }                            
            } else if (RegExp["$1"] == "9x"){
                system.win = "ME";
            } else {
                system.win = RegExp["$1"];
            }
        }
    }
    
    //mobile devices
    system.iphone = ua.indexOf("iPhone") > -1;
    system.ipod = ua.indexOf("iPod") > -1;
    system.ipad = ua.indexOf("iPad") > -1;
    system.nokiaN = ua.indexOf("NokiaN") > -1;
    
    //windows mobile
    if (system.win == "CE"){
        system.winMobile = system.win;
    } else if (system.win == "Ph"){
        if(/Windows Phone OS (\d+.\d+)/.test(ua)){;
            system.win = "Phone";
            system.winMobile = parseFloat(RegExp["$1"]);
        }
    }
    
    
    //determine iOS version
    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;  //can't really detect - so guess
        }
    }
    
    //determine Android version
    if (/Android (\d+\.\d+)/.test(ua)){
        system.android = parseFloat(RegExp.$1);
    }
    
    //gaming systems
    system.wii = ua.indexOf("Wii") > -1;
    system.ps = /playstation/i.test(ua);
    
    //return it
    return {
        engine:     engine,
        browser:    browser,
        system:     system        
    };

}();