在第I部分中,我们介绍了文档对象模型(Document Object Model,即 DOM)的部分内容,这个模型为文档结构提供了一个支持脚本编程的接口。通过 DOM,HTML 文档可以描述为一系列的结点,每个结点代表文档中的一个对象,包括所有的文本,标识,注释,和其它数据。开发者可以通过 JavaScript 来改变这些结点,从而改变页面在浏览器中的视觉效果。如果您读过上篇文章,就知道了如何使用 DOM 方法来从页面中创建,插入,和移除元素。
本文将较为深入地讨论 JavaScript 的结点接口,并且考察一些用于改变元素或文本结点视觉属性的不同方法。您将首先学到如何用 DOM 元素方法来改变元素属性,然后学习如何通过 DOM 级别二(DOM Level 2,即 DOM2)的风格规范接口来改变元素的风格属性。
在您用 DOM 接口操作元素结点之前,需要首先获得您希望操作的元素的一个引用。我在这里提到的“引用”意思是一个指向页面中正确对象的变量。您可能已经熟悉绝大部分浏览器都支持的 document.images
,document.forms
,和其它集合变量。这些集合就是一组页面内部对象的引用。如果您需要一个图像元素的引用,而该图像元素的NAME属性值为“mgHeader”,则您可以使用图像元素的集合,并通过其名称来抓取正确的元素:
var img = document.images["imgHeader"];
然而,这些集合变量只是支持页面元素的一个子集。举例来说,脚本中就不存在象 document.tables
或者 document.paragraphs
这样的集合,来为您获取相应类别元素的引用提供支持。
幸运的是,DOM2 接口提供了两个方法,可以帮助我们获取任意元素的引用(并且这个引用和元素本身紧密关联--请相信我,元素是可能发生变化的)。这两个方法是:
document.getElementById(string id)
:根据指定的ID返回一个元素的引用。 document.getElementsByTagName(string tagName)
:返回具有指定标识名称的所有元素的集合(数组)。 因此,如果您要获得ID属性值为“tableMain”的表格元素的引用,可以使用下面这行 JavaScript 代码:
var table = document.getElementById("tableMain");
现在变量 table
应该包含一个指向相应表格的引用。getElementById()
方法假定页面中存在具有和传入参数指定的值相匹配的 ID 属性的
目标元素。如果没有找到 ID 匹配的元素,则 getElementById
返回 null 值。
认识到元素的 NAME
属性和其 ID
属性并不一样是很重要的。举例来说,如果您习惯为图像标识设定 NAME
属性的值,则除非您同时设定了 ID
属性值,否则将不能通过 getElementById
方法来进行访问。最好是使元素同时具有唯一的 NAME
和 ID
的属性值。
当您需要获得所有特定类型元素的引用时,getElementsByTagName()
是很有用的。这个方法返回一个集合,包含所有能找到的匹配元素的引用。举例来说,如果您希望计算页面中表格的单元格的数目,则可以使用类似下面的代码:
var allTDs = document.getElementsByTagName("td");
alert("# of table cells: " + allTDs.length);
请试一下,点击下面这个按键,就可以调用 getElementsByTagName()
方法计算当前这个页面的表格的格子数目。
要获得集合中特定元素的引用,可以使用集合的 item()
方法,这个方法返回指定索引的元素的引用。如果您希望得到集合中的第一个和最后一个表格单元格的引用,可以使用下面的代码:
var allTDs = document.getElementsByTagName("td");
var firstTD = allTDs.item(0).id;
var lastTD = allTDs.item(allTDs.length-1).id;
var str = "# of table cells: " + allTDs.length + "/n";
str += "First TD: " + firstTD + "/n";
str += "Last TD: " + lastTD;
alert(str);
使用 item()
方法而不是直接引用集合位置下标的一个优点是,如果您提供的索引是非法的,或者目标元素不在集合中,item()
函数会返回null值;而引用一个集合中不存在的位置下标可能会产生一个错误信息,相比之下,我们通常更希望前者。
getElementsByTagName()
也是每个元素都市有的方法,这意味着我们可以得到某个特定元素内部的所有元素的引用集合。下面的代码就是在元素级别上调用 getElementsByTagName()
方法来取得一个表格对象中的所有图像的引用:
var table = document.getElementById("myTable");
var imgs = table.getElementsByTagName("img");
您一旦有了一个元素的引用,就可以对其属性进行操作了。
元素标识的属性会被浏览器翻译成对象(您创建的引用)的属性。DOM 接口为每个元素提供了两个方法,用来读取和设定这些属性值:
getAttribute(string name)
:返回由 name 参数指定的属性值。 setAttribute(string name, string value)
:增加一个指定名称和值的新属性,或者把一个现有的属性设定为指定的值。 我经常喜欢使用一个工具函数来观察一个元素,看看和它关联在一起的属性和方法。下文即将看到的 inspect()
函数通过 getElementById()
函数取得元素的引用,并弹出一个包含元素属性列表的警告框。属性和值的字符串是由 getAttribute()
方法取得的各个命名属性的值装配而成。
function inspect(elm){
var str = "";
for (var i in elm){
str += i + ": " + elm.getAttribute(i) + "/n";
}
alert(str);
}
要使用 inspect()
函数来考察一个表格元素时,只需简单地把表格元素传递给该函数就可以了:
table = document.getElementById("tableMain");
inspect(table);
您想看看这个函数是如何动作的吗?点击这个按键就可以考察下面的表格了。
one | two | three |
four | five | six |
seven | eight | nine |
设定一个新的元素属性可以通过 setAttribute()
方法来实现。只要把您希望设定的属性名称和值传递给这个函数就可以了。请注意,这两个参数必须是字符串,因此即使是数字值也必须放在引号里面。假定您要把表格的宽度重新调整为 400 像素,则可以使用下面的代码:
var table = document.getElementById("tableMain");
table.setAttribute("width","400");
下面的例子用 setAttribute()
和 changeSize()
方法来把这个表格的 WIDTH 属性设定为不同的值。
function changeSize(px){
var table = document.getElementById("tableMain2");
table.setAttribute("width",px);
}
one | two | three |
four | five | six |
seven | eight | nine |
如果元素中不存在指定名称的属性,setAttribute()
方法就会创建一个新的属性。事实上,使用 setAttribute()
方法和直接通过 JavaScript 设定属性值相比,没有任何本质上的好处。下面两行语句在本质上完成同样的事情:
table.setAttribute("border","2");
table.border = 2;
为了避免设定不希望的新属性,您可以使用元素的 hasAttribute()
方法来测试一个命名属性是否存在。hasAttribute()
方法根据元素是否拥有相应的属性,或者返回 true
,或者返回 false
。
var table = document.getElementById("tableMain");
if (table.hasAttribute("border")){
table.setAttribute("border","2");
} else {
alert("Table has no border");
}
应该注意的是,hasAttribute()
方法只在 Netscape 6/Mozilla 浏览器上得到支持,在书写本文的时候,IE5 还不支持这个方法。
到此为止,我们只讨论如何操作元素的属性。通常情况下,一个元素会使用 CSS 来定义特定的风格和格式。改变元素的 CSS 属性使用类似的方法,但是又有一点轻微的差别。
DOM 规范提供了另外一个接口,称为 DOM 级别二风格接口(DOM Level 2 Style),用来操作元素的 CSS 属性。元素的每一个 CSS 规则都可以由元素风格对象的一个属性来表现。
风格是一个对象,所以我们可以用一个与上文描述的 inspect() 相类似
的函数来考察它的属性。下文的 inspectStyle()
函数在考察风格属性值之前先考察目标元素是否有风格对象。正如我们在修改风格这篇文章中探讨的那样,在当前的 Netscape 6 和 Mozilla 的正式版本中存在一个缺陷,使得在这些浏览器中,嵌入的风格表单中的CSS规则不能正确地反映到风格对象中。因此,为了使这个演示正确,所有的元素都通过 STYLE
属性在自身的标识中定义 CSS。
function inspectStyle(elm){
if (elm.style){
var str = "";
for (var i in elm.style){
str += i + ": " + elm.style[i] + "/n";
}
alert(str);
}
}
var header = document.getElementById("h2");
inspectStyle(header);
点击下面的按键可以看到下文的H2元素的风格属性。请注意:一些 Mac OS X IE 5.1 预览版的用户在运行下面的脚本时会碰到问题。
您会注意到很多风格属性是空的,因为我们并没有将它们定义为其它值。您可以直接对风格属性进行设定。如果要读取并设定 HTML 页面的背景颜色(或者具体地说,是 BODY 元素的背景颜色),请看下面的代码:
var doc = document.getElementsByTagName("body").item(0);
var color = doc.style.backgroundColor;
alert ("Background color is: " + color);
doc.style.backgroundColor = "#0000ff";
操作元素的 CSS 属性是 DHTML 功能的关键。举例来说,您可以用 JavaScript 来改变表格的 LEFT 和 BACKGROUND-COLOR 这两个 CSS 属性,从而改变其颜色和在页面中的位置。请试一下下面的按键:
one | two | three |
four | five | six |
seven | eight | nine |
改变位置:
向右 100px向左 100px
改变颜色:
下面是完成上述功能的 JavaScript。在所有的这些情况下,表格的 ID“tableMain”都被传递给 getElementById() 函数,以便获取表格元素的引用。而新的 CSS 属性值被直接赋给风格对象。