⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xtree2.js

📁 这是一个树型控件
💻 JS
📖 第 1 页 / 共 3 页
字号:
/*----------------------------------------------------------------------------\
|                            xTree 2.0 PRE RELEASE                            |
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|             This is a pre release and may not be redistributed.             |
|              Watch http://webfx.eae.net for the final version               |
|-----------------------------------------------------------------------------|
|                   Created by Erik Arvidsson & Emil A Eklund                 |
|                  (http://webfx.eae.net/contact.html#erik)                   |
|                  (http://webfx.eae.net/contact.html#emil)                   |
|                      For WebFX (http://webfx.eae.net/)                      |
|-----------------------------------------------------------------------------|
| A tree menu system for IE 5.5+, Mozilla 1.4+, Opera 7, KHTML                |
|-----------------------------------------------------------------------------|
|     Copyright (c) 2003, 2004, 2005, 2006 Erik Arvidsson & Emil A Eklund     |
|-----------------------------------------------------------------------------|
| Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| use this file except in compliance with the License.  You may obtain a copy |
| of the License at http://www.apache.org/licenses/LICENSE-2.0                |
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| Unless  required  by  applicable law or  agreed  to  in  writing,  software |
| distributed under the License is distributed on an  "AS IS" BASIS,  WITHOUT |
| WARRANTIES OR  CONDITIONS OF ANY KIND,  either express or implied.  See the |
| License  for the  specific language  governing permissions  and limitations |
| under the License.                                                          |
|-----------------------------------------------------------------------------|
| Dependencies: xtree2.css - Used to define the look and feel                 |
|-----------------------------------------------------------------------------|
| 2004-02-21 | Pre release distributed to a few selected tester               |
| 2005-06-06 | Added single tab index to improve keyboard navigation          |
| 2006-05-28 | Changed license to Apache Software License 2.0.                |
|-----------------------------------------------------------------------------|
| Created 2003-??-?? | All changes are in the log above. | Updated 2006-05-28 |
\----------------------------------------------------------------------------*/


//
// WebFXTreePersisitance
function WebFXTreePersistence() {}
var _p = WebFXTreePersistence.prototype;
_p.getExpanded = function getExpanded(oNode) { return false; };
_p.setExpanded = function setExpanded(oNode, bOpen) {};



// Cookie handling
function WebFXCookie() {}

_p = WebFXCookie.prototype;

_p.setCookie = function setCookie(sName, sValue, nDays) {
	var expires = "";
	if (typeof nDays == "number") {
		var d = new Date();
		d.setTime(d.getTime() + nDays * 24 * 60 * 60 * 1000);
		expires = "; expires=" + d.toGMTString();
	}

	document.cookie = sName + "=" + escape(sValue) + expires + "; path=/";
};

_p.getCookie = function getCookie(sName) {
	var re = new RegExp("(\;|^)[^;]*(" + sName + ")\=([^;]*)(;|$)");
	var res = re.exec(document.cookie);
	return res != null ? unescape(res[3]) : null;
};

_p.removeCookie = function removeCookie(name) {
	this.setCookie(name, "", -1);
};


//
// persistence using cookies
//
// This is uses one cookie with the ids of the expanded nodes separated using '+'
//
function WebFXTreeCookiePersistence() {
	this._openedMap = {};
	this._cookies = new WebFXCookie;
	var s = this._cookies.getCookie(this.cookieName);
	if (s) {
		var a = s.split("+");
		for (var i = a.length - 1; i >= 0; i--)
			this._openedMap[a[i]] = true;
	}
}

_p = WebFXTreeCookiePersistence.prototype = new WebFXTreePersistence;

_p.cookieName = "webfx-tree-cookie-persistence"

_p.getExpanded = function getExpanded(oNode) {
	return oNode.id in this._openedMap;
};

_p.setExpanded = function setExpanded(oNode, bOpen) {
	var old = this.getExpanded(oNode);
	if (old != bOpen) {
		if (bOpen) {
			this._openedMap[oNode.id] = true;
		} else {
			delete this._openedMap[oNode.id];
		}

		var res = [];
		var i = 0;
		for (var id in this._openedMap)
			res[i++] = id;
		this._cookies.setCookie(this.cookieName, res.join("+"));
	}
};



// this object provides a few useful methods when working with arrays
var arrayHelper = {
	indexOf: function (a, o) {
		for (var i = 0; i < a.length; i++) {
			if (a[i] == o) {
				return i;
			}
		}
		return -1;
	},

	insertBefore: function (a, o, o2) {
		var i = this.indexOf(a, o2);
		if (i == -1) {
			a.push(o);
		} else {
			a.splice(i, 0, o);
		}
	},

	remove: function (a, o) {
		var i = this.indexOf(a, o);
		if (i != -1) {
			a.splice(i, 1);
		}
	}
};

///////////////////////////////////////////////////////////////////////////////
// WebFX Tree Config object                                                  //
///////////////////////////////////////////////////////////////////////////////
var webFXTreeConfig = {
	rootIcon        : "images/folder.png",
	openRootIcon    : "images/openfolder.png",
	folderIcon      : "images/folder.png",
	openFolderIcon  : "images/openfolder.png",
	fileIcon        : "images/file.png",
	iIcon           : "images/I.png",
	lIcon           : "images/L.png",
	lMinusIcon      : "images/Lminus.png",
	lPlusIcon       : "images/Lplus.png",
	tIcon           : "images/T.png",
	tMinusIcon      : "images/Tminus.png",
	tPlusIcon       : "images/Tplus.png",
	plusIcon        : "images/plus.png",
	minusIcon       : "images/minus.png",
	blankIcon       : "images/blank.png",
	defaultText     : "Tree Item",
	defaultAction   : null,
	defaultBehavior : "classic",
	usePersistence	: true
};

///////////////////////////////////////////////////////////////////////////////
// WebFX Tree Handler object                                                 //
///////////////////////////////////////////////////////////////////////////////

var webFXTreeHandler = {
	ie: /msie/i.test(navigator.userAgent),
	opera: /opera/i.test(navigator.userAgent),
	idCounter: 0,
	idPrefix: "wfxt-",
	getUniqueId: function () {
		return this.idPrefix + this.idCounter++;
	},
	all: {},
	getNodeById: function (sId) {
		return all[sId];
	},
	addNode: function (oNode) {
		this.all[oNode.id] = oNode;
	},
	removeNode:	function (oNode) {
		delete this.all[oNode.id];
	},

	handleEvent: function (e) {
		var el = e.target || e.srcElement;
		while (el != null && !this.all[el.id]) {
			el = el.parentNode;
		}

		if (el == null) {
			return false;
		}
		var node = this.all[el.id];
		if (typeof node["_on" + e.type] == "function") {
			return node["_on" + e.type](e);
		}
		return false;
	},

	dispose: function () {
		if (this.disposed) return;
		for (var id in this.all) {
			this.all[id].dispose();
		}
		this.disposed = true;
	},

	htmlToText: function (s) {
		return String(s).replace(/\s+|<([^>])+>|&amp;|&lt;|&gt;|&quot;|&nbsp;/gi, this._htmlToText);
	},

	_htmlToText: function (s) {
		switch (s) {
			case "&amp;":
				return "&";
			case "&lt;":
				return "<";
			case "&gt;":
				return ">";
			case "&quot;":
				return "\"";
			case "&nbsp;":
				return String.fromCharCode(160);
			default:
				if (/\s+/.test(s)) {
					return " ";
				}
				if (/^<BR/gi.test(s)) {
					return "\n";
				}
				return "";
		}
	},

	textToHtml: function (s) {
		return String(s).replace(/&|<|>|\n|\"\u00A0/g, this._textToHtml);
	},

	_textToHtml: function (s) {
		switch (s) {
			case "&":
				return "&amp;";
			case "<":
				return "&lt;";
			case ">":
				return "&gt;";
			case "\n":
				return "<BR>";
			case "\"":
				return "&quot;";	// so we can use this in attributes
			default:
				return "&nbsp;";
		}
	},

	persistenceManager: new WebFXTreeCookiePersistence()
};


///////////////////////////////////////////////////////////////////////////////
// WebFXTreeAbstractNode
///////////////////////////////////////////////////////////////////////////////

function WebFXTreeAbstractNode(sText, oAction) {
	this.childNodes = [];
	if (sText) this.text = sText;
	if (oAction) this.action = oAction;
	this.id = webFXTreeHandler.getUniqueId();
	if (webFXTreeConfig.usePersistence) {
		this.open = webFXTreeHandler.persistenceManager.getExpanded(this);
	}
	webFXTreeHandler.addNode(this);
}


_p = WebFXTreeAbstractNode.prototype;
_p._selected = false;
_p.indentWidth = 19;
_p.open = false;
_p.text = webFXTreeConfig.defaultText;
_p.action = null;
_p.target = null;
_p.toolTip = null;
_p._focused = false;

/* begin tree model */

_p.add = function add(oChild, oBefore) {
	var oldLast;
	var emptyBefore = this.childNodes.length == 0;
	var p = oChild.parentNode;

	if (oBefore == null) { // append
		if (p != null)
			p.remove(oChild);
		oldLast = this.getLastChild();
		this.childNodes.push(oChild);
	} else { // insertBefore
		if (oBefore.parentNode != this) {
			throw new Error("Can only add nodes before siblings");
		}
		if (p != null) {
			p.remove(oChild);
		}

		arrayHelper.insertBefore(this.childNodes, oChild, oBefore);
	}

	if (oBefore) {
		if (oBefore == this.firstChild) {
			this.firstChild = oChild;
		}
		oChild.previousSibling = oBefore.previousSibling;
		oBefore.previousSibling = oChild;
		oChild.nextSibling = oBefore;
	} else {
		if (!this.firstChild) {
			this.firstChild = oChild;
		}
		if (this.lastChild) {
			this.lastChild.nextSibling = oChild;
		}
		oChild.previousSibling = this.lastChild;
		this.lastChild = oChild;
	}

	oChild.parentNode = this;
	var t = this.getTree();
	if (t) {
		oChild.tree = t;
	}
	var d = this.getDepth();
	if (d != null) {
		oChild.depth = d + 1;
	}

	if (this.getCreated() && !t.getSuspendRedraw()) {
		var el = this.getChildrenElement();
		var newEl = oChild.create();
		var refEl = oBefore ? oBefore.getElement() : null;
		el.insertBefore(newEl, refEl);

		if (oldLast) {
			oldLast.updateExpandIcon();
		}
		if (emptyBefore) {
			this.setExpanded(this.getExpanded());
			// if we are using classic expand will not update icon
			if (t && t.getBehavior() != "classic")
				this.updateIcon();
		}
	}

	return oChild;
};



_p.remove = function remove(oChild) {
	// backwards compatible. If no argument remove the node
	if (arguments.length == 0) {
		if (this.parentNode) {
			return this.parentNode.remove(this);
		}
		return null;
	}

	// if we remove selected or tree with the selected we should select this
	var t = this.getTree();
	var si = t ? t.getSelected() : null;
	if (si == oChild || oChild.contains(si)) {
		if (si.getFocused()) {
			this.select();
			window.setTimeout("WebFXTreeAbstractNode._onTimeoutFocus(\"" + this.id + "\")", 10);
		} else {
			this.select();
		}
	}

	if (oChild.parentNode != this) {
		throw new Error("Can only remove children");
	}
	arrayHelper.remove(this.childNodes, oChild);

	if (this.lastChild == oChild) {
		this.lastChild = oChild.previousSibling;
	}
	if (this.firstChild == oChild) {
		this.firstChild = oChild.nextSibling;
	}
	if (oChild.previousSibling) {
		oChild.previousSibling.nextSibling = oChild.nextSibling;
	}
	if (oChild.nextSibling) {
		oChild.nextSibling.previousSibling = oChild.previousSibling;
	}

	var wasLast = oChild.isLastSibling();

	oChild.parentNode = null;
	oChild.tree = null;
	oChild.depth = null;

	if (t && this.getCreated() && !t.getSuspendRedraw()) {
		var el = this.getChildrenElement();
		var childEl = oChild.getElement();
		el.removeChild(childEl);
		if (wasLast) {
			var newLast = this.getLastChild();
			if (newLast) {
				newLast.updateExpandIcon();
			}
		}
		if (!this.hasChildren()) {
			el.style.display = "none";
			this.updateExpandIcon();
			this.updateIcon();
		}
	}

	return oChild;
};

WebFXTreeAbstractNode._onTimeoutFocus = function (sId) {
	var jsNode = webFXTreeHandler.all[sId];
	jsNode.focus();
};

_p.getId = function getId() {
	return this.id;
};

_p.getTree = function getTree() {
	throw new Error("getTree called on Abstract Node");
};

_p.getDepth = function getDepth() {
	throw new Error("getDepth called on Abstract Node");
};

_p.getCreated = function getCreated() {
	var t = this.getTree();
	return t && t.rendered;
};

_p.getParent = function getParent() {
	return this.parentNode;
};

_p.contains = function contains(oDescendant) {
	if (oDescendant == null) return false;
	if (oDescendant == this) return true;
	var p = oDescendant.parentNode;
	return this.contains(p);
};

_p.getChildren = _p.getChildNodes = function getChildNodes() {
	return this.childNodes;
};

_p.getFirstChild = function getFirstChild() {
	return this.childNodes[0];
};

_p.getLastChild = function getLastChild() {
	return this.childNodes[this.childNodes.length - 1];
};

_p.getPreviousSibling = function getPreviousSibling() {
	return this.previousSibling;
	//var p = this.parentNode;
	//if (p == null) return null;
	//var cs = p.childNodes;
	//return cs[arrayHelper.indexOf(cs, this) - 1]
};

_p.getNextSibling = function getNextSibling() {
	return this.nextSibling;
	//var p = this.parentNode;
	//if (p == null) return null;
	//var cs = p.childNodes;
	//return cs[arrayHelper.indexOf(cs, this) + 1]
};

_p.hasChildren = function hasChildren() {
	return this.childNodes.length > 0;
};

_p.isLastSibling = function isLastSibling() {
	return this.nextSibling == null;
	//return this.parentNode && this == this.parentNode.getLastChild();
};

_p.findChildByText = function findChildByText(s, n) {
	if (!n) {
		n = 0;
	}
	var isRe = s instanceof RegExp;
	for (var i = 0; i < this.childNodes.length; i++) {
		if (isRe && s.test(this.childNodes[i].getText()) ||
			this.childNodes[i].getText() == s) {
			if (n == 0) {
				return this.childNodes[i];
			}
			n--;
		}
	}
	return null;
};

_p.findNodeByText = function findNodeByText(s, n) {
	if (!n) {
		n = 0;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -