2010年10月17日 星期日

JavaScript DOM模型操作

Document Object Model(DOM) 能將HTML視為XML處理
對於JavaScript來說,可以藉此做到動態處理
DOM將網頁視為節點構成的階層樹,如下圖所示:

階層樹的頂點是Document,並往下聯繫到各個網頁元件形成的節點
HTML元件節點也被稱為元件節點(Element node)
網頁元件的文字內容則儲存在元件下的文字節點(Text node)
Attribute是元件的屬性,可以透過Element node取得,但不會直接出現在階層樹裡

document 提供了 getElementById()、getElementsByTagName()方法來導引到其它子節點

getElementById() 可以從整份DOCUMENT中取得有指定id的元素
getElementsByName() 與 getElementsByTagName() 也是有著類似作法的函式

不過因為後兩個函式取得的元件有可能為複數,所以需要用陣列存取
如:getElementsByTagName("div")[0]  取得第一個div元素

getElementById()一般是最常用到的函式
id在每個DOCUMENT中只能是獨特的,name卻有可能是重複的
此外, getElementsByName()在非IE的瀏覽器可能行不通


在各個節點可以取得我們需要的特性:
nodeName - 回傳節點的標籤名稱,如<div>會回傳 DIV
nodeValue - 儲存於節點的值,只限文字與屬性節點使用
nodeType - 回傳節點型態
                   element node回傳1,attribute node回傳2
                   text node回傳3,包括換行符號等
childNodes - 包含節點下所有子節點的陣列,以出現在HTML碼裡的順序排列
childElementCount - 回傳 element 子代 (child) 元素的數量
parentNode - 回傳其父節點
firstChild - 節點下的第一個子節點
lastChild - 節點下的最後一個子節點
nextSibling - 下一個節點(節點範圍不限同一層)
previousSibling - 上一個節點(節點範圍不限同一層)

較特殊的:
document.baseURI - 取得目前文件的路徑(即目前網址)
style - 設定或取得某個節點的屬性,類似CSS設定,如:node.style.width='100px';
className - 設定或取得節點的class屬性


另外說明.children屬性
這個也是相當常被看到的屬性,使用的方式也很類似childNodes
差別在於
1.childNodes是W3C標準,children則不是(但基本上browser都會實作這個屬性)
2.childNodes會回傳 NodeList,children則是HTMLCollection
3.children回傳的內容不包括 text node等,僅回傳 element node
   所以如有下列的情形
   <div>
         <a></a>
   </div>

   像這樣節點間存在換行符號、空白
   用 childNodes.firstChild 便有可能取不到我們真正想要的 node(視 browser 實作情形)

可以在節點上使用的方法則有
appendChild() - 加入子節點
cloneNode() -  參數設定為 true 可複製該元素的所有子代 (child)
                        設定為 false 則通常只會複製一個文字節點
    範例:
    var demo = document.getElementById("demo");
    var demo2 = demo.cloneNode(true);
    document.body.appendChild(demo2);

hasChildNodes() - 回傳boolean值,判斷有無子節點
hasAttributes() - 回傳是否有無屬性值
insertBefore() - 使用方式:parentNode.insertBefore(newElement, referenceElement)
removeChild() - 刪除子節點,使用方式:parentNode.removeChild(node)
replaceChild() - 使用方式:node.replaceChild(newChild, oldChild);
getAttribute() - 取得節點的某項屬性,如:node.getAttribute("nowrap")
setAttribute() - 設定節點的某項屬性,如:node.getAttribute("height", "100px")
removeAttribute() - 刪除節點的某項屬性,如:node.getAttribute("nowrap")


使用範例:document.getElementsByTagName("div")[0].childNodes[1].nodeValue = 1;
當然範例要先確定childNode[1]底下只有一個節點,否則會得不要想要的效果
如果不確定所要更改的節點內容是否有多個子節點
那麼更改的時候就要先清除所有的子節點後,再新增有新內容的新子節點,如:
var node = document.getElementById("target");
//有子節點的話,firstChild回傳true
while(node.firstChild){ node.removeChild(node.firstChild); }
node.appendChild(document.createTextNode("alter OK"));

當然先寫好一個替換節點文字內容的函式,通常是個方便的選擇,如:
function replaceNodeText(id, newText){
   var node = document.getElementById(id);
   while(node.firstChild){ node.removeChild(node.firstChild); } 
   node.appendChild(document.createTextNode(newText));
}

DOM提供了透過節點調整CSS的機制
透過節點物件的className特性可以操作網頁元件的類別(class)特性
如:document.getElementById("target").className = "deco2";
節點的style特性提供對單一樣式性質的存取
如:document.getElementById("target").style.visibility = "hidden";

前面看到過的createTextNode()只能建立純粹的文字內容
接著要提的createElement() 可以用來建立任何的HTML元件
建立段落文字的範例:
var newElem = document.createElement("p");
newElem.appendChild(document.createTextNode("Hello World"));
document.getElementById("target").appendChild(newElem); 

加入的段落文字會以符合標準的形式呈現 -> <p>Hello World</p>

沒有留言:

張貼留言