第12章 DOM2和DOM3


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

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

DOM变化

DOM2级和3级的目的在于扩展DOM API,以满足操作XML的所有需求,同时提供更好的错误处理及特性检测能力。
通过下列代码来确定浏览器是否支持这些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");

document.writeln("supports DOM 2 Core = " + supportsDOM2Core + "<br>");
document.writeln("supports DOM 3 Core = " + supportsDOM3Core + "<br>");
document.writeln("supports DOM 2 HTML = " + supportsDOM2HTML + "<br>");
document.writeln("supports DOM 2 Views = " + supportsDOM2Views + "<br>");
document.writeln("supports DOM 2 XML = " + supportsDOM2XML + "<br>");

在IE中运行显示其不支持DOM 3 Core,Edge支持。

针对XML命名空间的变化

有了XML命名空间,不同XML文档的元素就可以混合在一起,共同构成格式良好的文档,而不必担心命名冲突。
HTML不支持XML命名空间,XHTML支持。
命名空间要使用xmlns特性来指定。
XHTML的命名空间是http://www.w3.org/1999/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>

为了避免不同语言间的冲突,也需要使用命名空间来限定特性:

<xhtml:html xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <xhtml:head>
        <xhtml:title>Example XHTML page</xhtml:title>
    </xhtml:head>
    <xhtml:body xhtml:class="home">
        Hello world!
    </xhtml:body>
<xhtml:html>

在只基于一种语言编写XML文档的情况下,命名空间没有意义。

  1. Node类型的变化
    在DOM2级中,Node类型包含下列特定与命名空间的属性。
    • localName:不带命名空间前缀的节点名称。
    • namespaceURI:命名空间URI或者(在未指定的情况是)null。
    • prefix:命名空间前缀或者(在未指定的情况下是)null。
      DOM3级又引入了下列与命名空间有关的方法:
    • isDefaultNamespace(namespaceURI):在指定的namespaceURI是当前节点的默认命名空间的情况下返回true。
    • lookupNamespaceURI(prefix):返回给定prefix的命名空间。
    • lookupPrefix(namespaceURI):返回给定namespaceURI的前缀。
  2. Document类型的变化
    DOM2级中的Document类型包含下列与命名空间有关的方法:
    • 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", "*");
  1. Element类型的变化
    “DOM2级核心”中有关Element的变化,主要涉及操作特性。新增如下方法:
    • getAttributeNS(namespaceURI, localName):取得属于命名空间namespaceURI且名为localName的特性。
    • getAttributeNodeNS(namespaceURI, localName):取得属于命名空间namespaceURI且名为localName的特性节点。
    • hasAttributeNS(namespaceURI, localName):确定当前元素是否有一个名为localName的特性,而且该特性的命名空间是namespaceURI。注意:“DOM2级核心”也增加了一个hasAttribute()方法,用于不考虑命名空间的情况。
    • removeAttributeNS(namespaceURI, localName):删除属于命名空间namespaceURI且名为localName的特性。
    • setAttributeNS(namespaceURI, qualifiedName, value):设置属于命名空间namespace-URI且名为qualifiedName的特性的值为value。
    • setAttributeNodeNS(attNode):设置属于命名空间namespaceURI的特性节点。
  2. NamedNodeMap类型的变化
    NamedNodeMap类型新增了下列与命名空间有关的方法。由于特性是通过NamedNodeMap表示的,因此这些方法多数情况下只针对特性使用。
    • getNamedItemNS(namespaceURI, localName):取得属于命名空间namespaceURI且名为localName的项。
    • removeNamedItemNS(namespaceURI, localName):移除属于命名空间namespaceURI且名为localName的项。
    • setNamedItemNS(node):添加node,这个节点已经事先中指定了命名空间信息。

其他方面的变化

DOM的其他部分在“DOM2级核心”中也发生了一些变化。这些变化与XML命名空间无关,而是更倾向与确保API的可靠性及完整性。

  1. DocumentType类型的变化
    新增了3个属性:publicId、systemId和internalSubset。前两个表示的是文档声明中的两个信息段,在DOM1级中没有办法访问。
<!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"
在支持DOM2级的浏览器中,可以运行如下代码:

alert(document.doctype.publicId);
alert(document.doctype.systemId);

internalSubset用于访问包含在文档类型声明中的而外定义:

<!DOCTYPE HTML PUBLIC "~//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd" [<!ELEMENT name (#PCDATA)>] >

以上代码中document.doctype.internalSubset = “<!ELEMENT name (#PCDATA)>”。

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

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

var newNode = document.importNode(oldNode, true);   //导入节点及其子节点
document.body.appendChild(newNode);

importNode()方法在HTML中不常用,在XML文档中用得比较多。

“DOM2级视图”模块添加了一个名为defaultView的属性,其中保存一个指针,指向拥有给定文档的窗口(框架)。除IE之外的所有浏览器都支持defaultView属性。在IE中有一个等价的属性名叫parentWindow(Opera也支持这个属性)。因此,要确定文档的归属窗口,可以使用以下代码。

var parentWindow = document.defaultView || document.parenWindow;

“DOM2级核心”还为document.implementation对象规定了两个新方法:createDocumentType()和createDocument()。

createDocumentType()方法用于创建一个新的DocumentType节点,接收3个参数:文档类型名称、publicId、systemId。

var doctype = document.implementation.createDocumentType("html",
                    "~//W3C//DTD HTML 4.01//EN",
                    "http://www.w3.org/TR/html4/strict.dtd");

由于既有文档的文档类型不能改变,因此createDocumentType()只能在创建新文档时有用。

createDocument()方法接收3个参数:针对文档中元素的namespaceURI、文档元素的标签名、新文档的文档类型。

var doc = document.implementation.createDocument("","root",null);

该代码会创建一个没有命名空间的新文档,文档元素为,而且没有指定文档类型。

“DOM2级HTML”模块也为document.implementation新增了一个方法,createHTMLDocument()。该方法创建一个完整的HTML文档,包括、、和元素,方法接收一个参数,即新创建文档的标题。

var htmldoc = document.implementation.crateHTMLDocument("New Doc");
alert(htmldoc.title);       //“New Doc”
alert(typeof htmldoc.body); //"object"

只有Oprea和Safari支持该方法。

  1. Node类型的变化
    Node类型唯一与命名空间无关的变化就是添加了isSupported()方法。与DOM1级为document.implementation引入的hasFeature()方法类似,用于确定当前节点具有什么能力。该方法接收两个参数:特姓名和特性版本号,如果浏览器实现了相应特性,而且能够基于给定节点执行该特性,isSupported()就返回true。
if (document.body.isSupported("HTML", "20")) {
    //执行只有“DOM2级HTML”才支持的操作
}

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

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

DOM3级还针对为DOM节点添加额外数据引入了新方法:setUserData()方法将数据指定给节点,接收3个参数:要设置的键、实际的数据和处理函数。

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

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

var div = document.createElement("div");
div.setUserData("name", "Nicholas", function(operation, key, value, src, dest) {
    if(operation == 1) {
        dest.setUserData(key, value, functon(){});
    }
})

var newDiv = div.cloneNode(true);
alert(newDiv.getUserData("name"));      //"Nicholas"
  1. 框架的变化
    框架和内嵌框架分别用HTMLFrameElement和HTMLIFrameElement表示。

他们在DOM2级中都有一个新属性contentDocument,该属性包含一个指针,指向表示框架内容的文档对象。

var iframe = document.getElementById("myIframe");
var iframeDoc = iframe.contentDocument;         //在IE8以前的版本中无效

IE8之前的版本不支持框架中的contentDocument属性,支持contentWindow的属性,返回框架的window对象,这个window对象有一个document属性。

所有浏览器都支持contentWindow属性。


样式

HTML中三种定义样式的方式:

  1. 通过元素包含外部样式表文件。
  2. 使用

    “DOM2级样式”模块围绕3中应用样式的机制提供了一套API。
    确定浏览器是否支持DOM2级定义的CSS能力,使用如下代码:

    var supportsDOM2CSS = document.implementation.hasFeature("CSS", "2.0");
    var supportsDOM2CSS2 = document.implementation.hasFeature("CSS2", "2.0");
    

    访问元素的样式

    任何支持style特性的HTML元素在javascript中都有一个对应的style属性。这个style对象是CSSStyleDeclaration的实例,包含通过HTML的style特性指定的所有样式信息,但不包括与外部样式表或嵌入样式表经层叠而来的样式。

    在style特性中指定的任何CSS属性都将表现为这个style对象的相应属性。使用短划线(如:background-image)的CSS属性,必须将其转换成驼峰大小写形式才能通过js访问。

    多数情况下,都可以通过简单地转换属性名的格式来实现转换,其中float不能用作属性名,DOM2级样式规范规定相应的属性名应该是cssFloat;而对于IE而言是sytleFloat。

    只要取得一个有效的DOM元素的引用,就可以随时使用js为其设置样式。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>Example page</title>
    </head>
    <body>
        <div id="myDiv">
        </div>
        <script type="text/javascript">
            var myDiv = document.getElementById("myDiv");
    
            //设置背景颜色
            myDiv.style.backgroundColor = "red";
    
            //改变大小
            myDiv.style.width = "100px";
            myDiv.style.height = "200px";
    
            //指定边框
            myDiv.sytle.border = "1px solid black";
        </script>
    </body>
    </html>
    

    在标准模式下,所有度量值都必须制定一个度量单位。在混杂模式下,可以将style.width设置为“20”,浏览器会建设它是“20px”;但在标准模式下,会导致该样式被忽略。在时间中最好始终都制定度量单位。

    通过style对象可以取得在style特性中指定的样式:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>Example page</title>
    </head>
    <body>
        <div id="myDiv" style="background-color:blue; width:10px; height:25px">
        </div>
        <script type="text/javascript">
            var myDiv = document.getElementById("myDiv");
    
            alert(myDiv.style.backgroundColor);     //"blue"
            alert(myDiv.style.width);               //"10px"
            alert(myDiv.style.height);              //"25px"
        </script>
    </body>
    </html>
    

    如果没有为元素设置style特性,那么style对象中可能会包含一些默认的值,但这些值不能准确的反映该元素的样式信息。

    1. DOM样式属性和方法

      • cssText:通过它能够访问到style特性中的CSS代码。
      • length:应用给元素的CSS属性的数量。
      • parentRule:表示CSS信息的CSSRule对象。
      • getPropertyCSSValue(propertyName):返回包含给定属性值的CSSValue对象。
      • getPropertyPriority(propertyName):如果给定的属性使用了!important设置,则返回“important”,否则返回空。
      • getProgertyValue(propertyName):返回给定属性的字符串值。
      • item(index):返回给定位置的CSS属性名称。
      • removeProperty(propertyName):从样式中删除给定属性。
      • setProperty(propertyName, value, priority):将给定属性设置为相应的值,并加上优先权标志(“important”或者一个空字符串。)
    2. 计算的样式
      DOM2级样式增强了document.defaultView,提供了getComputedSytle()方法,该方法返回一个CSSStyleDeclaration对象,其中包含当前元素的所有计算的样式。该方法接收2个参数:要取得计算样式的元素和一个伪元素字符串(例如:after)。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>Example page</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>
        <script type="text/javascript">
            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"
        </script>
    </body>
    </html>
    

    IE不支持getComputedStyle()方法,而使用currentStyle属性。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>Example page</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>
        <script type="text/javascript">
            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
        </script>
    </body>
    </html>
    

    所有计算样式都是只读的,不能修改。


    操作样式表

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

    CSSStyleSheet继承自StyleSheet,继承的属性有:

    • disabled:表示样式表是否被禁用的布尔值。
    • href:如果样式表是通过包含的,则是样式表的URL,否则,是null。
    • media:当前样式表支持的所有媒体类型的集合。在IE中,media是一个反应和

    应用于文档的所有样式表是通过document.styleSheets集合来表示的,通过这个集合的length属性可以获知文档中样式表的数量。

    可以直接通过或

    function getStyleSheet(element) {
        reutrn element.sheet || element.styleSheet;
    }
    
    1. CSS规则
      CSSRule对象,表示样式表中的每一条规则。CSSStyleRule继承则CSSRule,包含以下属性:

      • cssText:返回整条规则对应的文本。
      • parentRule:如果当前规则是导入规则,这个属性引用的就是导入规则,否则,为null。IE不支持。
      • parentStyleSheet:当前规则所属的样式表。IE不支持。
      • selectorText:返回当前规则的选择符文本。
      • style:一个CSSStyleDeclaration对象,可以通过它设置和取得规则中特定的样式值。
      • type:表示规则类型的常量值。IE不支持。
    2. 创建规则
      DOM规定,要向现有样式表中添加新规则,需要使用insertRule()方法,该方法接收两个参数:规则文本和表示在哪里插入规则的索引。

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

    IE8及更早的版本支持addRule(),也接受两个必选参数:选择符文本和CSS样式信息。以及一个可选参数:插入规则的位置。

    addRule()中最多可以添加4095条样式规则,超过将会导致错误。

    1. 删除规则
      deleteRule()方法从样式表中删除规则,该方法接收一个参数:要删除的规则的位置。IE中类似的方法是removeRule()。

    元素大小

    1. 偏移量
      元素的可见大小由其高度、宽度决定,包括所有内边距、滚动条和边框大小(注意,不包括外边距)。
      • offsetHeight:元素在垂直方向上占用的空间大小,以像素计。包括元素的高度、(可见的)水平滚动条的高度、上边框和下边框的高度。
      • offsetWidth:元素在水平方向上占用的空间大小,以像素计。包括元素的宽度、(可见的)垂直滚动条的宽度、左边框宽度和右边框宽度。
      • offsetLeft:元素的左外边框至包含元素的做内边框之间的像素距离。
      • offsetTop:元素的上外边框至高寒元素的上内边框之间的像素距离。
        1d8da071cb4bc36a218c71f74041c5cc.png

    要想知道某个元素在页面上的偏移量,将这个元素的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 += current.offsetTop;
            current = current.offsetParent;
        }
    
        return actualTop;
    }
    

    所有这些偏移量都是只读的,而且每次访问它们都要重新计算。因此应该尽量避免重复访问这些属性;如果需要重复使用其中某些属性的值,可以将他们保存在局部变量中,以提高性能。

    1. 客户区大小
      元素的客户区大小(client dimension),指的是元素内容及其内边距所占据的空间大小。
      clientWidth是元素内容区宽度加上左右内边距宽度;
      clientHeight是元素内容区高度加上上下内边距宽度。
      ad2df6c15dca4fda18fab5607f1cdbc7.png

    与偏移量类似,客户区大小也是只读的。

    1. 滚动大小
      滚动大小(scroll dimension),指的是包含滚动内容的元素的大小。

      • scrollHeight:在没有滚动条的情况下,元素内容的总高度。
      • scrollWidth:在没有滚动条的情况下,元素内容的总宽度。
      • scrollLeft:被隐藏在内容区域左侧的像素数。通过设置这个属性可以改变元素的滚动位置。
      • scrollTop:被隐藏在内容区域上方的像素数。通过设置这个属性可以变元素的滚动位置。
    2. 确定元素大小
      getBoundingClientRect()方法,返回一个矩形对象,包含4个属性:left、top、right和bottom。描述了元素在页面中相对视口的位置。


    遍历

    DOM2级遍历和范围模块定义了两个用于辅助完成顺序遍历DOM结构的类型:NodeIterator和TreeWalker。能够基于给定的起点对DOM结构执行深度优先(depth-first)的遍历操作。


    范围

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值