zoukankan      html  css  js  c++  java
  • 第十二章 DOM2和DOM3

    元素大小

    偏移量

    offsetHeight: 元素在垂直方向上占用的空间大小,包括元素的高度,水平滚动条的高度,上边框高度和下边框高度。

    offsetWidth: 元素在水平方向上占用的空间大小,包括元素的宽度度,垂直滚动条的高度,左边框高度和右边框高度。

    offsetLeft: 元素的左外边框至包含元素的左内边框之间的像素距离。

    offsetRight: 元素的左外边框至包含元素的左内边框之间的像素距离。

    offsetTop: 

    offsetParent: 属性返回一个对象的引用,这个对象是距离调用offsetParent的元素最近的(在包含层次中最靠近的),并且是已进行过CSS定位的容器元素。

    如果这个容器元素未进行CSS定位, 则offsetParent属性的取值为根元素

    客户区大小

    元素内容及其内边距占据的空间大小。

    clientWidth

    clientHeight

    滚动大小

    包含滚动内容的元素大小。

    scrollHeight: 再没有滚动的情况下,元素内容的总高度。

    scrollWidth: 在没有滚动的情况下,元素内容的总宽度。

    scollLeft: 被隐藏再内容区域左侧的像素。通过设置这个属性可以改变元素的滚动位置。

    scollTop: 隐藏再内容区域上方的像素。通过设置这个属性可以改变元素的滚动位置。

    确定元素大小

    getBoundingClientRect():  为每个元素返回一个矩形对象,包含4个属性: left, top, right bottom。这些属性给出了元素再页面中相对视口的位置。

    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;
     }
    
    function getBoundingClientRect(element) {
      //获取形参的顶部滚动距离
       var scrollTop = document.documentElement.scrollTop;
       //获取形参的左边滚动距离
       var scrollLeft = document.documentElement.scrollLeft;
       
    
        //如果形参的getBoundingClientRect可以用的话
        if(element.getBoundingClientRect) {
            //检测这个函数的形参的自定义属性offset不是数字的时候
            if(typeof arguments.callee.offset != "number") {
               //创建一个div
               var temp = document.createElement("div");
               //给这个div绝对定位 
               temp.style.cssText = "position: absolute; left: 0; top: 0;";
              //把这个元素丢进文档树
               document.body.appendChild(temp);
               //用getboundingClientRect方法获取这个div的高度,-减去滚动的距离,的到这个元素的top值。
               arguments.callee.offset =-temp.getBoundingClientRect().top - scrollTop;
               //从文档树中删除这个div
               document.body.removeChild(temp);
              //解除引用
               temp = null;
             }
            //获取这个形参的bottom.top,left,和right
             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 = getEementTop(element);
             return {
               left: actualLeft - scrollLeft,
               right: actualLeft + element.offsetWidth - scrollLeft,
               top: actualTop - scrollTop,
               bottom: actualTop + elementoffsetHeifht - scrollTop
             }
    } 

    遍历

    DOM遍历是深度优先的DOM结构遍历,移动的方向至少有俩个,遍历以给定节点为根,不可能超出DOM树的根节点。

    任何节点都可以作为遍历的根节点。即可以向下遍历,或者向上遍历。

    NodeIterator:   

    document.createNodeIterator()
    //创建新实例

    接受4个参数.

    root:作为搜索起点的树中的节点。 

    whatToShow: 表示要访问那些节点的数字代码。

    filter:NodeFilter对象。一个表示应该接受还是拒绝某种特定节点的函数。

    每个NodeFilter对象只有一个方法,即accept-Node();如果应该访问给定节点返回NodeFilter.FILTER_ACCEPT,不应该访问返回NodeFilter.FILTER_SKIP;

    NodeFilter的俩个主要方法:

    nextNode() 下一个节点, previousNode(),上一个节点。

    例如一个展示《p》元素的节点迭代器

    var filter = {
       acceptNode: function(node) {
            // 如果形参的标签名等于p 就返回 NodeFilter.FILTER_ACCEPT,
            // 不然返回NodeFilter.FILTER.SKIP;
           return node.tagName.toLowerCase() == "p" ?
           NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER.SKIP;
       }
    };
    
    var iterator = document.createNodeIterator(root, Nodefilter.SHOW_ELEMENT, filter, false);

    遍历div元素中的所有元素

    var oDiv = document.getElementById("div1");
    var iterator = document.createNodeIterator(oDiv, NodeFilter.SHOW_ELEMENT, null, false);
    
    var node = iterator.nextNode();
    while(node !== null) {
       console.log(node.tagName);
       node = iterator.nextNode();
     }
    // DIV
    // P
    // B
    // UL
    // LI(3)

    如果只想返回遍历中遇到的li元素,只要使用一个过滤器

    var oDiv = document.getElementById("div1");
    var filter = function(node) {
       return node.tagName.toLowerCase() == "li" ? 
       NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
    // NodeFilter.FILTER_ACCEPT 和 NodeFilter.FILTER_SKIP都是跳过指定的节点 }
    var iterator = document.createNodeIterator(oDiv, NodeFilter.SHOW_ELEMENT, filter, false); var node = iterator.nextNode(); while(node !== null) { console.log(node.tagName); node = iterator.nextNode(); } //li(3)

    TreeWalker

    TreeWalker是NodeIterator的高级版本,提供了不同方向上的遍历DOM结构的方法

    parentNode():遍历到当前节点的父节点;

    firstChild(): 遍历到当前节点的第一个子节点。

    lastChild(): 遍历到当前节点的最后一个子节点。

    nextSiblings(): 遍历到当前节点的下一个同辈节点节点。

    previousSiblings(): 遍历到当前节点的上一个同辈节点。

    TreeWalker和NodeIterator一样接受4个参数, 作为遍历起点的根节点、要显示的节点类型、过滤器。一个表示是否扩展 实例引用的布尔值。

    var oDiv = document.getElementById("div1");
    var walker = document.createTreeWalker(oDiv,NodeFilter.SHOW_ELEMENT, filter, false);
    
    var filter = function (node) {
        return node.tagName.toLowerCase() == "li" ? 
         NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
         //  使用walker时NodeFilter.FILTER_REJECT跳过相应节点及该整个字树
     }
    
    var node = walker.nextNode();
    if( node !== null) {
       console.log(node.tagName);
       node = walker.nextNode();
    } 
    // LI

    使用TreeWalker遍历DOM树,即使不定义过滤器,也可以取得所有<li>元素。

    var oDiv = document.getElementById("div1");
    var walker = document.createTreeWalker(oDiv, NodeFilter.SHOW_ELEMENT, null, false);
    
    walker.firstChild();          //div的第一个子元素即,定位到<p>元素
    walker.nextSibling();     //p元素下一个同辈元素,即定位到<ul>元素
    
    var node = walker.firstChild(); //  转到uil的第一个子元素
    while(node !== null) {           .//  当 node不为空的时候,
      console.log(node.tagName);  //   弹出标签名
      node = walker.nextSibling(); //  保存walk的下一个同辈元素
    }

    范围

    为了方便控制页面,"DOM二级遍历和范围" 定义了“范围”接口。通过范围可以选择文档中的一个区域,而不比考虑节点的界限。

    var range = document.createRange();

    新创建的范围直接与创建它的文档关联,不能用于其他文档。创建范围之后,接下来就可以使用它再后台选择文档中的特定部分。设置位置之后,可以针对范围的内容进入很多操作。

    每个范围由一个range类型的实例表示

    startContainer: 包含范围起点的节点(选取中第一个节点的父节点)。

    startOffset: 范围在startContainer中的偏移量。

    endContainer: 包含范围终点的节点。

    endOffset: 包含范围在endContainer终点的偏移量=。

    commonAncestorContainer: startContainer和endContaine共同祖先节点再文档树中位置最深的那个。

    1用DOM范围实现简单选择

    用范围选择文档中的一部分。

    有俩种方法 selectNode() 或 selectNodeContents()。都接受一个参数,即DOM节点,然后使用这个DOM节点信息来填充范围。

    selectNode()选择整个节点,包括子节点。selectNodeContents()只选择节点的子节点。

    <body>
         <p id="p1"><b>Hello</b> world!</p>
    </body>

    可以使用下列的代码创建范围:

    var range1 = document.createRange();
    var range2 = document.createRange();
    
         p1 = document.getElementById("p1");
    
    range1.selectNode(p1);
    
    range2.selectNodeContents(p1);

    2、用DOM范围实现复杂选择

    使用setStart() ,setEnd()可以实现更复杂的范围选择接受一个参照节点和一个偏移量。

    setStart(): 参照节点变成startContainer,偏移量变成startOffset。

    setEnd():  参照节点endContainer, 偏移节点endOffset。

    <body>
         <p id="p1"><b>Hello</b> world!</p>
    </body>
    var p2 = document.getElementById("p1");
    helloNode = p1.firstChild.firstChild;
    worldNode = p1.lastChild;
    
    var range3 = document.createRange();
    //传入helloNode,并设置偏移量2 (也就是e的位置)
    range3.setStart(helloNode, 2);
    ////传入helloNode,并设置偏移量3  (也就是r的位置)
    range3.setEnd(worldNode, 3)

    3 操作DOM范围中的内容

    在创建范围时,内部会为这个范围创建一个文档片段,范围所属的全部节点都被添加到这个文档片段中。

    deleteContents(): 可以从文档中删除范围所包含的内容。

    extractContents(): 也可以从文档中移除范围内容,但是会返回文档片段。

    var text = document.getElementById("p2");
    var _this = text.firstChild.firstChild;
    var _is = text.lastChild;
    
    var range = document.createRange();
    range.setStart(_this, 2);
    range.setEnd(_is, 3);
    
    var fragment = range.extractContents();
    text.parentNode.appendChild(fragment);

    4、插入DOM范围中的内容

    insertNode(): 可以向范围选区开始处插入一个节点。

    <body>
       <span style="color: red">Inserted text</span>
    </body>
    var p1 = document.getElementById("p2");
    var hNode = p1.firstChild.firstChild;
    var wNode = p1.firstChild;
    
    var range = document.createRange();
    range.setStart(hNode, 2);
    range.setEnd(wNode, 3);
    var eSpan = document.createElement("span");
    eSpan.style.color = "red";
    eSpan.appendChild(document.createNodeText("Inserted text"));
    range.insertNode(eSpan);

    startContainer

  • 相关阅读:
    POJ 3279 Fliptile 枚举+搜索
    POJ 3278 Catch That Cow
    CS Academy Round41 BFS+DFS
    CS Academy Round41 Tennis Tournament
    CS Academy Round41 Cinema Seats
    POJ 1177 Picture
    HDU 1255 覆盖的面积
    POJ 1151 Atlantis 线段树+离散化
    HDU 4614 Vases and Flowers 线段树+二分
    凑数问题
  • 原文地址:https://www.cnblogs.com/zhangbaihua/p/5604555.html
Copyright © 2011-2022 走看看