只要你取得了文件中某個節點(Node),你就可以取得它的父節點、子節點、鄰接節點等,相關的特性有:
- parentNode可取得父節點
- previousSibling前鄰接節點
- nextSibling後鄰接節點
- firstChild首個子節點
- lastChild最後一個子節點
- childNodes所有直接子節點
以 W3C DOM 簡介 中的文件為例:
<html>
<head>
<title>首頁</title>
</head>
<body>
<h1>Hello!World!</h1>
<a href="Gossip/index.html">學習筆記</a>
</body>
</html>
<head>
<title>首頁</title>
</head>
<body>
<h1>Hello!World!</h1>
<a href="Gossip/index.html">學習筆記</a>
</body>
</html>
這份HTML文件,假設你使用document.body取得body節點,假設就是被body變數參考,從body開始,各特性可以取得的節點標示如下(假設如Internet Explorer中不考慮換行與縮排的文字節點):
document
|-html(body.parentNode)
|-head(body.previousSibling)
| |-title
| |-首頁
|
|body
|-h1(body.firstNode)
| |-Hello!World!
|
|-a(body.lastNode)
|-學習筆記
|-html(body.parentNode)
|-head(body.previousSibling)
| |-title
| |-首頁
|
|body
|-h1(body.firstNode)
| |-Hello!World!
|
|-a(body.lastNode)
|-學習筆記
如果是body.childNodes,則取得 NodeList 物件,這是一個類似陣列具有索引存取的特性,索引從0開始就是第一個子節點,所以body.childNodes[0]就是h1節點,body.childNodes[1]就是a節點。
(NodeList規範的是使用item()搭配索引來取得元素,不過在JavaScript中,可以直接使用[]搭配索引來取得元素。)
實際上比較不建議透過以上特性來存取元素,因為這會強烈依賴文件結構,一旦調整了文件內容,程式可能就無法運作了。比較常的作法是,如果節點是元素(Element),透過元素的getElementsByTagName()、getElementById()方法來取得節點。例如若想取得文件中所有的<p>標籤所代表的元素,則可以如下:
var ps = document.getElementsByTagName('p');
由於文件中可能不只有一個<p>標籤,取得的節點也可能不只一個,getElementsByTagName()取得的是NodeList,可依標籤在文件中的順序使用索引取得對應節點。例如,document.getElementsByTagName('p')[0]取得的就是文件中第一個出現的<p>標籤對應的節點。
如果標籤上定義有id屬性,則可以使用getElementById()來取得元素。例如文件中有個<div>:
<div id="console">Console here</div>
則可以透過以下取得:
var console = document.getElementById('console');
id在文件中基 本上應該是獨一無二的,如果文件中出現重複的id,那getElementById()取得的,會是文件中第一個符合的元素。只要是元素 (Element),都會有getElementsByTagName()、getElementById(),透過這些方法取得的元素,就是該元素下的子元素。例如文件有以下的內容:
<div id="test">
<div>Test 1 Here</div>
<div>Test 2 Here</div>
</div>
<div>Test 1 Here</div>
<div>Test 2 Here</div>
</div>
則以下可以取得Test 1 Here的內容:
var testDiv = document.getElementById('test');
var test1DivHtml = testDiv.getElementsByTagName('div')[0].innerHTML;
var test1DivHtml = testDiv.getElementsByTagName('div')[0].innerHTML;
innerHTML可以取得標籤內含之HTML,以字串形態傳回,innerHTML不是標準特性,不過幾乎所有瀏覽器都支援它,事實上,HTML 5已將innerHTML納入標準。
如果是HTMLDocument,則還會有個getElementsByName()方 法,只要標籤上有設定name屬性,就可以使用這個方法來取得對應元素。HTML文件中document就是HTMLDocument,所以就可以使用這 個方法。標籤的name屬性值可以重複,所以getElementsByName()取得的不只一個元素,會以NodeList收集符合的元素。
取得某個節點或元素,自然會想要知道有關這個節點或元素的一些資訊。例如方才使用innerHTML取得元素內含的HTML就是一個例子。另外,經常地,會想要得知元素的屬性為何,例如取得最上面列出的HTML文件中,<a>的href屬性:
var href = document.getElementsByTagName('a')[0].href;
如果要以標準的作法,則可以透過getAttribute()方法來取得標籤的屬性值。例如:
var href = document.getElementsByTagName('a')[0].getAttribute('href');
使用標準的作法,好處是處理像class屬性這樣的東西比較方便。例如有個標籤:
<div id="console" class="demo">DEMO</div>
如果要用特性的方式取得,由於class是保留字,必須改用className:
var clzName = document.getElementById('console').className;
但使用標準作法,在Firefox中可以這麼寫:
var clzName = document.getElementById('console').getAttribute('class');
不過,其實getAttribute()接受的名稱,存在著瀏覽器差異性,在Internet Explorer中以上是沒作用的,而必須寫:
var clzName = document.getElementById('console').getAttribute('className');
<label>的for屬性也是類似,由於for是JavaScript的關鍵字,使用特性取得時,必須改用htmlFor:
var htmlFor = document.getElementById('someLabel').htmlFor;
但使用標準方法的話,在Firefox中可以這麼寫:
var htmlFor = document.getElementById('someLabel').getAttribute('for');
但在Internet Explorer中仍必須:
var htmlFor = document.getElementById('someLabel').getAttribute('htmlFor');
要以特性方式要取得標籤設置的屬性,特性名稱要注意大小寫的問題,通常會是駝峰式命名。例如要取得HTML中設置的屬性如cellspacing、colspan、frameborder、maxlength、readonly、rowspan、tabindex、usemap等,要透過DOM的特性取得則必須是cellSpacing、colSpan、frameBorder、maxLength、readOnly、rowSpan、tabIndex、useMap等。
若使用getAttribute()則通常不用注意大小寫。例如若要取得某個<input>元素的readonly屬性,則使用getAttribute('readonly')、getAttribute('readOnly')、getAttribute('Readonly')等任意大小寫組合都是可以的。
float特性是JavaScript的保留字(雖然目前沒有使用),所以標準使用了cssFloat名稱,在Internet Explorer中則是使用styleFloat。
或許存取屬性最常見的,就是取得表單中某個<input>標籤中的value屬性。例如:
<input id="username" name="user" value="caterpillar">
你可以透過以下來取得欄位值:
var username = document.getElementById('username').value;
有個初學者常犯的錯誤,例如,想取得HTML文件中<a>標籤間的文字,卻撰寫如下:
var text = document.getElementsByTagName('a')[0].value;
這是錯的!<a>上面並沒有value屬性,對應的物件上也沒有value特性,而且要記得,文字也是一個節點,所以,你要先取得文字節點,也就是<a>的子節點,再使用data(定義在Text)或nodeValue(定義在Node)取得文字本身:
var a = document.getElementsByTagName('a')[0];
var text = a.firstChild.data;
var text = a.firstChild.data;