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

📄 node.js

📁 html树型结构 html树型结构
💻 JS
📖 第 1 页 / 共 2 页
字号:
/**
 * @fileoverview 这是复选框树的3个文件中的一个,表示树的一个节点。
 * @author xieye
 * @version 4.1  2007/06/17
 */
  
/*
 * 加命名空间xyTree
 */
(function() {
  if (!window.xyTree)
    window.xyTree = {};
})();

/**
 * 复选框树节点的构造方法
 * 必须按深度遍历的方法给树添加节点
 * 给节点设img属性可以自由添加自定义图片,图片最好是16*16
 * 可以给节点设一些业务需要的自定义的属性,用脚本的好处^-^,
 *   但是不能是构造方法里定义的如parent,child,tree等
 * @class 这个类构造一个复选框树的节点的实例
 * @constructor
 * @param {String} name 节点名称,会显示在屏幕上
 */
xyTree.Node = function(name) {
  /**
   * 节点的显示名称
   * @type String
   */
  this.name = name ;        
  
  /**
   * 节点的父节点
   * @type xyTree.Node
   */
  this.parent;

  /**
   * 节点的前一个节点
   * @type xyTree.Node
   */
  this.previous;

  /**
   * 节点的下一个节点
   * @type xyTree.Node
   */
  this.next;

  /**
   * 节点的子节点
   * @type Array:xyTree.Node
   */
  this.child = [];

  /**
   * 节点的级别,根节点为0
   * @type int
   */
  this.level = 0;
  
  /**
   * 节点数组对象,想要获得DivTree对象要用tempNode.tree.divtree
   * @type int
   */
  this.tree;

  /**
   * 节点在树中的序号,根节点为0
   * @type int
   */
  this.xuhao = 0;

  /**
   * 子节点正在显示吗?表示当前状态
   * @type boolean
   */
  this.displaychild = false;
	
  /**
   * 节点的复选框状态,0:不中, 1:选中, 2:部分
   * @type int
   */
  this.checked = 0;

  /**
   * 节点展开过的历史记录,一旦变true,无法改变,除非调树的改形状函数
   * @type boolean
   */
  this.zhankaiguo = false;

  /**
   * 节点的用户定义图标,可选属性
   * @type String
   */
  this.img;
  
  this.timecolor = 7;
}

/**
 * 调试用
 */
xyTree.Node.prototype.toString = function() {
  var s = '[' + this.id + ']=[' + this.name + ']';
  return s;
};


/*
<div>
  <img src="images/Lplus.png"  align="absbottom"  />
  <img src="images/foldericon.png"  align="absbottom"  style="margin-left:-6px;"  />
  <a href="javascript:void(0);">玄武分局</a>
  <div><img/><img/><a/>某某派出所</div> 
</div>
*/
/**
 * 创建节点的DOM对象
 * 这里的逻辑是最复杂的,插入行,结构见上面
 * @private
 * @return DOM对象,是一个div
 * @type HTMLElement:div
 */
xyTree.Node.prototype.innerhtml = function() {
  var div = document.createElement('div');
  var qj = this.tree.objectname; //得到全局对象的名称
  //给节点的div添加id,=树名+序号;
  div.id = qj + this.xuhao; 
  div.className = 'qiguai'; //做标记,寻找方便
  var current = this;

  //xieye(1):用for循环绘制前面的空格或竖线的图标
  //如:2级节点循环一次。3级节点,循环两次
  var oFragment = document.createDocumentFragment();
  for (var i = this.level - 1; i > 0; i--) {
    var img = document.createElement('img');
    img.src = this.getimgkongge(this.getparent(i));
    img.align = "absbottom";
    oFragment.appendChild(img);
  }
  //  div.appendChild(oFragment);
  
  //xieye(2):绘制加号和减号或T或L的图标,有单击事件,复杂
  var img = document.createElement('img');
  img.src = this.getimgjiahao();
  img.id = qj + xyTree.CONSTANT.treeJiahaoImgID + this.xuhao; //设ID
  img.align = "absbottom";
  img.onclick = function() { 
    //xieye:状态在全局变量节点中,
    //xieye:这里要判断,如果本节点无子节点
    var fu = this.parentNode;
    var childnodes = current.child;
  	
    if (childnodes.length == 0) {/*alert('无子节点');*/return;}
    var shimowei = current.next?false:true; //判断是否末尾
    if (!current.displaychild) { //如果节点的子节点未打开
    
      
      //alert('准备打开');
      current.displaychild = true;
      this.src = current.getimgdianji(current.displaychild, shimowei);
      //现在已经知道序号,要求他的父节点添加子节点
      if (!current.img)                //如果文件夹图标缺省,则会变化
        this.nextSibling.src = xyTree.TreeConfig.openFolderIcon;
			
      if (!current.zhankaiguo) { //所谓展开过是指它的子节点!
        //这里新加行	
      //alert('这里新加行');
        current.zhankaiguo = true;
        //加变减,减变加,但要考虑是不是末节点
        var oFragmentChildDiv = document.createDocumentFragment();
        for (var i = 0; i < childnodes.length; i++)
          oFragmentChildDiv.appendChild(childnodes[i].innerhtml());
        fu.appendChild(oFragmentChildDiv);	
      } else {
        //这里不新加行	
      //alert('这里不新加行');

        for (var i = fu.childNodes.length - 1; 
            fu.childNodes[i].className == 'qiguai' && i >= 0; i--)
          fu.childNodes[i].style.display = 'block';
      }
    } else {                           //如果节点的子节点打开了,准备收缩
      //alert('准备收缩');
      current.displaychild = false;
      //current.clickbyJiahaoimg();
      this.src = current.getimgdianji(current.displaychild, shimowei);
      if (!current.img)                //如果文件夹图标缺省,则会变化
        this.nextSibling.src = xyTree.TreeConfig.folderIcon;
      //xieye:把这个节点下面所有的div设为隐藏显示
      for (var i = fu.childNodes.length - 1; 
          fu.childNodes[i].className == 'qiguai' && i >= 0; i--)
        fu.childNodes[i].style.display = 'none';
    }
  };
  
  oFragment.appendChild(img);
  //  div.appendChild(img);
  
  //xieye(3):绘制文件夹图标,或者用户自定义
  img = document.createElement('img');
  img.src = this.getimgfold();
  //2007/06/15,现在可以加单独的图片了
  if (this.img)                        //如果用户自定义,则受样式控制
    img.className = xyTree.CONSTANT.treeUserImgStyle;
  img.align = "absbottom";
  img.onclick = function() {           //文件夹单击事件指定,谁都不准动!!
    this.previousSibling.onclick();
  };
  oFragment.appendChild(img);
  
  //xieye(4):绘制复选框的图标,有单击事件,复杂
  img = document.createElement('img');
  img.id = qj + xyTree.CONSTANT.treeCheckBoxID + this.xuhao; //做标记
  img.src = this.getfuxuanimg();
  img.align = "top";
  img.style.paddingTop = '3px';
  img.style.marginLeft = xyTree.TreeConfig.jianju1;
  img.onclick = function() { 
    //他的影响是双向的,
    //对于底部,全部选中
    //对于上方,要考虑是部分选中还是全部选中,并且立即更改属性并绘制
    var fu = this.parentNode;
    if (current.checked == 1 || current.checked == 2) {
      current.checked = 0;
      this.src = xyTree.TreeConfig.buzhongIcon;
    } else {
      current.checked = 1;
      this.src = xyTree.TreeConfig.quanzhongIcon;
    }
    current.upDigui(current);
    current.downDigui(current);
  }
  oFragment.appendChild(img);

  //xieye(5):绘制文字超链接
  var a = document.createElement('a');
  //a.href = 'javascript:void(0)';
  //var xuhao = this.xuhao;
  a.onclick = function() {
    //current.slowChange();
    current.tree.divtree.clickNode(current);
  };
  a.onfocus = function() {this.blur();}
  a.onmouseover = function (){this.style.color='blue';}
  a.onmouseout  = function (){this.style.color='black';}
  a.appendChild(document.createTextNode(this.name));
  a.style.marginLeft = xyTree.TreeConfig.jianju2;
  oFragment.appendChild(a);
  
  div.appendChild(oFragment);
  return div;
}

/**
 * 通过全局节点得到节点div对象
 * @return DOM对象,是一个div
 * @type HTMLElement:div
 */
xyTree.Node.prototype.getHtmlElement = function() {
  var dd = this.tree.objectname + this.xuhao;
  return document.getElementById(dd); 
}

/**
 * 通过全局节点得到节点的复选框img对象
 * @return DOM对象,是一个img
 * @type HTMLElement:img
 */
xyTree.Node.prototype.getHtmlElementfuxuanimg = function() {
  var dd = this.tree.objectname + xyTree.CONSTANT.treeCheckBoxID + this.xuhao;
  return document.getElementById(dd);
}

/**
 * 通过全局节点得到节点的加号img对象
 * @return DOM对象,是一个img
 * @type HTMLElement:img
 */
xyTree.Node.prototype.getHtmlElementjiahaoimg = function() {
  var dd = this.tree.objectname + xyTree.CONSTANT.treeJiahaoImgID + this.xuhao;
  return document.getElementById(dd);
}

/**
 * 确定复选框的状态,并向下递归
 * @param {xyTree.Node} node 对这个参数节点递归,调用对象节点没用
 */
xyTree.Node.prototype.downDigui = function(node) {
  function downDigui2(node2) {
    node2.checked = node2.parent.checked;
    node2.getHtmlElementfuxuanimg().src = node2.getimgbyyangshi(node2.parent.checked);
    if (node2.level == node2.tree.maxlevel) return;
   	
    if (!node2.displaychild  && !node2.zhankaiguo) return;//注意到这里不同的地方!
    for (var i = 0; i < node2.child.length; i++)
      downDigui2(node2.child[i]);
  }
  
  if (node.level == node.tree.maxlevel) return;
  //如果子节点不在显示并且子节点不存在内存 就返回
  if (!node.displaychild && !node.zhankaiguo) return;//注意这句话!
  for (var j = 0; j < node.child.length; j++)
    downDigui2(node.child[j]);
}

/**
 * 确定复选框的状态,并向上递归
 * @param {xyTree.Node} node 对这个参数节点递归,调用对象节点没用
 */
xyTree.Node.prototype.upDigui = function(node) {
  if (node.level == 0) return;
  var boo = true;  //先假定节点状态全部一样
  var boo2 = false;
  var parentyangshi = node.parent.checked;            //父节点样式,可能是0,1,2
  var yangshi = node.checked;          //获得当前节点的样式,记住不可能是局部,只会是0或1
  	
  var arr = node.parent.child;
  for (var i = 0; i < arr.length; i++) {
    var tempyangshi = arr[i].checked;
    if (tempyangshi != yangshi) {
      boo = false;
      break;	
    }	
  }
  //如果boo=false,说明有不同,父节点选2,看一样不一样,来决定是否递归
  //如果boo=true,说明是相同,父节点选当前样式,看一样不一样,来决定是否递归
  if (!boo) {
    node.parent.checked = 2;
  } else {
    node.parent.checked = yangshi;
  }
  node.parent.getHtmlElementfuxuanimg().src = 
    this.getimgbyyangshi(node.parent.checked); //这是改html样式
  if (node.parent.checked != parentyangshi)	//判断是否递归
    this.upDigui(node.parent);
}


/**
 * 返回祖先节点
 * @param {int} i 与目标节点的级别差
 * @return 返回祖先节点
 * @type xyTree.Node
 */
xyTree.Node.prototype.getparent = function(i) {
  function getparentdigui(i,node) {
    var node = node.parent;
    i--;
    if (i == 0)
      return node;
    return getparentdigui(i, node);
  }
  return getparentdigui(i, this);
}

/**
 * 根据父节点返回竖线还是空格,是一行div中最前面的图片
 * @param {xyTree.Node} node 当前节点
 * @return 返回竖线还是空格的图片
 * @type String
 */
xyTree.Node.prototype.getimgkongge = function(node) {
  //父节点不是末尾 ? 图片1 : 图片2
  return (node.next) ? xyTree.TreeConfig.iIcon : xyTree.TreeConfig.blankIcon;
}

/**
 * 返回加号位置的图片,4种情况
 * (1)有子节点,不是末尾
 * (2)有子节点,是末尾
 * (3)无子节点,不是末尾
 * (4)无子节点,是末尾
 * @return 返回加号位置的图片
 * @type String
 */
xyTree.Node.prototype.getimgjiahao = function() {
  var s;
  if (this.child.length > 0) { //有子节点
    if (this.next)  //不是末尾
      s = xyTree.TreeConfig.tPlusIcon;
    else           //是末尾   
      s = xyTree.TreeConfig.lPlusIcon;
  } else {                      //无子节点
    if (this.next)  //不是末尾
      s = xyTree.TreeConfig.tIcon;
    else           //是末尾   
      s = xyTree.TreeConfig.lIcon;
  }

⌨️ 快捷键说明

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