走訪文件



只要你取得了文件中某個節點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>

這份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)
                   |-學習筆記       

如果是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>

則以下可以取得Test 1 Here的內容:
var testDiv = document.getElementById('test');
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;