今天看到使用DOM核心API的几个例子,总结一下大致实现以下功能点:遍历文档、颠倒文档顺序、添加修改文档内容,最后总结了之前的知识点,创建了一个简易的TOC。
- 用到的几个属性主要是:childNodes、firstChild和nextSibling、parentNode、
- 使用到的接口方法:document.createElement()、document.createTextNode(“”)、node.removeChild()、node.appendChild()、node.setAttribute()、node.insertBefore()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>遍历文档节点</title>
<script type="text/javascript">
//遍历文档方法一: 利用 childNodes
function countTags(n){
var tagSum = 0;
if(n.nodeType == 1){ /*Node.ELEMENT_NODE*/
tagSum++;
}
//var childrenNodes = n.childrenNodes; 错误写法
var childrenNodes = n.childNodes;
if(childrenNodes.length>0){
for(var i=0; i<childrenNodes.length; i++){
tagSum += countTags(childrenNodes[i]);
}
}
return tagSum;
}
//遍历文档方法二: 利用 firstChild 和 nextSibling
function countCharacters(n){
if(n.nodeType == 3){ /*Node.TEXT_NODE*/
return n.length;
}
var numchars = 0;
for(var m=n.firstChild; m!=null; m=m.nextSibling){
numchars += countCharacters(m);
}
return numchars;
}
//三、颠倒文档顺序
function reverse(n){
var kids = n.childNodes;
var numkids = kids.length; // length:9----5个换行符 4个DOM节点
for(var i=numkids-1; i>=0; i--){
var c = n.removeChild(kids[i]);
n.appendChild(c);
}
}
//四、颠倒文档顺序升级版
function reverse_beta(n){
if(n.nodeType == 3){ /*NODE.TEXT_NODE*/
var text = n.data;
var reversed = "";
for(var i = text.length-1 ; i>=0 ; i-- ){
reversed += text.charAt(i);
}
n.data = reversed;
}
else{
var kids = n.childNodes;
var kidsnum = kids.length;
for(var j = kidsnum-1 ; j >=0 ; j--){
reverse_beta(kids[j]);
n.appendChild(n.removeChild(kids[j]));
}
}
}
//五、用等价的大写形式替换节点
function uppercase(n){
if(n.nodeType == 3){ /* NODE.TEXT_NODE*/
var newNode = document.createTextNode(n.data.toUpperCase());
var parent = n.parentNode;
parent.replaceChild(newNode, n);
}
else{
var kids = n.childNodes;
for(var i = 0 ; i < kids.length; i++){
uppercase(kids[i]);
}
}
}
//六、把一个节点的父节点重定为<b>元素
function embolden(node){
var bold = document.createElement("b");
var parent = node.parentNode;
parent.replaceChild(bold, node);
bold.appendChild(node);
}
//七、总例:
function maketoc(replace){
var toc = document.createElement("div");
toc.style.backgroundColor = "white";
toc.style.fontFamily = "sans-serif";
var anchor = document.createElement("a");
anchor.setAttribute("name", "TOC");
toc.appendChild(anchor);
anchor.appendChild(document.createTextNode("Table Of Contents"));
var table = document.createElement("table");
toc.appendChild(table);
var tbody = document.createElement("tbody");
table.appendChild(tbody);
//初始化一个数组,用来跟踪段号
var sectionNumbers = [0,0,0,0,0,0];
addSections(document.body, tbody, sectionNumbers);
//用带有TOC子树的替换参数替换指定的节点,将TOC插入文档
replace.parentNode.replaceChild(toc, replace);
function addSections(n, toc, sectionNumbers){
for(var m = n.firstChild; m!= null; m = m.nextSibling){
if((m.nodeType == 1)&&(m.tagName.length == 2)&&m.tagName.charAt(0) == "H"){
var level = parseInt(m.tagName.charAt(1));
if(!isNaN(level) && (level>=1) && (level<=6)){
//start这一段的操作有点意思,利用数组跟踪段号,可以用来研究一下数组的灵活用法
sectionNumbers[level-1]++;
for(var i = level; i<6; i++) sectionNumbers[i]=0;
var sectionNumber = "";
for(var i = 0; i<level; i++){
sectionNumber += sectionNumbers[i];
if(i<level-1) sectionNumber += ".";
}
//end
//创建文档中 返回到TOC的锚点
var anchor = document.createElement("a");
anchor.setAttribute("name", "SECT"+sectionNumber);
var backlink = document.createElement("a");
backlink.setAttribute("href", "#TOC");
backlink.appendChild(document.createTextNode("Contents"));
anchor.appendChild(backlink);
// 将锚元素插入到文档中的段标题之前
n.insertBefore(anchor, m);
//创建该段的链接并将其加入TOC
var link = document.createElement("a");
link.setAttribute("href", "#SECT"+sectionNumber);
var sectionTitle = getTextContent(m);
link.appendChild(document.createTextNode(sectionTitle));
var row = document.createElement("tr");
var col1 = document.createElement("td");
var col2 = document.createElement("td");
col1.setAttribute("align", "right");
col1.appendChild(document.createTextNode(sectionNumber));
col2.appendChild(link);
row.appendChild(col1);
row.appendChild(col2);
toc.appendChild(row);
m.insertBefore(document.createTextNode(sectionNumber+":"),m.firstChild);
}
}
else{
addSections(m, toc, sectionNumbers);
}
}
}
//遍历m节点,返回该节点下的所有Text节点的内容
function getTextContent(m){
var s = "";
var children = m.childNodes;
for(var i = 0; i<children.length; i++){
var child = children[i];
if(child.nodeType == 3){ /* Node.TEXT_NODE*/
s += child.data;
}else{
s += getTextContent(child);
}
return s;
}
}
}
</script>
</head>
<!-- 示例一:
<body οnlοad="alert('This document has ' + countTags(document) + ' tags.');">
This is a simple <i>document</i>.
</body> -->
<!-- 示例二:
<body οnlοad="alert('Document length:'+ countCharacters(document.body));">
This is a simple document. <p>How long is it?</p>
</body> -->
<!-- 示例三:
<body>
<p name="p1">paragraph #1</p>
<p name="p2">paragraph #2</p>
<p name="p3">paragraph #3</p>
<button οnclick="reverse(document.body)">Click me to reverse.</button>
</body> -->
<!-- 示例四:
<body>
<p name="p1">paragraph #1</p>
<p name="p2">paragraph #2</p>
<p name="p3">paragraph #3</p>
<button οnclick="reverse_beta(document.body)">Click me to reverse.</button>
</body> -->
<!-- 示例五:
<body>
<p id="p1">This<i>is</i> paragraph 1.</p>
<p id="p2">This<i>is</i> paragraph 2.</p>
<button οnclick="uppercase(document.getElementById('p1'))">Click me</button>
</body> -->
<!-- 示例六:
<body>
<p id="p1">This<i>is</i> paragraph 1.</p>
<p id="p2">This<i>is</i> paragraph 2.</p>
<button οnclick="embolden(document.getElementById('p1'))">Embolden</button>
</body> -->
<body οnlοad="maketoc(document.getElementById('toc'));">
<div>
<div id="toc"></div>
</div>
<h1>第一章 文档对象模型</h1>
<h2>DOM概览</h2>
<h2>使用DOM的核心API</h2>
<h3>遍历文档</h3>
<h3>给文档增加内容</h3>
<h3>TOC</h3>
<h2>DOM与IE的兼容性</h2>
<h2>DOM与Netscape的兼容性</h2>
</body>
</html>