www.pudn.com > tree.rar > tree.js


RayeTreeImg ={ 
	fd: "tree/folder.gif", 
	of: "tree/openfolder.gif", 
	i: "tree/I.png", 
	l: "tree/L.png", 
	t: "tree/T.png", 
	lm: "tree/Lminus.png", 
	lp: "tree/Lplus.png", 
	tm: "tree/Tminus.png", 
	tp: "tree/Tplus.png", 
	s: "tree/blank.png", 
	system:function(idx){ 
		return eval("imagePath + " + "this." + idx); 
	} 
	, 
	custom:function(img){ 
		return imagePath + img; 
	} 
} 
function RayeTree(e, loadMethod){ 
	this.type = "tree"; 
	this.element = e; 
	this.all = Array(); 
	this.exp = Array(); 
	this.element.instance = this; 
	this.childNodes = new RayeItemCollection(); 
	e.onmousedown = RayeTree.eventHandlers.onmousedown; 
	e.ondblclick = RayeTree.eventHandlers.ondblclick; 
	e.oncontextmenu = RayeTree.eventHandlers.oncontextmenu; 
	this.loadMethod = loadMethod; 
	this.eventListener ={ 
		onselectchange:null, 
		ondblclick:null, 
		ondragstart:null, 
		oncontextmenu:null 
	}; 
	var oThis = this; 
	this.readyState = 1; 
} 
RayeTree.prototype.addEventListener = function(s,cb){ 
	var retval = false; 
	switch(s){ 
		case "onselectchange": 
		this.eventListener.onselectchange = cb; 
		break; 
		case "ondblclick": 
		this.eventListener.ondblclick = cb; 
		break; 
		case "ondragstart": 
		this.eventListener.ondragstart = cb; 
		break; 
		case "oncontextmenu": 
		this.eventListener.oncontextmenu = cb; 
		default:break; 
	} 
	return true; 
} 
RayeTree.prototype.dragObject = function(){ 
	var so = this.childNodes.item(this.childNodes.selectedIndex[0]); 
	var e = document.createElement("nobr"); 
	e.className = "treeItem"; 
	var icn = so.ue.icon.cloneNode(true); 
	var lbl = so.ue.label.cloneNode(true); 
	e.appendChild(icn); 
	e.appendChild(lbl); 
	icn = lbl = null; 
	return Array({ 
		item:so, element:e, posElement:so.ue.icon 
	} 
	); 
} 
RayeTree.prototype.getDropItem = function(){ 
	return this.childNodes.item(this.childNodes.selectedIndex[0]); 
} 
RayeTree.prototype.ondrag = function(pos, oso){ 
	var c = this.childNodes; 
	var l = this.childNodes.length; 
	var to = c.item(2).element 
	var tp = getOffset(to); 
	var offset ={ 
		x:tp.left - to.offsetLeft, y:tp.top - to.offsetTop 
	}; 
	var so = null; 
	for(var i = 0;i < l;i ++){ 
		ty = c.item(i).element.offsetTop + offset.y - this.element.scrollTop; 
		if(ty <= pos.y && ty + c.item(i).ue.icon.offsetHeight >= pos.y){ 
			so = c.item(i); 
			break; 
		} 
	} 
	if(null != so){ 
		if(!RayeTree.contains(oso.element, so.element)){ 
			this.childNodes.select(so.index); 
		} 
	} 
	else{ 
	} 
} 
RayeTree.prototype.scrollToView = function(item){ 
	if(null == item) return; 
	var viewArea ={ 
		top:this.element.scrollTop, 
		bottom:this.element.scrollTop + this.element.offsetHeight 
	}; 
	var itemArea ={ 
		top:item.element.offsetTop, 
		bottom:item.element.offsetTop + item.ue.icon.offsetHeight 
	}; 
	if(itemArea.top >= viewArea.top && itemArea.bottom <= viewArea.bottom){ 
	} 
	else if(itemArea.top < viewArea.top){ 
		this.element.scrollTop = item.element.offsetTop; 
	} 
	else{ 
		this.element.scrollTop = itemArea.bottom - this.element.offsetHeight; 
	} 
} 
RayeTree.prototype.goDeep = function(path, cb){ 
	var idx = 0; 
	var l = path.length; 
	var e = null; 
	var oThis = this; 
var expandNext = function(start){ 
	start = start || false; 
	if(!start){ 
		idx ++; 
	} 
	while(idx < l - 1){ 
		e = oThis.all[path[idx]]; 
		if(null == e){ 
setTimeout(function(){ 
	expandNext(true); 
} 
, 50); 
return; 
} 
if(false == e.loaded){ 
e.expand(expandNext); 
return; 
} 
else{ 
e.expand(); 
idx ++; 
} 
} 
oThis.select(oThis.all[path[l - 1]]); 
cb(); 
} 
expandNext(true); 
} 
RayeTree.prototype.select = function(item, force){ 
	force = force || false; 
	if(this.childNodes.selectedIndex[0] != item.index || true == force){ 
		this.childNodes.select(item.index); 
		this.scrollToView(item); 
		item.expand(); 
		if("function" == typeof this.eventListener.onselectchange){ 
			this.eventListener.onselectchange(item); 
		} 
	} 
} 
RayeTree.prototype.appendChild = function(item, o, f){ 
	var rootFlag = false; 
	f = f || false; 
	var ti = new RayeTreeItem(o.id, o.title, o.dataSource, o.icon, 
	o.userData, f, item, this); 
	if(null != item){ 
		item.appendChild(ti); 
	} 
	else{ 
		this.root = ti; 
		this.element.appendChild(ti.element); 
	} 
	this.childNodes.add(ti); 
	this.all[o.id] = ti; 
	o = f = ti = null; 
} 
RayeTree.prototype.removeChild = function(item){ 
	var p = item.parent; 
	var c = item.getChildNodes(); 
	var l = c.length; 
	for(var i = 0;i < l;i ++){ 
		this.removeChild(c[i]); 
	} 
	delete this.all[item.id]; 
	this.childNodes.remove(item.index); 
	if(null != p){ 
		p.removeChild(item); 
	} 
} 
RayeTree.prototype.load = function(item, callback){ 
	callback = callback || null; 
	var oThis = this; 
	var p = item.parent 
	var frontImg = item.frontImg; 
	if(p != null){ 
		if(null != p){ 
			if(true == item.lastFlag){ 
				frontImg += "s"; 
			} 
			else{ 
				frontImg += "i"; 
			} 
		} 
	} 
	var LO = RayeTreeItem.loadingElement(frontImg); 
	var te = Object(); 
	te.element = LO; 
	te.index = 0; 
	item.appendChild(te); 
	var appended = false; 
	this.readyState = 1; 
	if("function" == typeof this.loadMethod){ 
var cb = function(e){ 
	if(!appended){ 
		appended = true; 
	} 
	else{ 
		return; 
	} 
	var l = e.length; 
	item.removeChild(te); 
	for(var i = 0;i < l;i ++){ 
		var o = e[i]; 
		var f = (i == l - 1); 
		oThis.appendChild(item, o, f); 
	} 
	oThis.readyState = 4; 
	if(callback){ 
		callback(item); 
	} 
} 
item.loaded = true; 
setTimeout(function(){ 
	oThis.loadMethod(item, cb); 
} 
,0); 
} 
} 
function RayeTreeItem(id, title, dataSource, icon, userData, lastFlag, parent, tree){ 
	this.id = id; 
	this.type = "treeItem"; 
	this.index = -1; 
	this.title = title; 
	this.dataSource= dataSource; 
	this.icon = icon; 
	this.userData = userData; 
	this.parent = parent ||null; 
	this.lastFlag = lastFlag || false; 
	this.frontImg = ""; 
	this.tree = tree; 
	if(parent != null){ 
		this.frontImg = parent.frontImg; 
		var pp = parent.parent; 
		if(null != pp){ 
			if(true == parent.lastFlag){ 
				this.frontImg += "s"; 
			} 
			else{ 
				this.frontImg += "i"; 
			} 
		} 
	} 
	this.element = RayeTreeItem.createElement(title, this.frontImg, 
	(dataSource != ""), lastFlag, icon, (null == parent)); 
	var te = this.element; 
	var imgs = this.element.getElementsByTagName("IMG"); 
	this.ue ={ 
		child:te.getElementsByTagName("DIV").item(0), 
		icon:imgs.item(imgs.length - 1), 
		expdr:(imgs.length > 1)?imgs.item(imgs.length - 2):null, 
		label:te.getElementsByTagName("SPAN").item(0), 
		item:te.getElementsByTagName("A").item(0) 
	} 
	this.loaded = false; 
	this.expanded = false; 
	this.element.instance = this; 
} 
RayeTreeItem.prototype.getChildNodes = function(){ 
	var e = this.ue.child.childNodes; 
	var retval = []; 
	var l = e.length; 
	for(var i = 0;i < l;i ++){ 
		retval[i] = e.item(i).instance; 
	} 
	return retval; 
} 
RayeTreeItem.prototype.appendChild = function(e){ 
	this.ue.child.appendChild(e.element); 
} 
RayeTreeItem.prototype.removeChild = function(e){ 
	this.ue.child.removeChild(e.element); 
} 
RayeTreeItem.prototype.onselect = function(){ 
	this.ue.item.className = "treeItemSelected"; 
	if("" == this.icon){ 
		this.ue.icon.src = RayeTreeImg.system("of"); 
	} 
} 
RayeTreeItem.prototype.onblur = function(){ 
	this.ue.item.className = ""; 
	if("" == this.icon){ 
		this.ue.icon.src = RayeTreeImg.system("fd"); 
	} 
} 
RayeTreeItem.prototype.onindexchange = function(n){ 
	this.index = n; 
} 
RayeTreeItem.prototype.reload = function(){ 
	var oThis = this; 
	if(4 != this.tree.readyState){ 
setTimeout(function(){ 
	oThis.reload(); 
} 
,500); 
return; 
} 
var e = []; 
for(var a in this.tree.exp){ 
e[a] = this.tree.exp[a]; 
} 
var si = null; 
if(this.tree.childNodes.selectedIndex[0]){ 
si = this.tree.childNodes.item(this.tree.childNodes.selectedIndex[0]).id; 
} 
var tc = this.getChildNodes(); 
if(0 < tc.length){ 
var p = this; 
} 
else{ 
var p = this.parent; 
if(null == p){ 
	p = this; 
} 
} 
p.collapse(); 
p.loaded = false; 
var c = p.getChildNodes(); 
var l = c.length; 
for(var i = 0;i < l;i ++){ 
this.tree.removeChild(c[i]); 
} 
var oThis = this; 
var expandFinish = function(item){ 
	var ic = item.getChildNodes(); 
	var l = ic.length; 
	for(var i = 0;i < l; i++){ 
		if(e[ic[i].id]){ 
			ic[i].expand(expandFinish); 
		} 
	} 
} 
p.expand(expandFinish); 
} 
RayeTreeItem.prototype.expand = function(cb){ 
	if(!this.dataSource) return false; 
	if(null != this.ue.expdr){ 
		if(this.lastFlag){ 
			this.ue.expdr.src = RayeTreeImg.system("lm"); 
		} 
		else{ 
			this.ue.expdr.src = RayeTreeImg.system("tm"); 
		} 
	} 
	this.ue.child.style.display = "block"; 
	if(!this.loaded){ 
		this.tree.load(this, cb); 
	} 
	this.expanded = true; 
	this.tree.exp[this.id] = true; 
} 
RayeTreeItem.prototype.collapse = function(){ 
	if(!this.dataSource) return false; 
	if(this.ue.expdr){ 
		if(this.lastFlag){ 
			this.ue.expdr.src = RayeTreeImg.system("lp"); 
		} 
		else{ 
			this.ue.expdr.src = RayeTreeImg.system("tp"); 
		} 
	} 
	this.ue.child.style.display = "none"; 
	this.expanded = false; 
	delete this.tree.exp[this.id]; 
} 
RayeTreeItem.prototype.toggle = function(){ 
	if(this.expanded){ 
		var so = this.tree.childNodes.item(this.tree.childNodes.selectedIndex[0]); 
		if(so.index != this.index && RayeTree.contains(this.element, so.element)){ 
			this.tree.select(this); 
		} 
		this.collapse(); 
	} 
	else{ 
		this.expand(); 
	} 
} 
RayeTreeItem.test = function(o){ 
	var retval = ""; 
	var tn = o.tagName.toUpperCase(); 
	var cn = String(o.className); 
	if("SPAN" == tn){ 
		retval = "label"; 
	} 
	else if("A" == tn){ 
		retval = "link"; 
	} 
	else if(/Expdr/.test(cn)){ 
		retval = "expdr"; 
	} 
	else if(/Icon/.test(cn)){ 
		retval = "icon"; 
	} 
	return retval; 
} 
RayeTreeItem.parse = function(o){ 
	var retval = Array(); 
	var cn = o.childNodes; 
	for (var i = 0;i < cn.length; i ++){ 
		var e = cn.item(i); 
		var tag = e.tagName; 
		if(typeof tag == "undefined") continue; 
		var ec = e; 
		do{ 
			ec = ec.firstChild; 
		} 
		while(null != ec && 3 != ec.nodeType && 4 != ec.nodeType); 
		if(null == ec){ 
			retval[tag] = ""; 
		} 
		else{ 
			retval[tag] = ec.nodeValue; 
		} 
	} 
	var cn = o.attributes; 
	for(var i = 0;i < cn.length;i ++){ 
		var t = cn.item(i); 
		retval[t.nodeName] = t.nodeValue; 
	} 
	return retval; 
} 
RayeTree.contains = function(a, b){ 
	if("undefined" != typeof a.contains){ 
		return a.contains(b); 
	} 
	else{ 
		var bp = b.parentNode; 
		var ap = a.parentNode; 
		while(null != bp && bp != a && bp != ap){ 
			bp = bp.parentNode; 
		} 
		if(null == bp || bp == ap){ 
			return false; 
		} 
		else{ 
			return true; 
		} 
	} 
} 
RayeTreeItem.createElement = function(label, frontImg, hasChild, lastFlag, icon, root){ 
	var retval = document.createElement("DIV"); 
	var nobr = document.createElement("NOBR"); 
	var a = document.createElement("A"); 
	a.href = "javascript:void(0);"; 
	var img = document.createElement("IMG"); 
	var imgIcon = document.createElement("IMG"); 
	var span = document.createElement("SPAN"); 
	span.innerHTML = label; 
	var divChild = document.createElement("DIV"); 
	divChild.className = "treeItemChild"; 
	frontImg = frontImg||""; 
	hasChild = hasChild || false; 
	lasFlag = lastFlag || false; 
	icon = icon || ""; 
	root = root || false; 
	var si = "" 
	if(lastFlag){ 
		si = "l"; 
	} 
	else{ 
		si = "t"; 
	} 
	if(hasChild){ 
		si += "p"; 
	} 
	img.src = RayeTreeImg.system(si); 
	if("" == icon){ 
		imgIcon.src = RayeTreeImg.system("fd"); 
	} 
	else{ 
		imgIcon.src = RayeTreeImg.custom(icon); 
	} 
	imgIcon.className = "treeIcon"; 
	retval.appendChild(nobr); 
	nobr.appendChild(a); 
	for(var i = 0;i < frontImg.length;i ++){ 
		var tImg = document.createElement("IMG"); 
		var ts = frontImg.substr(i,1); 
		tImg.src = RayeTreeImg.system(ts); 
		a.appendChild(tImg); 
		tImg = null; 
	} 
	if(false == root){ 
		if(si.length == 2){ 
			img.className = "treeItemExpdr"; 
		} 
		a.appendChild(img); 
	} 
	a.appendChild(imgIcon); 
	a.appendChild(span); 
	retval.appendChild(divChild); 
	retval.className = "treeItem"; 
	span = nobr = img = imgIcon = t = divChild = null; 
	return retval; 
} 
RayeTreeItem.loadingElement = function(frontImg){ 
	var retval = RayeTreeItem.createElement("载入中...", frontImg, false, true, "tree/loading.gif", false); 
	retval.getElementsByTagName("SPAN").item(0).className = "treeItemDisabled"; 
	return retval; 
} 
RayeTree.getReal = function(o){ 
	var e = o; 
	while(null != e && "undefined" == typeof e.instance){ 
		e = e.parentNode; 
	} 
	return e; 
} 
RayeTree.eventHandlers ={ 
	getEvent:function (e, el){ 
		if (!e){ 
			if (el) 
			e = el.document.parentWindow.event; 
			else 
			e = window.event; 
		} 
		if (!e.srcElement){ 
			var el = e.target; 
			while (el != null && el.nodeType != 1) 
			el = el.parentNode; 
			e.srcElement = el; 
		} 
		if (typeof e.offsetX == "undefined"){ 
			e.offsetX = e.layerX; 
			e.offsetY = e.layerY; 
		} 
		return e; 
	} 
	, 
	getDocument:function (e){ 
		if (e.target) 
		return e.target.ownerDocument; 
		return e.srcElement.document; 
	} 
	, 
	ondblclick:function(e){ 
		e = RayeTree.eventHandlers.getEvent(e,this); 
		var el = RayeTree.getReal(e.srcElement); 
		var tree = el.instance.tree; 
		if("function" == typeof tree.eventListener.ondblclick 
		&& el.instance.index == tree.childNodes.selectedIndex[0]){ 
			tree.eventListener.ondblclick(el.instance); 
		} 
	} 
	, 
	onmousedown:function(e){ 
		e = RayeTree.eventHandlers.getEvent(e,this); 
		var el = RayeTree.getReal(e.srcElement); 
		var srcInstance = el.instance; 
		var treeInstance = this.instance; 
		if("treeItem" == srcInstance.type){ 
			var ct = RayeTreeItem.test(e.srcElement); 
			switch(ct){ 
				case "icon": 
				case "label": 
				case "link": 
				treeInstance.select(srcInstance); 
				if("function" == typeof treeInstance.eventListener.ondragstart){ 
					treeInstance.eventListener.ondragstart(e, srcInstance); 
				} 
				break; 
				case "expdr": 
				srcInstance.toggle(); 
				break; 
				default: 
				break; 
			} 
		} 
	} 
	, 
	oncontextmenu:function(e){ 
		var treeInstance = this.instance; 
		if("function" == typeof treeInstance.eventListener.oncontextmenu){ 
			e = RayeTree.eventHandlers.getEvent(e,this); 
			var el = RayeTree.getReal(e.srcElement); 
			var srcInstance = el.instance; 
			var nodeInstance = null; 
			if("treeItem" == srcInstance.type){ 
				nodeInstance = srcInstance; 
				if(treeInstance.childNodes.selectedIndex[0] != nodeInstance.index){ 
					treeInstance.childNodes.select(nodeInstance.index); 
					treeInstance.scrollToView(nodeInstance); 
				} 
			} 
			return treeInstance.eventListener.oncontextmenu(e, nodeInstance, treeInstance); 
		} 
		return true; 
	} 
} 
function getOffset(o){ 
	var x = o.offsetLeft; 
	var y = o.offsetTop; 
	var e = o; 
	while(e = e.offsetParent){ 
		x += e.offsetLeft; 
		y += e.offsetTop; 
	} 
	return{ 
		left:x,top:y 
	}; 
}