則這段Html代碼的顯示效果為
分析這段Html代碼,讀者可以看到,每一個節點都占據一個表格行,節點文本後面還跟著一個Table來容納子節點。如此循環則使用表格套表格的方式實現了一個樹狀列表結構。
Html中,對於每一個節點都定義了一個惟一的編號,比如“NodeID”,在實際應用中則可以是任意樣式的ID號,而且每一個節點分成4個部分。首先是前面的展開收縮控制元素。用一個圖片元素來表示,當節點展開時使用圖標,當節點收縮時使用圖標。該圖片元素編號為“NodeID_expend”,占據了節點表格行的第一個單元格。由於樹狀結構有同層節點連接線,若節點不是上級節點的最後一個子節點則設置第一個單元格的背景圖片來模擬顯示同層節點連接線。
節點表格行的第二個單元格用來放置節點的圖標,文本和子節點的表格。每一個節點都有一個圖標,使用IMG元素來展示,元素編號是“NodeID_icon”,而且若有子節點,則節點可以展開和收縮,此時節點的圖標是不同的,需要動態設置。最典型的就是節點展開時使用圖標,而節點收縮時使用圖標,當然兩個圖標是可以一樣的。這裡使用擴展屬性“SrcBack”來設置節點第二個圖標的圖片地址,當節點展開或收縮時可以將圖片元素的SrcBack屬性值和標准的Src屬性值進行互換即可實現節點圖標的變化。
節點圖標後面就是用一個A標簽來顯示節點文本了,這個元素的編號為“NodeID_text”。
若節點有子節點,則在節點文本後面放置一個Table 元素來顯示子節點。該表格的編號為“NodeID_table”。這個表格裡面也是一個表格行來顯示一個節點數據。當用戶點擊節點的展開和收縮標記時,筆者就可以編寫腳步來控制容納子節點的Table對象的display的樣式值來顯示或隱藏這個表格,從而實現子節點的展開和收縮。
HTML代碼設計後,筆者開發的WEB控件的最終的目標就是生成這樣的Html代碼,其生成過程有很多種,有字符串拼湊的,有在服務器端用C#程序生成,也有在客戶端用Javascript腳本代碼來生成。在這裡使用XSLT來生成Html代碼,並支持在服務器端和客戶端生成代碼。
腳本設計
基本的Html代碼設計出來後,接著就開始設計客戶端腳本,使得這個靜態的樹狀列表具有動態的效果。這裡采用Javascript腳本語言,樹狀列表的動態效果就是用戶鼠標點擊某個節點時,若該節點有子節點,則設置包含子節點的表格元素在可見和不可見的狀態的切換,而且同時更新元素的圖標來表示節點的展開收縮狀態,此外還設置節點的文本為高亮度顯示來表示該節點處於選擇狀態。
讀者知道HTML的CSS樣式控制中有一個名為“display”的樣式,若設置“display”的值為“none”時則HTML元素不可見而且不占地方,就好像這個元素從來就沒有存在過,若設置“display”樣式為空字符串時,則Html元素是正常顯示。Javascript腳本就可以修改子節點表格元素的“display”樣式來顯示或隱藏子節點列表。
在Javascript中,很多HTML元素有“getAttribute”和“setAttribute”函數,用來讀取和設置擴展屬性,在上面的Html設計中,筆者對顯示節點圖標的圖片元素定義了一個名為“SrcBack”的非標准屬性。在Javascript中,可以使用代碼 “obj.getAttribute(“SrcBack”)”來獲得該屬性值,使用“obj.setAttribute(“SrcBack”,”新數據”)”來設置該屬性值;在IE浏覽器中,開發人員可以使用更簡潔的方式,直呼其名的獲得和設置擴展屬性值,也就是使用“obj.SrcBack”屬性,但這是微軟對Javascript和HTML DOM的擴展,只適用於IE,其他浏覽器是不支持的,為了使得控件具備一定的兼容性,筆者這裡使用“getAttribute”和 “setAttribute”這種符合Html國際標准的編程接口。
在腳本程序中有個很重要的問題是如何加載XML和XSLT文檔。很多時候這裡的XML文件是動態生成的,而XSLT文檔是事先編制好的。一般的需要三個文檔,一個是包容樹狀列表的主HTML頁面,一個是生成XML文檔的動態服務器頁面,還有一個是保存在服務器上的靜態的XSLT文件。這三個文件分開提供,則不利於程序的編寫和部署,為此這裡采用微軟IE浏覽器所特有的XML數據島(XML Island)的功能,將XML文檔和XSLT文檔嵌入到HTML文檔中,從而僅僅依賴一個Html文檔即可生成樹狀列表。
在Html中使用標簽XML來定義一個XML數據島元素。其范例為
<XML ID="XMLIslandID">
<METADATA>
<AUTHOR>John Smith</AUTHOR>
<GENERATOR>Visual Notepad</GENERATOR>
<PAGETYPE>Reference</PAGETYPE>
<ABSTRACT>SpecifIEs a data island</ABSTRACT>
</METADATA>
< /XML>
開發人員既可以使用它的src屬性來指定動態加載的XML文檔的URL地址,也可以直接在XML標簽之間填寫XML代碼。在Javascript 中,開發人員可以使用XML數據島對象的XMLDocument屬性來獲得XML文檔對象,也就是調用 “XMLIslandID.XMLDocument”語句,開發人員還可以使用響應它的“onreadystatechange”事件來執行該XML數據加載完畢後的處理。
XML數據島是IE浏覽器的特有的功能,其他浏覽器不支持XML數據島。關於XML數據島的詳細信息可參考MSDN中的相關說明。若要使得控件能在多個浏覽器中運行,則不得使用XML數據島。此處為了開發方便就采用XML數據島技術,不過這使得控件只能用於IE浏覽器。