js在操纵DOM中存在着很多跨浏览器方面的坑,本文花了我快要一周的时刻整顿,我将依据实例整顿那些大大小小的“坑”。
DOM的事情情势是:先加载文档的静态内容、再以动态体式格局对它们举行革新,动态革新不影响文档的静态内容。
PS:IE 中的一切 DOM 对象都是以 COM 对象的情势完成的,这意味着 IE 中的 DOM能够会和其他浏览器有肯定的差异。
Node 接口
特性/要领 范例/返回范例 说 明
nodeName String 节点的名字;依据节点的范例而定义
nodeValue String 节点的值;依据节点的范例而定义
nodeType Number 节点的范例常量值之一
ownerDocument Document 返回某元素的根元素
firstChild Node 指向在childNodes列表中的第一个节点
lastChild Node 指向在childNodes列表中的末了一个节点
childNodes NodeList 一切子节点的列表
previousSibling Node 返回选定节点的上一个同级节点,若不存在,则返回null
nextSibling Node 返回被选节点的下一个同级节点,若不存在,则返回null
hasChildNodes() Boolean 假如当前元素节点具有子节点,返回true,不然返回false
attributes NamedNodeMap 返回包括被选节点属性的 NamedNodeMap
appendChild(node) node 将node增加到childNodes的末端
removeChild(node) node 从childNodes中删除node
replaceChild(newnode, oldnode) Node 将childNodes中的oldnode替换成newnode
insertBefore Node 在已有子节点之前插进去新的子节点
firstChild 相当于 childNodes[0];lastChild 相当于childNodes[box.childNodes.length – 1]。
nodeType返回结点的范例
–元素结点返回1
–属性结点返回2
–文本结点返回3
innerHTML 和 nodeValue
关于文本节点,nodeValue 属性包括文本。
关于属性节点,nodeValue 属性包括属性值。
nodeValue 属性关于文档节点和元素节点是不可用的。
二者辨别
box.childNodes[0].nodeValue = ‘abc‘;//结果为:abc
abcbox.innerHTML = ‘abc‘;//结果为:abc
nodeName属性获得结点称号
–关于元素结点返回的是标记称号,如:返回的是”a”
–关于属性结点返回的是属性称号,如:class=”test” 返回的是test
–关于文本结点返回的是文本的内容
tagName
document.getElementByTagName(tagName):返回一个数组,包括对这些结点的援用
getElementsByTagName()要领将返回一个对象数组 HTMLCollection(NodeList),这个数组保存着一切雷同元素名的节点列表。
document.getElementsByTagName(‘*’);//猎取一切元素
PS:IE 浏览器在运用通配符的时刻,会把文档最最先的 html 的范例声明看成第一个元素节点。
document.getElementsByTagName(‘li’);//猎取一切 li 元素,返回数组
document.getElementsByTagName(‘li’)[0];//猎取第一个 li 元素,HTMLLIElement
document.getElementsByTagName(‘li’).item(0);//猎取第一个 li 元素,HTMLLIElement
document.getElementsByTagName(‘li’).length;//猎取一切 li 元素的数量
节点的相对援用:
返回文档的根节点:document.documentElement
返回当前文档中被击活的标签节点:document.activeElement
返回鼠标移出的源节点:event.fromElement
返回鼠标移入的源节点:event.toElement
返回激活事宜的源节点:event.srcElement
节点的相对援用:(设当前对节点为node)
返回父节点:node.parentNode || node.parentElement(IE)
返回子节点鸠合(包括文本节点及标签节点):node.childNodes
返回子标签节点鸠合:node.children
返回子文本节点鸠合:node.textNodes
返回第一个子节点:node.firstChild
返回末了一个子节点:node.lastChild
返回同属下一个节点:node.nextSibling
返回同属上一个节点:node.previousSibling
节点信息
是不是包括某节点:node.contains()
是不是有子节点node.hasChildNodes()
建立新节点
createDocumentFragment()--建立文档碎片节点
createElement(tagname)--建立标签名为tagname的元素
createTextNode(text)--建立包括文本text的文本节点
猎取鼠标点击事宜的位置
document.onclick = mouseClick;
function mouseClick(ev){
ev = ev || window.event;//window.event用来兼容IE
var x = 0; var y = 0;
if(ev.pageX){
x = ev.pageX;
y = ev.pageY;
}else if(ev.clientX){
var offsetX = 0 , offsetY = 0;
if(document.documentElement.scrollLeft){
offsetX = document.documentElement.scrollLeft;
offsetY = document.documentElement.scrollTop;
}else if(document.body){
offsetX = document.body.scrollLeft;
offsetY = document.body.scrollTop;
}
x = ev.clientX + offsetX;
y = ev.clientY + offsetY;
}
alert("你点击的位置是 x="+ x + " y=" + y);
}
以下所形貌的属性在chrome和Safari 都很给力的支撑了。
题目一:Firefox,Chrome、Safari和IE9都是经由过程非规范事宜的pageX和pageY属性来猎取web页面的鼠标位置的。pageX/Y猎取到的是触发点相对文档地区左上角间隔,以页面为参考点,不随滑动条挪动而变化
题目二:在IE 中,event 对象有 x, y 属性(事宜发作的位置的 x 坐标和 y 坐标)火狐中没有。在火狐中,与event.x 等效的是 event.pageX。event.clientX 与 event.pageX 有玄妙的差异(当全部页面有滚动条的时刻),不过大多数时刻是等效的。
offsetX:IE特有,chrome也支撑。鼠标相比较于触发事宜的元素的位置,以元素盒子模子的内容地区的左上角为参考点,假如有boder,能够涌现负值
题目三:
scrollTop为滚动条向下挪动的间隔,一切浏览器都支撑document.documentElement。
其他参照:http://segmentfault.com/a/1190000002559158#articleHeader11
参照表
(+为支撑,-为不支撑):
offsetX/offsetY:W3C- IE+ Firefox- Opera+ Safari+ chrome+
x/y:W3C- IE+ Firefox- Opera+ Safari+ chrome+
layerX/layerY:W3C- IE- Firefox+ Opera- Safari+ chrome+
pageX/pageY:W3C- IE- Firefox+ Opera+ Safari+ chrome+
clientX/clientY:W3C+ IE+ Firefox+ Opera+ Safari+ chrome+
screenX/screenY:W3C+ IE+ Firefox+ Opera+ Safari+ chrome+
检察下方DEMO:
你会发明offsetX在Firefox下是undefined,在chrome和IE则会一般显现。
https://jsfiddle.net/f4am208m/embedded/result/点击预览
图片形貌
offsetLeft和style.left辨别
1.style.left返回的是字符串,比方10px。而offsetLeft返回的是数值,比方数值10
2.style.left是可读写的,offsetLeft是只读的
3.style.left的值须要事前定义(在款式表中定义无效,只能取到在html中定义的值),不然取到的值是空的
getComputedStyle与currentStyle
getComputedStyle()接收两个参数:要获得盘算款式的元素和一个伪元素,假如不须要伪元素,则可所以null。然则,在IE中,并不支撑getComputedStyle,IE供应了currentStyle属性。
getComputedStyle(obj , false ) 是支撑 w3c (FF12、chrome 14、safari):在FF新版本中只须要第一个参数,即操纵对象,第二个参数写“false”也是人人通用的写法,目的是为了兼容老版本的火狐浏览器。
瑕玷:在规范浏览器中一般,但在IE6/7/8中不支撑
window.onload=function(){
var oBtn=document.getElementById('btn');
var oDiv=document.getElementById('div1');
oBtn.onclick=function(){
//alert(oDiv.style.width); //写在款式内外没法读取,只能获得写在行内的
//alert(getComputedStyle(oDiv).width); //适用于规范浏览器 IE6、7、8不辨认
//alert(oDiv.currentStyle.width); //适用于IE浏览器,规范浏览器不辨认
if(oDiv.currentStyle){
alert(oDiv.currentStyle.width);
}else{
alert(getComputedStyle(oDiv).width);
}
};
};
作废表单提交
<script type=”text/javascript”>
function listenEvent(eventObj,event,eventHandler){
if(eventObj.addEventListener){
eventObj.addEventListener(event,eventHandler,false);
}else if(eventObj.attachEvent){
event = "on" + event;
eventObj.attachEvent(event,eventHandler);
}else{
eventObj["on" + event] = eventHandler;
}
}
function cancelEvent(event){
if(event.preventDefault){
event.preventDefault();//w3c
}else{
event.returnValue = true;//IE
}
}
window.onload = function () {
var form = document.forms["picker"];
listenEvent(form,"submit",validateFields);
};
function validateFields(evt){
evt = evt ? evt : window.event;
...
if(invalid){
cancelEvent(evt);
}
}
</script>
肯定浏览器窗口的尺寸
关于主流浏览器来讲,比方IE9、Firefox,Chrome和Safari,支撑名为innerWidth 和 innerHeight的窗口对象属性,它返回窗口的视口地区,减去任何滚动条的大小。IE不支撑innerWidth 和 innerHeight
<script type=”text/javascript”>
function size(){
var w = 0, h=0;
if(!window.innerWidth){
w = (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth);
h = (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight);
}else{
w = window.innerWidth;
h = window.innerHeight;
}
return {width:w,height:h};
}
console.log(size());//Object { width: 1366, height: 633 }
</script>
有用的 JavaScript 计划(涵盖一切浏览器):
var w=window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
var h=window.innerHeight || document.documentElement.clientHeight|| document.body.clientHeight;
关于 IE 6、7、8的计划以下:
document.documentElement.clientHeight
document.documentElement.clientWidth
或许
document.body.clientHeight
document.body.clientWidth
Document对象的body属性对应HTML文档的<body>标签。Document对象的documentElement属性则示意 HTML文档的根节点。
attributes 属性
attributes 属性返回该节点的属性节点鸠合。
document.getElementById(‘box’).attributes//NamedNodeMap
document.getElementById(‘box’).attributes.length;//返回属性节点个数
document.getElementById(‘box’).attributes[0]; //Attr,返回末了一个属性节点
document.getElementById(‘box’).attributes[0].nodeType; //2,节点范例
document.getElementById(‘box’).attributes[0].nodeValue; //属性值
document.getElementById(‘box’).attributes[‘id’]; //Attr,返回属性为 id 的节点
document.getElementById(‘box’).attributes.getNamedItem(‘id’); //Attr
setAttribute 和 getAttribute
在IE中是不熟悉class属性的,需改成className属性,一样,在Firefox中,也是不熟悉className属性的,Firefox只熟悉class属性,所以一般做法以下:
element.setAttribute(class, value); //for firefox
element.setAttribute(className, value); //for IE
IE:能够运用猎取通例属性的要领来猎取自定义属性,也能够运用getAttribute()猎取自定义属性
Firefox:只能运用getAttribute()猎取自定义属性.
处置惩罚要领:一致经由过程getAttribute()猎取自定义属性
document.getElementById(‘box’).getAttribute(‘id’);//猎取元素的 id 值
document.getElementById(‘box’).id;//猎取元素的 id 值
document.getElementById(‘box’).getAttribute(‘mydiv’);//猎取元素的自定义属性值
document.getElementById(‘box’).mydiv//猎取元素的自定义属性值, IE 不支撑非
document.getElementById(‘box’).getAttribute(‘class’);//猎取元素的 class 值,IE 不支撑
document.getElementById(‘box’).getAttribute(‘className’);//非 IE 不支撑
PS:在 IE7 及更低版本的IE浏览器中,运用 setAttribute()要领设置 class 和 style 属性是没有结果的,虽然 IE8 处置惩罚了这个 bug,但照样不发起运用。
removeAttribute()要领
removeAttribute()能够移除 HTML 属性。
document.getElementById(‘box’).removeAttribute(‘style’);//移除属性
PS:IE6 及更低版本不支撑 removeAttribute()要领。
跨浏览器事宜Event对象
<!doctype html>
<html lang=”en”>
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
#drop{
width: 300px;
height: 200px;
background-color: #ff0000;
padding: 5px;
border: 2px solid #000000;
}
#item{
width: 100px;
height: 100px;
background-color: #ffff00;
padding: 5px;
margin: 20px;
border: 1px dashed black;
}
*[draggable = true]{
-moz-user-select: none;
-webkit-user-select: none;
cursor: move;
}
</style>
</head>
<body>
<div>
<p>将金黄色的小方块拖到赤色的大方块中,不兼容IE7及以下浏览器,兼容主流浏览器!</p>
</div>
<div id=”item” draggable=”true”></div>
<div id=”drop”></div>
<script type=”text/javascript”>
function listenEvent(target,type,handler){
if(target.addEventListener){//w3c
target.addEventListener(type,handler,false);
}else if(target.attachEvent){//IE
type = "on" + type;
target.attachEvent(type,handler);//IE
}else{
target["on" + type] = handler;
}
}
//作废事宜
function cancelEvent(e){
if(e.preventDefault){
e.preventDefault();//w3c
}else{
e.returnValue = false;//IE
}
}
//作废通报
function cancelPropagation(e){
if(e.stopPropagation){
e.stopPropagation();//w3c
}else{
e.cancelBubble = true;//IE
}
}
window.onload = function () {
var target = document.getElementById('drop');
listenEvent(target,'dragenter',cancelEvent);
listenEvent(target,"dragover",dragOver);
listenEvent(target,'drop', function (evt) {
cancelPropagation(evt);
evt = evt || window.event;
evt.dataTransfer.dropEffect = 'copy';
var id = evt.dataTransfer.getData('Text');
target.appendChild(document.getElementById(id));
});
var item = document.getElementById('item');
item.setAttribute("draggable",'true');
listenEvent(item,'dragstart', function (evt) {
evt = evt || window.event;
evt.dataTransfer.effectAllowed = 'copy';
evt.dataTransfer.setData('Text',item.id);
});
};
function dragOver(evt){
if(evt.preventDefault) evt.preventDefault();
evt = evt || window.event;
evt.dataTransfer.dropEffect = 'copy';
return false;
}
</script>
</body>
</html>
dataTransfer 对象
属性 形貌
dropEffect 设置或猎取拖曳操纵的范例和要显现的光标范例
effectAllowed 设置或猎取数据传送操纵可应用于该对象的源元素
要领 形貌
clearData 经由过程 dataTransfer 或 clipboardData 对象从剪贴板删除一种或多种数据花样
getData 经由过程 dataTransfer 或 clipboardData 对象从剪贴板猎取指定花样的数据
setData 以指定花样给 dataTransfer 或 clipboardData 对象给予数据
HTML5拖拽的浏览器支撑
Internet Explorer 9、Firefox、Opera 12、Chrome 以及 Safari 5 支撑拖放
为了使元素可拖动,需把 draggable 属性设置为 true :
<img draggable=”true” />
事宜 形貌
dragstart 拖拽事宜最先
drag 在拖动操纵上
dragenter 拖动到目的上,用来决议目的是不是接收安排
dragover 拖动到目的上,用来决议给用户的反应
drop 安排发作
dragleave 拖动脱离目的
dragend 拖动操纵完毕
上述代码的一些浏览器兼容性:
1.为了兼容IE,我们将window.event
赋给 evt
,其他浏览器则会准确将接收到的event
对象赋给evt
。
2.w3c运用addEventListener来为事宜元素增加事宜监听器,而IE则运用attachEvent。addEventListener为事宜冒泡到的当前对象,而attachEvent是window
3.关于事宜范例,IE须要加on + type
属性,而其他浏览器则不必
4.关于阻挠元素的默许事宜行动,下面是w3c和IE的做法:
e.preventDefault();//w3c
e.returnValue = false;//IE
5.关于作废事宜流传,w3c和IE也有差别的处置惩罚机制:
e.stopPropagation();//w3c
e.cancelBubble = true;//IE
跨浏览器猎取目的对象
//跨浏览器猎取目的对象
function getTarget(ev){
if(ev.target){//w3c
return ev.target;
}else if(window.event.srcElement){//IE
return window.event.srcElement;
}
}
关于猎取触发事宜的对象,w3c和IE也有差别的做法:
event.target;//w3c
event.srcElement;//IE
我们能够运用三目运算符来兼容他们:
obj = event.srcElement ? event.srcElement : event.target;
innerText的题目
innerText在IE中能一般事情,然则innerText在FireFox中却不可。
<script type=”text/javascript”>
if(navigator.appName.indexOf("Explorer") >-1){
document.getElementById('element').innerText = "my text";
} else{
document.getElementById('element').textContent = "my text";
}
</script>
跨浏览器猎取和设置innerText
//跨浏览器猎取innerText
function getInnerText(element){
return (typeof element.textContent == 'string') ? element.textContent : element.innerText;
}
//跨浏览器设置innerText
function setInnerText(element,text){
if(typeof element.textContent == 'string'){
element.textContent = text;
}else{
element.innerText = text;
}
}
oninput,onpropertychange,onchange的用法
onchange触发事宜必需满足两个前提:
a)当前对象属性转变,并且是由键盘或鼠标事宜引发的(剧本触发无效)
b)当前对象落空核心(onblur);
onpropertychange的话,只需当前对象属性发作转变,都邑触发事宜,然则它是IE专属的;
oninput是onpropertychange的非IE浏览器版本,支撑firefox和opera等浏览器,但有一点差别,它绑定于对象时,并不是该对象一切属性转变都能触发事宜,它只在对象value值发作转变时见效。
接见XMLHTTPRequest对象
<script type=”text/javascript”>
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();//非IE
}else if(window.ActiveXObject){
xhr = new ActiveXObject("Microsoft.XMLHttp");//IE
}
</script>
制止拔取网页内容
题目:
FF须要用CSS制止,IE用JS制止
处置惩罚要领:
IE: obj.onselectstart = function() {return false;}
FF: -moz-user-select:none;
三大不冒泡事宜
一切浏览器的focus/blur事宜都不冒泡,万幸的是大部分浏览器支撑focusin/focusout事宜,不过可恶的firefox连这个都不支撑。
IE6、7、8下 submit事宜不冒泡。
IE6、7、8下 change事宜要比及blur时才触发。
万恶的滚轮事宜
滚轮事宜的支撑可谓是杂乱无章,规律以下:
IE6-11 chrome mousewheel wheelDetla 下 -120 上 120
firefox DOMMouseScroll detail 下3 上-3
firefox wheel detlaY 下3 上-3
IE9-11 wheel deltaY 下40 上-40
chrome wheel deltaY 下100 上-100
关于鼠标滚轮事宜,IE支撑mousewheel,火狐支撑DOMMouseScroll。
推断鼠标滚轮是向上照样向下,IE是经由过程wheelDelta属性,而火狐是经由过程detail属性
事宜托付要领
//事宜托付要领
IE:document.body.onload = inject; //Function inject()在这之前已被完成
FF:document.body.onload = inject();
HTML5 的浏览器支撑状况
图片形貌
图片形貌
泉源地点:http://fmbip.com/litmus/
查询操纵
查询经由过程指的是经由过程一些特性字符串来找到一组元素,或许推断元素是不是是满足字符串。
IE6/7不辨别id和nam
在IE6/7下运用getElementById和getElementsByName时会同时返回id或name与给定值雷同的元素。因为name一般由后端商定,因而我们在写JS时,应保证id不与name反复。IE6/7不支撑getElementsByClassName和querySelectorAll
这两个函数从IE8最先支撑的,因而在IE6/7下,我们现实能够用的只要getElementByTagName。IE6/7不支撑getElementsByTagName(‘*’)会返回非元素节点
要么不必*,要么本身写个函数过滤一下。IE8下querySelectorAll对属性选择器不友好
险些一切浏览器预定义的属性都有了题目,只管运用自定义属性或许不必属性选择器。IE8下querySelectorAll不支撑伪类
有时刻伪类是很好用,IE8并不支撑,jquery供应的:first、:last、:even、:odd、:eq、:nth、:lt、:gt并不是伪类,我们在任何时刻都不要运用它们。IE9的matches函数不能处置惩罚不在DOM树上的元素
只需元素不在dom树上,肯定会返回false,着实不可把元素丢在body内里婚配完了再删掉吧,固然了我们也能够本身写婚配函数以防止回流。
to be continued…
材料参考:
http://w3help.org/zh-cn/kb/,
http://www.zhihu.com/question/29072028