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)