思路: 先查詢出所有數據的根結點,并對每個根結點檢查是不是有子結點,如果有子結點則在顯示時增加"+"圖片,沒有則不添加.但用戶點擊"+"圖片時,則通過AJAX調用邏輯流查詢觸發結點的所有子結點(采用遞歸方式,以每個子結點的父結點屬性從上向下查詢),并隱藏加載到觸發結點后面(以TR形式添加,并設置每個子元素的paraTaskno屬性為父結點taskno(其實仍是以遞歸方式,從上向下給每個子元素的paraTaskno屬性設置父元素的id)
服務端數據: 僅查詢根結點.
html代碼:
<viewlist id="e587ead4-daa3-431e-a0ed-fac40e013850">
<h:form name="page_form" action="com.bos.mp.taskStatistics.TaskStatistics.flow" method="post">
<input type="hidden" name="_eosFlowAction" value="pageQuery" >
<h:hiddendata property="criteria" />
<h:hidden property="page/begin"/>
<h:hidden property="page/length"/>
<h:hidden property="page/count"/>
<h:hidden property="page/isCount"/>
<w:panel id="list_panel" width="100%" title="任務列表">
<table align="center" border="0" width="100%" class="EOS_table">
<tr id="table_header">
<th>
任務名稱
</th>
<th>
項目名稱
</th>
<th>
項目模塊
</th>
<th>
工作占項目比率
</th>
<th>
負責人
</th>
<th>
審核人
</th>
<th>
計劃開始日
</th>
<th>
計劃完成日
</th>
<th>
任務狀態
</th>
<th>
完成率(%)
</th>
<th>
更新日期
</th>
<th>
原因
</th>
<th>
實際完成率(%)
</th>
<th>
實際完成日
</th>
<th>
提前/滯后完成天數
</th>
</tr>
<w:checkGroup id="group1">
<l:iterate property="mpprojectfollows" id="id1">
<%
long temp = 0;
if(null != ((DataObject)pageContext.getAttribute("id1")).getString("proEndDate")){
DataObject t=(DataObject)pageContext.getAttribute("id1");
String d1 = ((DataObject)pageContext.getAttribute("id1")).getString("comDate") == null ? new SimpleDateFormat("yyyy-MM-dd").format(new Date()):((DataObject)pageContext.getAttribute("id1")).getString("comDate");
String d2 = ((DataObject)pageContext.getAttribute("id1")).getString("proEndDate");
temp = RetOrgInfo.daysDifference(d1,d2);
}
if(temp<0 && !((DataObject)pageContext.getAttribute("id1")).getString("taskStatus").equals("完成")){
out.print("<tr class='EOS_table_row' style='background-color:red;' id='"+((DataObject)pageContext.getAttribute("id1")).getString("taskno")+"'>");
}else if(temp<0 && ((DataObject)pageContext.getAttribute("id1")).getString("taskStatus").equals("完成")){
out.print("<tr class='EOS_table_row' style='background-color:orange;' id='"+((DataObject)pageContext.getAttribute("id1")).getString("taskno")+"'>");
}else if(temp>0 && ((DataObject)pageContext.getAttribute("id1")).getString("taskStatus").equals("完成")){
out.print("<tr class='EOS_table_row' style='background-color:green;' id='"+((DataObject)pageContext.getAttribute("id1")).getString("taskno")+"'>");
}else{
out.print("<tr class='EOS_table_row' id='"+((DataObject)pageContext.getAttribute("id1")).getString("taskno")+"'>");
}
%>
<td align="left" >
<l:present property="childTasks" iterateId="id1">
<img src="<%=request.getContextPath() %>/common/skins/default/images/grouppanel/grouppanel_open.gif" onclick="node_click('<b:write iterateId="id1" property="taskno"/>');"/>
</l:present>
<h:hidden iterateId="id1" property="paraTaskno"/>
<a href="#" onclick="javascript:showTaskDet('<b:write iterateId="id1" property="taskno"/>');"><b:write iterateId="id1" property="taskName"/></a>
</td>
<td align="center">
<b:write iterateId="id1" property="projectName"/>
</td>
<td align="center">
<b:write iterateId="id1" property="modName"/>
</td>
<td align="center">
<b:write iterateId="id1" property="taskRate"/>
<l:notEmpty iterateId="id1" property="taskRate">
%
</l:notEmpty>
</td>
<td align="center">
<b:write iterateId="id1" property="planPres"/>
</td>
<td align="center">
<b:write iterateId="id1" property="auditorName"/>
</td>
<td align="center">
<b:write iterateId="id1" property="proStarDate" formatPattern="yyyy-MM-dd"/>
</td>
<td align="center">
<b:write iterateId="id1" property="proEndDate" formatPattern="yyyy-MM-dd"/>
</td>
<td align="center">
<b:write iterateId="id1" property="taskStatus"/>
</td>
<td align="center">
<b:write iterateId="id1" property="actorRated"/>
</td>
<td align="center">
<b:write iterateId="id1" property="actorDate" formatPattern="yyyy-MM-dd"/>
</td>
<td align="center">
<b:write iterateId="id1" property="reason"/>
</td>
<td align="center">
<b:write iterateId="id1" property="auditRate"/>
</td>
<td align="center">
<b:write iterateId="id1" property="comDate" formatPattern="yyyy-MM-dd"/>
</td>
<td align="center">
<%
if(temp<0){
out.print("滯后"+Math.abs(temp)+"天");
}else if(temp>0 && ((DataObject)pageContext.getAttribute("id1")).getString("taskStatus").equals("完成")){
out.print("提前"+temp+"天");
}
%>
</td>
</tr>
</l:iterate>
</w:checkGroup>
<tr>
<td colspan="16" class="command_sort_area">
<div id="pageroot" align="right">
<l:equal property="page/isCount" targetValue="true">
共
<b:write property="page/count"/>
條記錄 第
<b:write property="page/currentPage"/>
頁/
<b:write property="page/totalPage"/>
頁
</l:equal>
<l:equal property="page/isCount" targetValue="false">
第
<b:write property="page/currentPage"/>
頁
</l:equal>
<input type="button" onclick="firstPage('page', 'pageQuery', null, null, 'page_form');" value="首頁" <l:equal property="page/isFirst" targetValue="true">disabled</l:equal> >
<input type="button" onclick="prevPage('page', 'pageQuery', null, null, 'page_form');" value="上頁" <l:equal property="page/isFirst" targetValue="true">disabled</l:equal> >
<input type="button" onclick="nextPage('page', 'pageQuery', null, null, 'page_form');" value="下頁" <l:equal property="page/isLast" targetValue="true">disabled</l:equal> >
<l:equal property="page/isCount" targetValue="true">
<input type="button" onclick="lastPage('page', 'pageQuery', null, null, 'page_form');" value="尾頁" <l:equal property="page/isLast" targetValue="true">disabled</l:equal> >
</l:equal>
</div>
</td>
</tr>
</table>
</w:panel>
</h:form>
</viewlist>
<script>
var jquery = jQuery.noConflict();
//主結點展開/收起
function node_click(taskid){
var el=jquery("#"+taskid).find("img")[0]//event.srcElement
var path=el.src.substr(el.src.lastIndexOf("/")+1)
var prifix=el.src.substr(0,el.src.lastIndexOf("/"))
if(path=="grouppanel_open.gif"){
//顯示結點
var tr=jquery(el).closest("tr");
if(jquery(el).closest("tr").next().css("display")=="none"){
el.src=prifix+"/grouppanel_close.gif";
tr.nextAll("tr[paraTaskno='"+tr.attr("id")+"']").show();
}else{
readchildnodeByAjax(taskid);
jquery(el).trigger("click");
}
}else{
//隱藏結點
el.src=prifix+"/grouppanel_open.gif";
var tr=jquery(el).closest("tr");
recursion_node(tr,false);
}
}
//ajax讀取子結點
function readchildnodeByAjax(taskid){
var myAjax=new Ajax("com.bos.mp.projectfollow.mpprojectfollowbiz.QueryTask.biz");
myAjax.addParam("criteria/_entity","com.bos.mp.projectfollow.dataset.ProTaskQryEntity");
myAjax.addParam("criteria/_expr[0]/paraTaskno",taskid);
myAjax.submit();
//獲取"root/data/mpprojectfollows"結點數組
var nodes=myAjax.getXMLDom().selectNodes("root/data/mpprojectfollows");
for(var i=0;i<nodes.length;i++){
addElement(jquery("#"+taskid),nodes[i]);
}
}
/**
*動態增加tr結點,以請求的服務端數據來遍歷添加結點
*template:html頁面元素;node:服務端數據子實體
*/
function addElement(template,node){
var xml=jquery(node);
var template=addnode(template,xml)
var childnodes=xml.children("childTasks");
for(var i=0;i<childnodes.length&&jquery(xml.children("childTasks")[i]).text()!="";i++){
addElement(template,xml.children("childTasks")[i]);
}
}
/**
*以服務端的子實體對象(xml)構造一個結點添加到html元素(template)
*/
function addnode(template,xml){
var open_gif='<%=request.getContextPath() %>/common/skins/default/images/grouppanel/grouppanel_open.gif';
var close_gif="<%=request.getContextPath() %>/common/skins/default/images/grouppanel/grouppanel_close.gif"
//從模板結點構造出目標結點tr
var curtr=template.clone().insertAfter(template).hide()
.attr("id",jquery(xml.find("taskno")[0]).text())
.attr("paraTaskno",jquery(xml.find("paraTaskno")[0]).text());
//首個TD結點
var firsttd=jquery(curtr.children("td")[0]);
var td=jquery(curtr.children("td")[0]).css("padding-left",parseInt(firsttd.css("padding-left"))+10+"px")
.empty();
jquery("<a href='#'></a>").text(jquery(xml.find("taskName")[0]).text())
.bind("click",function(){
showTaskDet(jquery(xml.find("taskno")[0]).text());
}).appendTo(td);
var img=jquery("<img/>").prependTo(td);
if(jquery(xml.children("childTasks")[0]).text()!=""){
//非葉子結點,綁定事件
img.attr("src",open_gif);
img.bind("click",function(){
var path=jquery(this).attr("src");
var tr=jquery(this).closest("tr");
if(path==open_gif){
jquery(this).attr("src",close_gif);
recursion_node(tr,true);
}else{
jquery(this).attr("src",open_gif);
recursion_node(tr,false);
}
})
}else{
//葉子結點
img.attr("src",close_gif);
}
td.next().empty()//text(jquery(xml.find("projectName")[0]).text())
.next().empty()//text(jquery(xml.find("modName")[0]).text())
.next().text(jquery(xml.find("taskRate")[0]).text())
.next().text(jquery(xml.find("planPres")[0]).text())
.next().text(jquery(xml.find("auditorName")[0]).text())
.next().text(jquery(xml.find("proStarDate")[0]).text())
.next().text(jquery(xml.find("proEndDate")[0]).text())
.next().text(jquery(xml.find("taskStatus")[0]).text())
.next().text(jquery(xml.find("actorRated")[0]).text())
.next().text(jquery(xml.find("actorDate")[0]).text())
.next().text(jquery(xml.find("reason")[0]).text())
.next().text(jquery(xml.find("auditRate")[0]).text())
.next().text(jquery(xml.find("comDate")[0]).text())
.next().text("");
return curtr;
}
/**
*層疊遞歸方式顯示或隱藏結點
* node:jquery對象;isshow:boolean值
*/
function recursion_node(node,isshow){
var open_gif='<%=request.getContextPath() %>/common/skins/default/images/grouppanel/grouppanel_open.gif';
var close_gif="<%=request.getContextPath() %>/common/skins/default/images/grouppanel/grouppanel_close.gif"
var nodes=node.nextAll("tr[paraTaskno='"+node.attr("id")+"']")
for(var i=0;i<nodes.length;i++){
recursion_node(jquery(nodes[i]),isshow);
if(!isshow){
jquery(nodes[i]).hide();
}else{
jquery(nodes[i]).show();
}
}
if(nodes.length>0){
jquery(node.find("img")[0]).attr("src",!isshow?open_gif:close_gif)
}
}
</script>