现在市面上流行的浏览器有IE,FireFox, Opera,Safari等等,不同浏览器对于JavaScript的语言特性实现大致相同,但是对于DOM操作方式则大相径庭。 几乎所有的JavaScript框架都提供了浏览器兼容功能 Microsoft AJAX Library自然也不例外。
判断浏览器类型和版本。浏览器兼容层的优势,就是在于使用同样的编码方式,让相同的代码在不同的浏览器下表现统一。但是不同浏览器的某些差异是难以用框架来保证的,或者所有的差异都由框架来保证是不现实的。 因此,提供显示地判断浏览器类型和版本的功能不可或缺。
1.判断浏览器的类型
如果不使用Asp.Net Ajax框架,那么我们一般通过window.navigator.userAgent来判断当前访问页面的浏览器类型。在Asp.Net Ajax框架中我们使用Sys.Browser的属性来判断浏览器类型
Sys.Browser.agent | 表示浏览器类型。枚举类型,值分别有Sys.Browser.InternetExplorer,Sys.Browser.FireFox,Sys.Browser.Safari,Sys.Browser.Opera |
Sys.Browser.hasDebuggerStatement | 是否支持“debugger”命令 |
Sys.Browser.name | 浏览器名称 |
Sys.Browser.version | 浏览器版本 |
下面是一根据浏览器的类型得到显示窗口大小的经典例子
... {
var clientWidth;
var clientHeight;
switch (Sys.Browser.agent)
...{
case Sys.Browser.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:
clientWidth = window.innerWidth;
clientHeight = window.innerHeight;
break;
case Sys.Browser.Opera:
clientWidth = Math.min(window.innerWidth, document.body.clientWidth);
clientHeight = Math.min(window.innerHeight, document.body.clientHeight);
break;
default: // FireFox, etc.
clientWidth = Math.min(window.innerWidth, document.documentElement.clientWidth);
clientHeight = Math.min(window.innerHeight, document.documentElement.clientHeight);
break;
}
return ...{width: clientWidth, height: clientHeight};
}
从上面的例子可以看到,每种浏览器得到窗口的dom对象都不一样,基于浏览器兼容模式的开发困难点就在这里,我们不可能把所有的浏览器都考虑到,但是每种浏览器的dom对象原型都是不一样的。但Asp.Net Ajax帮我们封装了一部分。
2.针对dom元素的兼容操作
Sys.UI.DomElement静态类
在进行js开发的时候,我们会用到$get根据元素的id得到一个dom元素,这个符号是Sys.UI.DomElement.getElementById的缩写,不是js里面的document.getElementById方法的缩写。这个方法有两个参数,第一个是元素的id,第二个是元素的容器id。一般在一个dom中是不允许有两个相同id的元素。如果有我们通过documentById方法只能找到一个,那么可以根据元素所在的容器id来得到这个元素。
addCssClass(element,CssName) | 给一个元素指定一个样式,CssName代表样式的名称 |
removeCssClass(element,CssName) | 从一个元素上移除样式 |
containsCssClass(element,CssName) | 判断一个元素是否指定了一个样式 |
toggleCssClass(element,CssName) | 如果元素已经指定了样式,调用这个方法将移去样式,否则指定这样样式 |
getLocation(element) | 得到元素的在页面上的位置,返回Sys.UI.Point类型对象 |
setLocation(element,x,y) | 设置元素在页面上的位置 |
getBounds(element) | 得到元素在页面上的文职,并且包含元素的长、宽信息。返回Sys.UI.Bounds类型对象 |
那么我们在后面使用Sys.UI.DomElement.addCssClass方法的时候可以直接使用$addCss来代替。
3.针对DOM事件的兼容操作
仅仅比较IE和FireFox,DOM事件的操作也大相径庭。 添加和删除event handler的方法不同; 获取Event对象的方法不同; Event对象的方法和属性不同。
在Asp.Net Ajax框架中提供了一套Dom事件兼容操作。
添加Event Handler:
$addHandler(element, eventName, handler) 给dom元素的事件添加一个事件处理器
注:eventName是没有“on”的,与我们平时写js代码不一样。我们平时写一个button的click事件为
// cannot get the event object in different browsers
button.onclick = function () ... { /**//* .. */ } ;
// get the event object in different browsers
function eventHandler(e)
... {
// event object has different members
var element = e.srcElement | e.target;
}
// IE only
button.attachEvent( " onclick " , eventHandler);
button.detachEvent( " onclick " , eventHandler);
// FireFox
button.addEventListener( " click " , eventHandler);
button.removeEventListener( " click " , eventHandler);
// both browsers
if (button.attachEvent)
... {
button.attachEvent("onclick", eventHandler);
}
else
... {
button.addEventListener("click", eventHandler);
}
这两种方式一个兼容性不好,一个处理起来需要考虑的浏览器类型太多。在Asp.Net Ajax框架中我们使用如下方式添加事件
$addHandlers(element, events, owner)
• events为一个存放Event Handler的字典,这个字典应该是事件名作为key,handler作为value
• Owner为执行Event Handler的上下文对象
去除Event Handler:
$removeHandler(element, eventName, handler)
$removeHandlers(element);
在dom元素触发事件时,会将一个Sys.UI.DomEvent类的对象传递到事件处理器中,如下例
... {
$get("displayMouseEvent").innerHTML = String.format(
"altKey: {0} <br />" +
"ctrlKey: {1} <br />" +
"shitKey: {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,
e.clientX, e.clientY,
e.screenX, e.screenY,
e.offsetX, e.offsetY,
Sys.UI.MouseButton.toString(e.button));
}
preventDefault() | 阻止事件默认行为 |
stopPropagation() | 阻断事件向上传递,就是阻止事件冒泡传递至父元素 |
altKey / ctrlKey / shiftKey | 触发事件时用户是否按着Alt / Ctrl / Shift键 |
type | 一个表示事件类型的字符串 |
target | 触发事件的DOM元素 |
button | 一个Sys.UI.MouseButton的枚举值,表明触发事件时鼠标按的是左中右键的哪一个 |
keyCode | 一个表示当年按键的整数值,可以和Sys.UI.Key枚举的项找到对应关系 |
clientX & clientY | 鼠标在document可是范围内的位置(和滚动条状态无关) |
screenX & screenY | 鼠标在屏幕中的位置 |
offsetX & offsetY | 鼠标在触发事件的对象中的相对位置 |
rawEvent | 浏览器的原生事件对象 |