原先系統使用xtree讀取數據庫構造的樹,是jsp一次性生成所有的節點的,因為數據量也不大,所以用用還挺好。今天特來興致,決定改造。當點擊父節點的時候,才去數據庫動態的獲取子節點,這樣對于大數據量的系統,性能比較好。
首先下載 http://webfx.eae.net/dhtml/xtree2b/xtree2b-20050606.zip
這包里面有簡單的示例,廢話少說,動手
- <link type="text/css" rel="stylesheet" href="<%=request.getContextPath() %>/css/xtree2.css">
- <link type="text/css" rel="stylesheet" href="<%=request.getContextPath() %>/css/xtree2.links.css">
- <script type="text/javascript" src="<%=request.getContextPath() %>/script/xtree2.js"></script>
- <script type="text/javascript" src="<%=request.getContextPath() %>/script/xloadtree2.js"></script>
首先構造樹的jsp文件要加載相關js和css文件,上面down的zip里面都有,放到你的項目里面
jsp端加入腳本,構造樹
- <div style="left:20px;top:30px;width:100%;">
- <script>
- var tree = new WebFXTree('root node');
- tree.add(new WebFXLoadTreeItem("all node", "/cmsCatalogQueryAction.do?method=tree","javascript:modifyNode('cmsCatalogMaintAction.do?method=new')"));
- tree.showRootNode = false;
- tree.showRootLines = false;
- tree.write();
- </script>
/cmsCatalogQueryAction.do?method=tree是生成相關xml的action地址
javascript:modifyNode('cmsCatalogMaintAction.do?method=new')這個是點擊根節點的時候action的地址,比如鏈接到添加一級節點的頁面,(modifyNode是我項目里面用的js函數,目的是在右邊的frame里面打開后面的參數地址)
tree.showRootNode = false;
tree.showRootLines = false;
為了把all node作為根節點,所以隱藏root node節點
下面看看action端的寫法
- public ActionForward tree(
- ActionMapping actionMapping,
- ActionForm actionForm,
- HttpServletRequest request,
- HttpServletResponse response)
- throws Exception {
- response.setContentType("text/xml; charset=gbk");
- response.setHeader("Cache-Control", "no-cache");
- response.setDateHeader("Expires", 0);
- PrintWriter out = response.getWriter();
- String id = request.getParameter("id");
- Document doc = new Document(new Element("tree"));
- if (StringUtils.isEmpty(id)) {
- List list = getCmsFacade().getRootCatalogListByDomainID(HConstant.currentDomain.getId());
- transfer(doc, list);
- } else {
- List list = getCmsFacade().getCmsCatalogListByParentID(id);
- transfer(doc, list);
- }
- Format format = Format.getCompactFormat();
- format.setEncoding("gbk");
- format.setIndent("/t");
- XMLOutputter xout = new XMLOutputter(format);
- xout.output(doc, out);
- out.flush();
- out.close();
- return null;
- } // end tree
- private void transfer(Document doc, List r) {
- for (Iterator it = r.iterator(); it.hasNext();) {
- CmsCatalog one = (CmsCatalog) it.next();
- Element tree = doc.getRootElement();
- Element inner = new Element("tree").setAttribute("text", one.getZhCaption());
- tree.addContent(inner);
- inner.setAttribute("src", "/cmsCatalogQueryAction.do?method=tree&id="+ one.getId());
- inner.setAttribute("action", "javascript:refun('"+one.getId()+"','"+one.getZhCaption()+"')");
- }
- }
這邊的代碼要根據你的業務來寫了,我的欄目對象叫CmsCatalog。生成xml使用了jdom,代碼中的Document 和Element這些class都是這個包里面的
getCmsFacade().getRootCatalogListByDomainID是獲取本站點的所有一級欄目,
getCmsFacade().getCmsCatalogListByParentID是根據父ID得到下一級欄目列表,(不是得到所有的子,只獲取直接下級的子)
獲取到欄目list后,要轉換成對應xml規范,參看transfer方法,轉后的數據格式如下,以根節點為例
- <?xml version="1.0" encoding="gbk" ?>
- - <tree>
- <tree text="關于我們" src="/cmsCatalogQueryAction.do?method=tree&id=4028e44919c7e5290119c7e754330001" action="javascript:refun('4028e44919c7e5290119c7e754330001','關于我們')" />
- <tree text="新聞頻道" src="/cmsCatalogQueryAction.do?method=tree&id=4028e4491a04a4fb011a04ab42ae005e" action="javascript:refun('4028e4491a04a4fb011a04ab42ae005e','新聞頻道')" />
- <tree text="產品與解決方案" src="/cmsCatalogQueryAction.do?method=tree&id=4028e4491a80ec5b011a811c1b570002" action="javascript:refun('4028e4491a80ec5b011a811c1b570002','產品與解決方案')" />
- <tree text="服務與支持" src="/cmsCatalogQueryAction.do?method=tree&id=4028e4491a900271011a9042bb810003" action="javascript:refun('4028e4491a900271011a9042bb810003','服務與支持')" />
- <tree text="英才導航" src="/cmsCatalogQueryAction.do?method=tree&id=4028e4491a33c105011a33d2f5b90002" action="javascript:refun('4028e4491a33c105011a33d2f5b90002','英才導航')" />
- <tree text="聯系我們" src="/cmsCatalogQueryAction.do?method=tree&id=4028e4491a805657011a80d2cae90006" action="javascript:refun('4028e4491a805657011a80d2cae90006','聯系我們')" />
- </tree>
當點擊一個節點的時候,會執行refun這個js函數,為什么不直接寫一個鏈接呢? 因為一個欄目樹可能在很多地方都要用到,點擊樹的鏈接也因此可能不一樣了,所以不能在action寫死具體地址。構造樹的jsp頁面直接寫一個refun函數就ok了,自己去定義點擊節點時候的操作。服務端返回了兩個欄目參數給refun函數,一個是id,一個中文名稱
當點擊最后一級節點的時候,會提示加載節點錯誤的信息,這個是xloadtree的一個bug,我們手動修改下就ok了,編輯xloadtree2.js文件,找到
if (count == 0) {
jsNode.errorText = "Error loading " + jsNode.src + " (???)";
}
修改為
if (count == 0) {
jsNode.remove(jsNode._loadingItem);
t.setSuspendRedraw(false);
jsNode.update();
return;
}
當返回的xml 為空的時候,把節點設置為無子節點
到此,動態加載樹就完成了,相當簡單吧,你唯一要做的就是合理的把你的欄目列表從數據庫取出來,然后正確的填充到xml里面,就ok了