码迷,mamicode.com
首页 > 编程语言 > 详细

JavaScript高级程序设计:第十二章

时间:2016-01-08 01:49:01      阅读:387      评论:0      收藏:0      [点我收藏+]

标签:

DOM1级主要定义的是HTML和XML文档的底层结构。DOM2和DOM3级则在这个结构的基础上引入了更多的交互能力,也支持了更高级的XML特性。为此DOM2和DOM3级分为许多模块,这些模块如下:

         DOM2级核心;

         DOM2级视图;

         DOM2级事件;

         DOM2级样式;

         DOM2级遍历和范围;

         DOM2级HTML。

一、DOM变化

         DOM2级和3级的目的在于扩展DOM API,以满足操作XML的所有需求,同时提供更好的错误处理及特性检测能力。

1.针对XML命名空间的变化

         有了XML命名空间,不同的XML文档的元素就可以混在一起,共同构成良好的文档,而不必担心发生命名冲突。

         命名空间要使用xmlns特性来指定。XHTML的命名空间是http://www.w3.org/1999/xhtml,在任何格式良好XHTML页面中,都应该将其包含在<html>元素中,如下面的例子所示:

         <html  xmlns = “http://www.w3.org/1999/xhtml”>

                  <head>

                         <title>Example XHTML page</title>

                  </head>

                  <body>

                          Hello world!

                  </body>

         </head>

对这个例子而言,其中的所有元素都默认被视为XHTML命名空间中的元素。想要明确地为XML命名空间创建前缀,可以使用xmlns后跟冒号,再后跟前缀,如下所示:

         <xhtml:html xmlns:xhtml =”http://www.w3.org/1999/xhtml”>

                  <xhtml:head>

                          <xhtml:title>Example XHTML page</xhtml:title>

                  </xhtml:head>

                  <xhtml:body>

                          Hello world!

                  </xhtml:body>

         </xhtml:html>

①Node类型的变化

         在DOM2级中,Node类型包含下列特定于命名空间的属性。

         localName:不带命名空间前缀的节点名称

         namespaceURI:命名空间URI或者(在未指定的情况下是)null。

         prefix:命名空间前缀或者(在未指定的情况下是)null。

         DOM3级在此基础上更进一步,又引入了下列与命名空间有关的方法:

         isDefaultNamespace(namespaceURI):在指定的namespaceURI是当前节点的默认命名空间的情况下返回true。

         lookupNamespaceURI(prefix):返回给定prefix的命名空间。

         lookupPrefix(namespaceURI):返回给定namespaceURI的前缀。

②Document类型的变化

         DOM2级中的Document类型也发生了变化,包含了下列与命名空间有关的方法:

         createElementNS(namespaceURI,tagName):使用给定的tagName创建一个属于命名空间namespaceURI的新元素。

         createAttributeNS(namespaceURI,attributeName):使用给定的attributeName创建一个属于命名空间namespaceURI的新特性。

         getElementsByTagNameNS(namespaceURI,tagName):返回属于命名空间namespaceURI的tagName元素的NodeList。

③Element类型的变化

         DOM2级核心中有关Element的变化,主要涉及操作特性。新增的方法如下:

         getAttributeNS(namespaceURI,localName):取得属于命名空间namespaceURI且名为localName的特性。

         getAttributeNodesNS(namespaceURI,localName):取得属于命名空间namespaceURI且名为localName的特性节点。

         getElementsByTagNameNS(namespaceURI,localName):返回属于命名空间namespaceURI的tagName元素的NodeList。

         has AttributeNS(namespaceURI,localName):确定当前元素是否有一个名为localName的特性,而且该命名空间是namespaceURI。

         removeAttributeNS(namespaceURI,localName):删除属于命名空间namespaceURI且名为localName的特性。

         setAttributeNS(namespaceURI,qualifiedName,value):设置属于命名空间namespaceURI且名为qualifiedName的特性的值为value。

         setAttributeNodeNS(attNode):设置属于命名空间namespaceURI的特性节点。

④NamedNodeMap类型的变化

         namedNodeMap类型也新增了下列与命名空间有关的方法。由于特性是通过NamedNodeMap表示的,因此这些方法多数情况下只针对特性使用。

         getNamedItemNS(namespaceURI,localname):取得命名空间namespaceURI且名为localName的项。

         removeNamedItemNS(namespaceURI,localName):移除属于命名空间namespaceURI且名为localName的项。

         setNamedItemNS(node):添加node,这个节点已经事先指定了命名空间信息。

2.其他方面的变化

         ①DocumentType类型的变化

         DocumentType类型新增了3个属性:publicId、systemId和internalSubset。其中,前两个属性表示的是文档类型声明中的两个信息段,这两个信息段在DOM1级中是没有办法访问到的。

         ②Document类型的变化

         Document类型的变化中唯一与命名空间无关的方法是importNode()。这个方法的用途是从一个文档中取得一个节点,然后将其导入到另一个文档,使其成为这个文档结构的一部分。

         importNode()方法与Element的cloneNode方法非常相似,它接受两个参数:要复制的节点和一个表示是否复制子节点的布尔值。返回的结果是原来节点的副本,但能够在当前文档中使用。

        

         ③Node类型的变化

         Node类型中唯一与命名空间无关的变化,就是添加了isSupported()方法。与DOM1级为document.implementation引入的hasFeature()方法类似,isSupported()方法用于确定当前节点具有什么能力。这个方法也接受相同的两个参数:特性名和特性版本号。如果浏览器实现了相应特性,而且能够基于给定节点执行该特性,isSupported()就返回true。

         DOM3级引入了两个辅助比较节点的方法:isSameNode()和isEqualNode()。这两个方法都接受一个节点参数,并在传入节点与引用的节点相同或相等时返回true。所谓相同,指的是两个节点引用的是同一个对象。所谓相等,指的是两个节点是相同的类型,具有相等的属性,而且它们的attributes和childNodes属性也相等。

         DOM3级还针对DOM节点添加额外数据引入了新方法。其中,setUserData()方法会将数据指定给节点,它接受3个参数:要设置的键、实际的数据和处理的函数。以下代码可以将数据指定给一个节点。

         document.body.setUserData(”name”,”Nicholas”,function(){ });

         然后,使用getUserData()并传入相同的键,就可以获得该数据,如下所示:

         var value=document.body.getUserData(”name”);

         传入setUserData()中的处理函数会在带有数据的节点被复制、删除、重命名或引入一个文档时调用,因而你可以事先决定在上述操作发生时如何处理用户数据。处理函数接受5个参数:表示操作类型的数值(1表示复制、2表示导入、3表示删除、4表示重命名)、数据键、数据值、源节点和目标节点。在删除节点时,源节点是null;除在复制节点时,目标节点均为null。在函数内部,你可以决定如何存储数据。

         ④框架的变化

         框架和内嵌框架分别用HTMLFrameElement和HTMLFrameElement表示,它们在DOM2级中都有了一个新属性,名叫contentDocument。这个属性包含一个指针。指向表示框架内容的文档对象。

二、样式

1.访问元素的样式

         任何支持style特性的HTML元素在javascript中都有一个对应的style属性。这个style对象是CSSStyleDeclaration的实例,包含着通过HTML的style特性指定的所有样式信息,但不包含与外部样式表嵌入样式表经层叠而来的样式。在style特性中指定的任何CSS属性都将表现为这个style对象的相应属性。对于使用短划线的CSS属性名,必须将其转换成驼峰大小写形式,才能通过javascript来访问。例如:CSS中的background-image属性对应的javascript属性为style.backgroundImage。

         多数情况下,都可以通过简单地转换属性名的格式来实现转换。其中一个不能直接转换的CSS属性就是float。由于float是javascript中的保留字因此不能用作属性名。

         ①DOM样式属性和方法

         “DOM2级样式”规范还为style对象定义了一些属性和方法。这些属性和方法提供元素的style特性值的同时,也可以修改样式。下面列出了这些属性和方法:

         cssText:如前所述,通过它能够访问到style特性中的CSS代码。

         length:应用给元素的CSS属性的数量。

         parentRule:表示CSS信息的CSSRule对象。

         getPropertyCSSValue(propertyName):返回包含给定属性值的CSSValue对象。

         getPropertyPriority(propertyName):如果给定的属性使用了!important设置,则返回“!important”;否则,返回空字符串。

         getPropertyValue(propertyName):返回给定属性的字符串。

         item(index):返回给定位置的CSS属性的名称。

         removeProperty(propertyName):从样式中删除给定属性。

         setProperty(propertyName,value,priority):将给定属性设置为相应的值,并加上优先权标志(“important”或者一个空字符串)。

         ②计算的样式

 “DOM2级样式”增强了document.defaultView,提供了getComputedStyle()方法。这个方法接收两个参数:要取得计算机样式的元素和一个伪元素字符串,如“:after”,如果不需要伪元素信息,第二个参数可以是null。返回一个CSSStyleDeclaration对象,其中包含当前元素的所有计算的样式。例如:

<!DOCTYPE html>

<html>

         <head>

                  <title>Computed Style Example</title>

                  <style type="text/css">

                          #myDiv{

                                   background-color: blue;

                                   width: 100px;

                                   height: 200px;

                          }

                  </style>

         </head>

         <body>

                  <div id="myDiv" style="background-color:red;border:1px solid black"></div>

         </body>

</html>

以下代码取得这个元素计算后的样式:

         var myDiv=document.getElementById(“myDiv”) ;

         var computedStyle = document.defaultView.getComputedStyle(myDiv , null) ;

         alert(computedStyle.backgroundColor) ;     // ”red”

         alert(computedStyle.width) ;              // “100px”

         alert(computedStyle.height) ;              //”200px”

         alert(computedStyle.border) ;              //在某些浏览器中是”1px solid black”

需要注意的是:所有计算的样式都是只读的;不能修改计算后样式对象中的CSS属性。此外,计算后的样式也包含属于浏览器内部样式表的样式信息,因此任何具有默认值的CSS属性都会表现在计算后的样式中。

2.操作样式表

         CSSStyleSheet类型表示的是样式表,以下代码可以确定浏览器是否支持DOM2级样式表:

         var supportsDOM2StyleSheets =

                  document.implementation.hasFeature(“StyleSheets”, “2.0”) ;

         CSSStyleSheet继承自StyleSheet,后者可以作为一个基础接口来定义非CSS样式表。

         ①CSS规则

         CSSRule对象表示样式表中的每一条规则。CSSRule是一个供其他多种类型继承的基类型,其中最常见的就是CSSStyleRule类型,表示样式信息。

         ②创建规则

         DOM规定,要向现有样式表中添加新规则,需要使用insetRule()方法。这个方法接受两个参数:规则文本和表示在哪里插入规则的索引。下面是一个例子:

         sheet.insertRule(“body { background-color : silver }” , 0 ) ;   //DOM方法。

         这个例子插入的规则会改变元素的背景颜色。插入的规则将成为样式表中的第一条规则。

                          IE及更早版本支持一个类似的方法,名叫addRule(),也接受两必选参数:选择符文本和CSS样式信息;一个可选参数:插入规则的位置。例如:

         sheet.addRule(“body” , “background-color : silver” , 0 ) ;      // 仅对IE有效

         要以跨浏览器的方式向样式表中插入规则,可以使用下面的函数。这个函数接受4个参数:要向其中添加规则的样式表以及与addRule()相同的3个参数。下面是调用这个函数的代码:

         insertRule(document.styleSheets[0] , “body”, “background-color : silver” , 0) ;

         ③删除规则

         从样式表中删除规则的方法是deleteRule(),这个方法接受一个参数:要删除的规则的位置。例如,要删除样式表中的第一条规则,可以使用以下代码:

         sheet.deleteRule(0);       //DOM方法

         IE支持类似的方法叫做removeRule(),使用方法相同,如下所示:

         sheet.removeRule(0);    //仅对IE有效

         下面是一个能够跨浏览器删除规则的函数,第一个参数是要操作的样式表,第二个参数是要删除的规则的索引。

         调用这个方法如下:

         deleteRule(document.styleSheets[0] , 0) ;

3.元素大小

         ①偏移量

         元素的可见大小由其高度、宽度决定,包括所有内边距、滚动条和边框大小。通过下列4个属性可以取得元素的偏移量:

         offsetHeight:元素在垂直方向上占用的空间大小,以像素计。包括元素的高度、水平滚动条的高度、上边框高度和下边框高度。

         offsetWidth:元素在水平方向上占用的空间大小,以像素计。包括元素的宽度、垂直滚动条的宽度、左边宽度和右边框宽度。

         offsetLeft:元素的左外边框至包含元素的左内边框之间的像素距离。

         offsetTop:元素的上外边框至包含元素的上内边框之间的像素距离。

         其中,offsetLeft和offsetTop属性与包含元素有关,包含元素的引用保存在offsetParent属性中。offsetParent属性不一定与parentNode的值相等。

         ②客户区大小

         元素的客户区大小,指的是元素内容及其内边距所占据的空间大小。有关客户区大小的属性有两个:clientWidth和clientHeight。其中,clientWidth属性时元素内容区宽度加上左右内边距宽度;clientHeight属性时元素内容区高度加上上下内边距高度。

         ③滚动大小

         指的是包含滚动内容的元素的大小。以下是4个与滚动大小相关的属性

         scrollHeight:在没有滚动条的情况下,元素内容的总高度。

         scrollWidth:在没有滚动条的情况下,元素内容的总宽度。

         scrollLeft:被隐藏在内容区域左侧的像素数。通过设置这个属性可以改变元素的滚动位置。

         scrollTop:被隐藏在内容区域上方的像素数。通过设置这个属性可以改变元素的滚动位置。

         scrollWidth和scrollHeight主要用于确定元素内容的实际大小。

         ④确定元素大小

         getBoundingClientRect()方法。这个方法会返回一个矩形对象,包含4个属性:left、top、right、bottom。这些属性给出了元素在页面中相对于视口的位置。

三、遍历

         “DOM2级遍历和范围”模块定义了两个用于辅助完成顺序遍历DOM结构的类型:NodeIterator和TreeWalker。这两个类型能够基于给定的起点对DOM结构执行深度优先的遍历操作。遍历以给定节点为根,不可能向上超出DOM树的根节点。

1.NodeIterator

         Nodelterator类型是两者中比较简单的一个,可以使用document.createNodeIterator()方法创建它的新实例。这个方法接受4个参数:

         root:想要作为搜索起点的树中的节点。

         whatToShow:表示要访问哪些节点的数字代码

         filter:是一个NodeFilter对象,或者一个表示应该接受还是拒绝某种特定节点的函数。

         entityReferenceExpansion:布尔值,表示是否要扩展实体引用。

         whatToShow参数是一个位掩码,通过应用一或多个过滤器来确定要访问哪些节点。

         Nodelterator类型的两个方法是nextNode()和previousNode()。顾名思义,在深度优先的DOM子树遍历中,nextNode()方法用于向前前进一步,而previousNode()用于向后后退一步。

2.TreeWalker

         TreeWalker是NodeIterator的一个更高级的版本。除了包括nextNode()和previousNode()在内的相同的功能之外,这个类型还提供了下列用于在不同方向上遍历DOM结构的方法:

         parentNode():遍历到当前节点的父节点;

         firstChild():遍历到当前节点的第一个子节点;

         lastChild():遍历到当前节点的最后一个子节点;

         nextSibling():遍历到当前节点的下一个同辈节点;

         previousSibling():遍历到当前节点的上一个同辈节点。

         创建TreeWalker对象要使用document.createTreeWalker( )方法,这个方法接受4个参数与document.createNodeIterator( )方法相同:作为遍历起点的根节点、要显示的节点类型、过滤器和一个表示是否扩展实体引用的布尔值。由于这两个创建方法很相似,所以很容易用TreeWalker来代替NodeIterator。

4.范围

         (1)DOM中的范围

         DOM2级在Document类型中定义了createRange( )方法。在兼容DOM的浏览器中,这个方法属于document对象。使用hasFeature()或者直接检测该方法,都可以确定浏览器是否支持范围。如果浏览器支持范围,那么就可以使用createRange()来创建DOM范围。

         ①用DOM范围实现简单选择

         要使用范围来选择文档中的一部分,最简单的方式就是使用selectNode()或selectNodeContents()。这两个方法都接受一个参数:一个DOM节点。其中,selectNode()方法选择整个节点,包括其子节点;而selectNodeContents()方法则只选择节点的子节点。

         ②用DOM范围实现复杂选项

         要创建复杂范围就得使用setStart()和setEnd()方法。这两个方法都接受两个参数:一个参照节点和一个偏移量值。对setStart()来说,参照节点会变成:startContainer,而偏移量值会变成startOffset。对于setEnd()来说,参照节点会变成endContainer,而偏移量值会变成endOffset。

         ③操作DOM范围中的内容

         在创建范围时,内部会为这个范围创建一个文档片段,范围所属的全部节点都被添加到了这个文档片段中。为了创建这个文档片段,范围内容的格式必须正确有效。

         第一个方法:deleteContents()。这个方法能够从文档中删除范围所包含的内容。例如:

         var p1 = document.getElementById(“p1”) ;

                  helloNode = p1.firstChild.firstChild ;

                  worldNode = p1.lastChild ;

                  range = document.createRange() ;

                  range = setStart(helloNode , 2 ) ;

                  range = setEnd(worldNode , 3 ) ;

                  range.deleteContents( ) ;

         执行以上代码后,页面中会显示如下HTML代码:

         <p><b>He</b>rld!</p>

         与deleteContents()方法相似,extractContents()也会从文档中移除范围选区。但这两个方法的区别在于,extractContents()会返回范围的文档片段。利用这个返回值,可以将范围的内容插入到文档中的其他地方。

         还有一种做法,即使用cloneContents()创建范围对象的一个副本,然后在文档的其他地方插入该副本。

         ④插入DOM范围中的内容

         使用insertNode()方法可以向范围选区的开始处插入一个节点。

使用surroundContents()方法可以环绕范围插入内容,这个方法接收一个参数,即环绕范围内容的节点,在环绕范围插入内容时,后台会执行下列步骤:

提取出范围中的内容;

         将给定节点插入到文档中原来范围所在的位置上;

         将文档片段的内容添加到给定节点中。

         ⑤折叠DOM范围

         所谓折叠范围, 就是指范围中未选择文档的任何部分。

         使用collapse()方法来折叠范围,这个方法接收一个参数,一个布尔值,表示要折叠到范围的哪一端。参数true表示折叠刀范围的起点,参数false表示折叠刀范围的终点。要确定范围已经折叠完毕,可以检查collapsed属性,如下所示:

         range.collapse(true) ;          //折叠到起点

         alert(range.collapsed) ;         //输出true

         ⑥比较DOM范围

         在多个范围的情况下,可以使用compareBoundaryPoints()方法来确定这些范围是否有公共的边界。这个方法接受两个参数:表示比较方式的常量值和要比较的范围。

         ⑦复制DOM范围

         可以使用cloneRange()方法复制范围。这个方法会创建调用它的范围的一个副本。

         var newRange = range.cloneRange();

         新创建的范围与原来的范围包含相同的属性,而修改它的端点不会影响原来的范围。

         ⑧清理DOM范围

         使用完范围之后,最好是调用detach()方法,以便从创建范围的文档中分离出该范围。调用detach()之后,就可以放心地解除对范围的引用,从而让垃圾回收机制回收其内存了。

(2)IE8及更早版本的范围

         ①用IE范围实现简单的选择

         选择页面中某一区域的最简单方式,就是使用范围的findText()方法。这个方法会找到第一次出现的给定文本,并将范围移过来以环绕该文本。

         ②使用IE范围实现复杂的选择

         在IE中创建复杂范围的方法,就是以特定的增量向四周移动范围。为此,IE提供了4个方法:move()、moveStart()、moveEnd()、expand()。这些方法都接受两个参数:移动单位和移动单位的数量。

         ③操作IE范围中的内容

         在IE中操作范围中的内容可以使用text属性或pasteHTML()方法。如前所述,通过text属性可以取得范围中的内容文本;但是,也可以通过这个属性设置范围中的内容文本。

         ④折叠IE范围

         IE为范围提供的collapse()方法与相应的DOM方法用法一样。

         ⑤比较IE范围

         IE中的compareEndPoints()方法与DOM范围的compareBoundaryPoints()方法类似。这个方法接受两个参数:比较的类型和要比较的范围。

         ⑥复制IE范围

         在IE中使用duplicate()方法可以复制文本范围,结果会创建原范围的一个副本,如下面的例子所示:

         var newRange = range.duplicate() ;

         新创建的范围会带有与原范围完全相同的属性。

JavaScript高级程序设计:第十二章

标签:

原文地址:http://www.cnblogs.com/koto/p/5111792.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!