三、客戶端代碼
下面是程序的啟動頁面Tree.htm:
< HTML > < SCRIPT SRC="Renderer.js" LANGUAGE="JavaScript" >< /SCRIPT > < HEAD >< /HEAD > < BODY ID=bodyTree NAME="bodyTree" OnLoad="GetTree();" > < IFRAME ID=GetData STYLE="display:none" >< /IFRAME > < /BODY > < /HTML > 該頁面裝載時將執(zhí)行Renderer.js中的GetTree函數(shù)。HTML代碼中的IFRAME部分實現(xiàn)了客戶端和服務器端的通訊機制。 JavaScript函數(shù)GetTree的代碼如下:
function GetTree() { if (event.type == 'load') { if (typeof(divTree0)!='object') GetData.window.location.href = 'GetTreeData.asp?Level=0'; } else { try { objManip = eval('divTree' + event.srcElement.getAttribute('ElementId')); if (objManip.style.display == 'none') { objManip.style.display = ''; } else { objManip.style.display = 'none'; } } catch (e) { GetData.window.location.href = 'GetTreeData.asp?Level=' + event.srcElement.getAttribute(' ElementId'); } event.cancelBubble = true; } } 當文檔裝載時,onload事件被觸發(fā),GetTree函數(shù)得以執(zhí)行。函數(shù)檢查容器divTree0是否存在,并為IFRAME(ID為 GetData)讀取第一層節(jié)點(這些節(jié)點的父節(jié)點ID為0)。如前所述,所有的節(jié)點都必須處理鼠標單擊事件,而且事件句柄都是 GetTree函數(shù)。當某個節(jié)點(如div1)接收到一個鼠標事件時,程序將執(zhí)行GetTree函數(shù)中的else部分。如果發(fā)送該事件的節(jié)點已 經(jīng)讀取了子節(jié)點,則程序檢查這些子節(jié)點是否已經(jīng)顯示,然后切換子節(jié)點的顯示狀態(tài),從而實現(xiàn)了該層節(jié)點的擴展或折疊效果。檢 查子節(jié)點是否顯示的if語句封裝在一個try塊內(nèi),因此當子節(jié)點不存在時,程序將執(zhí)行catch部分,調用服務器腳本 GetTreeData.asp讀取子節(jié)點內(nèi)容。最后,程序設置event.cancelBubble = true,目的是禁止上一層容器處理該事件。
服務器腳本GetTreeData.asp返回的HTML代碼類如:
< HTML > < BODY OnLoad="parent.PopulateTree('1|0|節(jié)點1|2|0|節(jié)點2|3|0|節(jié)點3|4|0|節(jié)點4|');" > < /BODY > < /HTML > 可以看到,這里的Onload事件又調用了另外一個JavaScript函數(shù)PopulateTree。PopulateTree函數(shù)代碼如下:
function PopulateTree(strData) { var arrSplitData; var iCnt; var objTempDiv; var objMainDiv; if (strData=='') return; arrSplitData = strData.split("|"); objMainDiv = document.createElement('DIV'); objMainDiv.id = 'divTree' + arrSplitData[1]; objMainDiv.style.cssText = 'position:relative;left:10px;cursor:hand;'; for (iCnt=0;iCnt< arrSplitData.length-1;iCnt+=3) { objTempDiv = document.createElement('< DIV OnClick='GetTree()' OnSelectStart='return false;' > '); objTempDiv.id = 'div' + arrSplitData[iCnt]; objTempDiv.innerHTML = arrSplitData[iCnt+2]; objTempDiv.setAttribute('ElementId',arrSplitData[iCnt]); objTempDiv.setAttribute('ParentElementId',arrSplitData[iCnt+1]); objTempDiv.style.cssText = 'position:relative;cursor:hand;color:red;width:100px;font-size:x-small; '; objMainDiv.appendChild(objTempDiv); } if (arrSplitData[1]=='0') document.body.appendChild(objMainDiv); else eval('div' + arrSplitData[1]).appendChild(objMainDiv); } 我們已經(jīng)知道,PopulateTree函數(shù)由onLoad事件調用,它的參數(shù)是一個字符串,比如上例中的“1|0|節(jié)點1|2|0|節(jié)點 2|3|0|節(jié)點3|4|0|節(jié)點4|”,它是一個“節(jié)點標識|父節(jié)點標識|節(jié)點文本|……”的列表。
如果某個節(jié)點不含子節(jié)點,則該參數(shù)是一個空字符串,此時PopulateTree直接返回。如果子節(jié)點存在,則可以利用split函 數(shù)將子節(jié)點列表以數(shù)組形式保存。再接下來,就可以創(chuàng)建該層節(jié)點的容器,比如divTree0,然后遍歷數(shù)組創(chuàng)建各個節(jié)點,如 div1,div2……。如果某個節(jié)點的父節(jié)點ID為0,說明該節(jié)點沒有父節(jié)點,程序將把容器divTree0加入文檔的BODY;否則當該節(jié)點 的父節(jié)點ID不為0,則創(chuàng)建與其父節(jié)點對應的容器“divTree< < 父節(jié)點ID > >”。在創(chuàng)建節(jié)點的同時指定了鼠標單擊事件的句柄 GetTree函數(shù)。
注:可以修改GetTreeData.asp,使其返回的子節(jié)點列表(即PopulateTree的參數(shù))形式為“節(jié)點ID|節(jié)點文本|……”,也 就是省略父節(jié)點ID,因為任何一組子節(jié)點列表其父節(jié)點總是相同的。同時,還必須修改PopulateTree函數(shù),使其接受兩個參數(shù),第 一個參數(shù)是子節(jié)點列表,第二個是父節(jié)點ID。當節(jié)點數(shù)量較多時,采用這種方法有利于減少數(shù)據(jù)傳輸量,提高效率。
四、其他說明
綜上所述,整個程序的工作過程可以描述為:
瀏覽器讀入文檔,執(zhí)行GetTree函數(shù)。 GetTree調用GetTreeData.asp,讀取第一層節(jié)點數(shù)據(jù),然后回調PopulateTree函數(shù)。 PopulateTree函數(shù)生成divTree0以及節(jié)點div1,div2,……。 用戶單擊任意一個節(jié)點。 GetTree函數(shù)檢查 “divTree< < 節(jié)點ID > >” 是否已經(jīng)存在,如存在則切換子節(jié)點顯示狀態(tài),否則讀取子節(jié)點列表。 GetTreeData.asp返回子節(jié)點列表,回調PopulateTree函數(shù)。 PopulateTree生成相應的容器“divTree< < 父節(jié)點ID > >”,并生成節(jié)點“Div< < 節(jié)點ID1 > >”,“div< < 節(jié)點ID2 > >”……。 重復步驟4。 運行示例程序步驟如下(默認目錄d:Inetpubwwwroot):
創(chuàng)建一個目錄,把所有文件拷貝到該目錄。 在Web服務器上發(fā)布該目錄。 修改Tree.dsn中的數(shù)據(jù)庫路徑。 修改GetTreeData.asp中Tree.dsn文件路徑。 用瀏覽器打開Tree.htm。 示例程序中的IFRAME是隱藏的,如果要顯示它,則請刪除IFRAME的屬性“STYLE="display:none"”,此時還可以查看節(jié)點 的HTML源代碼 (出處:熱點網(wǎng)絡)
|