javascript DOM详解之DOM2与DOM3

DOM2与DOM3主要是在DOM1的基础上引入更多的交互能力,支持了更高级的XML特性。
DOM2做的主要的扩展子集具体为:
DOM Level 2 Core:在一级核心的基础上,为节点添加了更多的方法和属性。
DOM Level 2 Views:为文档定义了基于样式信息的不同视图
DOM Level 2 Events:说明了如何使用事件与DOM进行交互。
DOM Level 2 Style:定义了如何以编程的方式来访问和改变CSS样式的信息
DOM Level 2 Traversal and Range:引入了遍历DOM和选择其特定部分的新接口
DOM Level 2 HTML:在一级的HTML上构建添加了更多的属性、方法和新接口

DOM的变化
DOM2和DOM3,实现了对既有的API进行扩展,提供了更好的错误处理以及特性检测能力。这从很大程度上支持了命名空间。要确定浏览器是否支持DOM2和DOM3,可以使用以下的代码:
var supportsDOM2Core=document.implementation.hasFeature("Core","2.0");
var supportsDOM3Core=document.implementation.hasFeature("Core","3.0");
var supportsDom2HTML=document.implementation.hasFeature("HTML","2.0");
var supportsDOM2Views=document.implementation.hasFeature("Views","2.0");
var supportsDom2XML=document.implementation.hasFeature("XML","2.0");

针对XML命名空间的变化
有了XML的命名空间,不同XML可以合并成为一个XML。从技术上说,html不支持XML命名空间,但是XHTML支持。命名空间要使用xmlns特性来指定。
使用示例:
<html  xmlns="http://www.w3.org/1999/xhtml">, 使用它来替换<html>
但是,想要明确的为XML命名空间创建前缀,可以使用xmlns后跟冒号,再后跟前缀。
<xhtml:html xmlns:xhtml=   "http://www.w3.org/1999/xhtml" > ,使用它来替换<html>
为了区分XHTML中元素,避免混乱,也需要使用命名空间来进行限定标签名称和标签属性。

DOM2提供的针对命名空间的解决方法
1.Node类型的方法
在DOM2级别中,Node类型包含特定于命名空间的属性
localname:不带命名空间前缀的节点名称
namespaceURI:命名空间的URI或者(未指定的情况下)null
prefix:命名空间前缀或者(未指定的情况下)null
当节点使用命名空间前缀时,其nodeName等于prefix+":"+localName
例如:<s:svg xmlns:s="http://www.w3.org/2000/svg" width="100%" height="290" version="1.1" id="svg">
          </s:svg>
localname:svg     tagName:  s:svg          namespaceURI:http://www.w3.org/2000/svg     prefix:s
DOM3在此基础上更进一步,引入例如与命名空间相关的方法:
isDefaultNamespace(namespaceURI):在指定的namespaceURI是当前节点的默认命名空间的情况下返回true
lookupNamespaceURI(prefix):返回给定的prefix的命名空间
lookupPrefix(namespaceURI):返回给定的namespaceURI的前缀
2.Document类型的变化
DOM2为命名空间创建了一下的方法:方法的意义类似DOM1的
createElementNS(namespaceURI,tagName):
createAttributeNS(namespaceURI,attributeName):
getElementsByTagNameNS(namespaceURI,tagName):
3Element类型的变化
DOM2级核心中有关Element的变化主要涉及操作特性。新增方法具体意义参见DOM1的:
getAttributeNS(namespaceURI,localname):
getAttributeNodeNS(namespaceURI,localname):
getElementsByTagNameNS(namespaceURI,tagName):
hasAttributeNS(namespaceURI,attributeName):
removeAttributeNS(namespaceURI,attributeName):
setAttributeNS(namespaceURI,qualifiedName,value):
setAttributeNodeNS(attNode):
4.NamedNodeMap类型的变化,同上
getNamedItemNS(namespaceURI,localName):
removeNamedItemNS(namespaceURI,localName):
setNamedItemNS(node):

其它方面的变化
这些变化与XML命名空间无关,而是更倾向于确保API的可靠性和完整性。
1.DocumentType类型的变化
新增了三个属性:
publicId:
systemId:
interbalSubset:
以下面的标签为例:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 //EN"  "http://www.w3.org/TR/html4/strict.dtd">
publicId=-//W3C//DTD HTML 4.01 //EN
systemId= http://www.w3.org/TR/html4/strict.dtd  
  最后一个属性interSubset不常用,访问内部子集用的,XML用的较多。
2.Document类型的变化
唯一与命名空间无关的方法是importNode(),这个是用来从一个文档中取得一个节点,然后导入另一个文档的,使其成为另一个文档结构的一部分。它接收两个参数:要复制的节点和一个鄙视是否复制子节点的布尔值。
var newNode=document.importNode(oldNode,true);
document.body.appendChild(newNode);
在DOM2视图中,新加了一个属性defaultView属性,指向拥有给定文档的窗口。IE中的等价属性是parentWindow,因此要确定文档的归属窗口,可以使用以下代码:
var parentWindow=document.defaultView||document.parentWindow;
除了上述的方法和属性外,DOM2核心还为document.implementation对象规定了新方法:createDocumentType()和createDocument().前者用于创建一个新的DocumentType节点,接收三个参数:文档类型名称,publicId,systemId。例子:
var doctype=document.implementation.createDocumentType("html","-//W3C//DTD HTML 4.01 //EN", "http://www.w3.org/TR/html4/strict.dtd");
创建新文档的时候要使用createDocument()方法,接收三个参数:针对文档元素的namespaceURI,,文档元素的标签名,新文档的文档类型。例子:
var doc=doucment.implementation.createDocument("","root",null);//xml document
var  doc=document.implementation.createDocument("http://www.w3.org/1999/xhtml","html",doctype);//xhtml;
新增的创建HTML文档的方法
var htmldoc=document.implementation.createHTMLDocument("new doc");
3.Node类型的变化
Node类型中唯一与命名空间无关的新增方法是isSupported(),它被用来确定当前节点具有什么能力,接收两个参数:特性名称和特性版本号。
if(document.body.isSupported("HTML","2.0")){//支持DOM2级HTML支持的操作}
DOM3引入了两个辅助比较节点的方法:isSameNode()和isEqualNode(),都只接受一个参数,如果传入的节点和引用的节点一样,则返回true。相等与节点相同是不一样的。
DOM3还针对DOM节点添加额外的数据新引入了新的方法。其中setUserData()方法会将给定的数据给节点,它接收三个参数:要设置的key,实际的数据,处理函数。
document.body.setUserData("name","Nicholas",function(){});
var value=document.body.getUserData("name");
传入setUserData()中的处理函数会在带有数据的节点被复制、删除、重命名或引入一个文档时调用,因而你可以决定在上述操作发生时如何处理数据。处理函数要接受5个参数:操作类型的数值(1表示复制,2表示导入,3表示删除,4表示重命名)、数据键、数据值、源节点和目标节点。在删除节点时,源节点为null;复制时,目标节点为null。
var div=document.createElement("div");
div.setUserData("name","Nicholas",function(operation,key,value,src,dest){
  if(operation==1){
  dest.setUserData(key,value,function(){  });
  }      
   });
var mydiv=div.cloneNode(true);
alert(mydiv.getUserData("name"));
4.框架的变化
框架和内嵌框架分别用HTMLFrameElement和HTMLIFrameElement表示,它们在DOM2中都有了一个新的属性:contentDocument,它指向表示框架内容的文档对象。
var iframe=document.getElementById("myIframe");
var iframeDoc=iframe.contentDocument||iframe.contentWindow.document;


样式
在HTML中定义样式的方式有3种:通过<link/>元素包含外部样式表文件、使用<style/>元素定义嵌入样式,使用style特性定义针对于特定元素的样式。下面是检测浏览器是否支持DOM2定义的CSS能力:
var supportDOM2CSS=document.implementation.hasFeature("CSS","2.0");
var supportDOM2CSS2=document.implementation.hasFeature("CSS2","2.0");

访问元素的样式表
CSS属性与javascript的样式属性有一定的关联关系,例如CSS的color与js的style.color对应,font-family与style.fontFamily对应,float与style.cssFloat对应。
示例:
var mydiv=document.getElementbyId("mydiv");
mydiv.style.background="red";
mydiv.style.width=" 100px";
在设置度量值时必须指定一个度量单位。
1.DOM样式属性和方法
DOM2样式规范还为style对象定义了一些属性和方法。这些属性和方法在提供元素的style特性值的同时,也可以修改样式。详细信息如下:
cssText:能够访问到style特性中的CSS代码
length:应用给元素的CSS属性的数量
parentRule:表示CSS信息的CSSRule对象。
getPropertyCSSValue(propertyName):返回包含给定属性值的CSSValue对象。
getPropertyPriority(propertyName):如果给定的属性使用了!important设置,则返回“important”;否则返回空字符串。
getPropertyValue(propertyValue):返回给定属性的字符串值
item(index):返回给定位置的CSS属性的名称
removeProperty(propertyName):从样式表中删除属性
setProperty(propertyName,value,priority):将给定的属性值设为相应的值,并加上优先权标志(“important”或者空字符串)
2.计算样式
DOM2计算样式的方法:document.defaultView.getComputedStyle(),参数有两个,第一个要取得计算样式的元素,第二个是伪元素字符串,如果不需要,可以是null。IE不支持它,但是提供了类似的属性document.getElementById(id).currentStyle。通过domNode.currentstyle来获取

操作样式表
CSSStyleSheet对象是一套只读的借口,下面的代码确定浏览器是否支持DOM2级的样式表:
var supportDOM2StyleSheets=document.implementation.hasFeature("StyleSheets","2.0");
CSSStyleSheet继承自StyleSheeet,后者作为一个基础借口来定义非CSS样式表.从StyleSheet接口继承来的属性如下:
disabled:可读写,设为true,禁用样式表
href:用link引入的会是URL其它null
media:当前样式表支持的所有媒体的集合
ownerNode:指向拥有当前当前样式表的节点的指针。可能为link,style,null(@important导入)
parentStyleSheet:在当前样式表使用important导入的情况下,这个属性是一个指向导入它的样式表的指针。
title:ownerNode中title的属性值
type:表示样式表类型的字符串
cssRules:样式表中表示样式规则的集合,IE不支持,但有类似的rules属性
ownerRule:如果样式表通过@import导入的,这个属性就是一个指针,指向表示导入的规则,否则为null,IE不支持
deleteRule(index):删除cssRules集合中指定位置的规则。IE不支持这个方法,但支持一个类似removeRule()方法。
insertRule(rule,index):向cssRules集合中指定的位置插入字符串,IE不支持,但是提供类似的addRule()方法。
应用于文档的所有样式表是通过document.styleSheets集合来表示的。

CSS规则
CSSStyleRule对象包含以下的属性:
cssText:返回整条规则对应的文本
parentRule:如果当前规则是导入规则,则引用导入规则,否则为null
parentStyleSheet:当前规则所属样式表
selectorText:返回当前规则的选择符文本
style:可以通过它设置和取得规则中特定的样式值
type:规则类型的常量值
最常用的为cssText,selectorText,style。

创建规则
添加新规则用insertRule()方法。接收参数为:规则文本和表示在哪里插入规则的索引。
sheet.insertRule("body{background:silver}",0);
但是这种方式并不常用,下面是插入规则的兼容性代码
function insertRule(sheet,selectortext,cssText,position){
  if(sheet.inertRule){
   sheet.insertRule(selectorText+"{"+cssText+"}",position);
  }else if(sheet.addRule){
    sheet.addRule(selectorText,cssText,position);
  }
}
同时还有删除规则的代码,也不常用
function deleteRule(sheet,index){
  if(sheet.deleteRule){
    sheet.deleteRule(index);
  }else if(sheet.removeRule){
   sheet.removeRule(index);
  }
}

元素的大小
偏移量问题
元素的可见大小由其高度、宽度决定,包括所有的内边距、滚动条和边框大小。可以通过下面四个属性取得元素的偏移量。
offsetHeight:元素在垂直方向上占用的空间大小,以像素计。
offsetWidth:元素在水平方向上占用的空间大小,以像素计。
offsetLeft:元素的左外边框至包含元素的左内边框之间的像素距离
offsetTop:元素的上外边框至包含元素的上内边框之间的像素距离
其中,offsetLeft和offsetTop属性与包含元素相关,包含元素的引用保存在offsetParent属性中。
下面是取得元素的左和上偏移量,但是当使用表格和内嵌框架时,计算出来的数据会有很大的误差
function getElementLeft(element){
  var actualLeft=element.offsetLeft;
  var current=element.offsetParent;
  
  while(current!=null){
    actualLeft+=current.offsetLeft;
current=current.offsetParent;
  }
  return actualLeft;   
}
function getElementTop(element){
  var actualTop=element.offsetTop;
  var current=element.offsetParent;
  
  while(current!=null){
    actualTop!=null;
current=current.offsetParent;
  }
  return actualTop; 
}

客户区大小
元素的客户区大小指的是元素内容距及其内边距所占据的空间大小。相关属性有两个:clientWidth和clientHeight。其中,clientWidth属性是元素内容区域的宽度加上左右内边距宽度;clientHeight属性是元素内容区高度加上上下内边距高度。
获取客户区大小的方法
function getWiewport(){
  if(document.compatMode=="BackCompat"){
    return {
    width:document.body.clientWidth,
height:document.body.clientHeight
};
  }else{
  return {
    width:document.documentElement.clientWidth,
height:document.documentElement.clientHeight
  };
  }
}

滚动大小
滚动大小指的是包含滚动内容的元素大小。有的无设置也可以滚动,例如html;有的必须在CSS中设置overflow才能滚动。相关属性有4个,如下:
scrollHeight:在没有滚动条的情况下,元素内容的总高度。
scrollWidth:没有滚动条的情况下,元素内容的总宽度。
scrollLeft:被隐藏在内容区域左侧的像素数,通过设置这个属性可以改变元素的滚动位置
scrollTop:被隐藏在内容区域上方的像素数,通过设置这个属性可以改变元素的滚动位置
scrollWidth和scrollHeight主要用于确定元素的实际大小。对于不包含滚动条的页面而言,scrollWidth和scrollHeight与clientWidth和clientHeight之间的关系并不明确。在确定文档的总高度时,必须取得scrollWidth/clientWidth和scrollHeight/clientHeight中的最大值,才能保证在跨浏览器的环境下得到精确地结果。
var docHeight=Math.max(document.documentElement.scrollHeight,document.documentElement.clientHeight) ;
var docWidth=Math.max(document.documentElement.scrollWidth,document.documentElement.clientWidth);
对于运行在混杂模式下的情况,用document.body代替document.documentElement即可
scrollTop和scrollWidth确定元素的当前滚动状态,使用下面的代码,可以讲滚动状态调回顶部
function scrollToTop(element){
  if(element.scrollTop!=0){
   element.scrollTop=0;
  }
}

确定元素的大小
使用表格布局或者滚动元素的情况下,结果不准确。代码:
function getBoundingClientRect(element){
   var scrollTop=document.documentElement.scrollTop;
   var scrollLeft=document.documentElement.scrollLeft;
   
   if(element.getBoundingClientRect){
      if(typeof arguments.callee.offset!="number"){
    var temp=document.createElement("div");
temp.style.cssText="position:absolute;left:0;top:0;";
document.body.appendChild(temp);
arguments.callee.offset=-temp.getBoundingClientRect().top-scrollTop;
document.body.removeChild(temp);
temp=nill;
  }
  var rect=element.getBoundingClientRect();
  var offset=arguments.callee.offset;
  return {
    left:rect.left+offset,
right:rect.right+offset,
top:rect.top+offset,
bottom:rect.bottom+offset
  };
   }else{
    var actualLeft=getElementLeft(element);
var actualTop=getElementTop(element);
return {
  left;actualLeft-scrollLeft,
  right:actualLeft+element.offsetWidth-scrollLeft,
  top:actualTop-scrollTop,
  bottom:actualTop+element.offsetHeight-scrollTop
};    
   }
}


遍历
DOM2的遍历和范围模块定义了两个用于辅助完成顺序遍历DOM结构的类型:NodeIterator和TreeWalker。这两个类型都能够基于给定的起点对DOM结构执行深度优先的遍历操作。使用下列代码可以检测浏览器对DOM2级遍历能力的支持:
var supportTraversal=document.implementation.hasFeature("Traversal","2.0");
var supportNodeIterator=(typeof document.createNodeIterator=="function");
var supportTreeWalker=(typeof document.createTreeWalker=="function");

NodeIterator
NodeIterator是比较简单的一种,可以使用document.createNodeIterator()方法创建它的新实例。该方法接收4个参数:
root:想要作为搜索起点的树中的节点
whatToShow:表示要访问那些节点的数字代码
filter:是一个NodeFilter对象,或者一个表示应该接受还是拒绝特定类型节点的函数
entityReferenceExpansion:布尔值,表示是否要扩展实体引用。在HTML中不可用,因为HTML不可扩展。
whatToShow参数是一位掩码,通过一个或者多个过滤器来确定要访问那些节点。这个参数的值以常量形式在NodeFilter类型中定义,如下所示:
1、NodeFilter.SHOW_ALL:搜索所有节点;
2、NodeFilter.SHOW_ELEMENT:搜索元素节点;
3、NodeFilter.SHOW_ATRRIBUTE:搜索特性节点;
4、NodeFilter.SHOW_TEXT:搜索文本节点;
5、NodeFilter.SHOW_ENTITY_REFERENCE:搜索实体引用节点;
6、NodeFilter.SHOW_ENTITY:搜索实体节点;
7、NodeFilter.SHOW_PROCESSING_INSTRUCTION:搜索PI节;
8、NodeFilter.SHOW_COMMENT:搜索注释节点;
9、NodeFilter.SHOW_DOCUMENT:搜索文档节点;
10、NodeFilter.SHOW_DOCUMENT_TYPE:搜索文档类型节点;
11、NodeFilter.SHOW_DOCUMENT_FRAGMENT:搜索文档碎片节节;
12、NodeFilter.SHOW_NOTATION:搜索记号节点;
除了NodeFilter.SHOW_ALL之外,可以使用按位或操作符来组合多个选项,如下所示:
var whatToShow=NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT;
可以通过createNodeIterator()方法的filter参数来指定自定义的NodeFilter对象,或者指定一个功能类似的节点过滤器函数。每个NodeFilter对象只有一个方法,即acceptNode();如果应该访问给定的节点,该方法返回NodeFilter.FILTER_ACCEPT,如果不应该访问该节点,返回NodeFilter.FILTER_SKIP.因为NodeFilter是一个抽象类型,不能直接创建实例,在必要时,只要创建一个包含acceptNode的对象,然后传入createNodeIterator()中即可。
下面是一个只显示<p>元素的节点迭代器:
var filter={
  acceptNode:function(node){
    return node.tagName.toLowerCase()=="p"?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP;
  }
};

var iterator=document.createNodeIterator(root,NodeFilter.SHOW_ELEMENT,filter,false);
但是filter也可以使用下面的样子
var filter=function(node){
   return node.tagName.toLowerCase()=="p"?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP; 
}
NodeIterator类型主要的方法有两个nextNode()和previousNode().nextNode()是向前前进一步,previousNode()是向后后退一步


TreeWalker是NodeIterator的一个更高级的版本。除了nextNode()和previousNode(),还有下面的方法:
parentNode():进入当前节点的父节点;
firstChild():进入当前节点的第一子节点;
lastChild():进入当前节点的最后一个子节点
nextSibling():进入当前节点的下一个兄弟节点
previousSibling():进入当前节点的前一个兄弟节点
创建TreeWalker需要使用document.createTreeWalker来创建,接收4个参数,与document.createNodeIterator方法类似。
使用示例:
var div=document.getElementById("div1");

var filter=function(node){
   return node.tagName.toLowerCase()=="li"?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP; 
}

var walker=document.createTreeWalker(div,NodeFilter.SHOW_ELEMENT,filter,false);
在过滤的类型中,NodeFilter.FILTER_REJECT是跳过相应的节点和其子节点。NodeFilter.FILTER_SKIP是跳过相应的节点,进入其子节点继续。而且在TreeWalker中,即使不加过滤函数filter,只通过它的方法也可以进行DOM的遍历。
它还有属性currentNode,表示上一次遍历中返回的节点。IE中没有对应的类型和方法。


范围
DOM2在Document类型中定义了createRange()方法,在兼容DOM的浏览器中,这个方法属于document对象。可以使用下面的方法检测是否支持范围:
var supportsRange=document.implementation.hasFeature("Range","2.0");
var alsoSupportsRange=(typeof document.createRange=="function");
创建范围是为了更加精细化操作DOM结构,因此在很多情况下是用不到它的。如果要使用它,先看一下范围的创建吧:
var range=document.createRange();
每个范围由一个Range类型的实例表示,每个实例有一些方法和属性:
startContainer:包含范围起点的节点(即选取中第一个节点的父节点)
startOffset:范围在startContainer中起点的偏移量。如StartContainer是文本节点,则startOffset就是范围起点之前跳过的字符数量。否则,startOffset就是范围中第一个子节点在父节点中的索引。
endContainer:包含范围终点的节点(即选取最后一个节点的父节点)。
endOffset:范围在endContainer中终点的偏移量(规则如startoffset)
commonAncestorContainer:startContainer和endContainer共同的祖先节点在文档树种位置最深的那个。
实现DOM范围的简单选择,最简单的方式就是使用selectNode()或者selectNodeContents()。这两个方法都是接收一个参数,即一个DOM节点,然后使用该节点中的信息来填充范围。selectNode()方法选择整个节点,selectNodeContent()方法选择节点的子节点。代码实例:
var range1=document.createRange();
var range2=document.createRange();
var tt=document.getElementById("tt");
range1.selectNode(tt);// 范围1的部分是节点tt,包含节点本身
range2.selectNodeContent(tt);// 范围2的部分是节点tt的内容,不包括节点本身
为了更加精细化操作DOM结构,还可以使用以下的方法:
setStartBefore(refNode):将范围设置到refNode之前,这样refNode也在范围内,而且是第一个节点
setStartAfter(refNode):将范围起点设到refNode之后
setEndBefor(refNode):将范围的终点设到refNode之前
setEndAfter(refNode):将范围的终点设到refNode之后,refNode是范围的最后一个节点

使用DOM范围实现复杂的选择
要创建复杂的范围就的是用setStart()和setEnd()方法。这两个方法接受两个参数,一个是参照节点,一个是偏移量。对setStart()来说,参照节点变成startContainer,而偏移量会变成startOffset。对于setEnd()来说,参照节点变成endContainer,而偏移量会变成endOffset.
var range1=document.createRange();
var range2=document.createRange();
var tt=document.getElementById("tt");
var tindex=-1;
var i,len;
for(i=0,len=tt.parentNode.childNodes.length;i<len;i++){
  if(tt.parentNode.childNodes[i]==p1){
    tindex=i;
break;
  }
}
range1.setStart(tt.parentNode,tindex);
range1.setEnd(tt.parentNode,tindex+1);
range2.setStart(tt,0);
range2.setEnd(tt,tt.childNodes.length);
但这并不是这两个方法主要用途,主要用途是选择节点的一部分,而不是整个节点的方式进行的选择。
var range=document.createRange();
range.setStart(helloNode,2);// 节点helloNode的第三个字符处开始
range.setEnd(worldNode,3);  // 节点worldNode的第四个字符处结束

操作DOM范围中的内容
第一个方法 deleteContents(),删除范围中的内容。调用方式:range.deleteContents();
第二个方法 extractContents(),从文档区域移除范围的内容,返回范围内容的文档片段,可以对文档片段进行进一步操作,调用方式:var fragment=range.extractContents();
第三个方法 cloneContents(),创建一个文档片段,保存范围的副本,可以对文档片段进行进一步操作,调用方式:
var fragment=range.cloneContents();

插入DOM范围中的内容
除了向范围内部插入内容之外,还可以环绕范围插入内容,此时要使用surroundContents()方法。这个方法接收一个参数,即环绕范围内容的节点。下面是一段示例代码:
var p1=document.getElementById("p1"),
helloNode=p1.firstChild.firstChild,
worldNode=p1.lastChild,
range=document.createRange();

range.selectNode(helloNode);
var span=document.createElement("span");
span.style.backgroundColor="yellow";
range.surroundContents(span);

折叠DOM范围
范围折叠就是指范围中未选择文档的任何部分。通俗的描述就是当你选择范围内的文本,点击左键的时候,光标会落在范围的开始或者范围的结束。使用collapse()进行折叠,接收一个参数,一个布尔值,表示要折叠到范围的那一端,true表示范围的起点,false表示范围的终点。要确定范围已经折叠外币,可以用collapsed属性检查。
range.collapse(true);
检测折叠可以帮我们确定范围中的两个节点是否是相邻的。

比较DOM的范围
在有多个范围的情况下,可以使用compareBoundaryPoints()方法来确定这些范围是否有公共边界。这个方法接收两个参数:比较方式的常量值和要比较的范围,比较方式的常量值如下所示:
Range.START_TO_START:比较第一个范围和第二个范围的起点
Range.START_TO_END:比较第一个范围的起点和第二个范围的终点
Range.END_TO_END:比较第一个范围和第二个范围的终点
Range.END_TO_START:比较第一个范围的终点和第二个范围的起点
第一个范围的点在第二个之前返回-1,,相等返回0,第一个范围的点在第二个范围的点之后返回1
使用方法:
range1.compareBoundaryPoints(Range.START_TO_START,range2);

复制DOM的范围
可以使用cloneRange()方法复制范围,返回范围的一个副本
var newRange=range.cloneRange();

清理DOM范围
在使用完范围之后,最好调用detach()方法,清理范围,回收内存.
range.detach();// 从文档中分离
range=null;//  解除引用


IE8以及更早版本的范围
范围的创建
var range=document.body.createTextRange();
范围的选择
var found=range.findText("hello");
还可以附加第二个参数表示方向,正值表示向前搜索,负值表示向后搜索
var foundAgain=range.findText("hello",1);
与selectNode()方法最接近的是moveToElementText(),这个方法接收一个DOM元素,并选择该元素的所有文本,包括HTML标签。
var range=document.body.createTextRange();
var p1=document.getElementById("p1");
range.moveToElementText(p1);
在文本范围中包含HTML的情况下,可以使用属性htmlText获取范围的全部内容。IE的范围中没有任何的属性可以随着范围选区的变化而动态更新。
IE的复杂范围选择
move(),moveStart(),moveEnd(),expand(),均接收两个参数:移动单位移动单位的数量,其中移动单位是下列的一种字符串:
“character”,"word","sentence","textedit"。最后一个表示范围选区的开始或结束位置。
使用expand()方法可以将范围规范化,也就是说,将任何部分选择的文本全部选中。
range.moveStart("wrod",2);
range.moveEnd("character",1);
range.move("sentence",5);
操作IE范围内容
可以使用text属性或者pasteHTML()方法。
使用text属性后,HTML标签保持不变,向范围内插入HTML代码的时候,使用pasteHTML()。
range.pasteHTML("<span>GO</span>");
但是当范围内存在HTML标签时,很容易出现不可预料的错误。
折叠范围方法与DOM的一样检测是否折叠的方法是查看boundingWidth属性是否为0,为0则表示折叠。
range.boundingWidth==0;
比较范围的方法compareEndpoints(),接收两个参数,比较类型和比较范围。比较范围的字符串:“StartToStart”,
"StartToEnd","EndToEnd","EndToStart".比较后返回的情况与DOM范围比较的情况是一样的。
IE中还有两个方法比较范围:isEqual()用于确定两个范围是否相等,inRange()确定一个范围是否包含另一个范围。
range1.isEqual(range2);
range1.inRange(range2);
使用duplicate()方法可以复制文本范围:var newRange=range.duplicate();









你可能感兴趣的:(javascript DOM详解之DOM2与DOM3)