码迷,mamicode.com
首页 > 其他好文 > 详细

第十三章 脚本化文档

时间:2015-03-04 00:58:11      阅读:129      评论:0      收藏:0      [点我收藏+]

标签:

客户端javascript存在使得静态的html文档编程了交互式的web应用。校本化web页面内容是javascript的核心目标。本章———本书最重要的章节之一,阐述了它是如何做到的客户端javascript的存在使得静态的html文档变成了交互式的web应用。校本化web页面javascript核心目标。本章将阐述它是如何做到的。

第11章和12章解释了每一个web浏览器窗口、标签也和框架由一个window对象所示。每个window对象有一个document对象,document对象表示窗口的内容,它就是本章的主题。尽管如此,Document对象并非独立的,它是一个巨大的API的核心对象,叫做文档对象模型(Document Object Model ,DOM),它代表和操作文档的内容

本章开始部分解释DOM的基本框架,然后进一步解释以下内容:

  • 如何在文档中查询或选取单独元素
  • 如何将文档作为节点树来遍历,如何找到文档元素的祖先、兄弟和后代元素
  • 如何查询和设置文档的元素的属性
  • 如何查询、设置和修改文档内容
  • 如何通过创建、插入和删除节点来修改文档结构
  • 如何与html表单一起工作

本章最后一节涵盖其它各种文档特性,包括referrer属性、write()方法和查询当前文档中选取的文档文本的技术等

1.DOM概览

文档对象模型(DOM)是表示和操作HTML和XML文档内容的基础API。API不是特别复杂,但是需要了解大量的构架细节。首先:应该理解HTML或XML文档的嵌套元素在DOM树对象中的表示。HTML文档树的结构包含表示HTML标签或元素(如body,<p>)和表示文本字符串的字节,它也可能包含HTML注释的节点。考虑一下简单的HTML文档:

            <html>
                <head>
                    <title>title name</title>
                </head>
                <body>
                    <h1>an html Document</h1>
                    <p>this is a <i>simple</i>docuent</p>
                </body>
            </html>    

此文档DOM,HTML文档的树状表示:

技术分享

 如果还未熟悉计算机编程中的树状结果,借用家谱图形容是比较有用的方法。在一个节点之上的直接节点是其父节点,在其下一层的直接节点是其子节点。在同一层上具有相同父节点的是兄弟及诶单。在一个节点之下的所有层级的一组节点是其后代节点。一个节点任何父节点和其上层的所有节点是祖先节点

上图的每个方框是文档的一个节点,它表示一个Node对象,我们将在后续几节中讨论Node的属性和方法, 并且可以在第四部分查到这些属性和方法。上图中包含三种类型不同的节点。树行的根部是Document节点,它代表整个文档代表HTML元素的节点是Element节点代表文本的节点是Text节点。Document、Element和Text是Node的子类,在第四部分中它们有自己的条目。Document和Element是两个重要的DOM类,本章大部分内容将删除它们的属性和方法。

下图展示了Node及其在类型层次结构中的子类型。注意,通用的Document和Element类型与HTMLDocument和HTMLElement类型之间有严格的区别。Document类型代表一个HTML或XML文档 ,Element类型代表了该文档中的一个元素。HTMLDocument和HTMLElement子类只是征对于HTML文档和元素。此书中,我们经常使用类名Document和Element,甚至在指代HTML文档时也不例外。在第四部分也是如此:HTMLDocument和HTMLElement类型 属性和方法记录于Document和Element参考页中

上文的每个方框是文档的一个节点,它表示一个Node对象,我们将在后续几节中讨论Node的属性和方法, 并且可以在第四部分查到这些属性和方法。上图中包含三种类型不同的节点。树行的根部是Document节点,它代表整个文档。 代表HTML元素的节点是Element节点,代表文本的节点是Text节点。Document、Element和Text是Node的子类,在第四部分中它们有自己的条目。Document和Element是两个重要的DOM类,本章大部分内容将删除它们的属性和方法。

下图展示了Node及其在类型层次结构中的子类型。注意,通用的Document和Element类型与HTMLDocument和HTMLElement类型之间有严格的区别。Document类型代表一个HTML或XML文档 ,Element类型代表了该文档中的一个元素。HTMLDocument和HTMLElement子类只是征对于HTML文档和元素。此书中,我们经常使用类名Document和Element,甚至在指代HTML文档时也不例外。在第四部分也是如此:HTMLDocument和HTMLElement类型 属性和方法记录于Document和Element参考页中。

文档节点的部分层次结构:

技术分享

值得注意的是,上图中HTMLElement的很多子类型代表HTML元素的具体类型。每个类型定义多个javascript属性,它们对应具体的元素或元素组,(本章4.i节)的HTML属性。有些具体元素也定义额外的属性和方法,它们并不是简单地映射HTML语法。第四部分涵盖这些类型及其额外的特性。

最后,上图还展示了到目前还未接触的一些节点类型,Conmment节点代表HTML或XML的注释。由于注释基本上是文本字符串,因此它们很像表示文档中显式文本的Text节点CharacterData通常是Text和Conmment的祖先,它定义这两种节点所共享的方法Attr节点类型代表XML或HTML属性,但它几乎从不使用,因为和文档节点不同,Element类型定义了将属性当做“名/值”对使用方法。DocumentFragment类(未在上图显式)在实际文档中并不存在的一种节点:它代表一系列没有常规父节点的节点,对一些文档操作来说DocumentFragment非常有用,本章6.iiii将涵盖这部分内容。DOM也定义了一些不常使用的类型,如像代表Doctype声明和xml处理指令等类型。

2.选取文档元素

大多数客户端javascript程序运行时总是在操作一个或多个文档元素,这些程序启动时,可以使用全局变量document来引用Document对象。但是,为了操作文档中的元素,必须通过某种方式来获得或选取这些文档元素的Element对象,DOM定义了很多方式来选取元素,查询文档的一个或多个元素有如下的方法:

  • 用指定的id属性
  • 用指定的name属性
  • 用指定的标签名字
  • 用指定的css类
  • 用匹配的css选择器

随后几节将解释每一种元素选取技术

i.通过id选取元素

任何HTML元素可以有一个id属性,在文档中值必须唯一,即同一个文档中两个元素不能有相同的ID。可以用Document对象的getElementById()方法选取一个基于唯一ID的元素,此方法我们在11章和12章都说明过了:

var section1 = document.getElementById("section1")

这就是最简单和常用的选取元素的方法。如果想要操作一组指定的文档元素,提供这些元素的id属性,并且使用ID查找这些Element对象。

如果需要通过ID查找多个元素,会发现下面的例子getElements()函数非常有用:

            /**
             * 函数接受任意多的字符串参数
             * 每个参数将当做元素的id传给document.getElementById()
             * 返回一个对象,它把这些id映射到对应的Element对象
             * 如任何一个id对应的元素未定义,则抛出一个Error对象
             **/
            function getElement( /*ID(s)*/ ) {
                var elements = {}; //开始是一个map映射对象
                for (var i = 0; arguments.length; i++) { //循环每个参数
                    var id = arguments[i]; //参数是元素的id
                    var elt = document.getElementById(id); //查找元素
                    if (elt == null)
                        throw new Error("No element with id: " + id); //抛出异常
                    elements[id] = elt; //id和元素之间的映射
                }
                return elements; //对于元素映射返回id
            }

在低于IE8版本的浏览器中,getElementById()对匹配元素不区分大小写,而且也返回匹配name属性的元素。

ii.通过name名字获取元素

HTML的name属性最初打算为表单元素分配名字,在表单数据提交到服务器时使用该属性的值。类似id属性,name是给元素分配的名字,但是区别id,name的属性值不是必须唯一:多个元素可能有同样的名字,在表单中,单选和复选按钮通常是这样的情况。而且和id不一样的是name属性值是在少数HTML元素中有效,包括表单、表单元素、<iframe>和<img>元素

基于name属性的值选取html元素,可以使用Document对象的getElementByName()方法。

            var radiobuttons = document.getElementsByName("favorite_color");

getElementsByName()定义在HTMLDocument类中,而不在Document类中,所有它只征对HTML文档可用,在xml文档中不可用。它返回一个NodeList对象,后者的行为类似若干Element对象的只读数组。在IE中,getElementByname()也返回id属性匹配中只读的元素。为了兼容,应该小心谨慎,不要将ID和name同名。

在12章7节中我们看到,为某些HTML元素设置name属性将自动为window对象中创建对于的属性,对Document对象也类似。为<form><img><iframe><applet><embed><object>元素(其中只有<object>元素没有后背对象)设置name属性值, 即在Document对象中创建以此name属性值为名字的属性。

如果给定的名字只有一个元素,自动创建的文档属性对于的值该是元素本身。如果有多个元素,该文档属性的值是一个NodeList对象,它表现为一个包含这些元素的数组。如12章7节所示,为若干命名<iframes>元素创建的文档属性比较特殊:它们指代这些框架的window对象而不是Element对象。这就意味这有些元素可以作为Document属性仅通过名字来选取:

                 //征对<form name="shipping">元素,得到Element对象
                var form = document.shipping;

在14章7节介绍了为什么不要用为窗口对象自动创建的属性,这同样适用用为文档对象自动创建的属性。如果需要查找命名的元素,最好显式地调用getElementByName()来查找它们。

iii.通过标签名选取元素

Document对象的getElementsByTagName()方法可用来选取指定类型(标签名)的所有HTML或XML元素。例如,如下代码,在文档中获得包含所有<span>元素的只读类数组对象。

                var spans = document.getElementsByTagName("span");

类似于getElementByName(),getElementByTagName()返回一个NodeList对象(关于NodeList类,见本节补充的信息)。在NodeList中返回的元素按照在文档中的顺序排序的,所有可用如下代码选取文档中的第一个p元素

                var firstspan = document.getElementsByTagName("span")[0];

<html>标签是不区分大小写的,在HTML文档中使用getElementsByTagName()时,它进行不区分大小写的标签名比较。例如,上述的变量span将包含所有写成<SPAN>的span标签。

给getElementByTagName()传递通配符参数"*"将获得一个代表文档中所愿元素的NodeList对象

Element定义getElementByTagName()方法,其原理和Document版本一样,但是它只选取调用该方法的元素的后代元素。因此,要查找文档的第一个<p>元素里所有<span>元素,代码如下:

            var firstpara = document.getElementsByTagName("p")[0];
            var firstParaSpan = firstpara.getElementsByTagName("span");

由于历史的原因,HTMLDocument类定义的一些快捷属性来访问各种各样的节点。例如images、forms和links等属性行为执行类似只读数组<img>、<from>和><a>(但只包含哪些有href属性的<a>标签)元素结合。这些属性指代HTMLCollection对象,它们很像NodeList对象,但是除此之外它们可以用元素的id或名字来索引,我们已经看到用法如下的表达式来索引一个命名的<form>元素:

document.shiping;

用document.forms属性也可以更具体地引用命名(或有ID)表单,如下:

document.forms.shipping

HTMLDocument对象还定义两个属性,它们指代包含特殊的单个元素而不是元素的集合。document.body是一个HTML文档的 <body>元素,document.head是<head>元素,浏览器隐式地创建它们。Document类的documentElement属性指代文档的根元素,在HTML文档中,它总指代<HTML>元素

节点列表和HTML集合

节点列表和HTML集合 getElementByName()和getElementByTagName()都返回NodeList对象,类似document.images和document.forms的属性为HTMLCollection对象 这些对象都是只读的类数组对象(7章11节),它们有length属性,也可以像正真的数组一样所有(只是读而不写),可以对一个NodeList或HTMLCollection的内容用如下标准的循环进行迭代:

            for (var i = 0; i < document.images.length; i++) //循环所有的图片
            document.images[i].style.display = "none";

不能直接在NodeList和HTML集合上调用Array的方法,但可以间接地使用:

var content Array.prototype.map.call(document.getElementsByTagName("p"),function(e){return e.innerHTML;});

HTMLCollection对象也有额外的命名属性,也可以通过数字和字符串来索引。

由于历史元素,NodeList和HTMLCollection对象也都能当做函数:以数字或字符串为参数调用它就如同使用数字或字符串索引它们一般,不鼓励这种怪异的方法。

NodeList和HTMLCollection对象也都能当做函数都不是为像javascript这样的动态语言设计的。它们都定义了item()方法,期望输入一个整数,并返回此处索引的元素。在javascript根本没有必要调用此方法,因为简单的使用数组索引就能替代。类似的,HtmlCollection定义了namedItem()方法,它返回指定属性名的值,但在javascript程序可以用数组索引或常规属性来访问。

NodeList和HTMLCollection对象不是历史文档状态的一个静态快照,而通常是事实的,并且当文档变化时它们所包含的元素能随之改变,这是其中一个重要和令人惊讶的特性。假设在一个没有<div>元素的文档中调用getElementByTagName("div"),此时返回值是一个length为0的NodeList对象。如果再在此文档中插入一个新的<div>,元素将自动成为NodeList的一个成员,并且它的length属性变成1。

通常,NodeList和HTMLCollection的实时性非常有用,如果要迭代一个NodeList对象时再文档中添加或删除元素,首先要对NodeList对象生成一个静态的副本:

        var snapshot = Array.prototype.slice.call(nodelist,0)

iiii.通过css类选取元素

HTML的class属性是用空格分开的有0个或者多个标识符的列表。class为我们描述了一种定义相关文档元素集的方法:只要元素有同样的class属性,它们就是同一个集合的一部分。class是javascript的保留词,因此客户端JavaScript使用className属性来获得HTML中class的属性。class属性通常和CSS样式表一同使用将同样的样式作用在一系列元素之上,我们将在16章继续了解它。另外,HTML5定义了一个方法,getElementsByClassName(),允许我们通过class属性的标识符选择一系列文档中的元素。

类似getElementsByTagName(),可以作用在HTML文档和HTML元素上调用getElementsByClassName() ,返回一个实时的NodeList对象,包含所有文档或元素节点中匹配的后代节点。getElementByClassName()只需要传入一个字符串参数,字符串参数可以使用空格隔开的标识符。只有当元素的class属性完全包含标识符的元素才会被匹配,但是标识符的顺序无关紧要。注意class属性和getElementsByClassName()方法都是用空格进行分隔,而不是逗号。下面是使用getElementsByClassName()的一些例子:

             // 找到所有class属性值为"warning"的元素
            var warnings = document.getElementsByClassName("warning");
             // 查找奕log命名且包含有"error"和"fatal"类的元素的所有后端
            var log = document.getElementById("log");
            var total = log.getElementsByClassName("error fatal");

如今的web浏览器会参照文档开头处声明的<!DOCTYPE>的严格程度,选择使用“怪异模式”或者“标准模式”来显示HTML文档。怪异模式存在是为了解决后向的兼容性问题,其中一个怪异模式是在class属性中和CSS样式表中的类标示符是大小写不敏感的。getElementsByClassName()使用和CSS样式表相同的匹配算法。当一个文档在怪异模式下运行时是大小写不敏感的,否则,大小写敏感。

处理IE8及其较低的版本,getElementByClassName()在所有当前浏览中都实现,IE8支持querySelectorAll()方法,下一节会介绍它。而getElementByClassName()方法则是在其之上实现的。

iiiii.通过css选择器选取元素

CSS样式有一种非常强大的语法,那就是选择器。它用来描述文档中的若干或多组元素。这里有一些最基本的例子来说明基本语法。元素可以用ID、标签名或类描述

            #nav //id="nav"的元素
            div //所有的<div>元素
            .warning //所有早class属性值包含了“waring”的元素

更一般地,元素可以给予属性值来选取

            p[lang = "fr"] //所有使用语法段落,如:<p lang="fr">
            * [name = "x"] //所有包含name = "x"属性的元素

这些基本的选择器可以组合使用:

            span.fatal.error //其class中 包含"fatal"和"error"的所有<span>元素
             span[lang = "fr"].warning //所有使用语法且class中包含"warning"的<span>元素

选择器可以指定文档结构:

        #log span //id="log"元素中所有的<span>元素
        #log>span //id="log"元素的子元素中的所有<span>元素
        body>h1:first-child //<body>的子元素中的第一个<h1>元素

选择器可以组合起来选取多个或多组元素

    div,#log //所有的元素,以及id="log"的元素

如你所见,css选择器可以让使用上述所有的方法选取元素:通过ID、名字、标签名和类名。与css3选择器的标准化一起的另一个称作“选择器API”的w3c标准定义了获取匹配一个给定选择器元素的javascript方法(选择器API标准不是HTML5的一部分,但与之有相关紧密联系,更多http://www.w3.org/TR/selectors-api/)该API的关键是Document方法querySelectorAll()。它接受包含一个css选择器的字符串参数,返回一个表示文档中匹配选择器的所有元素的NodeList对象。与前面选取的元素是不同的,querySelectorAll()返回的nodeList对象并不是实时的:它包含在调用时刻选择器所匹配的元素,但它并不更新后续文档的变化。如果没有匹配的元素,querySelectorAll()将返回一个空的NodeList对象。如果选择器字符串非法,querySelectorAll()将抛出一个异常。

除了querySelectorAll(),文档还定义了querySelector()方法。与querySelectorAll()工作原理相似,但它只返回一个匹配元素。如果没有匹配元素则返回null

css还定义了一些伪元素,":first-line"和"first-letter"等。在css中它们匹配的文本节点一部分不是实际元素。如果querySelectorAll()或querySelector()一起使用它们是不匹配的。而且很多浏览器会拒绝返回“:link”和":visited"等伪类匹配结果,因为这会泄露用户的浏览历史记录。

当期所有的浏览器都支持querySelectorAll()和querySelector()方法。但是注意,这些方法的规范并不要求支持css3浏览器:鼓励浏览器和在样式表中一样的选择器集合。当前的浏览器除IE都支持css3选择器,IE7和IE8支持css2选择器

querySelectorAll()是终级的选取元素的方法:它是一种强大的技术 ,通过让客户端javascript选择它们想要操作的元素甚至现在没有querySelectorAll()的元素支持的浏览器都可以使用css3选择器。jQuery库17章使用这种机遇css选择器的查找作为它的核心编程规范式。基于jQuery的web应用程序使用一个轻便的、跨浏览器的、和querySelectorAll()等效的方法,命名为$().

jQuery的css3选择器匹配代码以及作为一个独立的标准库并发布了,命名为Sizzle(http://sizzlejs.com/)。它已经被Dojo和其它一些客户端库所采纳.

iiiiii.document.all[]

在DOM标准化之前,IE4引入了document.all[]集合来表示所有文档中的元素(除了Text节点)。document.all[]已经成被标准的方法,现在已经废弃不使用了,但是引入它是革命性的,它在以各种方式使用的已有代码中仍然能看到

                     document.all[0] //文档中的第一个元素
                     document.all["nav"] //id或name为"nav"的元素(或多个元素)
                     document.all.nav //同上
                     document.all.tags("div") //文档中的所有div元素
                     document.all.tags("p")[0] //文档中的第一个<p>元素

3.文档结构和遍历

一旦从文档中选取了一个元素,有时需要查找文档中与之在结构上相关的部分(父亲、兄弟和子女)。文档从概念上可以看做是一颗节点对象树。节点类型定义了遍历该树所需的属性。我们将在下面的小节中介绍。另一个API允许文档作为元素的对象树来遍历,第二小节将介绍这个(通常也更容易使用的)API。

i.作为节点树的文档

Document对象、它的Element对象和文档中表示文本的Text对象都是Node对象。Node定义了以下重要属性

parentNode
该节点父节点(或者征对类似Document对象的应该是null,因为它没有父节点)
childNodes
只读数组的对象(NodeList对象),它是该节点的实时表示
firstChild、lastChild
该节点子节点的第一个和最后一个,如果该节点没有字节点则为null
nextSibling、previousSibling
该节点的兄弟节点的前一个和下一个。具有相同父节点的两个节点为兄弟节点。节点的顺序反映了它们在文档中出现的顺序。这两个属性将节点之间的以双向链表的形式连接起来。
nodeType
该节点的类型,9代表Document节点,1代表Element节点,3代表Text节点,8代表Comment节点,11代表DocumentFragment节点

nodeValue
Text节点或Comment节点的文本内容
nodeName
元素的标签名,以大写形式表示

使用这些Node属性,可以用下面类似的表达式得到文档的第一个节点下面的第二个子节点的引用

            document.childNodes[0].childNodes[1];
            document.firstChild.firstChild.nextSibling;

假如上述的代码如下:

        <html>
            <head>
            <title>test</title>
            </head>
            <body>
                hello world!
            </body>
        </html>

那么第一个字节点下的第二个元素就是BODY,它的nodeType为1,nodeName为BODY

但请注意,该API对文档文本的变化极其敏感。例如,如果修改了文档,在<html>和<head>标签插入一个新,那么表示该新航的Text节点就是文档的第一个子节点下面的第一个子节点,并且<head>元素就是第二个,子节点不是body元素了。

ii.作为元素树的文档

当将主要的兴趣点集中在文档中的元素上而并非它们之间的文本(和它们之间的空白),我们可以使用另外一个更有用的API.它将文档看做是Element对象树,忽略部分文档:Text和Comment节点。

该API的第一部分是Element对象的children属性。类似ChildNodes,它是一个NodeList对象,但不同是的children列表只包含Element对象。Children非标准属性,但是在所有当前浏览器里都能工作。IE也实现好一段时间了,大多数浏览器也如法炮制,最后采纳的是Firefox3.5。

注意:Text和Comment节点没有children属性,它意味着上述Node.parentNode属性不可能返回Text或Comment节点。任何Element的parentNode总是令一个Element,或者追溯到树根的Document或DocumentFragment节点

基于元素的文档遍历API的第二部分是Element属性,后者类似Node对象的子属性和兄弟属性:

firstElementChild,lastElementChild
类似firstChild和lastChild,但只代表Element

nextElementSibling,previousElementSibing
类似nextSibing和previousSibling,但只代表兄弟Element

childElementCount
子元素的数量。返回的值和chilren.length值相等

子元素和兄弟元素的属性是标准属性,并在除IE之外的浏览器已经实现http://www.w3.org/TR/ElementTraversal/

由于逐个元素的文档遍历的API并未完全标准化,我们任然可以通过像下面的例子可移植的遍历函数那样实现这种功能:

             /*****可移植的遍历函数******/
            
            /**
             * 返回元素e的第n层祖先元素,如果不存在此类祖先或祖先不是Element,例如(Document或者DocumentFragment)则返回null
             * 如果n为0,则返回e本身,如果n为1(或省略),则返回父元素。如果n为2,则返回祖父元素,依次类推
             **/
            function parent(e, n) {
                    if (n === undefined) n = 1;
                    while (n-- && e) e = e.parentNode;
                    if (!e || e.nodeType !== 1) return null;
                    return e;
                }
            
            
                /**
                 *返回元素e的第n个兄弟元素,如果n为正,返回后续的第n个兄弟元素;
                 * 如果n为负,返回前面n个兄弟元素,如果n为零,返回e本身
                 **/
            function sibling(e, n) {
                    while (e && n !== 0) { //如果e未定义,立刻返回它
                        if (n > 0) { //查找后续的兄弟元素
                            if (e.nextElementSibling) e = e.nextElementSibling;
                            else {
                                for (e = e.nextSibling; e && e.nodeType !== 1; e = e.nextSibling)
                                /*空循环*/
                                ;
                            }
                            n--;
                        } else { //查找前边的兄弟元素
                            if (e.previousElementSibling) e = e.previousElementSibling;
                            else {
                                for (e = e.previousElementSibling; e && e.nodeType !== 1; e = e.previousElementSibling)
                                /*空循环*/
                                ;
                            }
                            n++
                        }
                    }
                    return e;
                }
            
            
                /**
                 * 返回元素e的第n代子元素,如果不存在则为null
                 * 负值n代表从后往前计数,0表示第一个子元素,而-1代表最后一个,-2代表倒数第二,依次类推
                 **/
            function child(e, n) {
                if (e.children) { //如果children数组存在
                    if (n < 0) n += e.children.length; //转换负的n为数组索引
                    if (n < 0) return null; //如果它仍为负,说明没有子元素
                    return e.children[n]; //返回值指定的子元素
                }
                //如果e没有children数组,找到第一个字元素并向前数,或找到最后一个子元素并往回鼠
                if (n >= 0) { //非负,从第一个元素向前数
                    //找到e的第一个子元素
                    if (e.firstElementChild) e = e.firstElementChild;
                    else {
                        for (e = e.firstElementChild; e && e.nodeType !== 1; e = e.nextSibling)
                        /*空循环*/
                        ;
                    }
                    return sibling(e, n); //返回第一个子元素的第n个兄弟严肃
                } else { //n为负数,从第一个元素往回数
                    if (e.lastElementChild) e = e.lastElementChild;
                    else {
                        for (e.lastElementChild; e && e.nodeType !== 1; e = e.previousElementSibling)
                        /*空循环*/
                        ;
                    }
                    return sibling(e, n + 1); //+1来转化最后1个子元素的最后1个兄弟元素
                }
            }

自定义Element的方法

所有当前浏览器,都实现了DOM,故类似Element和HTMLDocument(IE8支持Element、HTMLDocument和Text的可扩展属性,但不支持Node,Document、HTMLDocument或HTMLElement更具体的子类型的可扩展属性)等类型都是想String和Array都是类。它们不是构造函数(将在本章后面看到如何创建新的Element对象),但它们有原型,可以用自定义方法扩展它

            Element.prototype.next = function() {
                if (this.nextElementSibling) return this.nextElementSibling;
                var sib = this.nextSibling;
                while (sib && sib.nodeType !== 1) sib = sib.nextSibling;
                return sib;
            };

上文中的可移植的遍历函数兵没有定义为Element方法是因为这种技术在IE7中不支持

尽管如此,如果希望将IE专有的特性在除了IE之外的其它浏览器中得以实现,这种扩展DOM类型的能力是非常有用的。从上面注意到Element非标准children属性由IE首先引入,并已经被其它浏览器所采纳。类似Firefox3.0不支持它的浏览器可以用下面的代码模拟此属性

             //在不包含此属性的IE浏览器模拟Element.children属性
             //注意:返回值为静态数组,而不是时实的NodeList对象
            if (!document.documentElement.children) {
                Element.prototype.__defineGetter__("children", function() {
                    var kids = [];
                    for (var c = this.firstChild; c != null; c = c.nextSibling)
                        if (c.nodeType === 1) kids.push(c);
                    return kids;
                });
            }

__defineGetter__方法,(6章7节i有介绍)完全是非标准的,但它用来一直类似代码非常完美。

本章未完结,欢迎大家关注更新,可以浏览学习前一节内容 第十二章:window对象

将更新内容:

4.属性

5.元素的内容

6.创建、插入、和删除节点

7.例子:生成目录表

8.文档和元素的几何形状和滚动

9.HTML表单

10.其它文档特性

第十三章 脚本化文档

标签:

原文地址:http://www.cnblogs.com/ahthw/p/4309343.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!