1. 程式人生 > 其它 >ASP.NET AJAX(12)__瀏覽器相容功能判斷瀏覽器的型別和版本Sys.Browser針對DOM元素的相容操作針對DOM事件的相容操作

ASP.NET AJAX(12)__瀏覽器相容功能判斷瀏覽器的型別和版本Sys.Browser針對DOM元素的相容操作針對DOM事件的相容操作

目前,常見的瀏覽器IE(6,8,9),chrome,firefox,safari等,還有國內的一些曾經靠恐嚇使用者來提高使用率的某瀏覽器(河蟹社會),這些瀏覽器對於Javascript的語言特性實現大致是相同的,但是對於DOM操作方式卻大相徑庭,所以我們通常需要自己對不同瀏覽器對於DOM的操作方式進行分而治之,或者我們往往是使用一些Javascript框架提供的相容功能,當然也有我們的Microsoft AJAX Library

判斷瀏覽器的型別和版本

瀏覽器相容層的優勢在於,我們可以使用同樣的編碼方式,讓相同的程式碼在不同瀏覽器下的表現統一,因為在這個相容層內部,分別實現了或者規避了一些瀏覽器的不同的實現,但是不同的瀏覽器的某些差異難以使用框架來保證,因此提供顯式的判斷瀏覽器的型別和版本是必不可少的

Sys.Browser

  • 通過windows.navigator.userAgent來判斷
  • Sys.Brower.agent表示瀏覽器型別(可能的值InternetExplorer/FireFox/Safari/Opera)
  • Sys.Brower.hadDebuggerStatement:是否支援debugger命令
  • Sys.Brower.name:瀏覽器名稱
  • Sys.Brower.version:瀏覽器版本
一個通過瀏覽器型別獲得顯示視窗的大小的示例

建立一個aspx頁面

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="GetClientBoundsByBrowerType.aspx.cs" Inherits="Demo11_GetClientBoundsByBrowerType" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
        
        <script language="javascript" type="text/javascript">
            document.write(window.navigator.userAgent);//列印瀏覽器資訊
        </script>
        
        <hr />
        
        <script language="javascript" type="text/javascript">
            document.write("Has Debugger Statement:" + Sys.Browser.hasDebuggerStatement + "<hr/>");//是否支援debugger
            document.write("Name:" + Sys.Browser.name + "<hr/>");//瀏覽器名稱
            document.write("Version:"+Sys.Browser.version);//瀏覽器版本
        </script>
        
        <script language="javascript" type="text/javascript">
            function getClientBounds() {
                var clientWidth;
                var clientHeight;
                switch (Sys.Browser.agent) {//判斷瀏覽器型別
                    case Sys.Browser.InternetExplorer: //如果瀏覽器是InternetExplorer
                        clientWidth = document.compatMode == "CSS1Compat" ? document.documentElement.clientWidth : document.body.clientWidth;
                        clientHeight = document.compatMode == "CSS1Compat" ? document.documentElement.clientHeight : document.body.clientHeight;
                        break;
                    case Sys.Browser.Safari: //如果瀏覽器是Safari
                        clientWidth = window.innerWidth;
                        clientHeight = window.innerHeight;
                        break;
                    case Sys.Browser.Opera: //如果瀏覽器是Opera
                        clientWidth = Math.min(window.innerWidth, document.body.clientWidth);
                        clientHeight = Math.min(window.innerHeight, document.body.clientHeight);
                        break;
                    case Sys.Browser.Firefox: //如果瀏覽器是Firefox
                        clientWidth = Math.min(window.innerWidth, document.documentElement.clientWidth);
                        clientHeight = Math.min(window.innerHeight, document.documentElement.clientHeight);
                        break;
                }
                return { width: clientWidth, height: clientHeight };
            }
        </script>
        <hr />
        <div id="clientBounds"></div>
        <script language="javascript" type="text/javascript">
            window.onresize = function() {//當瀏覽器的大小改變的時候呼叫
            var bounds = getClientBounds();
                $get("clientBounds").innerHTML = String.format("Width:{0}<br/>Height:{1}",bounds.width,bounds.height);
            }
        </script>
    </form>
</body>
</html>

我這裡使用的是IE8,chrome14.0和firefox6進行測試,得到的結果如下所示

IE8

chrome14.0

firefox6

這裡我要提一下,其實Microsoft AJAX Library是沒有直接的提供chrome的支援的,我這裡使用它進行測試,完全是因為我這裡只裝了這三種瀏覽器,在chrome下,很多東西得出的結果是不正確的,只是讓大家明白這裡的不同,不要太多關注與它對chrome的支援

同樣,這裡我們也可以看到,在取到瀏覽器的尺寸的時候,各種瀏覽器的取得方法,是完全不相同的,這就是我們前面提到的對於DOM操作方式卻大相徑庭

針對DOM元素的相容操作

  • Sys.UI.DomElement靜態類中
  • $get=.getElementById=function(id,parent);//只是效果,並不等同
  • Sys.UI.DomElement.addCssClass=function(element,className);
  • Sys.UI.DomElement.removeCssClass=function(element.className);
  • Sys.UI.DomElement.containsCssClass=function(element,className);//判斷元素下是否有這個className類
  • Sys.UI.DomElement.toggleCssClass=function(element,className);//如果元素有className,則去除,如果沒有則新增
  • 可以自行新增縮寫方法:eg:$addCss=Sys.UI.DomElement.addCssClass
  • Sys.UI.DomElement.getLocation=function(element)//返回Sys.UI.DomElement型別物件的位置
  • Sys.UI.DomElement.setLocation=funcation(element,x,y)
  • Sys.UI.DomElement.getBounds=funcation(element)//得到元素的大小和位置返回Sys.UI.Bounds
一個針對DOM元素的相容操作的示例

建立一個名為DomElementOperations.aspx的頁面

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="DomElementOperations.aspx.cs" Inherits="Demo11_DomElementOperations" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <style type="text/css">
        .red{color:Red;}
        .large{font-size:xx-large;}
    </style>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
        
        <script language="javascript" type="text/javascript">
            //自行新增的縮寫方法
            $addCss = Sys.UI.DomElement.addCssClass;
            $removeCss = Sys.UI.DomElement.removeCssClass;
            $containCss = Sys.UI.DomElement.containsCssClass;
            $toggleCss = Sys.UI.DomElement.toggleCssClass;
        </script>
        
        <input type="checkbox" id="inputElement" /><%--這裡我們使用了兩個相同的id--%>
        <div id="someContainer">
            <input type="text" id="inputElement" /><%--這裡我們使用了兩個相同的id,這個元素包裹在了一個DIV裡--%>
        </div>
        <script language="javascript" type="text/javascript">
            document.write($get("inputElement").type + "<br/>");//這裡將會列印checkbox,因為開始找到的是一個checkbox
            document.write($get("inputElement", $get("someContainer")).type + "<br/>"); //這裡指定了將在id為someContainer的元素裡找,所以是一個input
        </script>
        <hr />
        <div id="someText">
            Xiaoyaojian
        </div>
        <input type="button" value="Add Red" onclick="$addCss($get('someText'),'red')" /><%--新增一個red樣式--%>
        <input type="button" value="Remove Red" onclick="$removeCss($get('someText'),'red')" /><%--去除一個red樣式--%>
        <input type="button" value="Toggle Large" onclick="$toggleCss($get('someText'),'large')" /><%--如有有large這個元素,則去除,如果沒有則新增--%>
        <input type="button" value="Container Large" onclick="alert($containCss($get('someText'),'large'))" /><%--判斷元素上是否有large這個樣式--%>
        
        <hr />
        
        <div id="anElement" style="background-color:Red; color:White; position:absolute; overflow:hidden;">
            Hello World
        </div>
        
        <script language="javascript" type="text/javascript">
            function setRandomLocation() {
                var left = Math.floor(Math.random() * 100);
                var top = Math.floor(Math.random() * 100);
                Sys.UI.DomElement.setLocation($get("anElement"), left, top);//設定位置,他相對左上角的位置是隨機產生的
            }

            function setRandomSize() {
                $get("anElement").style.width = Math.floor(Math.random() * 100 + 50) + "px"; //設定元素的寬
                $get("anElement").style.height = Math.floor(Math.random() * 100 + 50) + "px";//設定元素的高
            }
            
            function showLocation() {
                var point = Sys.UI.DomElement.getLocation($get("anElement"));//顯示元素相對瀏覽器左上角位置
                alert(String.format("x:{0},y:{1}",point.x,point.y));
            }

            function showBounds() {//顯示元素的寬高(大小)和相對瀏覽器左上角的位置
                var point = Sys.UI.DomElement.getBounds($get("anElement"));
                alert(String.format("x:{0},y:{1},width:{2},height:{3}", point.x, point.y,point.width,point.height));
            }
        </script>
        
        <input type="button" value="Set Location" onclick="setRandomLocation()" />
        <input type="button" value="Set Size" onclick="setRandomSize()" />
        <input type="button" value="Show Location" onclick="showLocation()" />
        <input type="button" value="Show Bound" onclick="showBounds()" />
    </form>
</body>
</html>

在頁面的程式碼註釋裡,我自認為已經寫的足夠的清楚,所以我在這裡就不多做解釋

針對DOM事件的相容操作

出現的原因

  • 新增和刪除event handler的方法不同
  • 獲取Event物件的方法不同
  • Event物件的方法和屬性不同
  • …等等
  • 因為種種原因,微軟提供了一套“第三種形式的”DOM事件操作

提供的操作

  • 新增Event Handler:$addHandler(element,eventName,handler);//這裡的事件名沒有“on”
  • 新增Event Handler$addHandlers(element,events,owner);//events為一個存放Event Handler的字典,Owner為執行EventHandler的上下文物件
  • 去除Event Handler :$removeHandler(element,eventName,handler);
  • 去除所有的Event Handler: $clearHandlers(element);
  • Event Handler簽名:on***(event);//event為一個Sys.UI.DomEvent類的物件
  • Sys.UI.DomEvent.preventDefault();//組織事件的預設行為
  • Sys.UI.DomEvent..stopPropagation();//阻斷事件的向上傳遞
  • Sys.UI.DomEvent.altKey/ctrlKey/shiftKey;//觸發事件時使用者是否按著Alt/Ctrl/Shift鍵
  • Sys.UI.DomEvent.type:一個表示事件型別的字串
  • Sys.UI.DomEvent.target:觸發事件的DOM元素
  • Sys.UI.DomEvent.button:一個Sys.UI.MouseButton的列舉
  • Sys.UI.DomEvent.keyCode:一個表示當前按鍵的整數值,可以和Sys,UI,Key列舉的項找到對應關係
  • Sys.UI.DomEvent.clientX/clientY:滑鼠在document可視範圍內的位置(和滾動條狀態無關)
  • Sys.UI.DomEvent.screenX/screenY:滑鼠在螢幕中的位置
  • Sys.UI.DomEvent.offsetX/offsetY:滑鼠在觸發事件的物件中的相對位置
  • Sys.UI.DomEvent.rawEvent:瀏覽器原生事件物件
一個針對DOM事件的相容操作的示例

建立一個asp頁面,我們如果沒有這個瀏覽器相容層的情況下,我們如果為一個按鈕在javascript中為一個按鈕新增一個事件, 則需要如下程式碼來相容不同的瀏覽器

<input type="button" value="Button" id="aButton" onclick="eventHandler(event)" />
        
        <script language="javascript" type="text/javascript">
            var button = document.getElementById("aButton");

            //只對IE有效果
            button.attachEvent("onclick", eventHandler);
            button.detachEvent("onclick", eventHandler);

            //只對firefox有效果
            button.addEventListener("onclick", eventHandler);
            button.removeEventListener("onclick", eventHandler);

            //相容兩種瀏覽器
            if (button.attachEvent) {
                button.attachEvent("onclick", eventHandler);
            }
            else {
                button.addEventListener("onclick", eventHandler);
            }
        </script>

而在我們有了這個瀏覽器相容層的情況下,我們只需要做如下的操作

在頁面中首先新增一個ScriptManager

<div style="width:300px; height:300px; background-color:Red" id="mouseEvent">
        </div>
        
        <script language="javascript" type="text/javascript">
            function onMouseDown(e) {
                $get("displayMouseEvent").innerHTML = String.format(
                    "altKey:{0}<br/>"+
                    "ctrlKey:{1}<br/>"+
                    "shiftKey:{2}<br/>"+
                    "clientX & Y:({3},{4})<br/>"+
                    "screenX & Y:({5},{6})<br/>"+
                    "offsetX & Y:({7},{8})<br/>" +
                    "button:{9}",
                    e.altKey,e.ctrlKey,e.shiftKey,//是否按著Alt/Ctrl/Shift這幾個鍵
                    e.clientX,e.clientY,//可視範圍內的位置
                    e.screenX,e.screenY,//相對於螢幕的位置
                    e.offsetX, e.offsetY,//相對於元素內部的位置
                    Sys.UI.MouseButton.toString(e.button));//表示按下的按鍵,左/右/中(按下滾輪)
            }

            $addHandler($get("mouseEvent"), "mousedown", onMouseDown); //為上面的div新增一個mousedown事件,觸發這個事件,呼叫onMouseDown方法
        </script>
        
        <div id="displayMouseEvent"></div><%--要顯示資訊的DIV—%>

這時,我們可以在紅塊內點選滑鼠的左右中鍵,並同時按下Alt/Ctrl/Shift鍵盤,就可以清晰的反映到下面的DIV的資訊裡