使用DOM技术操纵文档
使用insertBefore方法
insertBefore方法的功能和appendChild相似,都是将一个孩子节点连接到一个父亲节点,但insertBefore方法允许我们指定孩子节点的位置。insertBefore的语法是fatherObj.insertBefore(childObj, brotherObj),返回值是被连接的孩子节点。执行后,childObj的位置在brotherObj之前。来看看下面的例子:
<html>
<head>
<title>DOM Demo </title>
</head>
<body id="bodyNode">
<script language="JavaScript">
<!--
alert("页面初始状态");
tableObj = document.createElement("TABLE");
tbodyObj = document.createElement("TBODY");
tr1Obj = document.createElement("TR");
tr2Obj = tr1Obj.cloneNode();
tr3Obj = tr1Obj.cloneNode();
tr1td1Obj = document.createElement("TD");
tr1td2Obj = tr1td1Obj.cloneNode();
tr2td1Obj = tr1td1Obj.cloneNode();
tr2td2Obj = tr1td1Obj.cloneNode();
tr3td1Obj = tr1td1Obj.cloneNode();
tr3td2Obj = tr1td1Obj.cloneNode();
row1cell1Obj = document.createTextNode("This is row 1, cell 1");
row1cell2Obj = row1cell1Obj.cloneNode();
row2cell1Obj = row1cell1Obj.cloneNode();
row2cell2Obj = row1cell1Obj.cloneNode();
row3cell1Obj = row1cell1Obj.cloneNode();
row3cell2Obj = row1cell1Obj.cloneNode();
row1cell2Obj.nodeValue = "This is row 1, cell 2";
row2cell1Obj.nodeValue = "This is row 2, cell 1";
row2cell2Obj.nodeValue = "This is row 2, cell 2";
row3cell1Obj.nodeValue = "This is row 3, cell 1";
row3cell2Obj.nodeValue = "This is row 3, cell 2";
returnValue = tableObj.insertBefore(tbodyObj);
tbodyObj.insertBefore(tr3Obj);
tbodyObj.insertBefore(tr2Obj, tr3Obj);
tbodyObj.insertBefore(tr1Obj, tr2Obj);
tr1Obj.insertBefore(tr1td2Obj);
tr1Obj.insertBefore(tr1td1Obj, tr1td2Obj);
tr2Obj.insertBefore(tr2td2Obj);
tr2Obj.insertBefore(tr2td1Obj, tr2td2Obj);
tr3Obj.insertBefore(tr3td2Obj);
tr3Obj.insertBefore(tr3td1Obj, tr3td2Obj);
tr1td2Obj.insertBefore(row1cell2Obj);
tr1td1Obj.insertBefore(row1cell1Obj);
tr2td2Obj.insertBefore(row2cell2Obj);
tr2td1Obj.insertBefore(row2cell1Obj);
tr3td2Obj.insertBefore(row3cell2Obj);
tr3td1Obj.insertBefore(row3cell1Obj);
bodyNode.insertBefore(tableObj);
// -->
</script>
</body>
</html>
上面的代码又一次演示了一个Table的动态创建过程。首先创建Table的各个行、列以及单元格的节点,然后混合使用insertBefore将这些节点进行连接形成一个Table,最后通过语句bodyNode. insertBefore (tableObj)将Table装载进文档中。可以看到,如果省略掉第2个参数brotherObj采用fatherObj.insertBefore(childObj)方式,那么一定是在要连入的父亲节点还没有孩子节点的情况下,这时,就和appendNode方法的功能完全一样了。
使用removeNode方法
removeNode方法的功能是删除一个节点,语法为node.removeNode(false)或者node.removeNode(true),返回值是被删除的节点。removeNode(false)表示仅仅删除指定节点,然后这个节点的原孩子节点提升为原双亲节点的孩子节点。removeNode(true)表示删除指定节点及其所有下属节点。被删除的节点成为了孤立节点,不再具有有孩子节点和双亲节点。来看看下面的例子:
<html>
<head>
<title>DOM Demo</title>
</head>
<body id="bodyNode">
This is the document body
<p id="p1Node">
This is paragraph 1.</p>
<p id="p2Node">
This is paragraph 2.</p>
<p id="p3Node">
This is paragraph 3.
<img id="imgNode" src="myexam.gif">This text follows the image
<table id="tableNode">
<tbody>
<tr>
<td bgcolor="yellow">
This is row 1, cell 1
</td>
<td bgcolor="orange">
This is row 1, cell 2
</td>
</tr>
<tr>
<td bgcolor="red">
This is row 2, cell 1
</td>
<td bgcolor="magenta">
This is row 2, cell 2
</td>
</tr>
<tr>
<td bgcolor="lightgreen">
This is row 3, cell 1
</td>
<td bgcolor="beige">
This is row 3, cell 2
</td>
</tr>
</tbody>
</table>
</p>
<p id="p4Node">
This is paragraph 4.</p>
<script language="JavaScript">
<!--
var msg = "";
function printChildren() {
childCount = bodyNode.childNodes.length;
msg += "bodyNode.childNodes.length = " + bodyNode.childNodes.length + "\n";
for (var i = 0; i < childCount; i++) {
msg += "bodyNode.childNodes[i].nodeName = " + bodyNode.childNodes[i].nodeName + "\n";
}
alert(msg);
}
msg = "页面初始状态" + "\n\n";
printChildren();
msg = "对页面内容进行修改后" + "\n\n";
msg += "Deleting Paragraph 3\n";
var deletedNode = p3Node.removeNode(false);
msg += "deletedNode.nodeName = " + deletedNode.nodeName + "\n";
msg += "deletedNode.childNodes.length = " + deletedNode.childNodes.length + "\n";
printChildren();
// -->
</script>
</body>
</html>
上述代码首先显示页面的初始内容以及bodyNode的每个孩子节点的nodeName属性值,然后仅仅删除p3Node。删除p3Node前,bodyNode有6个孩子节点,p3Node有4个孩子节点。删除p3Node后,节点p3Node的4个孩子节点提升为bodyNode的孩子节点,这样bodyNode就有了9个节点。p3Node被删除后返回值为deletedNode,它的nodeName属性值为P,孩子节点数为0,也就是说,它成为一个孤立节点。
现在我们将上述代码中的deletedNode = p3Node.removeNode(false)修改为deletedNode = p3Node.removeNode(true),你会看到,删除p3Node后,bodyNode的孩子节点数变为5。
使用replaceNode方法
replaceNode方法的功能是用新创建的节点替换一个节点及其下属节点,语法为oldNode.replaceNode(newNode),返回值是被替换的节点。来看看下面的例子:
<html>
<head>
<title>DOM Demo </title>
</head>
<body id="bodyNode">
This is the document body
<p id="p1Node">
This is paragraph 1.</p>
<p id="p2Node">
This is paragraph 2.</p>
<p id="p3Node">
This is paragraph 3.
<img id="imgNode" src="myexam.gif">This text follows the image
<table id="tableNode">
<tr>
<td bgcolor="yellow">
This is row 1, cell 1
</td>
<td bgcolor="orange">
This is row 1, cell 2
</td>
</tr>
<tr>
<td bgcolor="red">
This is row 2, cell 1
</td>
<td bgcolor="magenta">
This is row 2, cell 2
</td>
</tr>
<tr>
<td bgcolor="lightgreen">
This is row 3, cell 1
</td>
<td bgcolor="beige">
This is row 3, cell 2
</td>
</tr>
</table>
</p>
<p id="p4Node">
This is paragraph 4.</p>
<script language="JavaScript">
<!--
var msg = "";
function printChildren() {
childCount = bodyNode.childNodes.length;
msg += "bodyNode.childNodes.length = " + bodyNode.childNodes.length + "\n";
for (var i = 0; i < childCount; i++) {
msg += "bodyNode.childNodes[i].nodeName = " + bodyNode.childNodes[i].nodeName + "\n";
}
alert(msg);
}
msg = "页面初始状态" + "\n\n";
printChildren();
msg = "对页面内容进行修改后" + "\n\n";
msg += "Replacing Paragraph 3\n";
var b = document.createTextNode("New Body Page");
var replacedNode = p3Node.replaceNode(b);
msg += "replacedNode.nodeName = " + replacedNode.nodeName + "\n";
msg += "replacedNode.childNodes.length = " + replacedNode.childNodes.length + "\n";
msg += "p2Node.nodeName = " + p2Node.nodeName + "\n";
printChildren();
// -->
</script>
</body>
</html>
上述代码首先显示页面的初始内容以及bodyNode的每个孩子节点的nodeName属性值,然后用新创建的文本项节点替换p3Node。替换后,bodyNode的孩子节点数目没有变,原来的P节点替换为文本项节点。变量replaceNode表示被替换的节点p3Node,它仍包含原来的4个孩子节点。
replaceNode方法的另一个功能是删除节点及其下属节点,就象前面介绍的removeNode(true)一样。这时,我们只需将replaceNode方法的参数设置为一个现存的节点就可以。现在,我们将上述代码中的b = document.createTextNode("New Body Page")修改为b = p2Node,你会看到,p3Node及其下属节点被删除了,没有替换节点生成,bodyNode的孩子节点数变为5。
如果replaceNode方法的参数为空,也就是执行replaceNode(),那么将导致浏览器脚本运行错误。
使用swapNode方法
swapNode方法的功能是交换2个节点(包括其下属节点)在文档Tree中的位置,语法为firstNode.swapNode(secondNode),返回值是节点firstNode。来看看下面的例子:
<html>
<head>
<title>DOM Demo</title>
</head>
<body id="bodyNode">
This is the document body
<p id="p1Node">
This is paragraph 1.</p>
<p id="p2Node">
This is paragraph 2.</p>
<p id="p3Node">
This is paragraph 3.
<img id="imgNode" src="myexam.gif">This text follows the image
<table id="tableNode">
<tbody>
<tr>
<td bgcolor="yellow">
This is row 1, cell 1
</td>
<td bgcolor="orange">
This is row 1, cell 2
</td>
</tr>
<tr>
<td bgcolor="red">
This is row 2, cell 1
</td>
<td bgcolor="magenta">
This is row 2, cell 2
</td>
</tr>
<tr>
<td bgcolor="lightgreen">
This is row 3, cell 1
</td>
<td bgcolor="beige">
This is row 3, cell 2
</td>
</tr>
</tbody>
</table>
</p>
<p id="p4Node">
This is paragraph 4.</p>
<script language="JavaScript">
<!--
var msg = "";
function printChildren() {
childCount = bodyNode.childNodes.length;
msg += "bodyNode.childNodes.length = " + bodyNode.childNodes.length + "\n";
for (var i = 0; i < childCount; i++) {
msg += "bodyNode.childNodes[i].nodeName = " + bodyNode.childNodes[i].nodeName + "\n";
}
alert(msg);
}
msg = "页面初始状态" + "\n\n";
printChildren();
msg = "对页面内容进行修改后" + "\n\n";
msg += "Swapping Paragraph 3 with Paragraph 2\n";
var b = p2Node;
var swappedNode = p3Node.swapNode(b);
msg += "swappedNode.nodeName = " + swappedNode.nodeName + "\n";
msg += "swappedNode.childNodes.length = " + swappedNode.childNodes.length + "\n";
msg += "p2Node.nodeName = " + p2Node.nodeName + "\n";
printChildren();
// -->
</script>
</body>
</html>
上述代码首先显示页面的初始内容以及bodyNode的每个孩子节点的nodeName属性值,然后交换p3Node和p2Node的位置。交换后,bodyNode的孩子节点数目没有变,变量swappedNode表示p3Node,它仍包含原来的4个孩子节点。
swapNode方法的另一个功能是替换节点及其下属节点,就象前面介绍的replaceNode方法一样。这时,我们只需将replaceNode方法的参数设置为一个新创建的节点就可以。现在,我们将上述代码中的b = p2Node修改为b = document.createTextNode("This is a swapped in text"),你会看到,p3Node及其下属节点被新创建的文本项节点所替换,原来的节点类型P变为了文本项节点类型#text。
结语
以上我们详细讲解了JavaScript语言中在层次关系上操纵对象的各种DOM属性和方法原理,并且配以例程演示了实际的运行效果。我相信你已经完全掌握了如何使用这些方法,并会逐渐加深对DOM技术的喜爱。因为,DOM技术确实简化了文档对象的访问方式,为开发人员在对象层次上操纵文档提供了最便捷的手段。