HTML DOM
DOM Core(核心)提供HTML與XML文件瀏覽、處理和維護階層架構的功能。主要有二大功能:- 瀏覽(Navigator):走訪各節點
- 參考(Reference):存取節點
提供一致的走訪方式,只要建立好樹狀結構,所有能走訪到的節點就是標籤物件,文字節點都可以使用相同的nodeValue屬性更改其內容。
DOM HTML
HTML專屬的DOM API,提供現成的物件模型。需使用id/name屬性或forms[]、images[]等物件集合才能取得標籤物件, 而且每種標籤物件都擁有不同的屬性。DOM Core可使用在HTML與XML,DOM HTML則針對HTML。
每一節點都是一個物件
- DOM HTML提供各節點物件的屬性和方法
- DOM Core提供屬性來走訪節點
W3C DOM只能更改文字節點的內容,其它標籤物件的屬性和方法還是來自DOM HTML。
轉換為節點樹
<table> <tbody> <tr><td>HTML</td><td>CSS</td></tr> <tr><td>Javascript</td><td>jQuery</td></tr> </tbody> </table>
瀏覽器會將由伺服器所傳遞過來的HTML轉換為一節點樹,節點樹一定由html元素為根節點,html底下一定有兩個子點節,head元素子節點與body元素子節點。我們可以把這一層一層的關係畫成圖,此圖又稱節點(樹)圖。
節點(樹)圖
以上面table結構為例,圖一:節點(樹) |
節點(樹狀)結構:
- 下一層的子節點 → Child Node → tbody是table的Child Node
- 上一層的父節點 → Parent Node → table是tbody的Parent Node
- 左右節點(兄弟) → Sibling Node → tr與tr或tr之下td與td,各為Sibling Node
- 最下層葉節點 → Leaf Node → td為Leaf Node
- 文字節點(HTML的內容) → Text Node → HTML/CSS/Javascript/jQuery
在轉換一般table時需注意,要先將table轉換成HTML 4.0版的表格,即擁有<tbody>標籤,這樣在訪問時,才不會出錯。
另注意<font>,IE在轉換時,會在<font>後多加一個文字節點#text,目前HTML標準已不建議使用<font>標籤,請改用CSS。
在DOM中有3種節點
- 元素節點:element node,各種標籤便是這些元素節點的名稱,元素節點可以包含其他元素,唯一沒有被包含只有根元素<html>
- 屬性節點:attribute node,屬性節點總是被包含在元素節點之中,例<a href="http://blog.kkbruce.net">KKBruce Blog</a>,a是元素節點名稱,href是屬性節點名稱
- 文字節點:text node,標籤裡具體的文字內容,網頁最終目的是向使用者展示內容
W3C DOM屬性
名稱 | 說明 | 類型/傳回類型 |
---|---|---|
firstChild | 傳回第一個子節點childNodes物件集合,包含此節點下所有的子節點 | Node |
lastChild | 傳回最後一個子節點的childNodes物件集合,包含此節點下所有的子節點 | Node |
parentNode | 傳回父節點的物件,如已是根節點,傳回null | Node |
nextSibling | 傳回下一個兄弟節點物件,如已是最後一個節點,傳回null | Node |
previousSibling | 傳回上一個兄弟節點物件,如已是第一個節點,傳回null | Node |
nodeName | 傳回節點的HTML標籤(英文大寫)名稱 | String |
nodeType | 傳回節點種類,1是標籤(element node)、2是屬性(attribute node)、3為文字(text node) | Number |
specified | 布林值,傳回在HTML標籤是否有設定指定的屬性值 | Boolean |
W3C DOM讀寫屬性
名稱 | 說明 | 類型/傳回類型 |
---|---|---|
nodeValue | 存取文字節點(text node),其他種類的節點傳回null | String |
W3C DOM物件集合
W3C DOM物件集合可以取得下一層子節點和節點的屬性。名稱 | 說明 | 類型/傳回類型 |
---|---|---|
attributes | 節點屬性的物件集合,可以直接使用名稱來存取,僅用於元素節點 | NameNodeMap |
childNodes | 所有子節點的物件集合(Array),方法item(i)可訪問第i+1個節點 | NodeList |
在IE中可以直接使用id/name屬性來取得指定的節點物件,但用此方法實作的程式碼相容性不佳, 建議先使用getElementById("id")來取得指定的節點物件,然後再實作以確保Browser相容性。例如,
// 相容性不好 myid.childNodes[0].firstChild.nodeValue = "ASP.NET MVC"; // 相容性好 var objValue = document.getElementById("myid"); objValue.childNodes[0].firstChild.nodeValue = "ASP.NET MVC";
IE與其他Browser中childNodes走訪不同問題
我們在使用childNodes走訪節點時,IE會依順序走訪各元素節點,但其他瀏覽器不光是元素節點,連它們之間的空格也被當成子節點計算。例如,<ul id="comicList"> <li>航海王</li> <li id="Naruto">火影忍者</li> <li>海棉寶寶</li> <ul>
可以使用以下JavaScript在IE與其他瀏覽器測試,
var eleUL=document.getElementById("comicList"); var listName=""; if (ele.hasChildNodes()) { var eleLI = eleUL.childNodes; for (var i=0,len=eleLI.length;i<len;i++){ listName += eleLI[i].nodeName + "\n"; } alert(listName); }
在IE的測試結果:
- LI
- LI
- LI
在Firefox測試結果:
- #text
- LI
- #text
- LI
- #text
- LI
解決瀏覽器走訪不同問題
function nextSib(node){ var tempLast = node.parentNode.lastChild; //取得node的最後一個節點 if (node ==tempLast) { //是否為最後一個節點 return null; } var tempObj = node.nextSibling; //非最後一個,可找下一個Node while ( tempObj.nodeType!=1 && tempObj.nextSibling!=null) //nodeType不是元素節點且不是最後一個,即找到元素節點為止 tempObj = tempObj.nextSibling; //往下找下一個 return (tempObj.nodeType==1) ? tempObj:null; //如果是元素節點,傳回節點本身,否則傳回null }
function prevSib(node){ var tempFirst = node.parentNode.firstChild; //取得node的第一個節點 if (node ==tempFirst) { //是否為第一個節點 return null; } var tempObj = node.previousSibling; //非第一個,可往上找上一個Node while ( tempObj.nodeType!=1 && tempObj.previousSibling!=null) //nodeType不是元素節點且不是第一個,即找到元素節點為止 tempObj = tempObj.previousSibling; //往上找上一個 return (tempObj.nodeType==1) ? tempObj:null; //如果是元素節點,傳回節點本身,否則傳回null }
我們可以透過這兩個函式來走訪,而不用擔心相容性問題。
var eleLI = document.getElementById("Naruto"); var nextItem = nextSib(eleLI); var preItem = prevSib(eleLI); if (nextItem != null) //傳回不是null,是元素節點 ...
W3C DOM方法
W3C DOM提供方法能建立、刪除、複製、交換、取代節點。名稱 | 範例 | 說明 |
---|---|---|
appendChild | obj(父). | 在obj(父)節點新增子節點 |
cloneNode | objNew = objDup. | 複製objDup節點的新節點物件, |
createElement | objNew = document. | 建立一個HTML節點物件 |
createTextNode | objNew = document. | 建立文字節點 |
hasChildNodes | objNode. | 檢查節點是否擁有子節點, |
insertBefore | obj(父). | 在obj(父)節點前插入一個子節點obj(子), |
removeChild | obj.parentNode. | 先找到要刪除的節點,透過 |
replaceChild | obj.parentNode. | 先找到要替換的節點, |
getAttribute | obj.getAttribute | 讀取obj的attr屬性值, |
setAttribute | obj.setAttribute | 設定 |
insertAfter()函式
DOM只有提供insertBefore()在目標元素之前插入新元素,或是appendChild()在父元素的childNodes尾新增新元素, 如果需要在特用元素後插入新元素,需自行撰寫。function insertAfter(newElement, targetElement){ // 取得目標元素的上層節點 var tParent = targetElement.parentNode; // 檢查是否有子元素 if (tParent.lastChild == targetElement) // 附加至子節點後 tParent.appendChild(newElement); else // 新增至節點之前 tParent.insertBefore(newElement, targetElement.nextSibling); }
新增HTML Tag步驟
- 建立節點
- 進行處理
建立節點
// 新增HTML節點 var objNew = document.createElement("P"); // 新增文字節點 var objText = document.createTextNode("新增說明文字");
進行處理
// 將objNew節點加入objNode節點最後面 objNode.appendChild(objNew); // 將objText文字節點加入objNew節點之後 objNew.appendChild(objText);
例如,在一個空的<table>可以一層一層加上<tr>、<td>來自由動態產生你所想要的<table>。
改變節點文字的安全步驟
- 刪除所有子節點:removeChild()
- 根據新內容,建立新內容節點:createElement(),createTextNode()
- 將新內容節點,附加在目標節點之下:appendChild()
function replaceNodeText(id, newText){ var node=document.getElementById(id); while (node.firstChild) node.removeChild(node.firstChild); node.appendChild(document.createTextNode(newText)); }
DOM與CSS樣式
DOM提供了透過節點取用樣式的途徑。className屬性:提供對節點樣式類別的存取。
alert(ele.className); ele.className = "highlight";
style屬性:提供對單一樣式的存取。
ele.style.visibility = "hidden"; ele.style.display = "none";
表格裡的"範例",例如「obj.parentNode.replaceChild(newNode,oldNode)」,不會自己"斷行",造成會超出頁面的問題,這我在想想怎麼改進。
回覆刪除也謝謝你的回應!
我已經修改表格"斷行"問題,在主流瀏覽器及 1024 * 768 Monitor 上都能正常斷句。
回覆刪除謝謝分享,在寫多檔上傳,要加上移除檔案,再找怎麼移除節點,就借用了prevSib方法,感謝。
回覆刪除