一个异步即时加载的树控件,JS+Ajax实现.主要原理是页面加载时仅加载一级子树,当点击子树结点时再即时加载其二级结点,往下同理.和TreeView的加载方案完全不同,这对于枝繁叶茂的树的加载效率有明显提高.笔者在加载行政区划信息时,采用单线程递归的同步方式加载要1分多钟,改成非递归后约35秒,后又改成多线程约20秒.而改成异步即时加载的方式后前台基本上感觉不到树的加载.对于更大的树来说效果必然更加可观.代码如下:
示例:
//前台:
//后台
var extendSign = "+";
var shrinkSign = "-";
var noneSign = " ";
var TreeList = null;
function TreeControl(controlID,controlName,CallBackFunc)
{
this.controlID = controlID;
this.CallBackFunc = CallBackFunc;
this.controlName = controlName;
if($(controlID) == null)
{
this.CreateRoot();
CallBackFunc(this,"div_" + this.controlID,-1);
if(TreeList == null)
{
TreeList = new Array();
document.detachEvent('onclick', HideTreeList);
document.attachEvent('onclick', HideTreeList);
}
TreeList.push(this);
}
}
TreeControl.prototype.Show = function(eventSource,solveFunc)
{
this.eventSource = (eventSource == undefined || eventSource == null ? event.srcElement : $(eventSource));
if(solveFunc != undefined && solveFunc != null)
{
this.solveFunction = solveFunc;
}
this.setClickBolder();
var leftpos = 0, toppos = 0;
var ev = this.eventSource;
while(ev.tagName.toUpperCase() != "HTML" && ev.tagName.toUpperCase() != "BODY")
{
leftpos += ev.offsetLeft;
toppos += ev.offsetTop;
ev = ev.offsetParent;
}
$(this.controlID).style.left = leftpos;
$(this.controlID).style.top = toppos + 17;
$(this.controlID).style.display = 'block';
}
TreeControl.prototype.CreateRoot = function()
{
var strHTML = "";
var divObj = document.createElement("div");
divObj.id = this.controlID;
divObj.style.left=(document.body.clientWidth-220)/2;
divObj.style.width="100px";
divObj.style.top="100px";
divObj.style.backgroundColor="#fffff2";
divObj.style.display="none";
divObj.style.height="auto";
divObj.style.zIndex="999";
divObj.style.position="absolute";
divObj.className='layer';
strHTML += "<div id='div_" + this.controlID + "' class='scroll' onclick='" + this.controlName + ".setClickBolder();' style='width:150px; height:250px; overflow:auto' title='树控件' >";
strHTML += "</div>";
strHTML += "<input id='ipt_" + this.controlID + "_SelectData' type='hidden' />";
divObj.innerHTML = strHTML;
document.body.appendChild(divObj);
}
TreeControl.prototype.CreateLeaf = function(parentID,dataStr)
{
var totalHtmlStr = "";
var dataList = (Trim(dataStr) != '' ? dataStr.split('/xFE') : new Array());
totalHtmlStr += " <table id='tbl_" + leafName + "' style='width: auto' border='0' cellspacing='0' cellpadding='0'>";
for(var i=0;i<dataList.length;i++)
{
var curHtmlStr = "";
var leafName = parentID.substring(4)+"_" + i;
var inDataList = dataList.split('/xFD');
curHtmlStr += " <tr>";
curHtmlStr += " <td nowrap style='width: 0%' align='center'>";
curHtmlStr += " <a id='a_" + leafName + "' style='cursor: hand' src='javascript:' onclick='" + this.controlName
+ ".VerifyNode(" + "/"div_" + leafName + "/"," + inDataList[0] + ")' title = '展开[" + inDataList[1] + "]'>" + extendSign + "</a> ";
curHtmlStr += " </td>";
curHtmlStr += " <td nowrap style='width: 100%' align='left'>";
curHtmlStr += " <label id='lbl_" + leafName + "' style='cursor: hand' onclick='" + this.controlName + ".GetData();' title='选择["
+ inDataList[1] + "]' >" + inDataList[1] + "</label>";
curHtmlStr += " </td>";
curHtmlStr += " </tr>";
curHtmlStr += " <tr>";
curHtmlStr += " <td nowrap style='width: 0%' align='center'>";
curHtmlStr += " </td>";
curHtmlStr += " <td nowrap style='width: 100%' align='left'>";
curHtmlStr += " <div id='div_" + leafName + "' style='width: 100%;display:none' border='0' cellspacing='0' cellpadding='0'>";
curHtmlStr += " </div>"
curHtmlStr += " </td>";
curHtmlStr += " </tr>";
totalHtmlStr += curHtmlStr;
}
totalHtmlStr += " </table>";
$(parentID).innerHTML = totalHtmlStr;
if($('a_' + parentID.substring(4)) != null)
{
if(Trim(dataStr) == '')
{
$('a_' + parentID.substring(4)).innerHTML = noneSign;
$('a_' + parentID.substring(4)).style.cursor = '';
$('a_' + parentID.substring(4)).title = "结点[" + $("lbl_"+parentID.substring(4)).innerText + "]已是最底层!";
}
else
{
$('a_' + parentID.substring(4)).innerHTML = shrinkSign;
$('a_' + parentID.substring(4)).title = "折叠[" + $("lbl_"+parentID.substring(4)).innerText + "]";
$(parentID).style.display = 'block';
}
}
}
TreeControl.prototype.GetData = function()
{
var lblObj = event.srcElement;
while(lblObj.tagName != "LABEL")
{
lblObj = lblObj.parentNode;
}
var strData=Trim(lblObj.innerText);
if(typeof(this.solveFunction)=="undefined" || this.solveFunction==null)
{
this.eventSource.value = strData;
}
else
{
this.solveFunction(strData);
}
this.hideBodyMenu();
}
TreeControl.prototype.VerifyNode = function(parentID,currid)
{
var aObj = event.srcElement;
while(aObj.tagName != 'A' && aObj.tagName != 'BODY')
{
aObj = aObj.parentNode;
}
if(aObj.tagName != 'A' || aObj.innerHTML == noneSign)
{
return;
}
if(aObj.innerHTML == extendSign)
{
if(Trim($(parentID).innerHTML) == '')
{
this.CallBackFunc(this,parentID,currid);
}
else
{
$(parentID).style.display = 'block';
aObj.innerHTML = shrinkSign;
aObj.title = "折叠[" + $("lbl_"+parentID.substring(4)).innerText + "]";
}
}
else
{
$(parentID).style.display = 'none';
aObj.innerHTML = extendSign;
aObj.title = "展开[" + $("lbl_"+parentID.substring(4)).innerText + "]";
}
}
TreeControl.prototype.setClickBolder = function()
{
this.clickBolder = true;
}
TreeControl.prototype.hideBodyMenu = function()
{
if(this.clickBolder)
{
this.clickBolder = false;
}
else
{
$(this.controlID).style.display = 'none';
}
}
function HideTreeList()
{
for(var i=0 ; i<TreeList.length ; i++)
{
TreeList.hideBodyMenu();
}
}
示例:
//前台:
var tree = new TreeControl("tree","tree",TreeGetData);
function TreeGetData(control,parentID,currid)
{
Test.GetAreaInfo(currid,SolvFunc);
function SolvFunc(response)
{
control.CreateLeaf(parentID,response.value);
}
}
//后台
[Ajax.AjaxMethod]
public string GetAreaInfo(int parentId)
{
string condition = "codesetid = 'AB' and parentid = ";
condition += (parentId == -1 ? "codeitemid" : Convert.ToString(parentId) + " and parentid <> codeitemid");
DataTable dt = DBTableOpt.Select("codeitemid,codeitemdesc", "codeitem", condition, null, null, "codeitemid");
return PubBaseOpt.getCellString(0, 100, "/xFE", "/xFD", dt, out curPageNum, out totalPageNum, out totalRecord);
}