www.gusucode.com > SiteEngine(建站引擎) 7.0 个人免费版源码程序 > data/js/jquery/jquery.jqTree.js

    (function ($) {
/**
 * jqTree 1.0 - jQuery xml Tree plugin 
 *
 * tony@trirand.com
 *
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 */
$.fn.jqTree = function( url, p ) {
	p = $.extend({
		useDblClicks : false, //not used yet
		saveNodesStateInCookies : true,
		expandedClassName : "",
		collapsedClassName: "collapsed",
		selectedClassName : "selected",
		plusMinusClassName : "plusminus",
		treeClass : "tree",
		imgpath: "",
		collapsedImage : "plus.gif",
		expandedImage : "minus.gif",
		noChildrenImage : "nochild.gif",
		defaultImage : "folder.png",
		xmlCaption : "caption",
		xmlUrl : "url",
		xmlId : "id",
		xmlRetreiveUrl : "retreiveUrl",
		xmlIcon : "icon",
		xmlExpanded : "expanded",
		loadingText : "Loading ...",
		onSelectNode : null
	}, p || {});

	Tree = function() {}

/*
  Private members
*/
	Tree.obj = null;
	Tree.instanceCount = 0;
	Tree.instancePrefix = "alder";
	Tree.cookiePrefix = "alder";
	Tree.dwnldQueue = new Array;
	Tree.dwnldCheckTimeout = 100;

/*
  Interval handler. Ckecks for new nodes loaded.
  Adds loaded nodes to the tree.
*/
	Tree.checkLoad = function () {
	var i, httpReq;
	for (i = 0; i<Tree.dwnldQueue.length; i++)
		if ((httpReq = Tree.dwnldQueue[i][0]).readyState == 4 /*COMPLETED*/)
		{
			var node = Tree.dwnldQueue[i][1];
		// unqueue loaded item
			Tree.dwnldQueue.splice(i, 1);
			Tree.appendLoadedNode(httpReq, node);
			if (p.saveNodesStateInCookies)
				Tree.openAllSaved(Tree.getId(node));
		}
		// will call next time, not all nodes were loaded
	if (Tree.dwnldQueue.length != 0)
		window.setTimeout(Tree.checkLoad, Tree.dwnldCheckTimeout);
	}
/*
  Adds loaded node to tree.
*/
  Tree.appendLoadedNode = function (httpReq, node) {
    // create DomDocument from loaded text
    var xmlDoc = Tree.loadXml(httpReq.responseText);
    // create tree nodes from xml loaded
    var newNode = Tree.convertXml2NodeList(xmlDoc.documentElement);
    // Add loading error handling here must be added
    node.replaceChild(newNode, Tree.getNodeSpan(node));
  }
/*
  Event handler when node is clicked.
  Navigates node link, and makes node selected.
*/
Tree.NodeClick = function (event)
{
  var node = event.srcElement /*IE*/ || event.target /*DOM*/;
  // <li><a><img> - <img> is capturing the event
//  alert($(node).attr("id"))
  if (p.onSelectNode) p.onSelectNode( $(node).attr("id"), $(node).attr("title"), node.parentNode.empty )
  while (node.tagName != "A")
    node = node.parentNode;
  node.blur();
  node = node.parentNode;
  Tree.obj = Tree.getObj(node);
  Tree.expandNode(node);
  Tree.selectNode(node);
}

/*
  Event handler when plus/minus icon is clicked.
  Desides whenever node should be expanded or collapsed.
*/
Tree.ExpandCollapseNode = function (event)
{
  var anchorClicked = event.srcElement /*IE*/ || event.target /*DOM*/;
  // <li><a><img> - <img> is capturing the event
  while (anchorClicked.tagName != "A")
    anchorClicked  = anchorClicked.parentNode;
  anchorClicked.blur();
  var node = anchorClicked.parentNode;
  // node has no children, and cannot be expanded or collapsed
  if (node.empty)
    return;
  Tree.obj = Tree.getObj(node);
  if (Tree.isNodeCollapsed(node))
    Tree.expandNode(node);
  else
    Tree.collapseNode(node);
  // cancelling the event to prevent navigation.
  if (event.preventDefault == undefined)
  { // IE
    event.cancelBubble = true;
    event.returnValue = false;
  } // if
  else
  { // DOM
    event.preventDefault();
    event.cancelBubble = true;
  } // else
}

/*
  Determines if specified node is selected.
*/
Tree.isNodeSelected = function (node)
{
  return (node.isSelected == true) || (Tree.obj.selectedNode == node);
}

/*
  Determines if specified node is expanded.
*/
Tree.isNodeExpanded = function (node)
{
  return (p.expandedClassName == node.className) || (node.expanded == true);
}

/*
  Determines if specified node is collapsed.
*/
Tree.isNodeCollapsed = function (node)
{
  return (p.collapsedClassName == node.className) || (node.collapsed == true);
}

/*
  Determines if node currently selected is at same
  level as node specified (has same root).
*/
Tree.isSelectedNodeAtSameLevel = function (node)
{
  if (Tree.obj.selectedNode == null) // no node currently selected
    return false;
  var i, currentNode, children = node.parentNode.childNodes; // all nodes at same level (li->ul->childNodes)
  for (i = 0; i < children.length; i++)
    if ((currentNode = children[i]) != node && Tree.isNodeSelected(currentNode))
      return true;
  return false;
}

/*
  Mark node as selected and unmark prevoiusly selected.
  Node is marked with attribute and <a> is marked with css style
  to avoid mark <li> twise with css style expanded and selected.
*/
Tree.selectNode = function (node)
{
  if (Tree.isNodeSelected(node)) // already marked
    return;
  if (Tree.obj.selectedNode != null)
  {// unmark previously selected node.
    Tree.obj.selectedNode.isSelected = false;
    // remove css style from anchor
    $("A",Tree.obj.selectedNode).get(1).className = "";
  } // if
  // collapse selected node if at same level
  if (Tree.isSelectedNodeAtSameLevel(node))
    Tree.collapseNode(Tree.obj.selectedNode);
  // mark node as selected
  Tree.obj.selectedNode = node;
  node.isSelected = true;
  $("A",node).get(1).className = p.selectedClassName;
  
}

/*
  Expand collapsed node. Loads children nodes if needed.
*/
Tree.expandNode = function (node, avoidSaving)
{
  if (node.empty)
    return;
  $("IMG",node).get(0).src = p.expandedImage;
  node.className = p.expandedClassName;
  node.expanded = true;
  node.collapsed = false;
  if (Tree.getNodeSpan(node) != null)
    Tree.loadChildren(node);
  if (p.saveNodesStateInCookies && !avoidSaving)
    Tree.saveOpenedNode(node);
}

/*
  Collapse expanded node.
*/
Tree.collapseNode = function (node, avoidSaving)
{
  if (node.empty)
    return;
  $("IMG",node).get(0).src = p.collapsedImage;
  node.className = p.collapsedClassName;
  node.collapsed = true;
  node.expanded = false;
  if (p.saveNodesStateInCookies && !avoidSaving)
    Tree.saveClosedNode(node);
}

/*
  Cancel loading children nodes.
*/
Tree.CancelLoad = function (event)
{ 
  var i, node = event.srcElement /*IE*/ || event.target /*DOM*/;
  while (node.tagName != "LI")
    node = node.parentNode;
  // search node in queue
  for (i = 0; i<Tree.dwnldQueue.length; i++)
    if (Tree.dwnldQueue[i][1] == node)
    {
      // remove from queue
      Tree.dwnldQueue.splice(i, 1);
      // collapse node
      Tree.collapseNode(node);
    } // if
}

/*
  Loads text from url specified and returns it as result.
*/
Tree.loadUrl = function (purl, pasync)
{
  var ret = $.ajax({async:pasync, type:"GET",url: purl, dataType:"xml", error: function(req,err) { alert(req.responseText + " Error Type: "+err  ); } });
  return pasync == true ? ret : ret.responseText;
}

/*
  Creates XmlDom document from xml text string.
*/
Tree.loadXml = function (xmlString)
{
  var xmlDoc;
  if (window.DOMParser) /*Mozilla*/
    xmlDoc = new DOMParser().parseFromString(xmlString, "text/xml");
  else
  {
    if (document.implementation && document.implementation.createDocument)
      xmlDoc = document.implementation.createDocument("","", null); /*Konqueror*/
    else
      xmlDoc = new ActiveXObject("Microsoft.XmlDom"); /*IE*/
    
    xmlDoc.async = false;
    xmlDoc.loadXML(xmlString);
  } // else
  return xmlDoc;
}

/*
  Finds loading span for node.
*/
Tree.getNodeSpan = function (node)
{
  var span = $("span",node);
  return (span.length > 0 && (span = span[0]).parentNode == node) ? span : null;
}

/*
  Enqueue load of children nodes for node specified.
*/
Tree.loadChildren = function (node)
{
  // get url with children  - Opera do not like #
  var url = $("A",node)[0].href
  url = url != null && url.length != 0 && url != "#" ? url : "javascript:void(0)"; 
  // retreive xml text from url
  var httpReq = Tree.loadUrl(url, true);
  // enqueue node loading
  if (Tree.dwnldQueue.push(new Array (httpReq, node)) == 1){
    window.setTimeout(Tree.checkLoad, Tree.dwnldCheckTimeout);
  }
}

/*
  Creates HTML nodes list from XML nodes.
*/
Tree.convertXml2NodeList = function (xmlElement)
{
  var ul = document.createElement("UL");
  var index = 0;
  $(xmlElement.childNodes).each(function () { 
    if (this.nodeType == 1 ) /* ELEMENT_NODE */ {
      ul.appendChild(Tree.convertXml2Node(this)).nodeIndex = index++;
    }
  });
  return ul;
}

/*
  Creates HTML tree node (<li>) from xml element.
*/
Tree.convertXml2Node = function (xmlElement)
{
  var li = document.createElement("LI");
  var a1 = document.createElement("A");
  var a2 = document.createElement("A");
  var i1 = document.createElement("IMG");
  var i2 = document.createElement("IMG");
  var hasChildNodes =  false;
  $(xmlElement.childNodes).each(function () { 
    if (this.nodeType === 1 ) {/* ELEMENT_NODE */ 
      hasChildNodes = true;
      return false;
    }
  });
  
  var retreiveUrl = $(xmlElement).attr(p.xmlRetreiveUrl);
  
  // plus/minus icon
  i1.className = p.plusMinusClassName;
  a1.appendChild(i1);
  $(a1).click( function(e) {Tree.ExpandCollapseNode(e);} )
  
  // plus/minus link
  a1.href = retreiveUrl != null && retreiveUrl.length != 0 && retreiveUrl != "#" ? retreiveUrl : "javascript:void(0)";
  li.appendChild(a1);
  
  // node icon
  var icoimg = $(xmlElement).attr(p.xmlIcon);
  if ( icoimg && icoimg.length !=0) { i2.src = p.imgpath+icoimg; } else { i2.src = p.defaultImage;}  
//  i2.src = $(xmlElement).attr(p.xmlIcon) || p.defaultImage;
  a2.appendChild(i2);
  
  // node link
  var lnk = $(xmlElement).attr(p.xmlUrl);
  a2.href = lnk != null && lnk.length !=0 && lnk != "#" ? $(xmlElement).attr(p.xmlUrl) : "javascript:void(0)";
  a2.id = $(xmlElement).attr(p.xmlId) || "none";
  a2.title = $(xmlElement).attr(p.xmlCaption);
  a2.appendChild(document.createTextNode($(xmlElement).attr(p.xmlCaption)));
  $(a2).click( function(e) {Tree.NodeClick(e);} )
  li.appendChild(a2);
  // loading span
  if (!hasChildNodes && retreiveUrl != null && retreiveUrl.length != 0)
  {
    var span = document.createElement("SPAN");
    $(span).html(p.loadingText);
    $(span).click( function(e) {Tree.CancelLoad(e);} )

    li.appendChild(span);
  } // if
  
  // add children
  if (hasChildNodes)
    li.appendChild(Tree.convertXml2NodeList(xmlElement));
  if (hasChildNodes || retreiveUrl != null && retreiveUrl.length != 0)
  {
    if ($(xmlElement).attr(p.xmlExpanded)=== "true")
      Tree.expandNode(li, true);
    else
      Tree.collapseNode(li, true);
  } // if
  else
  {
    i1.src = p.noChildrenImage; // no children
    li.empty = true;
  } // else

  return li;
}

/*
  Retreives current tree object.
*/
Tree.getObj = function (node)
{
  var obj = node;
  while (obj != null && obj.tagName != "DIV")
    obj = obj.parentNode;
  return obj;
}

Tree.getId = function (node)
{
  var obj = Tree.getObj(node);
  if (obj)
    return obj.id;
  return "";
}

/*
  Retreives unique id for tree node.
*/
Tree.getNodeId = function (node)
{
  var id = "";
  var obj = node;
  while (obj != null && obj.tagName != "DIV")
  {
    if (obj.tagName == "LI" && obj.nodeIndex != null)
      id = "_" + obj.nodeIndex + id;
    obj = obj.parentNode;
  } // while
//  if (obj != null && obj.tagName == "DIV")
//    id = obj.id + "_" + id;
  return id;
}

/*
  Saves node as opened for reload.
*/
Tree.saveOpenedNode = function (node)
{
  var treeId = Tree.getId(node);
  var state = Tree.getAllNodesSavedState(treeId);
  var nodeState = Tree.getNodeId(node) + ",";
  if (state.indexOf(nodeState) == -1)
  {
    state += nodeState;
    Tree.setAllNodesSavedState(treeId, state);
  } // if
}

/*
  Saves node as closed for reload.
*/
Tree.saveClosedNode = function (node)
{
  var treeId = Tree.getId(node);
  var state = Tree.getAllNodesSavedState(treeId);
  state = state.replace(new RegExp(Tree.getNodeId(node) + ",", "g"), "");
  Tree.setAllNodesSavedState(treeId, state);
}

Tree.getAllNodesSavedState = function (treeId)
{
  var state = Tree.getCookie(Tree.cookiePrefix + "_" + treeId);
  return state == null ? "" : state;
}

Tree.setAllNodesSavedState = function (treeId, state)
{
  Tree.setCookie(Tree.cookiePrefix + "_" + treeId, state);
}

/*
  Enques list of all opened nodes
*/
Tree.openAllSaved = function(treeId)
{
  var nodes = Tree.getAllNodesSavedState(treeId).split(",");
  var i;
  for (i=0; i<nodes.length; i++)
  {
    var node = Tree.getNodeById(treeId, nodes[i]);
    if (node && Tree.isNodeCollapsed(node))
      Tree.expandNode(node);
  } // for
}

Tree.getNodeById = function(treeId, nodeId)
{
  var node = document.getElementById(treeId);
  if (!node)
    return null;
  var path = nodeId.split("_");
  var i;
  for (i=1; i<path.length; i++)
  {
    if (node != null)
    {
      node = node.firstChild;
      while (node != null && node.tagName != "UL")
        node = node.nextSibling;
    } // if
    if (node != null)
      node = node.childNodes[path[i]];
    else
      break;
  } // for
  return node;
}

Tree.setCookie = function(sName, sValue)
{
  document.cookie = sName + "=" + escape(sValue) + ";";
}

Tree.getCookie = function(sName)
{
  var a = document.cookie.split("; ");
  for (var i=0; i < a.length; i++)
  {
    var aa = a[i].split("=");
    if (sName == aa[0]) 
      return unescape(aa[1]);
  } // for
  return null;
}

if(p.imgpath !== "" ) {
  p.collapsedImage = p.imgpath+p.collapsedImage;
  p.expandedImage = p.imgpath+p.expandedImage;
  p.noChildrenImage = p.imgpath+p.noChildrenImage;
  p.defaultImage = p.imgpath+p.defaultImage;
}

return this.each( function( ) {
  var div = document.createElement("DIV");
  div.id = Tree.instancePrefix + Tree.instanceCount++;
  div.className = p.treeClass;
	if(typeof onSelectNode !== 'function') {onSelectNode=false;}  
  var xml = Tree.loadUrl(url, false);
  var xmlDoc = Tree.loadXml(xml);
  var newNode = Tree.convertXml2NodeList(xmlDoc.documentElement);
  div.appendChild(newNode);
  if (this != undefined)
  {
    if (this.appendChild) // is node
      this.appendChild(div);
    else if ($(this)) // is node id
      $(this).appendChild(div);
  } // if
  if (p.saveNodesStateInCookies)
    Tree.openAllSaved(div.id);
  xml = null;
  $(window).unload( function() { Tree = null;} )

});
}
})(jQuery)