JavaScript高级程序设计读书笔记12

第12章 DOM2和DOM3

DOM变化

  • 可以通过下列代码来确定浏览器是否支持这些DOM模块
    1
    2
    3
    4
    5
    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");

针对XML命名空间的变化

  • HTML不支持XML命名空间,单XHTML支持XML命名空间。

其他方面的变化

DocumentType类型的变化

  • DocumentType类型新增了3个属性:publicId、systemId和internalSubset.
  • publicId、systemId表示文档类型声明中的两个信息段,在DOM1中无法访问。

    Document类型的变化

  • Document类型的变化中唯一与命名空间无关的方法是importNode()。
  • 用途:从文档中取得一个节点,然后将其导入另一个文档,使其成为文档结构的一部分。
  • 注意:每个节点都有一个ownerDocument属性,表示所属文档,如果调动appendChild()是传入的节点属于不同的文档

    Node类型的变化

  • Node类型中唯一与命名空间无关的变化,为添加了isSupported()方法。与DOM1级document.implementation引入的hasFeature()方法类似。
  • isSupported()方法用于确定当前节点具有什么能力,接受两个参数:特性名和特性版本号。

    框架的变化

  • 框架和内嵌框架分别用HTMLFrameElement和HTMLIFrameElement表示,在DOM2中新增contentDocument(包含一个指针,指向表示框架内容的文档对象)

样式

访问元素的样式

  • 任何支持style特性的HTML元素在JavaScript中都有一个对应的style属性,这个style对象是CSSStyleDeclaration的实例,包含着通过HTML的style特性指定的所有样式信息,但不包含与外部样式表或嵌入样式表经层叠而来的样式。
  • 支持style特性的HTML元素在JavaScript中都有一个对应的style属性。对于使用短划线的css属性,必须将其转换成驼峰大小写形式。
  • 多数情况下,都可以通过简单地转化属性名的格式来实现转换。其中一个不能直接转换的CSS属性就是float。
  • 由于float是JavaScript中的保留字,因此不能用作属性名。

操作样式表

  • insertRule():创建规则。参数:规则文本和表示在哪里插入规则的索引。
  • deletRule():删除规则。参数:要删除的规则位置。

元素大小

  • 偏移量:元素在屏幕上占用的所有可见的空间

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    function getElementLeft(element){
    var actualLeft = element.offsetLeft;
    var current = element.offsetParent;

    while(current !== null){
    actualLeft += current.offsetLeft;
    current = current.offsetParent;
    }
    return actuaLeft;
    }

    function getElementTop(element){
    var actualTop += current.offsetTop;
    var current = current.offsetParent;

    while (current != null){
    actualTop += current.offsetTop;
    current = current.offsetParent;
    }
    return actualTop;
    }
  • 客户区大小(client dimension),指的是元素内容及其内边距所占的空间大小。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function getViewport(){
    // 检查document.compatMode属性,以确定浏览器是否运行在混杂模式
    if (document.compatMode == "BackCompat"){
    return(
    width: document.body.clientWidth,
    height: document.body.clientHeight
    );
    }else{
    return{
    //documentElement 属性可返回文档的根节点
    width: document.documentElement.clientWidth,
    height: document.documentElement.clientHeight
    };
    }
    }
  • 滚动大小: 包含滚动内容的元素的大小。

  • scrollHeight 在没有滚动条的情况下,元素内容的高度
  • scrollWidth 在没有滚动条的情况下,元素内容的总宽度
  • scrollLeft 隐藏在内容区域左侧的像素数
  • scrollTop 隐藏在内容区域上方的像素数
  • 在确定文档的总高度时(包括基于视口的最小高度),必须取得scrollWidth/clientWidth和scrollHeight/clientHeight中的最大值,才能保证在跨浏览器的环境下得到精确的结果:

    1
    2
    3
    4
    //对于运行在混杂模式下的IE,则需要用document.body代替document.documentElement
    var docHeight = Math.max(document.documentElement.scrollHeight, documentElement.clientHeight);

    var docWidth = Math.max(document.documentElement.scrollWidth, documentElement.clientWidth);
  • 确定元素大小,在IE8及以前认为文档左上角坐标是(2,2),其他浏览器包括IE9则将传统的(0,0)作为起点坐标。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    function getBoundingClientRect(element){

    var scrollTop = document.documentElement.scrollTop;
    var scrollLeft = document.documentElement.scrollLeft;

    if(element.getBoundingClientRect(element)){
    var temp = document.createElement("div");
    temp.style.cssText = "position:absolute; left:0; top:0;";
    document.body.appendChild("temp");

    arguments.callee.offset = -temp.getBoundingClientRect().top - scrollTop;

    document.body.removeChild(temp);
    temp = null;
    }

    var rect = element.getBoundingClientRect();
    var offset = arguments.callee.offset;

    return(
    left: rect.left + offset,
    right: rect.right + offset,
    top: rect.top + offset,
    bottom: rect.bottom + offset,
    );
    }else{
    var actualLeft = getElementLeft(element);
    var actualTop = getElementTop(element);

    return{
    left: aotualLeft - scrollLeft,
    right: actualLeft + element.offsetWidth - scrollLeft,
    top: actualTop - scrollTop,
    bottom: actualTop + element.offsetHeight - scrollTop
    }
    }

遍历

  • NodeIterator(迭代节点)和TreeWalker;这两个类型能够基于给定的起点对DOM结构执行深度优先(depth-first)的遍历操作。

NodeIterator

  • 可以使用document.createNodeIterator()方法创建新的实例,接收4个参数。
    • root:想要作为搜索起点的树中的节点
  • whatToShow:表示要访问哪些节点的数字代码
  • filter:是一个NodeFilter对象,或者一个表示应该接受还是拒绝某种特定节点的函数
  • entityRefrenceExpansion:布尔值,表示是否要扩展实体引用。在HTML页面中没用,因为其中的实体引用不能扩展。
  • 如何创建一个只显示p元素的节点迭代器
    1
    2
    3
    4
    5
    6
    7
    8
    var filter = {acceptNode: function(){
    return node.tageName.toLowerCase() == "p"?
    NodeFilter.FILTER_ACCEPT:
    NodeFilter.FILTER_SKIP;
    }
    };

    var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT, filter, false);

TreeWalker

  • 比NodeIterator更高级的版本。除了nextNode()和previousNode()在内的相同功能之外还提供其他方法。
    • parentNode():遍历到当前节点的父节点;
    • firstChild():遍历当前节点的第一个子节点;
  • lastChild():遍历当前节点的最后一个子节点;
  • nextSibling():遍历当前节点的下一个同辈节点;
  • previousSibling():遍历当前节点的上一个同辈节点;
  • TreeWalker真正强大的地方在于能够在DOM结构中沿任何方向移动,即使不使用过滤器也可以得到想要的元素.

范围

DOM中的范围

  • createRange()方法创建范围。var range = document.createRange();

简单选择

  • selectNode() 选择整个节点
  • selectNodeContents() 选择节点的子节点

复杂选择

  • setStart()和setEnd()方法:接受两个参数,一个是参照节点,一个是偏移量

操作DOM范围中的内容

  • deleteContents(),删除范围中的内容。调用方式:range.deleteContents();
  • extractContents(),从文档区域移除范围的内容,返回范围内容的文档片段,可以对文档片段进行进一步操作,调用方式:var fragment=range.extractContents();
  • cloneContents(),创建一个文档片段,保存范围的副本,可以对文档片段进行进一步操作,调用方式:var fragment=range.cloneContents();

插入DOM范围中的内容

  • 除了向范围内部插入内容之外,还可以环绕范围插入内容,此时要使用surroundContents()方法。这个方法接收一个参数,即环绕范围内容的节点。

折叠DOM范围

  • 范围折叠就是指范围中未选择文档的任何部分。通俗的描述就是当你选择范围内的文本,点击左键的时候,光标会落在范围的开始或者范围的结束。
  • 使用collapse()进行折叠,接收一个参数,一个布尔值,表示要折叠到范围的那一端,true表示范围的起点,false表示范围的终点。要确定范围已经折叠外币,可以用collapsed属性检查。

比较DOM的范围

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

复制DOM的范围

  • 可以使用cloneRange()方法复制范围,返回范围的一个副本var newRange=range.cloneRange();

清理DOM范围

  • 在使用完范围之后,最好调用detach()方法,清理范围,回收内存.
    range.detach();// 从文档中分离
    range=null;// 解除引用