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的資訊裡