JavaScript 高级程序设计(第12章 DOM2和DOM3)

第12章 DOM2和DOM3

  1. DOM2 级核心(DOM Level 2 Core):在 1 级核心基础上构建,为节点添加了更多方法和属性。
  2. DOM2 级视图(DOM Level 2 Views):为文档定义了基于样式信息的不同视图。
  3. DOM2 级事件(DOM Level 2 Events):说明了如何使用事件与 DOM 文档交互。
  4. DOM2 级样式(DOM Level 2 Style):定义了如何以编程方式来访问和改变 CSS 样式信息。
  5. DOM2 级遍历和范围(DOM Level 2 Traversal and Range):引入了遍历 DOM 文档和选择其特定
    部分的新接口。
  6. DOM2 级 HTML(DOM Level 2 HTML):在 1 级 HTML 基础上构建,添加了更多属性、方法和新接口。

可以通过下列代码来确定浏览器是否支持这些 DOM 模块。

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

1. DOM 变化

DOM2 级和 3 级的目的在于扩展 DOM API,以满足操作 XML 的所有需求,同时提供更好的错误处理及特性检测能力。从某种意义上讲,实现这一目的很大程度意味着对命名空间的支持

  1. DOM2 级核 心”没有引入新类型,它只是在 DOM1 级的基础上通过增加新方法和新属性来增强了既有类型。
  2. “DOM3 级核心”同样增强了既有类型,但也引入了一些新类型。

(1) 针对XML命名空间的变化

  1. 有了 XML 命名空间,不同 XML 文档的元素就可以混合在一起,共同构成格式良好的文档,而不必担心发生命名冲突。
  2. HTML 不支持 XML 命名空间,但 XHTML 支持 XML 命名空间。
  3. 命名空间要使用 xmlns 特性来指定
  4. XHTML 的命名空间是 http://www.w3.org/1999/xhtml,在任何 格式良好 XHTML 页面中,都应该将其包含在元素中。
  • 其中的所有元素默认都被视为 XHTML 命名空间中的元素。

        
            Example XHTML page
        
        
            Hello world!
        

  • 要想明确地为 XML 命名空间创建前缀,可以使用 xmlns 后跟冒号,再后跟前缀。

        
            Example XHTML page
        
        //为了避免不同语言间的冲突,也需要使用命名空间来限定特性
            Hello world!
        

  • 在混合使用两种语言的情况下,命名空间的用处

        
            Example XHTML page
        
        
            
                
            
        

* Node 类型的变化
  1. 在 DOM2 级中,Node 类型包含下列特定于命名空间的属性

(1) localName: 不带命名空间前缀的节点名称。
(2) nameSpaceURI: 命名空间URI或者(在未指定的情况下是)null。
(3) prefix:命名空间前缀或者(在未指定的情况下是)null。
nodeName 等于 prefix+":"+ localName。

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

(1) isDefaultNamespace(namespaceURI):在指定的 namespaceURI 是当前节点的默认命名空
间的情况下返回 true。
(2) lookupNamespaceURI(prefix):返回给定 prefix 的命名空间。
(3) lookupPrefix(namespaceURI):返回给定 namespaceURI 的前缀。

* Document 类型的变化

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

(1) createElementNS(namespaceURI, tagName):使用给定的 tagName 创建一个属于命名空 间 namespaceURI 的新元素。
(2) createAttributeNS(namespaceURI, attributeName):使用给定的 attributeName 创 建一个属于命名空间 namespaceURI 的新特性。
(3) getElementsByTagNameNS(namespaceURI, tagName):返回属于命名空间 namespaceURI 的 tagName 元素的 NodeList。

*Element 类型的变化

(1) getAttributeNS(namespaceURI,localName):取得属于命名空间 namespaceURI 且名为 localName 的特性。
(2) getAttributeNodeNS(namespaceURI,localName):取得属于命名空间 namespaceURI 且 名为 localName 的特性节点。
(3) getElementsByTagNameNS(namespaceURI, tagName):返回属于命名空间 namespaceURI 的 tagName 元素的 NodeList。
(4) hasAttributeNS(namespaceURI,localName):确定当前元素是否有一个名为 localName 的特性,而且该特性的命名空间是 namespaceURI。注意,“DOM2 级核心”也增加了一个 hasAttribute()方法,用于不考虑命名空间的情况。
(5) removeAttriubteNS(namespaceURI,localName):删除属于命名空间 namespaceURI 且名 为 localName 的特性。
(6) setAttributeNS(namespaceURI,qualifiedName,value):设置属于命名空间 namespace- URI 且名为 qualifiedName 的特性的值为 value。
(7) setAttributeNodeNS(attNode):设置属于命名空间 namespaceURI 的特性节点。

* NamedNodeMap 类型的变化

(1) getNamedItemNS(namespaceURI,localName):取得属于命名空间 namespaceURI 且名为
localName 的项。
(2) removeNamedItemNS(namespaceURI,localName):移除属于命名空间 namespaceURI 且名
为 localName 的项。
(3) setNamedItemNS(node):添加 node,这个节点已经事先指定了命名空间信息。

(2) 其他方面的变化

* DocumentType 类型的变化

DocumentType 类型新增了 3 个属性:publicId、systemId 和 internalSubset

  1. 前两 个属性表示的是文档类型声明中的两个信息段
  2. 属性 internalSubset,用于访问包含在文档类型声明中的额外定义。
]>

alert(document.doctype.publicId);
//    "-//W3C//DTD HTML 4.01//EN"

alert(document.doctype.systemId);
//   "http: //www.w3.org/TR/html4/strict.dtd"

alert(document.doctype.internalSubset);
//   ""
*Document 类型的变化

importNode()方法:

  1. 这个方法的用途是从一个文档中取得一个节点,然后将其导入到另一个文档,使其成为这个文档结构的一部分。
  2. 每个节点都有一个 ownerDocument 属性,表示所属的文档。如果调用 appendChild()时传入的节点属于不同的文档(ownerDocument 属性的值不一样),则会导致错误。但在调用 importNode()时传入 不同文档的节点则会返回一个新节点,这个新节点的所有权归当前文档所有。
  3. 接受两个参数:要复制的节点和一个表示是否复制子节点的布尔值。
//导入节点及其所有子节点
var newNode = document.importNode(oldNode, true); 
document.body.appendChild(newNode);

defaultView 的属性:

  1. DOM2 级视图”模块属性,其中保存着一个指针,指向拥有给 定文档的窗口(或框架)
  2. 在 IE 中有一个等价的属性名叫 parentWindow(Opera 也支持这个属性)。
var parentWindow = document.defaultView || document.parentWindow;
DOM2 级核心”还为document.implementation 对象规定了 两个新方法:createDocumentType()createDocument()
  1. createDocumentType() 方法 : 于创建一个新的 DocumentType 节点,接受 3 个参数:文档类型名称、publicId、systemId。
  2. createDocument()方法:3 个参数:针对文档中元素的 namespaceURI、文档元素的标签名、新文档的文档类型。
var doctype = document.implementation.createDocumentType(
                     "html",
                     " -//W3C//DTD XHTML 1.0 Strict//EN",
                     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
var doc = document.implementation.createDocument(
                      "http://www.w3.org/1999/xhtml",
                      "html",
                      doctype);
DOM2 级 HTML”模块也为 document.implementation新增了一个方法,名叫 createHTMLDocument()
  1. createHTMLDocument()方法:这个方法的用途是创建一个完整的 HTML 文档,包括、、和 <body>元素。这个方法只接受一个参数,即新创建文档的标题(放在<title>元素中的字符串),返回 新的 HTML 文档</li> </ol> </blockquote> <h5>* Node 类型的变化</h5> <h4><code>isSupported()方法</code></h4> <blockquote> <ol> <li>DOM1 级为 document.implementation引入的hasFeature()方法类似。</li> <li>用于确定当前节点具有 什么能力。这个方法也接受相同的两个参数:<code>特性名</code>和<code>特性版本号</code>。如果浏览器实现了相应特性,而且能够基于给定节点执行该特性,isSupported()就返回 true。</li> </ol> </blockquote> <h6>DOM3 级引入了两个辅助比较节点的方法:<code>isSameNode()</code>和 <code>isEqualNode()</code>。</h6> <blockquote> <ol> <li> <code>isSameNode()方法</code>接受 一个节点参数,并在传入节点与引用的节点相同时返回 true。</li> <li> <code>isEqualNode()</code>接受 一个节点参数,并在传入节点与引用的节点等时返回 true。</li> </ol> </blockquote> <pre><code>//这里创建了两个具有相同特性的<div>元素。这两个元素相等,但不相同。 var div1 = document.createElement("div"); div1.setAttribute("class", "box"); var div2 = document.createElement("div"); div2.setAttribute("class", "box"); alert(div1.isSameNode(div1)); //true alert(div1.isEqualNode(div2)); //true alert(div1.isSameNode(div2)); //false </code></pre> <blockquote> <p>(1) 所谓<code>相同</code>,指的是两个节点引用的是同一个对象。<br> (2) 所谓<code>相等</code>,指的是两个节点是相同的类型,具有相等的属性(nodeName、nodeValue, 等等),而且它们的 attributes 和 childNodes 属性也相等(相同位置包含相同的值)。</p> </blockquote> <h6>DOM3 级还针对为 DOM 节点添加额外数据引入了新方法。其中,<code>setUserData()方法</code>会将数据指定给节点,它接受 3 个参数:要设置的键、实际的数据(可以是任何数据类型)和处理函数。</h6> <blockquote> <ol> <li>传入 setUserData()中的处理函数会在带有数据的节点被<code>复制、删除、重命名或引入一个文档时调用</code>,因而你可以事先决定在上述操作发生时如何处理用户数据。</li> <li>处理函数接受<code>5 个参数</code>:表示操作类 型的数值(1 表示复制,2 表示导入,3 表示删除,4 表示重命名)、数据键、数据值、源节点和目标节点。</li> <li>在删除节点时,源节点是 null;除在复制节点时,目标节点均为 null。在函数内部</li> </ol> </blockquote> <pre><code>var div = document.createElement("div"); div.setUserData("name", "Nicholas", function(operation, key, value, src, dest){ if (operation == 1){ dest.setUserData(key, value, function(){}); } }); var newDiv = div.cloneNode(true); alert(newDiv.getUserData("name")); //"Nicholas" </code></pre> <h5>* 框架的变化</h5> <blockquote> <ol> <li>框架和内嵌框架分别用<code>HTMLFrameElement</code> 和 <code>HTMLIFrameElement</code> 表示,它们在 DOM2 级中都有 了一个新属性,名叫 <code>contentDocument</code>。这个属性包含一个指针,指向表示框架内容的文档对象。</li> <li>IE8 之前不支持框架中的 contentDocument 属性,但支持一个名叫 <code>contentWindow</code> 的属性,该属性返回框架的 window 对象,而这个 window 对象又有一个 document 属性。</li> </ol> </blockquote> <pre><code>var iframe = document.getElementById("myIframe"); var iframeDoc = iframe.contentDocument || iframe.contentWindow.document; </code></pre> <h2>2. 样式</h2> <blockquote> <p>在 HTML 中定义样式的方式有 3 种:通过<code><link/>元素</code>包含外部样式表文件、使用<code><style/>元素</code> 定义嵌入式样式,以及使用 <code>style 特性</code>定义针对特定元素的样式。</p> </blockquote> <p>确定浏览器是否支持 DOM2 级定义的 CSS 能力:</p> <pre><code> var supportsDOM2CSS = document.implementation.hasFeature("CSS", "2.0"); var supportsDOM2CSS2 = document.implementation.hasFeature("CSS2", "2.0"); </code></pre> <h4>(1) 访问元素的样式</h4> <blockquote> <ol> <li>任何支持 style 特性的 HTML 元素在 JavaScript 中都有一个对应的 style 属性。</li> <li>这个 style 对象 是 <code>CSSStyleDeclaration 的实例</code>,包含着通过 HTML 的 style 特性指定的所有样式信息,但不包含与外部样式表或嵌入样式表经层叠而来的样式。</li> <li>在 style 特性中指定的任何 CSS 属性都将表现为这个 style 对象的相应属性。</li> <li>对于使用短划线(分隔不同的词汇,例如 background-image)的 CSS 属性 名,必须将其转换成<code>驼峰大小写形式</code>,才能通过 JavaScript 来访问。</li> </ol> </blockquote> <div class="image-package"> <div class="image-container" style="max-width: 700px; max-height: 198px;"> <div class="image-view"> <a href="http://img.e-com-net.com/image/info10/285625d304764d269a9cec42cbbfbee6.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info10/285625d304764d269a9cec42cbbfbee6.jpg" width="650" height="95"></a> </div> </div> <div class="image-caption"></div> </div> <blockquote> <ol start="5"> <li>由于 <code>float</code>是 JavaScript 中的保留字,因此不能用作属性名。“DOM2 级样式”规范规定 样式对象上相应的属性名应该是 <code>cssFloat</code>;Firefox、Safari、Opera 和 Chrome 都支持这个属性,而 IE 支持的则是 <code>styleFloat。</code> </li> </ol> </blockquote> <h5>* DOM 样式属性和方法</h5> <h6>“DOM2 级样式”规范还为 style 对象定义了一些属性和方法。这些属性和方法在提供元素的 style特性值的同时,也可以修改样式。</h6> <blockquote> <p>(1) cssText:如前所述,通过它能够访问到 style 特性中的 CSS 代码。<br> (2) length:应用给元素的 CSS 属性的数量。<br> (3) parentRule:表示 CSS 信息的 CSSRule 对象。<br> (4) getPropertyCSSValue(propertyName):返回包含给定属性值的 CSSValue 对象。<br> (5) getPropertyPriority(propertyName):如果给定的属性使用了!important 设置,则返回"important";否则,返回空字符串。<br> (6) getPropertyValue(propertyName):返回给定属性的字符串值。<br> (7) item(index):返回给定位置的 CSS 属性的名称。<br> (8) removeProperty(propertyName):从样式中删除给定属性。<br> (9) setProperty(propertyName,value,priority):将给定属性设置为相应的值,并加上优先权标志("important"或者一个空字符串)。</p> </blockquote> <ol> <li><p>在<code>读取模式</code>下,<code>cssText</code> 返回浏览器对 style特性中 CSS 代码的内部表示。在<code>写入模式</code>下,赋给 cssText 的值会重写整个 style 特性的值;也就是 说,以前通过 style 特性指定的样式信息都将丢失。</p></li> <li><p>style 对象实际上就相当于一个集合,都可以使用<code>方括号</code>语法来代替 <code>item()</code>来取得给定位置的 CSS 属性。</p></li> </ol> <pre><code>var prop, value, i, len; for (i=0, len=myDiv.style.length; i < len; i++){ prop = myDiv.style[i]; //或者 myDiv.style.item(i) value = myDiv.style.getPropertyValue(prop); alert(prop + " : " + value); } </code></pre> <ol start="3"> <li> <code>getPropertyCSSValue()方法</code>,它返回一个包含两个属性的 CSSValue 对象,这两个属性分别是:<code>cssText</code>和 <code>cssValueType</code>。</li> </ol> <blockquote> <p>(1) <code>cssText 属性</code>的值与 getPropertyValue()返回的值相同。<br> (2) <code>cssValueType 属性</code>则是一个数值常量,表示值的类型:0 表示继承的值,1 表示基本的值,2 表示 值列表,3 表示自定义的值。</p> </blockquote> <h5>* 计算的样式</h5> <p>DOM2 级样式”增强了 document.defaultView,提供了 <code>getComputedStyle()方法</code>。</p> <blockquote> <ol> <li>这个方法接受<code>两个参数</code>:要取得计算样式的元素和一个伪元素字符串(例 如":after")。如果不需要伪元素信息,第二个参数可以是 null。</li> <li>getComputedStyle()方法返回一 个 CSSStyleDeclaration 对象(与 style 属性的类型相同),其中<code>包含当前元素的所有计算的样式</code>。</li> </ol> </blockquote> <pre><code><!DOCTYPE html> <html> <head> <title>Computed Styles Example
    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"
    1. IE 不支持 getComputedStyle()方法,在 IE 中,每个具有 style 属性 的元素还有一个 currentStyle 属性。这个属性是 CSSStyleDeclaration 的实例,包含当前元素全 部计算后的样式。
    var myDiv = document.getElementById("myDiv");
    var computedStyle = myDiv.currentStyle;
    alert(computedStyle.backgroundColor);//"red"
    alert(computedStyle.width);//"100px"
    alert(computedStyle.height);//"200px"
    alert(computedStyle.border);//undefined
    

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

    (2) 操作样式表

    1. CSSStyleSheet 类型表示的是样式表,包括通过元素包含的样式表和在