1.访问元素的样式
任何支持sytle特性的html元素在js中都有一个对应的style属性。style对象包含着通过HTML的style特性指定的所有样式信息,但不包括与外部样式表或嵌入样式表经层叠而来的样式;
css属性将表现为这个style对象的相应属性;
var myDir=document.getElementById("myDir");
//设置背景颜色
myDir.style.backgroundColor="red";
//改变大小
myDir.style.width="100px";
myDir.style.height="200px";
//指定边框
myDir.style.border="1px solid black";
通过属性名取得属性的值
var prop,value,i,len;
for(i=0,len=myDir.length;i<len;i++){
prop=myDir.style[i]; //或者 myDir.style.item(i);
value=myDir.style.getPropertyValue(prop);
alert(prop+":"+value);
value=myDir.style.getPropertyCSSValue(prop); //CSSText和cssValueText是搞函数返回对象的两个属性
alert(prop+":"+value.CSSText+"("+value.cssValueType+")");
}
getComputedStyle()方法能够取得计算的样式;
第一个参数是计算样式的元素,第二个参数是一个伪元素字符串;
如果不需要伪元素信息,则第二个参数可以是null
var myDir=document.getElementById("myDir");
var computedStyle=document.defaultView.getComputedStyle(myDir,null);
alert(commputedStyle.backgroundColor); //red
IE不支持getComputedStyle(),但在IE中每个具有style属性的元素都还有一个currentStyle属性,用来取得计算的样式;
var myDir=document.getElementById("myDir");
var computedStyle=MyDir.currentStyle;
alert(commputedStyle.backgroundColor); //red
2.操作样式表
CSSStyleSheet类型表示的是样式表。继承自StyleSheet;是一套只读的接口;
应用于文档的所有样式表是通过document.styleSheets集合来表示的。通过这个集合的length属性可以获知文档中样式表的数量,而通过方括号语法或item()方法可以访问文档中每一个样式表。
CSSRule对象表示样式表中的每一条规则,它是一个供其他类型继承的基类型,其中最常见的就是CSSStyleRule类型;
CSSStyleRule对象最常用的三个属性:
①cssText:返回整条规则对应的文本,IE不支持这个属性;
②selectorText:返回当前规则的选择符文本;
③style:一个CSSStyleDeclaration对象,可以通过它设置和取得规则中特定的样式值
div.box{
background-color:blue;
width:100px;
heigth:200px;
}
假设这条规则位于页面的第一个样式表中,而这个样式表中只有这一条样式规则;
var sheet=document.styleSheet[0]; //取得文档中第一个样式表
var rules=sheet.cssRule||sheet.rules; //取得样式表中的规则列表
var rule=rules[0]; //取得第一条规则
alert(rule.selectorText); //"div.box"
alert(rule.cssText); //完整的CSS代码
alert(rule.style.width); //100px
rule.style.backgroundColor="red"; //修改样式信息
创建规则
InsertRule(规则文本,在哪里插入规则的索引),可以向样式表中添加新规则;
IE以及更早版本支持的是,addRule(选择符文本,css样式信息,插入规则的位置)
最多可以使用addRule()添加4095条规则,否则报错;
跨浏览器的方式向样式表中插入规则:
//(要插入规则的样式,选择符文本,规则信息,插入位置)
function inserRlue(sheet,selectorText,cssText,position){
if(sheet.insertRule){
sheet.insertRule(selectorText+"{"+cssText+"}",position);
}else if(sheet.addRule){ //IE浏览器
sheet.addRule(selectorText,cssText,position);
}
}
insertRule(document.styleSheet[0],"body","background-color:red",0);
删除规则
删除规则的方法时deleteRule(要删除的规则的位置)
IE支持的删除规则的方法:removeRule(要删除的规则的位置)
考虑到删除规则可能影
响css层叠效果,所以要慎用删除规则
跨浏览器删除规则的函数
function deleteRule(sheet,index){
if(sheet.deleteRule){
sheet.deleteRule(index);
}else if(sheet.removeRule){
sheet.removeRule(index);
}
}
元素大小
1)偏移量:包括元素在屏幕上占用的所有可见的空间
元素的可见大小由其高度、宽度决定,包括所有的内边距、滚动条和边框大小
以下图形表示跟元素有关的属性的意义
某个元素在页面上的偏移量等于元素的offsetLeft和offsetTop与其offsetParent的相同属性相加
取得元素在页面左偏移量的函数:
function getEleementLeft(element){
var actualLeft=element.offsetLeft;
var current=element.offsetParent;
while(current!=null){
actualLeft+=current.offsetLeft;
current=current.offsetParent;
}
return actualLeft;
}
取得元素在页面上偏移量的函数:
function getEleementTop(element){
var actualTop=element.offsetTop;
var current=element.offsetParent;
while(current!=null){
actualTop+=current.offsetTop;
current=current.offsetParent;
}
return actualTop;
}
客户区大小
元素的客户区大小,指的是元素内容及其内边距所占据的空间大小;
客户区的大小就是元素内部空间的大小,因此滚动条占用的空间就不就算在内;
客户区大小是只读的,每次访问都要重新计算;
确定浏览器视口大小使用的函数:
function getViewport(){
if(doocument.compatMode=="BackCompat"){ //混杂模式,IE7之前的版本
return{
width:document.body.clientWidth;
height:document.body.clientHeight;
};
}else{
return{
width:document.documentElement.clientWidth;
height:document.documentElement.clientHeight;
};
}
}
滚动大小
滚动大小指的是包含滚动内容的元素的大小;
scrollheight和scrollWidth主要用于确定元素内容的实际大小;
在不包含滚动页面的时候,scrollHeight和scrollWidth与clientHeight和clientWidth之间的关系并不清晰;在这种情况下,基于document.documentEleement查看的这些属性会在浏览器发现一些不一致的问题;
遍历
NodeIterator和TreeWalker这两个类型能够基于给定的起点对Dom结构执行深度优先的遍历操作。
IE不支持DOM遍历;
DOM遍历是深度优先的DOM结构遍历,即移动方向至少有两个。遍历以给定节点为根,不可能向上超出DOM树的根节点。
任何节点都可以作为根节点;
HTML页面:
<!DOCTYPE html>
<html>
<head>
<title>example</title>
</head>
<body>
<p><b>hello</b> world!</p>
</body>
</html>
展示这个页面DOM结构树
NodeIterator
创建实例:document.createNodeIterator(root,whatToShow,filter,entityReferenceExpansion)
刚创建的实例有一个内部指针指向根节点;
root:想要作为搜索起点的树中节点;
whatToShow:表示要访问哪些节点的数字代码;
filter :是一个NodeFilter对象,或者一个表示应该接受还是拒绝某种特定节点的函数;(如果不指定过滤器,则为null)
entityReferenceExpansion:布尔值,表示是否要扩展实体引用;
创建一个只显示<p>元素的节点迭代器;
var filter={
acceotNode:function(node){
return node.tagName.toLowerCase()=="p"?
NodeFilter.FILTER_ACCEPT: //接收
NodeFilter.FILTER_SKIF; //跳过当前节点到下一个节点
}
};
var iterator=document.createNodeIterator(root,NodeFilter.SHOW_ELEMENT,filter,false);
NodeIterator类型有两个操作方法:
1)nextNode() 方法用于向前前进一步;
2)previousNode()方法用于向后退一步
TreeWalker
TreeWalker是NodeIterator的一个更高的版本;
创建实例:document.createTreeWalker(root,wahtToShow,filter,entityReferenceExansion)
具有的方法:
除了nextNode(),previousNode()方法之外,还有
1)parentNode():遍历当前节点的父节点
2)firstNode():遍历当前节点的第一个子节点;
3)lastChild():遍历当前节点的最后一个子节点;
4)nextSibling():遍历当前节点的下一个同辈节点;
5)previouSibling():遍历当前节点的上一个同辈节点;
6)currentNode属性:表示任何遍历方法在上一次遍历中返回的节点。利用它可以修改遍历继续进行的起点;
TreeWalker真正强大的地方在于在DOM结构中可以沿任意方向移动,使用TreeWalker遍历DOM树,即使不使用过滤器也可以取得某些特定的元素;
var div=document.getElementById("div1");
var filter={
acceotNode:function(node){
return node.tagName.toLowerCase()=="li"?
NodeFilter.FILTER_ACCEPT: //接收
NodeFilter.FILTER_SKIF; //跳过当前节点到下一个节点
}
};
var walker=document.createTreeWalker(div,NodeFilter.SHOW_ELEMENT,filter,false);
var node=walker.nextNode();
while(node!=null){
alert(node.tagname);
node=wakler.nextNode();
}
范围
如果浏览器支持范围,那么就可以是创建范围实例,新创建的范围直接与创建它的文档关联到一起,不能用于其他文档。
创建范围并设置了其位置之后,还可以针对范围的内容执行很多操作,从而实现对底层DOM树的更精准的控制;
每一个范围由一个Range类型的实例表示;
1、使用范围选择文档的一部分;
selectNode(node):选择的是整个节点,包括其子节点;
selectNodeContents(node):只选择节点的子节点;
var range1=document.createRange();
var range2=document.createRange();
p1.document.getElementById("p1");
range1.aelectNode(p1);
range2.selectNodeContents(p1);
2、用DOM范围实现复杂的选择
setStart(参数节点,偏移量值)
setEnd(参数节点,偏移量)
选取"hello world!"中的“llo”到“world!”的“o”;
var p1=document.getElementById("p1");
helloNode=p1.firstChild.firstChild;
worldNode=p1.lastChild;
var range=document.createRange();
range.setStart(helloNode,2);
range.setEnd(worldNode,3);
在创建范围时,内部会为这个范围创建一个文档片段;会自动补全该范围内缺少的标签;
在使用操作方法之前,拆分的节点并不会产生格式良好的文档片段,原始HTML在DOM被修改之前会始终保持不变;
比如在前一个例子中修改后的DOM实质上是:
<p id="p1"><b>he</b><b>llo</b> world!</p>
3、操作DOM范围中的内容
1)deleteContents():从文档中删除范围所含的内容;
var p1=document.getElementById("p1");
helloNode=p1.firstChild.firstChild;
worldNode=p1.lastChild;
var range=document.createRange();
range.setStart(helloNode,2);
range.setEnd(worldNode,3);
range.deleteContents(); //从文档中删除该范围
删除后页面变成
<p id="p1"><b>he</b>rld!</p>
2)extractContents():从文档中移除范围,返回范围额文档片段,可以将返回的文档片段加入到文档的其他地方;
var p1=document.getElementById("p1");
helloNode=p1.firstChild.firstChild;
worldNode=p1.lastChild;
var range=document.createRange();
range.setStart(helloNode,2);
range.setEnd(worldNode,3);
var fragment=range.extractContents();
p1.parentNode.appendChild(fragment);
页面变化如下:
<p id="p1"><b>he</b>rld!</p>
<b>llo</b> wo
3)cloneContents()创建范围对象的一个副本,然后在文档的其他地方插入该副本;
var p1=document.getElementById("p1");
helloNode=p1.firstChild.firstChild;
worldNode=p1.lastChild;
var range=document.createRange();
range.setStart(helloNode,2);
range.setEnd(worldNode,3);
var fragment=range.cloneContents();
p1.parentNode.appendChild(fragment);
页面变化如下:
<p id="p1"><b>hello</b> world!</p>
<b>llo</b> wo
4、插入DOM范围中的内容
1)insertNode():可以向范围中的开始处插入一个节点;
var p1=document.getElementById("p1");
helloNode=p1.firstChild.firstChild;
worldNode=p1.lastChild;
var range=document.createRange();
range.setStart(helloNode,2);
range.setEnd(worldNode,3);
var span=document.createElement("span");
span.style.color="red";
span.appendChild(document.createTextNode("insert node"));
range.insertNode(span);
页面变化如下:
<p id="p1"><b>he<span style="color:red">insert text</span>llo</b> world!</p>
2)surroundContents():该方法可以环绕范围插入内容;
在环绕范围插入内容是,后台会执行下列步骤:
①提取出范围中的内容;
②将给定的节点插入到文档中的原来位置上;
③将文档片段的内容添加到给定节点中;
var p1=document.getElementById("p1");
helloNode=p1.firstChild.firstChild;
worldNode=p1.lastChild;
var range=document.createRange();
range.setStart(helloNode,2);
range.setEnd(worldNode,3);
var span=document.createElement("span");
span.style.backgroundColor="red";
range.surroundContents(span);
页面变化
<p id="p1"><b>he</b><span style="background-color:red"><b>llo</b> wo</span>rld!</p>
5.折叠DOM范围
使用collapse()方法来折叠范围,这个方法接收一个参数布尔值,表示要折叠到范围的哪一端;
true时表示折叠到范围的起点,即光标定位到范围的起点;
false时表示折叠到范围的终点;
6、比较DOM范围
compareBoundaryPoints(比较方式的常量值,比较的范围)方法确定这些范围是否有公共的边界(起点或终点)
如果第一个范围中的点位于第二个范围中的点之前,返回-1
如果第一个范围中的点位于第二个范围中的点之后,返回1;
如果两个点相等,返回0;
7、赋值DOM范围
使用cloneRange()方法复制范围,这个方法会创建调用它范围的一个副本;
var newrange=range.cloneRange();
8、清理DOM范围
使用完范围之后最好是调用detach()方法,以便从创建范围的文档中分离出该范围,调用detach()之后,就可以放心的解除对范围的引用,从而让垃圾回收机制回收其内存;
range.detach(); //从文档中分离范围
range=null; //删除引用
IE8及更早版本中的范围
IE9支持DOM范围,但IE8以及更早的版本不支持DOM范围。支持的是文本范围,文本范围是IE的专有特性,其他浏览器都不支持。
文本范围:处理的主要是文本,不一定是DOM节点。
1)创建文本范围:
var range=document.body.createTextRange()
document创建的范围可以在页面的任何地方使用;
2)用IE范围实现简单的选择
① var found=range.findText("hello");
选择某一区域的最简单的方式,这个方法会找到第一次出现的给定文本,并将范围移过来以围绕该文本。返回布尔值;
② range.text; //hello
可以得到范围中包含的文本;
③ var frange=range.findText("hello",1);
findText()可以传入第二个参数,一个表示会向哪个方向的继续搜索的数值。负值表示应该从当前位置向后搜索,而正值表示应该向前搜索。
④ moveToElement(),这个方法接收一个DOM元素,并选择该元素的所有文本,包括HTML标签;
range.moveToElement(p1);
range.htmlText;
在文本中包含HTML的情况下,可以使用htmlText属性取得范围的全部内容,包括HTML和文本。
IE的范围没有任何属性可以随着范围选区的变化而动态更新;
3)使用IE范围实现复杂的选择
move()、moveStart()、moveEnd()和expand()这些方法可以以特定的增量向四周移动范围。都接收两个参数:移动单位和移动单位的数量;移动单位的类别:
“character” 字符 “word” 单词 sentence 句子 textedit 移动到当前选区开始或结束的位置;
moveStart()可以移动范围的起点 moveEnd()可以移动范围的终点;
range.moveStart("world",2); //起点移动两个单词
range.moveEnd("character",1); //终点移动1个字符
4)操作范围中的内容
操作范围中内容可以使用text属性和pasteHTML()
range.pasteHTML("<b>bob</b>");
5)折叠范围
collapse()方法与相应的DOM方法一样,传入true则把范围折叠到起点,传入false则把范围折叠到终点;
range.collapse(true);
6)比较IE范围
compareEndPoints(比较的类型,比较的范围),返回结果与DOM范围的比较是一样的;
range1.compareEndPoints("StartToStart",range2);
isEqual()用于确定两个范围是否相等;
inRange()用于确定一个范围是否包含另个范围;
range1.isEqual(range2);
range1.inRange(range2);
7)复制IE范围
duplicate()方法可以复制文本范围,结果会创建原范围的一个副本;
var newrange=range.duplicate();