zoukankan      html  css  js  c++  java
  • JavaScript高级程序设计:第十二章

    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;

                                       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() ;

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

  • 相关阅读:
    leetcode Convert Sorted List to Binary Search Tree
    leetcode Convert Sorted Array to Binary Search Tree
    leetcode Binary Tree Level Order Traversal II
    leetcode Construct Binary Tree from Preorder and Inorder Traversal
    leetcode[105] Construct Binary Tree from Inorder and Postorder Traversal
    证明中序遍历O(n)
    leetcode Maximum Depth of Binary Tree
    限制 button 在 3 秒内不可重复点击
    HTML 和 CSS 画三角形和画多边行基本原理及实践
    在线前端 JS 或 HTML 或 CSS 编写 Demo 处 JSbin 与 jsFiddle 比较
  • 原文地址:https://www.cnblogs.com/koto/p/5111792.html
Copyright © 2011-2022 走看看