DOM变化
针对XML命名空间的变化
命名空间要使用 xmlns 特性来指定。XHTML 的命名空间是 www.w3.org/1999/xhtml ,在任何格式良好 XHTML 页面中,都应该将其包含在<html>元素中。如下例中,混合了 XHTML 和 SVG 语言
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Example XHTML page</title>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
viewBox="0 0 100 100" style="width:100%; height:100%">
<rect x="0" y="0" width="100" height="100" style="fill:red"/>
</svg>
</body>
</html>
-
Node类型的变化
DOM2级中,Node类型包含下列特定于命名空间的属性:
- localName:不带命名空间前缀的节点名称
- namespaceURI:命名空间 URI ,在未指定的情况下是null
- prefix:命名空间前缀或者,在未指定的情况下是null
DOM3级中,引入了下列与命名空间有关的方法:
- isDefaultNamespace(namespaceURI):在指定的 namespaceURI 是当前节点的默认命名空间的情况下返回 true
- lookupNamespaceURI(prefix):返回给定 prefix 的命名空间
- lookupPrefix(namespaceURI):返回给定 namespaceURI 的前缀
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Example XHTML page</title> </head> <body> <s:svg xmlns:s="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 100 100" style="width:100%; height:100%"> <s:rect x="0" y="0" width="100" height="100" style="fill:red"/> </s:svg> </body> </html> alert(document.body.isDefaultNamespace("http://www.w3.org/1999/xhtml"); //true //假设 svg 中包含着对<s:svg>的引用 alert(svg.lookupPrefix("http://www.w3.org/2000/svg")); //"s" alert(svg.lookupNamespaceURI("s")); //"http://www.w3.org/2000/svg" -
Document类型的变化
DOM2级包含了下列与命名空间的方法:
- createElementNS(namespaceURI, tagName):使用给定的 tagName 创建一个属于命名空间 namespaceURI 的新元素。
- createAttributeNS(namespaceURI, attributeName):使用给定的 attributeName 创建一个属于命名空间 namespaceURI 的新特性。
- getElementsByTagNameNS(namespaceURI, tagName):返回属于命名空间 namespaceURI的 tagName 元素的 NodeList
//创建一个新的 SVG 元素 var svg = document.createElementNS("http://www.w3.org/2000/svg","svg"); //创建一个属于某个命名空间的新特性 var att = document.createAttributeNS("http://www.somewhere.com", "random"); //取得所有 XHTML 元素 var elems = document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "*"); -
ELement类型的变化
“DOM2 级核心”中有关 Element 的变化,主要涉及操作特性。新增的方法如下:
- getAttributeNS(namespaceURI,localName):取得属于命名空间 namespaceURI 且名为localName 的特性。
- getAttributeNodeNS(namespaceURI,localName):取得属于命名空间 namespaceURI 且名为 localName 的特性节点。
- getElementsByTagNameNS(namespaceURI, tagName):返回属于命名空间 namespaceURI的 tagName 元素的 NodeList。
- hasAttributeNS(namespaceURI,localName):确定当前元素是否有一个名为 localName的特性,而且该特性的命名空间是 namespaceURI。注意,“DOM2 级核心”也增加了一个hasAttribute()方法,用于不考虑命名空间的情况。
- removeAttriubteNS(namespaceURI,localName):删除属于命名空间 namespaceURI 且名为 localName 的特性。
- setAttributeNS(namespaceURI,qualifiedName,value):设置属于命名空间 namespaceURI 且名为 qualifiedName 的特性的值为 value。
- setAttributeNodeNS(attNode):设置属于命名空间 namespaceURI 的特性节点。
-
NameNodeMap类型的变化
- getNamedItemNS(namespaceURI,localName):取得属于命名空间 namespaceURI 且名为localName 的项。
- removeNamedItemNS(namespaceURI,localName):移除属于命名空间 namespaceURI 且为 localName 的项。
- setNamedItemNS(node):添加 node,这个节点已经事先指定了命名空间信息。
其他方面的变化
-
DocumentType类型的变化
DocumentType类型新增了3个属性:publicId、systemId、internalSubset。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd" [<!ELEMENT name (#PCDATA)>] >在上例中,document.doctype.publicId 等于 "-//W3C//DTD HTML 4.01//EN",document.doctype.systemId 等于 "www.w3.org/TR/html4/st…" ,document.doctype.internalSubset 访问在文档声明中的额外定义,等于<!ELEMENT name (#PCDATA)>
-
Document类型的变化
-
importNode():从一个文档中取得一个节点,然后将其导入到另一个文档,使其成为这个文档结构的一部分。接收两个参数:要复制的节点和否复制子结点的布尔值
-
defaultView属性:保存着一个指针,指向拥有给定文档的窗口(或框架)。
-
document.implementation新增两个方法
-
createDocumentType():创建新的DocumentType节点,接收三个参数:文档类型名称、publicId、systemId。只在创建新文档时有用
-
createDocument():创建新文档。接收三个参数:针对文档中元素的 namespaceURI、文档元素的标签名、新文档的文档类型
-
createHTMLDocument():创建一个完整的HTML文档。接收一个参数,新建的文档标题(放在<title>元素中的字符串),返回新的HTML文档
//创建一个新的 HTML 4.01 Strict 文档类型 var doctype = document.implementation.createDocumentType("html", "-//W3C//DTD HTML 4.01//EN","http://www.w3.org/TR/html4/strict.dtd"); //创建一个空的新XML文档 var doc = document.implementation.createDocument("", "root", null); //创建一个标题为New Doc的HTML文档 var htmldoc = document.implementation.createHTMLDocument("New Doc");
-
-
-
Node类型的变化
- isSupported():确定当前节点具有什么能力。接收两个参数:特性名和特性版本号。如果浏览器实现了相应特性,而且能够基于给定节点执行该特性,isSupported()就返回 true。
- isSameNode():判断传入节点与引用方法的节点是否为同一个节点
- isEqualNode():判断传入节点与引用方法的节点是否相等(类型相同、属性相等、子节点相等)
- setUserData():将数据指定给节点。接受三个参数:要设置的键、实际的数据、处理函数。传入 setUserData()中的处理函数会在带有数据的节点被复制、删除、重命名或引入一个文档时调用,因而你可以事先决定在上述操作发生时如何处理用户数据。处理函数接受 5 个参数:表示操作类型的数值(1 表示复制,2 表示导入,3 表示删除,4 表示重命名)、数据键、数据值、源节点和目标节点。在删除节点时,源节点是 null;除在复制节点时,目标节点均为 null。
- getUserData():获取节点键的值
if(document.body.isSupported("HTML","2.0")){ //执行只有DOM2级HTML才支持的操作 } 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 document.body.setUserData("name", "Nicholas", function(){}); var value = document.body.getUserData("name"); -
框架的变化
contentDocument:包含一个指针,指向表示框架内容的文档对象
var iframe = document.getElementById("myIframe"); var iframeDoc = iframe.contentDocument; //在 IE8 以前的版本中无效
样式
访问元素的样式
通过style属性指定css样式访问元素的样式,短划线的属性转换为驼峰大小写的形式。
如"background-image"——"style.backgroundImage";"color"——"style.color"。只有float不能通过转换属性名的方式获取,因为float是js的保留字,获取float样式的方式:style.cssFloat,IE中为style.styleFloat
-
DOM样式属性和方法
- 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"或者一个空字符)
-
计算的样式
getComputedStyle():接收两个参数:要取得计算样式的元素、一个伪元素字符串(null时返回包含当前元素的所有计算样式的对象)
操作样式表
- disabled:表示样式表是否被禁用的布尔值。这个属性是可读/写的,将这个值设置为 true 可以禁用样式表
- href:如果样式表是通过<link>包含的,则是样式表的 URL;否则,是 null
- media:当前样式表支持的所有媒体类型的集合
- ownerNode:指向拥有当前样式表的节点的指针,样式表可能是在 HTML 中通过<link>或<style/>引入的(在 XML 中可能是通过处理指令引入的)。如果当前样式表是其他样式表通过@import 导入的,则这个属性值为 null
- parentStyleSheet:在当前样式表是通过@import 导入的情况下,这个属性是一个指向导入它的样式表的指针
- title:ownerNode 中 title 属性的值。
- type:表示样式表类型的字符串。对 CSS 样式表而言,这个字符串是"type/css"。
- cssRules:样式表中包含的样式规则的集合
- ownerRule:如果样式表是通过@import 导入的,这个属性就是一个指针,指向表示导入的规则;否则,值为 null
- deleteRule(index):删除 cssRules 集合中指定位置的规则
- insertRule(rule,index):向 cssRules 集合中指定的位置插入 rule 字符串
-
CSS规则
CSSRule 对象表示样式表中的每一条规则。实际上,CSSRule 是一个供其他多种类型继承的基类型,其中最常见的就是 CSSStyleRule 类型,表示样式信息,CSSStyleRule 对象包含下列属性:
- cssText:返回整条规则对应的文本。由于浏览器对样式表的内部处理方式不同,返回的文可能会与样式表中实际的文本不一样
- parentRule:如果当前规则是导入的规则,这个属性引用的就是导入规则;否则,这个值为null
- parentStyleSheet:当前规则所属的样式表
- selectorText:返回当前规则的选择符文本
- style:一个 CSSStyleDeclaration 对象,可以通过它设置和取得规则中特定的样式值
- type:表示规则类型的常量值。对于样式规则,这个值是 1
-
创建规则
insertRule():向现有样式表中添加新规则。接收两个参数:规则文本、插入规则的索引
sheet.insertRule("body { background-color: silver }", 0); //DOM 方法 -
删除规则
deleteRule():从样式表中删除规则。接收一个参数:要删除规则的位置
sheet.deleteRule(0); //删除样式表中的第一条规则
元素大小
-
偏移量:只读
包括元素在屏幕上占用的所有可见的空间
- offsetHeight:元素在垂直方向上占用的空间大小,以像素计。包括元素的高度、(可见的)水平滚动条的高度、上边框高度和下边框高度
- offsetWidth:元素在水平方向上占用的空间大小,以像素计。包括元素的宽度、(可见的)垂直滚动条的宽度、左边框宽度和右边框宽度
- offsetLeft:元素的左外边框至包含元素的左内边框之间的像素距离
- offsetTop:元素的上外边框至包含元素的上内边框之间的像素距离
-
客户区大小:只读
元素内容及其内边距所占据的空间大小
- clientWidth:元素内容宽度 + 左右内边距宽度
- clientHeight:元素内容高度 + 上下内边距高度
-
滚动大小:可读可写
包含滚动内容的元素的大小
- scrollHeight:在没有滚动条的情况下,元素内容的总高度。
- scrollWidth:在没有滚动条的情况下,元素内容的总宽度。
- scrollLeft:被隐藏在内容区域左侧的像素数。通过设置这个属性可以改变元素的滚动位置。
- scrollTop:被隐藏在内容区域上方的像素数。通过设置这个属性可以改变元素的滚动位置。
-
确定元素大小
getBoundingClientRect():返回一个矩形对象,包含4个属性:left、top、right和bottom。这些属性给出了元素在页面中相对于视口的位置。
遍历
“DOM2 级遍历和范围”模块定义了两个用于辅助完成顺序遍历 DOM 结构的类型:NodeIterator和 TreeWalker。
NodeIterator
可以使用 document.createNodeIterator()创建新实例。这个方法接受下列 4 个参数。
- root:搜索起点。
- whatToShow:要访问节点的数字代码。
- filter:一个 NodeFilter 对象,或者一个表示应该接受还是拒绝某种特定节点的函数。可以通过该参数指定自定义的NodeFilter对象。每个 NodeFilter 对象只有一个方法,即 acceptNode();如果需要访问给定的节点,该方法返回 NodeFilter.FILTER_ACCEPT,如果不需要访问给定的节点,该方法返回 NodeFilter.FILTER_SKIP。该参数也可以是一个与 acceptNode()方法类似的函数,如下例中的filter1所示
- entityReferenceExpansion:布尔值,表示是否要扩展实体引用
NodeIterator类型的两个主要方法是nextNode()和previousNode()。nextNode()用于向前前进一步,previousNode()用于向后后退一步
<div id="div1">
<p><b>Hello</b> world!</p>
<ul>
<li>List item 1</li>
<li>List item 2</li>
<li>List item 3</li>
</ul>
</div>
//返回遍历中遇到的<li>元素
var div = document.getElementById("div1");
var filter = {
acceptNode:function(node){
return node.tagName.toLowerCase() == "li" ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
}
}
var filter1 = function(node){
return node.tagName.toLowerCase() == "li" ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
};
var iterator = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT, filter1, false);
var node = iterator.nextNode();
while (node !== null) {
console.log(node.tagName); //输出标签名
node = iterator.nextNode();
}
TreeWalker
TreeWalker除了包括nextNode()和previousNode()外,还包括下列不同方向上遍历DOM结构的方法:
- parentNode():遍历到当前节点的父节点
- firstChild():遍历到当前节点的第一个子节点
- lastChild():遍历到当前节点的最后一个子节点
- nextSibling():遍历到当前节点的下一个同辈节点
- previousSibling():遍历到当前节点的上一个同辈节点
创建 TreeWalker 对象要使用 document.createTreeWalker()方法,该方法接收以下4个参数:
- root:搜索起点。
- whatToShow:要访问节点的数字代码。
- filter:可取值除了NodeFilter.FILTER_ACCEPT 和 NodeFilter. FILTER_SKIP 之外,还可以使用 NodeFilter.FILTER_REJECT。NodeFilter.FILTER_SKIP 会跳过相应节点继续前进到子树中的下一个节点,而 NodeFilter.FILTER_REJECT 则会跳过相应节点及该节点的整个子树
- entityReferenceExpansion:布尔值,表示是否要扩展实体引用
范围
“DOM2 级遍历和范围”模块定义了“范围”(range)接口
DOM中的范围
使用document.createRange() 方法创建DOM范围——Range类型的实例。实例中包含以下属性:
- startContainer:包含范围起点的节点(即选区中第一个节点的父节点)
- startOffset:范围在 startContainer 中起点的偏移量。如果 startContainer 是文本点、注释节点或 CDATA 节点,那么 startOffset 就是范围起点之前跳过的字符数量。否则,startOffset 就是范围中第一个子节点的索引
- endContainer:包含范围终点的节点(即选区中最后一个节点的父节点)
- endOffset:范围在 endContainer 中终点的偏移量(与 startOffset 遵循相同的取值规则)
- commonAncestorContainer:startContainer 和 endContainer 共同的祖先节点在文档中位置最深的那个
-
用DOM范围实现简单选择
selectNode() 和 selectNodeContents() 方法可以使用范围来选择文档中的一部分。两个方法都接收一个DOM节点参数。selectNode() 方法选择整个节点,包括其子结点;selectNodeContents() 方法只选择子节点
<!DOCTYPE html> <html> <body> <p id="p1"><b>Hello</b> world!</p> </body> </html> var range1 = document.createRange(); var range2 = document.createRange(); var p1 = document.getElementById("p1"); range1.selectNode(p1); range2.selectNodeContents(p1);可以使用下列方法更精细地控制将哪些节点包含在范围内:
- setStartBefore(refNode):将范围的起点设置在refNode之前
- setStartAfter(refNode):将范围的起点设置在refNode之后
- setEndBefore(refNode):将范围的终点设置在refNode之前
- setEndAfter(refNode):将范围的终点设置在refNode之后
-
用DOM范围实现复杂选择
使用setStart()和setEnd()方法创建复杂的范围。这两个方法接收两个参数:参照节点和偏移量
-
操作DOM范围中的内容
deleteContents():从文档中删除范围所包含的内容,不会返回删除的片段
extractContents():从文档中删除范围选区,并返回所删除的文档片段,可以将返回的片段插入到文档的其他地方
cloneContents():创建范围对象的一个副本,然后可以在文档的其他地方插入该副本
-
插入DOM范围中的内容
insertNode(refNode):向范围选区的开始处插入一个节点
surroundContents(refNode):在范围选区插入内容,该方法接受一个参数,环绕范围内容的节点
<!DOCTYPE html> <html> <body> <p id="p1"><b>Hello</b> world!</p> </body> </html> var p1 = document.getElementById("p1"); helloNode = p1.firstChild.firstChild; worldNode = p1.lastChild; range = document.createRange(); range.setStart(helloNode, 2); range.setEnd(worldNode, 3); var span = document.createElement("span"); span.style.color = "red"; span.appendChild(document.createTextNode("Inserted text")); range.insertNode(span); //结果为<p id="p1"><b>He<span style="color: red">Inserted text</span>llo</b> world</p> 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); //结果为<p><b><span style="background-color:yellow">Hello</span></b> world!</p> -
折叠DOM范围
折叠范围,指范围中未选择文档的任何部分
collapse():折叠范围。接受一个布尔值参数,表示要折叠到范围的一端,true 表示折叠到范围的起点,参数 false 表示折叠到范围的终点。要确定范围已经折叠完毕,可以检查 collapsed 属性
-
比较DOM范围
compareBoundaryPoints():有多个范围时,确定这些范围是否有公共的边界(起点或终点)。接受两个参数:比较方式的常量值和要比较的范围,表示方式的常量值如下:
- Range.START_TO_START(0):比较第一个范围和第二个范围的起点;
- Range.START_TO_END(1):比较第一个范围的起点和第二个范围的终点;
- Range.END_TO_END(2):比较第一个范围和第二个范围的终点
- Range.END_TO_START(3):比较第一个范围的终点和第一个范围的起点。
该方法的返回值:-1——第一个范围中比较点的位置在第二个范围比较点的位置之前;0——两个点相等;1——第一个范围中的点位于第二个范围中的点之后
var range1 = document.createRange(); var range2 = document.createRange(); var p1 = document.getElementById("p1"); range1.selectNodeContents(p1); range2.selectNodeContents(p1); range2.setEndBefore(p1.lastChild); alert(range1.compareBoundaryPoints(Range.START_TO_START, range2)); //0 alert(range1.compareBoundaryPoints(Range.END_TO_END, range2)); //1 -
复制DOM范围
cloneRange():创建调用它的范围的一个副本了,新创建的范围与原来的范围包含相同的属性,并且修改副本的端点不会影响原来的范围。
var nerRange = range.cloneRange(); -
清理DOM范围
detach():从创建范围的文档中分离出该范围。在使用范围之后最好调用该方法。
//使用范围最后再执行这两个步骤 range.detach();//从文档中分离 range = null;//解除引用