每个Window对象有一个document属性引用了Document对象。Document对象表示窗口的内容。它并非独立的,它是一个巨大的API中的核心对象,叫做文档对象模式DOM,它代表和操作文档的内容。
文档对象模式DOM是表示和操作HTML和XML文档内容的基础API.HTML文档的树状结构包含表示HTML标签或元素(如《body》<p>)和表示文本字符串的节点,它也可能包含表示HTML注释的节点
每个方框是文档的一个节点,它表示一个Node对象。我们将在后续几节中讨论node的属性和方法,它包含3种不同类型的节点,树形的根部是Document节点,它代表整个文档。代表html元素的节点是Element节点,代表文本的节点是Text节点。Document、Element和Text是Node的子类
注意,通用的Document和Element类型与HTMLDocment和HTMLElement类型之间是有严格的区别的。Docment类型代表一个HTML或XML文档,Element类型代表该文档中的一个元素。HTMLDocument和HTMLElement子类只是针对HTML文档和元素。
为了操作文档中的元素,必须通过某种方式获得或选取这些引用文档元素的Element对象。DOM定义许多方式来选取元素。查询文档的一个或个多个元素有如下方法:
用指定的id属性
用指定的name属性
用指定的标签名字
用指定的CSS
匹配指定的CSS选择器
多个元素可能有同样的名字,在表单中,单选和复选按钮通常是这种情况,而且,和id不一样的是name属性只在少数html元素中有效,包括表单,表单元素、《iframe》和《img》元素
geiElementByName定义在HTMLDocument类中,而不在Document类中,所以它只针对HTML文档可用,在XML文档中不可用,它返回一个NodeList对象,后者的行为类似一个包含若干Element对象的只读数组。在IE中,getElementByName也返回id属性匹配指定值的元素。为了兼容,应该小心谨慎,不要将同样的字符串同时用作名字和ID。
为某些HTML元素设置name属性将自动为Window对象中创建对应的属性,对Document对象也类似。为form、img iframe applet embed object设置name属性值,即在Document对象中创建以此name属性值为名字的属性(当然假设文档还没有该名字的属性),如果给定的名字只有一个元素,自动创建的文档属性对应的该值是元素本身。如果有多个元素,该文档属性的值是一个NodeList对象,它表现为一个包含这些元素的数组。为若干命名为《iframe》元素所创建的文档属性比较特殊:它们指代这些框架的Window对象而不是Element对象
这就意味着有些元素可以作为D哦促门徒属性仅通过名字来选取
<form name="shipping_address" >元素,得到Element对象
var form=document.shipping_address,
所以不要用为窗口对象自动创建的属性,这同样适用于为文档对象自动创建的属性。如果需要查找命名的元素,最好显示的调用getElemengtsByName来查找它们
类似于getElementsByName,getElementsByTagName()返回一个NodeList对象。在NodeList中返回的元素按照在文档中的顺序排序的
var firstpara=document.getElementsByTagName("p")[0];
HTML标签是不区分大小写的,给getElementsByTagName传递通配参数“*”将获得一个代表文档中所有元素的NodeList对象
Element类也定义getElementsByTagName方法,其原理和Document版本一样,但是它只选取该方法的元素的后代元素
由于历史的原因,HTMLDocument类定义一些快捷属性来访问各种各样的节点。例如images forms和links等属性指向行为类似只读数组的<img>,<form> <a>(但只包含那些与href属性的<a>标签)元素集合。这些属性指代HTMLCollection对象,它们很像NodeList对象,但是除此之外它们可以用元素的ID或者名字来索引。早些时候,我们已经看到用如下的表达式来引用一个命名的<form>元素:
document.shipping_address
用document.forms属性也可以更具体的引用命名(或有ID的)表单,如下:
document.forms.shipping_address
HTMLDoument也定义embeds和plugins属性,它们是同义词,都是HTMLCollection类型的</embed>元素的集合。anchors是非标准属性,它指代有一个name属性的<a>元素而不是一个href属性
HTMLDocument对象还定义两个属性,它们指代特殊的单个元素而不是元素的集合。
document.body是一个html文档的《body》元素,document.head是《head》元素。这些属性总是会定义:如果文档源代码未显示的包含《head》和《body》元素,浏览器将隐式地创建它们。Document类的documentElement属性指代文档的根元素。在HTML文档中,它总是指代《html》元素
getElementsByName和getElementsByTagName都返回NodeList对象,而类似document.images和document.forms的属性为HTMLCollection对象
这些对象都是只读的类数组对象,它们有length属性,也可以像真正的数组一样索引(只是读而不写)
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对象时在文档中添加或者删除的元素,首先会需要对NodeList对象生成一个静态的副本
var snapshot=Array.prototype.slice.call(nodelist,0);
类似getElementsByTagName,在HTML文档和HTML元素上都可以调用getElementsByClassName,它的返回值是一个实时的NodeList对象,包含文档或元素所有匹配的后代节点。它只需要一个字符串参数,但是该字符串可以由多个空格隔开的标识符组成。只有当元素的class属性值包含所有指定的标识符时才匹配,但是标识符的顺序是无关紧要的
除了IE8及其比较低的版本,getElementsByClassName在所有当前的浏览器中都实现了,IE8确实支持querySelectorAll()方法,可以在其上实现的
Document方法querySelectorAll。它接受包含一个css选择器的字符串参数,返回一个表示文档中匹配选择器的所有元素的NodeList对象。与前面描述的选取元素的方法不同,它返回的NodeList对象并不是实时的:它包含在调用时刻选择器所匹配的元素,但它并不更新后续文档的变化。如果没有匹配的元素,querySlectorAll将返回一个空的NodeList对象,如果选择器字符串非法,querySelectorAll将抛出一个异常
querySelector只是返回第一匹配的元素(以文档顺序)或者如果没有匹配的元素就返回null
这两个方法在Element节点中也有定义(并且也在DocumentFragme节点中)。在元素上调用时,指定的选择器仍然在整个文档中进行匹配,然后过滤出结果集以便它只包含指定元素的后代元素。这看起来是违反常规的,因为它意味着选择器字符串包含元素的祖先而不仅仅是上述所匹配的元素
所有当前的浏览器都支持querySelectorAll和querySelctor方法,但是注意,这些方法的规范并不要求支持css3选择器:鼓励浏览器支持和在样式表中一样的选择器集合,当前的浏览器除了ie都支持css3选择器。ie7和8都支持css2选择器
querySlectorAll是终极的选取元素的方法。通过 它客户端javascript程序能够选择它们想要操作的元素,jquery库使用这种基于css选择器的查询作为它的核心编程方式,基于jquery的web应用程序使用一个轻便的,跨浏览器的、和querySelectorAll等效的方法,命名为$().
Document对象,它的Element对象和文档中表示文本的Text对象都是Node对象。
它们有以下重要的属性:
parentNode
该节点的父节点,或者针对类似Document对象应该是null,因为它没有父节点
childNodes
只读的类数组对象(NodeList对象),它是该节点的字节点的实时表示。
firstChild、lastChild
该节点的字节点中的第一个和最后一个,如果该节点没有子节点则为null
nextSibling previoursSibling
该节点的兄弟节点中的前一个和下一个。具有相同父节点的两个节点为兄弟节点
nodeType
该节点的类型。9代表Document节点、1代表Element节点,3代表Text节点,8代表comment节点,11代表DocumentFragment节点
nodeValue
Text节点或comment节点的文本内容
nodeName
元素的标签名,以大写形式表示。
注意该API对文档文本的变化及其敏感
作为元素树的文档
当将主要的兴趣点集中在文档中的元素上而不是它们之间的文本(和它们之间的空白)上时,我们可以使用另外一个更有用的API.它将文档看做是Element对象树,忽略部分文本“Text”和Comment节点。
Element对象的children属性,类似childNodes,它也是一个NodeList对象,但是不同的是chlidren列表只包含Element对象。children并非标准属性,但是它在所有当前的浏览器中都能工作
注意,Text和comment节点没有children属性,它意味着上述node.parentNode属性不可能返回Text或Comment节点。任何Element的parentNode总是另一个Element,或者追溯到树根的Document或DocumentFragment节点
firstElementChild和lastElementChild
类似firstChild和lastChild,但只代表子Element
nestElementSibling,previousElementSibling
类似nextSibling和previousSibling,但只代表兄弟Element
childElementCount
子元素的数量。返回的值和children.length值相等。
子元素和兄弟元素的属性是标准属性,并在除了IE之外的浏览器中都已实现。
属性
HTML元素由一个标签和一组称为属性的名/值对组成,html元素的属性值在代表这些元素的HTMLElement对象的属性中是可用的,DOM还定义了另外的API来获取或设置XML属性值和非标准的HTML属性。
表示HTML文档元素的HTMLElement对象定义了读写属性,它们映射了元素的HTML属性。HTMLElement定义了通用的HTTP属性(id,标题lang和dir)的属性,以及事件处理程序属性(如onclick)。特定的Element子类型为其元素定义了特定的属性。例如,查询一张图片的url,可以使用表示《img》元素的HTMLElement对象的src属性
var image=document.getElementById(“myimage”);
var imgurl=image.src;
img.id==="myimage";
同样的,可以为一个form元素设置表单提交的属性
var f=document.forms[0];
f.action="http://www.example.com/submit.php";
f.method="post";
HTML属性名不区分大小写,但javascript属性名则大小写敏感。从HTML属性名转换到javascript属性名应该采用小写。但是,如果属性名包含不止一个单词,则将除了第一个单词以外的单词的首字母大写,例如:defaultChenked和tabIndex。
有些HTML属性名在JavaScipt中是保留字,对于这些属性,一般的规则是为属性名加前缀html,例如HTML的for属性(label元素)在javascipt中变为htmlForm属性,class在javascript中是保留字,它是html非常重要的class属性,是上面规则的一个例外:在javaScript代码中它变为className
表示HTML属性的值通常是字符串。当属性为布尔值或数值(例如,input元素的defaultChecked和maxLength属性),属性也是布尔值或数值,而不是字符串,时间处理程序属性值总是Function对象(或null)。html5规范定义了一个新的属性(如input和相关元素的form属性)用以将元素ID转换为实际的E了门厅对象,最后,任何HTML元素的style属性值是CSSStyleDeclaration对象,而不是字符串
HTMLElement和其子类型定义了一些属性,它们对应于元素的标准HTML属性。Element类型还定义了getAttribute()和setAttribute方法来查询和设置非标准的HTML属性,也可用来查询和设置XML文档中元素上的属性。
这两个方法和前面的基于属性的api之间两个重要的区别。首先,属性值都被看做是字符串,getAttribute不返回数值,布尔值或对象。其次,方法使用标准属性名,甚至当这些名词为javascript保留字时也不例外。对HTML元素来说,属性名不区分大小写
element类型还定义了两个相关的方法,hasAttribute和removeAttribute,它们用来检测命名属性是否存在和完全删除属性。
当属性为布尔值时这些方法特别有用:有些属性(如html的表单元素的disabled属性)在一个元素中是否存在是重点关键,而其值却无关紧要
数据集属性
在html5文档中,任意以“data-”为前缀的小写的属性名字都是合法的。这些数据集属性将不会对其元素的表现产生影响,它们定义了一种标准的,附加额外数据的方法,并不是在文档合法性上做出让步。
html5还在element对象上定义了dataset属性。该属性指代一个对象,它的各个属性对应于去掉前缀的data-属性。因此dataset.x应该保存data-x的值。代连字符的属性对应于驼峰命名法属性名:data-jquery-test属性就变成了dataset.jqueryTest属性,
注意,dataset属性是(或将是,当实现以后)元素的data-属性的实时、双向接口。设置或删除dataset的一个属性就等于设置或移除对应元素的data-属性。
作为attr节点的属性
还有一种使用Element的属性的方法。Node类型定义了attributes属性。针对非Element对象的任何节点,该属性为null。对于Element对象,attributes属性是只读的类数组对象,它代表元素的所有属性。类似NodeLists,attributes对象也是实时的,它可以用数字索引访问,这意味这可以枚举元素的所有属性。并且,它也可以用属性名索引
document.body.attributes[0]
document.body.attributes.bgcolor
document.body.attributes["ONLOAD"]
当索引attributes对象时得到的值是Attr对象,attr对象一类特殊的Node,但从来不会像Node一样去用。Attr的name和value属性返回该属性的名字和值
作为HTML的元素内容
读取element的innerHTML属性作为字符串标记返回那个元素的内容,在元素上设置该属性调用了web浏览器的解析器,用新字符串内容的解析展现形式替换元素当前内容
web浏览器很擅长解析HTML,同时设置innerHTML效率非常高,甚至在指定的值需要解析时效率也是相当不错,但注意,对innerHTML属性用“+=”操作符重复追加一小段文本通常效率低下,因为它既要序列化又要解析
html5还标准化了outerHTML属性。当查询outerHTML时,返回的HTML或XML标记的字符串包含被查询元素的开头和结尾标签。当设置元素的outerHTML时,元素本身被新的内容所替换,只有element节点定义了outerHTML属性,Document节点无
outerHTML在出了firefox的所有当前浏览器中都支持。
ie引入的另一个特性是inertAdjacentHTML方法,它将在html5中标准化,它将任意的后头抹了标记字符串插入到指定的元素相邻的位置。标记是该方法的第二个参数,并且相邻的精确含义依赖第一个参数的值。第一个参数为具有以下值之一的字符串:
beforebegin,afterbegin、beforeend,afterend,insertAdjacentHTML在当前版本的firefox中不支持
作为纯文本的元素内容
有时需要查询纯文本形式的元素内容,或者在文档中插入纯文本(不必转义HTML标记中使用的尖括号和&符号)。标准的方法是Node的textContent属性来实现
var para=document.getElementsByTagName("p")[0];
var text=para.textContent;
para.textContent="hello world";
textContent属性在除了IE的所有当前的浏览器中都支持。在IE中,可以用Element的innetText属性来代替。它除了firefox的所有当前浏览器中都支持
textContent和innetText属性非常相似,通常可以互换,不过要小心空元素(在javascript中字符串“”是假值)和未定义的属性之间的区别
textContent属性就是将指定元素的所有后代Text节点简单的串联在一起。innerText没有一个明确指定的行为,但是和textContent有一些不同。innerText不返回script元素的内容。它忽略多余的空白,并试图保留表格格式。同时innerText针对某些表格元素(如table tbody tr)是只读的属性。
作为Text节点的元素内容
另一种方法处理元素的内容来是当作一个子节点列表,每个字节点可能有它自己的一组子节点。当考虑元素的内容时,通常感兴趣的是它的Text节点,在XML文档中,你也必须准备好处理CDATASection节点-它是Text的子类型,代表了CDATA段的内容
nodeValue属性可以读和写,设置它可以改变Text或CDATASection节点所显示的内容。
Text和CDATASection都是CharacterData的子类型,可以在第四部分查看相关信息。CharacterData定义了data属性,它和nodeValue的文本相同。
我们已经看到用HTML和纯文本字符串如何来查询和修改文档内容,也已经看到我们能够遍历Document来检查组成Doumnent的每个Element和Text节点。在每个节点级别修改文档也是有可能的。Document类型定义了创建Element和Text对象的方法,Node类型定义了在节点中插入、删除和替换的方法。
function loadasync(url){
var head=document.getElementsByTagName("head")[0];
var s=document.createElement("script");
s.src=url;
head.appendChild(s);
}
创建节点
创建新的Element节点可以使用Document对象的createElement方法,给方法传递元素的标签名:对HTML文档来说该名字不区分大小写,对XML文档则需要区分大小写
Text节点用类似的方法创建:
var newnode=document.createTextNode("text node content");
另一种创建新文档节点的方法是复制已存在的节点。每个节点有一个cloneNode方法来返回该节点的一个全新副本。给方法传递
参数true也能够递归的复制所有的后代节点,或传递参数false只执行一个浅复制。在除了IE的其他浏览器中,Document对象还定义了一个类似的方法叫做importNode。如果给它传递另一个文档的一个节点,它将返回一个适合本文档插入的节点的副本,传递true作为第二个参数,该方法将递归地导入所有的后代节点。
插入新节点
一旦有了一个新节点,就可以用Node的方法appendChild或insertBefore将它插入到文档中。appendChild是izai需要插入的Element节点上调用的,它插入指定的节点使其成为那个节点的最后一个子节点。
insertBefore就像appendChild一样,除了它接受两个参数。第一个参数就是待插入的节点,第二个参数是已存在的节点,新节点将插入该节点的前面。该方法应该是在新节点的父节点上调用,方法的第二个参数必须是该父节点的子节点。如果传递null作为第二个参数,insertBefore的行为类似appendChild,它将节点插入在最后
function insetAt(parent,child,n){
if(n<0||n>parent.childNodes.length) throw new Error("invalid index");
else if(n==parent.childNodes.length) parent.appendChild(child);
else parent.insertBefore(child,parent.childNodes[n]);
}
如果调用appendChlid或者insertBefore将已存在文档中的一个节点再次插入,那个节点将自动从它当前的位置删除并在新的位置重新插入:没有必要显示的删除该节点
删除和替换节点
removeChild()方法是从文档树中删除一个节点。但是请小心:该方法不是在待删除的节点上调用,而是在其父节点上调用,在父节点上调用该方法,并将需要删除的字节点作为方法参数传递给它
n.parentNode.removeChild(n);
replaceChild方法删除一个子节点并用一个新的节点取而代之。在父节点上调用该方法,第一个参数是新节点,第二个参数是需要代替的节点
n.parentNode.replaceChild(document.createTextNode("[redacted]"),n);
DocumentFragment是一种特殊的Node,它作为其他节点的一个临时的容器,像这样创建一个DocumentFragment:
var frag=document.createDocumentFragment();
像Document节点一样,DocumentFragment是独立的,而不是任何其他文档的一部分。它的parentNode总是为null,但类似Element,它可以有任意多的子节点,可以用appendChild、insertBefore等方法来操作它们。
DucumentFragment的特殊之处在于它使得一组节点被当作一个节点看待:如果给appendChild、insertBefore或replaceChild传递一个DocumentFragment,其实将该文档片段的所有字节点插入到文档中,而非片段本身。(文档那个片段的子节点从片段移动到文档中,文档片段清空以便重用)
元素坐标和视口坐标
元素的位置是以像素来度量的,向右代表X坐标的增加,向下代表Y坐标的增加。但是,有两个不同的点作为坐标系的原点:元素的x和y坐标可以相对于文档的左上角或相对于显示文档的视口的左上角。在顶级窗口和标签页中,视口只是实际显示文档内容的浏览器的一部分:它不包括浏览器外壳(如菜单、工具条和标签页)。针对框架页面中显示的文档,视口是定义了框架页的iframe元素,无论在任何中情况下,当讨论元素的位置时,必须弄清楚所使用的坐标是文档坐标还是视口坐标,视口坐标有时也叫做窗口坐标。
如果文档比视口要小,或者说它还未出现滚动,则文档的左上角就是视口的左上角,一般来说,文档和视口坐标系统是同一个。但是,一般来说,要在两种坐标系之间互相转换,必须加上或减去滚动的偏移量(scroll offset)。例如,在文档坐标中如果一个元素的Y坐标是200像素,并且用户已经把浏览器向下滚动75像素,那么视口坐标元素的Y坐标是125像素。同样,在视口坐标中如果一个元素的x坐标是400,并且用户已经水平滚动了视口200像素,那么文档坐标中元素的x坐标是600像素。
文档坐标比视口坐标更加基础,并且在用户滚动时它们不会发生变化。不过,在客户端编程中使用视口坐标是非常常见的。当使用css指定元素的位置时运用了文档坐标,但是最简单的查询元素位置的方法返回视口坐标中的位置。类似地,当为鼠标事件注册事件处理程序函数时,报告的鼠标指针的坐标是在视口坐标系中的。
为了在坐标系之间互相转换,我们需要判断浏览器窗口的滚动条的位置。window对象的pageXOffset和pageYOffset属性在所有的浏览器中提供这些值,除了IE8及更早的版本以为。Ie也可以通过scrollLeft和scrollTop属性来获得滚动条的位置。令人迷惑的是,正常情况下通过查询文档的根节点(document.documentElement)来获取这些属性值。但在怪异模式下,必须文档的《body》元素document。body上查询它们
function getScrollOffsets(w){
w=w||window;
if(w.pageXOffset!=null)return {x:w.pageXOffset,y:w.pageYOffset};
var d=w.document;
if(document.compatMode=="CSS1Compat"){
return {x:d.documentElement.scrollLeft,y:d.documentElement.scrollTop};
}
return {x:d.body.scrollLeft,y:d.body.scrollTop};
}
查询元素的几何尺寸
判定一个元素的尺寸和位置最简单的办法是调用它的getBoundingClientRect方法。它不需要参数,返回一个有left、right、top、和buttom属性的对象。left对象和top属性表示元素左上角的x和Y坐标,right和bottom属性表示元素的右下角的X和Y坐标
这个方法返回元素在视口坐标中的位置。为了转化为甚至用户滚动浏览器窗口以后仍然有效的文档坐标,需要加上滚动的便宜量
var box=e.getBoundingClientRect();
var offsets=getScrollOffsets();
var x=box.left+offsets.x;
var y=box.top+offsets.y;
在很多浏览器(和w3c)中,getBoundingClientRect返回的对象还包含width和height属性,但是在原始的IE中未实现。为了简便起见,可以这样计算元素的width和height
var box=e.getBoundingClientRect();
var w=box.width||(box.right-box.left);
var h=box.heith||(box.bottom-box.top);
元素内容被一块可选的空白区域所包围,叫做内边距,内边距被边框所包围,边框被外边距所包围。内边距、边框和外边距都是可选的。getBoundingClientRect所返回的坐标包含元素的边框和内边距,但不包含元素的外边距。
如getElementsByTagName这样的dom方法返回的结果是实时的,当文档变化时这些结果能自动更新,但getBoundingClientRect和getClientRects所返回的矩形对象和矩形对象列表并不是实时的。它们只是调用方法时文档视觉状态的静态快照,在用户滚动或改变浏览器窗口大小时不会更新它们。
滚动
Window对象的scrollTo(和其同义词scroll)方法接受一个点的X和Y坐标(文档坐标),并作为滚动条的偏移量设置它们。也就是,窗口滚动到指定的点出现在视口的左上角。如果指定的点太接近文档的下边缘或右边缘,浏览器将尽量保证它和视口的左上角之间最近。但无法达到一致
window的scrollBy()和scroll和scrollTo类似,但是它的参数是相对的,并在当前滚动条的偏移量上增加
javascript:void setInterval(function (){scrollBy(0,10)},200);
通常,除了滚动到文档中用数字表示的位置,我们只是想它滚动使得文档中的某个元素可见。可以利用getBoundingClientRect计算元素的位置,并转换为文档坐标,然后用scrollTo方法达到目的。但是在需要显示的HTML元素上调用scrollIntoView方法更加方便。该方法保证了元素咋视口中可见。默认情况下,它试图将元素的上边缘放在或尽量接近视口的上边缘。如果只传递false作为参数,它将试图将元素的下边缘放在或尽量接近时时候。只要有助于元素在视口内可见。浏览器也会水平滚动窗口。
任何HTML元素的只读属性offsetWidth和offsetHeight以css像素返回它的屏幕尺寸。返回的尺寸包含元素的边框和内边距
,除去了外边距。
所有HTML元素拥有offsetLeft和offsetTop属性来返回元素的x坐标和y坐标。对于很多元素,这些值是文档坐标,并直接指定元素的位置。但对于已定义元素的后代元素和一些其他元素(如表格单元),这些属性返回的坐标是相对于祖先元素的而不是文档。offsetParent属性指定这些属性所相对的父元素。如果offsetParent为null,这些属性都是文档坐标
除了这些名字以offset开头的属性以外,所有的文档元素定义了其他两组属性,其名称一组以client开头,另一组以scroll开头。即,每个HTML元素都有一些这些属性;
为了理解这些client和scroll属性,你需要知道HTML元素的实际内容有可能比分配用来容纳内容的盒子更大,因此单个元素可能有滚动条。内容区域是视口,就像浏览器的窗口,当实际比视口更大时,需要把元素的滚动条位置考虑进去。
clientWidth和clientHeight类似offsetWidth和offsetHeight,不同的是它们不包含边框大小,只包含内容和它的内边距。同时,如果浏览器咋内边距和边框之间添加了滚动条,clientWidth和clientHeight在其返回值中也不包含滚动条。注意对于类似i code span这些内联元素,clientWidth和clientHeight总是返回0.有一个特殊的案例,在文档的根元素上查询这些属性时,它们的返回值和窗口的innerWidth和innerHeight属性值相等
clientLft和clientTop属性没什么作用,通常这些值就等于左边和上边的边框宽度。对于内联元素,它们总是为0.
scrollWidth和scollHeight是元素的内容区域加上它内边距再加上任何溢出内容的尺寸。当内容正好和内容区域匹配而没有溢出时,这些属性和clientWidth和cliengHeight是相等的。但当溢出时,它们就包含溢出的内容,返回值比clientWidth和clientHeight要大
最后,scrollLeft和scrollTop指定元素的滚动条的位置。注意,scrollLeft和scrollTop是可写的属性,通过设置它们来让元素中的内容滚动。(HTML元素并没有类似Window对象的scrollTo方法)
document.forms是一个HTMLColllection对象,可以通过数字序号或id或name来选取表单元素。Form对象本身的行为类似多个表单元素组成的HTMLCollectiion集合,现在也可以通过name或数字序号来索引。如果名为address的表单的第一个元素的name是street,可以使用以下任何一种表达式
document.forms.address[0]
document.forms.address.street
document.address.street//当有name=“address”,而不是只有id=“address”
如果要明确的选取一个表单元素,可以索引表单对象的elements属性:
document.forms.address.elements[0];
document.forms.address.elements.street
name属性在HTML表单提交中有特殊的目的,它在表单中较为常用,在其他元素中较少使用。它应用于相关的复选按钮组和强制共享name属性值的,互斥的单选按钮组,请记住,当用name来索引一个HTMLCollection对象并且它包含多个元素共享name时,返回值是一个类数组对象,它包含所有匹配的元素。
elements数组是form对象中最有趣的属性,action encoding method和target属性(property)直接对应于form元素的action、encoding、method和target等html属性(attribute),这些属性都控制了表单是如何来提交数据到web服务器并如何显示的
在javascript产生之前,要用一个专门的提交按钮来提交表单,用一个专门的重置按钮来重置各表单元素的值,javascript的form对象支持两个方法submit和reset方法,它们完成同样的目的,调用form对象的submit方法来提交表单,调用reset方法来重置表单元素的值。
所有(多数)表单元素通常都有以下属性
type
标识表单元素类型的只读的字符串,针对用input标签定义的表单元素而言,就是其type属性的值,其他表单元素(如textarea和select)定义type属性是为了轻松的标识它们,与input元素在类型检测时互相区别
form对包含元素的form对象的只读引用,或者如果元素没有包含在一个form元素中,则其值为null
name
只读的字符串,有html属性name指定
value
可读/写的字符串,指定了表单元素包含或代表的值。它就是当提交表单时发送到web服务器的字符串。也是javascript程序有时候会感兴趣的内容。针对text和textarea元素,该属性值包含了用户输入的文本。针对用input标签创建的按钮元素(除了用button标签创建的按钮),该属性值指定了按钮显示的文本。但是,针对单选和复选按钮元素,该属性用户不可见也不能编辑。它仅是用HTML的value属性来设置的一个字符串。它在表单提交是使用,但在关联表单元素的额外数据时也很有用。
表单和元素的事件处理程序
每个Form元素都一个onsubmit事件处理程序来侦测表单提交,还有一个onreset事件处理程序来侦测表单重置。表单提交前调用onsubmit程序,它通过返回false能够取消提交动作。这给javascipt程序一个机会来检查用户的输入错误,目的是为了避免不完整或无效的数据通过网络提交到服务端程序。注意,onsubmit事件处理程序只能通过单击提交按钮来触发。直接调用表单的submit方法不触发onsubmit事件处理程序。
onreset事件处理程序和onsubmit是类似。它在表单重置之前调用,通过返回false能够阻止表单元素被重置
<form onreset="return onfirm('')">
onreset只能通过单击重置按钮来触发。直接调用表单的reset方法不会触发onreset事件处理程序。
当用户与表单元素交互时它们往往会触发click或change事件。通过定义onclick或onchange事件处理程序可以处理这些事件,一般来说,当按钮表单元素激活时它们会触发click事件。当用户改变其他表单元素所代表的值时它们会触发change事件。当用户在一个文本域输入文本或从下拉列表中选择了一个选项后就发生这样的改变。注意,在一个文本域中该事件不是每次用户输入一个键值时都会触发,它仅当用户改变了元素的值然后将焦点移动到其他元素上时才会触发。也就是说,调用该事件处理程序就意味着一个完整的改变。单选按钮和复选按钮都有一个状态标识,它们的click和change事件都会触发;两个之中change事件更加有用。
表单元素在收到键盘的焦点时也会触发focus事件,失去焦点时会触发blur事件
在事件处理程序中关键字this是触发该事件的文档元素的一个引用。既然在form元素中的元素都有一个form属性引用了该包含的表单,这些元素的事件处理程序总是能够通过this.form来得到form对象的引用。更进一步,这意味这某个表单元素的事件处理程序能够通过this。form。x得到该表单中以x命名的元素。
单选和复选框元素都定义了checked属性。该属性是可读/写的布尔值,它指定了元素当前是否选中。defaultChecked属性也是布尔值,它是HTML属性checked的值。它指定了元素在第一次加载页面时是否选中
不同的文本输入元素定义onkeypress、onkeydown和onkeyup事件处理程序。可以从onkeypress和onkeydown事件处理程序返回false,防止记录用户的按键。这很有用,例如,如果希望强制用户在特定文本输入域仅输入数字。
如果select元素有multiple属性,也就是select对象的type属性值为select-multiple,那么就允许用户选取多个选项。否则
没有多选属性,那只能选取单个选项,它的type属性值为select-one
Select元素定了options属性,它是一个包含了多个Option元素的类数组对象。
当用户选取或取消选取一个选项时,select元素触发onchange事件处理程序,针对“select-one”Select元素,它的可读/写属性selectedIndex指定了哪个选项当前被选中。针对select-multiple元素,单个selectedIndex属性不足以表示被选中的一组选项,在这种情况下,要判定哪些选项被选中,就必须遍历options[]数组的元素,并检测每个Option对象的selected属性值,除了其select属性,每个option对象都有一个text属性,它指定了select元素中的选项所显示的纯文本字符串。设置该属性可以改变显示给用户的文本。
通过设置options.length为一个希望的值可以截断option元素数组,而设置options。length为0可以从select元素移除所有的选项。设置options[]数组中某点的值为null可以从Select元素中移除某个option对象。这将删除该option对象,options[]数组中高端的元素自动移下来填补空缺
为select元素增加一个新的选项,首先用Option()构造函数创建一个Option对象,然后将其添加到options[]属性中
这些专用的select元素的api已经很老了。可以用那些标准的调用更明确的插入和移除选项元素:document.createElement(),node.inertBefore(),node.removeChild()等。
Ducument的属性
cookie
允许javascript程序读、写http cookie特殊的属性。
domain
该属性允许当Web页面之间交互时,相同域名下互相信任的web服务器之间协作放宽同源策略安全限制
lastModified
包含文档修改时间的字符串
location
与window对象的location属性引用同一个Location对象
referrer
如果有,它表示浏览器导航到当前链接的上一个文档。该属性值和http的referer头信息的内容相同,只是拼写上有两个rr
title
文档的title和</title>标签之间的内容
url
文档的url,只读字符串而不是Location对象,该属性值与location。href的初始值相同,只是不包含Location对象的动态变化。例如,如果用户在文档中导向到一个新的片段,location。href会发生变化,但是document。URL则不会