Javascript学习8 - 脚本化文档(Document对象)

时间:2023-03-08 17:42:16
Javascript学习8 - 脚本化文档(Document对象)

原文:Javascript学习8 - 脚本化文档(Document对象)

每个Web浏览器窗口(或帧)显示一个HTML文档,表示这个窗口的Window对象有一个document属性,它引用了一个Document对象。
    一个文档对象模型或者说DOM就是一个API,它定义了如何访问组成一个文档的对象。W3C定义了一个标准的DOM,使用Document API,可以作用于HTML和XML文档的通用功能,添加特定于HTML的属性和方法。
    Document对象的详细属性可以见:http://www.w3school.com.cn/htmldom/dom_obj_document.asp

    8.1 Document属性
        cookie      : 允许Javascript程序读写HTTP cookie.
        lastModfied : 一个字符串,包含文档修改日期
        location    : 等价于URL,已经废弃。
        referrer    : 文档URL,包含把浏览器带到当前文档的链接。
        title       : 文档标记<title>之间的文本。
        URL         : 一个字符串,声明装载文档的URL。
    8.2 文档对象集合 【遗留DOM】
        anchors[]   : 文档中所有的锚
        applets[]   : 代表文档中的Java applet
        forms[]     : 代表文档中的form元素。
        images[]    : 所有<img>元素的集合
        links[]     : 所有超链接Link对象
        以上这些称之为遗留DOM集合,它们可以脚本化,但是,它们不能改变文档的结构。可以查看并修改链接的目标地址,从表单元素读取和写入值,但是,无法改变文档相互的结构。
    8.3 命名document对象
        一般来说,可以使用基于数字来索引文档对象集合元素,但是,基于位置索引不稳定,小的文档改变顺序可以破坏代码。
        所以,可以为文档元素分配名字,通过名字来引用这些元素。
        例如,以下form元素的访问:
            <form name="f1">....</form>
        可以这样访问:
            document.forms[0]  
        也可以这样:
            document.forms.f1 或者 document.forms["f1"]
       有以下表单
            <form name="shipping">  <input type="text" name="zipcode"> </form>
        可以做以访问:

document.forms[].elements[]document.shipping.zipcode

8.4 Document对象上的事件句柄
        在HTML中,把函数赋予一个事件句柄属性来定义它们,以下的HTML代码加下事件句柄:
            <form name="myform" onsubmit="return validateform();">...</form>
        除了在onsubmit中加入javascript函数外,也可以在JS中直接把函数赋予事件句柄属性
          

document.myform.onsubmit = validateform;   //注意,不是调用函数,不需要()

8.5 W3C DOM 节点
        W3C DOM 取代了遗留DOM,强大而标准化,在介绍DOM之前,有一些预备知识:
        ①需要把文档表示为树
            HTML文档在DOM中表示为对象的一棵树,树中有各种各样的节点,节点之上的节点是父节点(parent),直接位于一个节点下层的节点是子节点(children).位于同一层次的节点是兄弟节点(sibling).一个节点的下一个层次节点的集合是那个节点的扣代(descentdant).一个节点的父节点、祖父节点及其它所有位于其它的节点集合是那个节点的祖先(ancestor)
        ②节点Node
            一个节点表示为一个Node接口,Node接口定义了遍历和操作树的属性和方法。
            Node.childNodes 返回节点的孩子集合
            Node.firstChild,lastChild,nextSibling,previousSibling,parentNode 属性提供了遍历节点的树的一种方法
            Node.appendChild(), removeChild(),replaceChild(),insertBefore() 这些方法能够向一个文档树中添加节点或者移动节点。
        ③节点的类型
            每个Node对象都有一个nodeType属性,它指定了节点是什么类型。
            常见节点类型:
            Element             Node.ELEMENT_NODE               1
            Text                Node.TEXT_NODE                  3
            Document            Node.DOCUMENT_NODE              9
            Comment             Node.COMMENT_NODE               8
            DocumentFragment    Node.DOCUMENT_FRAGMENT_NODE     11
            Attr                Node.ATTRIBUTE_NODE             2
           DOM树部的Node是一个Document对象,这个对象的documentElemtn属性引用一个Element对象,它代表了文档的根元素。对于HTML文档,这是<html>标记。
            在一个DOM树中只有一个Document对象,DOM树的大部分节点是表示标记的Element对象和表示文本串的Text对象。
            DOM API的部门类分层图见15-2
        ④属性
            用Element接口的getAttribute()方法、SetAttribute()方法和RemoveAttribute()方法可以获得、增加、删除一个元素的属性(如img的src属性和width属性)

      8.6 DOM HTML API
            HTMLDocument是HTML专有的Document接口的子接子。HTMLElement是HTML专有的Element接口的子接口。另外,DOM为许多HTML元素定义了标记专有的接口,如HTMLBodyElement、HTMLTitleElement、HTMLInputElement...这些标记专有的接口通常定义了HTML标记属性的属性集合。
            ● HTMLDocument接口定义了支持各种文档的属性和方法,包括location、forms[]数组、write()方法
            ● HTMLElement接口定义了id,style,title,lang,dir和className属性。
            ● 其它的专有的HTML..相关接口也定义了专有的属性和方法,如HTMLInputElement定义了focus(),blur()...
            一个访问DOM接口的例子:
           

var n = document.documentElement;  // This is a Node object.var children = n.childNodes;       // This is a NodeList object.var head = children.item();       // Here is one way to use a NodeList.var body = children[];            // But this way is easier!

另一个需要了解的是:DOM标准定义了接口,而不是类,所以它没有定义任何构造函数方法。如果想创建一个Text对象,把它插入文档,不能用如下代码:
            var t = new Text("this is a new text node");  // No such constructor
            取而代之的是,DOM在Document接口中定义了大量有用的工厂方法(factory method).因此,要为文档创建一个Text节点,可以使用以下代码:
            var t = document.createTextNode("this is a new text node");

    8.7 遍历文档
        DOM把一个HTML文档表示为Node对象的树,对于任何一个树形结构来说,最常用的事就是遍历树。
        →依次检查树的每个节点。如以下代码所示:

 1function countTags(n) {                         // n is a Node 2    var numtags = ;                            // Initialize the tag counter 3    if (n.nodeType ==  /**//*Node.ELEMENT_NODE*/)  // Check if n is an Element 4         numtags++;                              // Increment the counter if so 5    var children = n.childNodes;                // Now get all children of n 6    for(var i=; i < children.length; i++) {    // Loop through the children 7         numtags += countTags(children[i]);      // Recurse on each one 8    } 9    return numtags;                             // Return the total}

除了childNodes属性,Node接口还定义了其它几个有用的属性,包括firstChild,lastChild,nextSibling,previousSibling.
        →获得DOM节点下所有的文本:
 

 1       function getText(n) { 2            // Repeated string concatenation can be inefficient, so we collect 3            // the value of all text nodes into an array, and then concatenate 4            // the elements of that array all at once. 5            var strings = []; 6            getStrings(n, strings); 7            return strings.join(""); 8 9            // This recursive function finds all text nodes and appends            // their text to an array.            function getStrings(n, strings) {                if (n.nodeType ==  /**//* Node.TEXT_NODE */)                    strings.push(n.data);                else if (n.nodeType ==  /**//* Node.ELEMENT_NODE */) {                    // Note iteration with firstChild/nextSibling                    for(var m = n.firstChild; m != null; m = m.nextSibling) {                        getStrings(m, strings);                    }                }            }        }

8.8 在文档中查找元素
        ● getElementsByTagName()方法
            调用getElementsByTagName(param)方法,返回一个数组,该数组元素是文档中所有param元素。
            例如:
            var tables = document.getElementsByTagName("table");
            alert("This document contains " + tables.length + " tables");  // 文档中定义了多少个Table
            如果把特殊字符"*"传递给getElementsByTagName,它将返回文档中所有元素的列表。

            有时不想操作元素列表,而想操作文档中一个特定元素,如果对文档中结构有充分的了解,仍可以使用getElementsByTagName方法:
            var myParagraph = document.getElementsByTagName("p")[3];
            但这并不是最好的方法。最好的办法是使用getElementsById()方法、
        ● getElementById()方法
            getElementById方法不像getElementsByTagName返回一个数组列表,因为每个id属性值唯一,所以getElementById方法只返回一个元素。
            getElementById是一个很重要的方法,非常常见。
            以下通过getElementById方法获得表格中某个Cell的值。
           

var tableOfContents = document.getElementById("TOC");var rows = tableOfContents.getElementsByTagName("tr");var numrows = rows.length;

● getElementsByName()方法
            与getElementById方法相似,它查询元素的name属性,而不是id属性。另外,一个文档中的name属性可能不唯一,所以getElementsByName方法返回的是元素的数组,而不是一个元素。
           

var link = document.getElementsByName("top")[];// Find all <input type="radio" name="shippingMethod"> elementsvar choices = document.getElementsByName("shippingMethod");

8.9 修改文档内容
        DOM API的真正威力在于用Javascript动态修改文档的特性。
        →对元素的一个列表按字母排序
    

 1<script> 2function sortkids(e) { 3     // This is the element whose children we are going to sort 4     if (typeof e == "string") e = document.getElementById(e); 5 6     // Transfer the element (but not text node) children of e to a real array 7     var kids = []; 8     for(var x = e.firstChild; x != null; x = x.nextSibling) 9         if (x.nodeType ==  /**//* Node.ELEMENT_NODE */) kids.push(x);     // Now sort the array based on the text content of each kid.     // Assume that each kid has only a single child and it is a Text node     kids.sort(function(n, m) { // This is the comparator function for sorting                   var s = n.firstChild.data; // text of node n                   var t = m.firstChild.data; // text of node m                   if (s < t) return -;      // n comes before m                   else if (s > t) return ;  // n comes after m                   else return ;             // n and m are equal               });     for(var i = ; i < kids.length; i++) e.appendChild(kids[i]);}</script><ul id="list"> <!-- This is the list we'll sort --><li>one<li>two<li>three<li>four <!-- items are not in alphabetical order --></ul><!-- this is the button that sorts the list --><button onclick="sortkids('list')">Sort list</button>

→把文档内容转换为大小写

 1function upcase(n) { 2    if (n.nodeType ==  /**//*Node.TEXT_NODE*/) { 3        // If the node is a Text node, change its text to uppercase. 4        n.data = n.data.toUpperCase(); 5    } 6    else { 7        // If the node is not a Text node, loop through its children 8        // and recursively call this function on each child. 9        var kids = n.childNodes;        for(var i = ; i < kids.length; i++) upcase(kids[i]);    }}

→把一个节点的父节点重定为<b>元素

 1<script> 2function embolden(n) { 3    if (typeof n == "string") n = document.getElementById(n); // Lookup node 4    var b = document.createElement("b"); // Create a new <b> element 5    var parent = n.parentNode;           // Get the parent of the node 6    parent.replaceChild(b, n);           // Replace the node with the <b> tag 7    b.appendChild(n);                    // Make the node a child of the <b> element 8} 9</script><!-- A couple of sample paragraphs --><p id="p1">This <i>is</i> paragraph #1.</p><p id="p2">This <i>is</i> paragraph #2.</p><!-- A button that invokes the embolden() function on the element named p1 --><button onclick="embolden('p1');">Embolden</button>

8.10 修改节点属性
        可以调用element.setAttribute()方法来设置一个节点的属性,如:
       

var headline = document.getElementById("headline");  // Find named elementheadline.setAttribute("align", "center");            // Set align='center'//或者:headline.align = "center";  // Set alignment attribute.

8.11 Document段
        DocumentFragment是一种特殊类型的节点,它自身不出现在文档中,只作为连续节点集合的临时容器,并允许将这些节点作为一个对象来操作。
        把一个DocumentFragment插入文档时,插入的不是DocumentFragment本身,而是它所持有的子节点。
       

function reverse(n) {     // Create an empty DocumentFragment as a temporary container     var f = document.createDocumentFragment();     while(n.lastChild) f.appendChild(n.lastChild);     // Finally, move the children of f all at once back to n, all at once.     n.appendChild(f);}

8.12 给文档添加内容
        Document.createElement()方法和Document.createTextNode()方法创建新的Element节点和Text节点。
        而方法Node.appendChild()、Node.insertBefore()和Node.replaceChild()可以用来将它们添加到一个文档。

    8.13 innerHTML属性
        该属性可以用来获得和设置结点中HTML文本。例如:
       

var table = document.createElement("table");  // Create the <table> elementtable.border = ;                             // Set an attribute// Add a Name|Type|Value header to the tabletable.innerHTML = "<tr><th>Name</th><th>Type</th><th>Value</th></tr>";