道非道 非常道

勤思、谨言、慎行、厚积、薄发

统计

web

天圆

经济 政治 军事

键康

xtree.js

  1 
  2 /*----------------------------------------------------------------------------\
  3 |                       Cross Browser Tree Widget 1.17                        |
  4 |-----------------------------------------------------------------------------|
  5 |                          Created by Emil A Eklund                           |
  6 |                  (http://webfx.eae.net/contact.html#emil)                   |
  7 |                      For WebFX (http://webfx.eae.net/)                      |
  8 |-----------------------------------------------------------------------------|
  9 | An object based tree widget,  emulating the one found in microsoft windows, |
 10 | with persistence using cookies. Works in IE 5+, Mozilla and konqueror 3.    |
 11 |-----------------------------------------------------------------------------|
 12 |          Copyright (c) 2000, 2001, 2002, 2003, 2006 Emil A Eklund           |
 13 |-----------------------------------------------------------------------------|
 14 | Licensed under the Apache License, Version 2.0 (the "License"); you may not |
 15 | use this file except in compliance with the License.  You may obtain a copy |
 16 | of the License at http://www.apache.org/licenses/LICENSE-2.0                |
 17 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
 18 | Unless  required  by  applicable law or  agreed  to  in  writing,  software |
 19 | distributed under the License is distributed on an  "AS IS" BASIS,  WITHOUT |
 20 | WARRANTIES OR  CONDITIONS OF ANY KIND,  either express or implied.  See the |
 21 | License  for the  specific language  governing permissions  and limitations |
 22 | under the License.                                                          |
 23 |-----------------------------------------------------------------------------|
 24 | Dependencies: xtree.css (To set up the CSS of the tree classes)             |
 25 |-----------------------------------------------------------------------------|
 26 | 2001-01-10 | Original Version Posted.                                       |
 27 | 2001-03-18 | Added getSelected and get/setBehavior  that can make it behave |
 28 |            | more like windows explorer, check usage for more information.  |
 29 | 2001-09-23 | Version 1.1 - New features included  keyboard  navigation (ie) |
 30 |            | and the ability  to add and  remove nodes dynamically and some |
 31 |            | other small tweaks and fixes.                                  |
 32 | 2002-01-27 | Version 1.11 - Bug fixes and improved mozilla support.         |
 33 | 2002-06-11 | Version 1.12 - Fixed a bug that prevented the indentation line |
 34 |            | from  updating correctly  under some  circumstances.  This bug |
 35 |            | happened when removing the last item in a subtree and items in |
 36 |            | siblings to the remove subtree where not correctly updated.    |
 37 | 2002-06-13 | Fixed a few minor bugs cased by the 1.12 bug-fix.              |
 38 | 2002-08-20 | Added usePersistence flag to allow disable of cookies.         |
 39 | 2002-10-23 | (1.14) Fixed a plus icon issue                                 |
 40 | 2002-10-29 | (1.15) Last changes broke more than they fixed. This version   |
 41 |            | is based on 1.13 and fixes the bugs 1.14 fixed withou breaking |
 42 |            | lots of other things.                                          |
 43 | 2003-02-15 | The  selected node can now be made visible even when  the tree |
 44 |            | control  loses focus.  It uses a new class  declaration in the |
 45 |            | css file '.webfx-tree-item a.selected-inactive', by default it |
 46 |            | puts a light-gray rectangle around the selected node.          |
 47 | 2003-03-16 | Adding target support after lots of lobbying                |
 48 | 2006-05-26 | Changed license to Apache Software License 2.0.                |
 49 |-----------------------------------------------------------------------------|
 50 | Created 2000-12-11 | All changes are in the log above. | Updated 2006-05-26 |
 51 \----------------------------------------------------------------------------*/
 52 
 53 // tree config 对象,设定框架的基本信息。
 54 var webFXTreeConfig = {
 55     rootIcon        : 'images/foldericon.png',
 56     openRootIcon    : 'images/openfoldericon.png',
 57     folderIcon      : 'images/foldericon.png',
 58     openFolderIcon  : 'images/openfoldericon.png',
 59     fileIcon        : 'images/file.png',
 60     iIcon           : 'images/I.png',
 61     lIcon           : 'images/L.png',
 62     lMinusIcon      : 'images/Lminus.png',
 63     lPlusIcon       : 'images/Lplus.png',
 64     tIcon           : 'images/T.png',
 65     tMinusIcon      : 'images/Tminus.png',
 66     tPlusIcon       : 'images/Tplus.png',
 67     blankIcon       : 'images/blank.png',
 68     defaultText     : 'Tree Item',
 69     defaultAction   : 'javascript:void(0);',
 70     defaultBehavior : 'classic',
 71     //默认是否打开树的根节点。
 72     usePersistence    : true
 73 };
 74 
 75 // tree handler 对象,设定常用的值和方法。
 76 var webFXTreeHandler = {
 77     idCounter : 0,
 78     idPrefix  : "webfx-tree-object-",
 79     all       : {},
 80     behavior  : null,
 81     selected  : null,
 82     onSelect  : null/* should be part of tree, not handler */
 83     getId     : function() { return this.idPrefix + this.idCounter++; },
 84     toggle    : function (oItem) { this.all[oItem.id.replace('-plus','')].toggle(); },
 85     select    : function (oItem) { this.all[oItem.id.replace('-icon','')].select(); },
 86     // 当节点得到焦点时,使id的元素执行  focus(),节点方法。
 87     focus     : function (oItem) { this.all[oItem.id.replace('-anchor','')].focus(); },
 88     blur      : function (oItem) { this.all[oItem.id.replace('-anchor','')].blur(); },
 89     keydown   : function (oItem, e) { return this.all[oItem.id].keydown(e.keyCode); },
 90     cookies   : new WebFXCookie(),
 91     insertHTMLBeforeEnd    :    function (oElement, sHTML) {
 92         // 当可以用 insertAdjacentHTML 方法时
 93         if (oElement.insertAdjacentHTML != null) {
 94             //sHTML插件 oElement 结束标签前
 95             oElement.insertAdjacentHTML("BeforeEnd", sHTML)
 96             return;
 97         }
 98         //当不可以用 insertAdjacentHTML 方法时
 99         var df;    // DocumentFragment
100         var r = oElement.ownerDocument.createRange();
101         r.selectNodeContents(oElement);
102         r.collapse(false);
103         df = r.createContextualFragment(sHTML);
104         oElement.appendChild(df);
105     }
106 };
107 
108 
109 /*
110  * WebFXCookie class
111  * cookie 操作类
112  */
113 function WebFXCookie() {
114     if (document.cookie.length) { this.cookies = ' ' + document.cookie; }
115 }
116 
117 //给 cookie 赋值,方法
118 WebFXCookie.prototype.setCookie = function (key, value) {
119     // 给 cookie 赋值方式,后面没有指定失效日期,
120     // 则浏览器默认是在关闭浏览器(也就是关闭所有窗口)之后过期。
121     //escape()  方法是把字符串按 URL 编码方法来编码的
122     document.cookie = key + "=" + escape(value);
123 }
124 /**
125  * @function 返回 cookie  中存储着 key的值。
126  * 1.找到关键字在 cookies 中存储的位置
127  * 2.判断存储位署 start 是否为-1,如果为-1表示不存在返回null
128  * 3.检索start位置到';'的第一个位置,并赋予变量 end
129  * 4.如果 end =-1 ,表示不存在,则把 cookies 的长度赋予它
130  * 5.end -= start ,计算出关键字key 的长度.
131  * 6.使用 substr 方法 从起始索引号提取字符串中指定数目的字符。
132  * 7.提取'='后至字符串长度减去  '=' 的位置。
133  */
134 WebFXCookie.prototype.getCookie = function (key) {
135     if (this.cookies) {
136         var start = this.cookies.indexOf(' ' + key + '=');
137         if (start == -1) { return null; }
138         var end = this.cookies.indexOf(";", start);
139         if (end == -1) { end = this.cookies.length; }
140         end -= start;
141         var cookie = this.cookies.substr(start,end);
142       // unescqpe 方法,处理从cookie 接收过来的值,并按 URL编码格式转换成字符串。
143         return unescape(cookie.substr(cookie.indexOf('=') + 1, cookie.length - cookie.indexOf('=') + 1));
144     }
145     else { return null; }
146 }
147 
148 
149 
150 /*
151  * WebFXTreeAbstractNode class
152  * tree 抽象节点类
153  */
154 function WebFXTreeAbstractNode(sText, sAction) {
155     this.childNodes  = [];
156     this.id     = webFXTreeHandler.getId();
157     this.text   = sText || webFXTreeConfig.defaultText;
158     this.action = sAction || webFXTreeConfig.defaultAction;
159     this._last  = false;
160     webFXTreeHandler.all[this.id] = this;
161 }
162 
163 /*
164  * To speed thing up if you're adding multiple nodes at once (after load)
165  * use the bNoIdent parameter to prevent automatic re-indentation and call
166  * the obj.ident() method manually once all nodes has been added.
167  */
168 /**
169  * @function WebFXTreeAbstractNode 类的 add 方法 .
170  * @param node 节点, bNoIdent 
171  */
172 WebFXTreeAbstractNode.prototype.add = function (node, bNoIdent) {
173     //将this 对象赋予  node 节点的父节点。
174     node.parentNode = this;
175     //this 节点的添加一个节点是 node 节点。
176     this.childNodes[this.childNodes.length] = node;
177     // 变量 root  节点,由 this 赋予
178     var root = this;
179     //为什么是2呢?因为  节点下标从 0开始数,并且要去掉它本身这个节点。
180     if (this.childNodes.length >= 2) {
181         this.childNodes[this.childNodes.length - 2]._last = false;
182     }
183     // root 变量成为根节点
184     while (root.parentNode) { 
185         root = root.parentNode;
186     }
187     //如果树已经显示
188     if (root.rendered) {
189         if (this.childNodes.length >= 2) {
190             //document.getElementById(this.childNodes[this.childNodes.length - 2].id + '-plus').src = ((this.childNodes[this.childNodes.length -2].folder)?((this.childNodes[this.childNodes.length -2].open)?webFXTreeConfig.tMinusIcon:webFXTreeConfig.tPlusIcon):webFXTreeConfig.tIcon);
191             //判断应该显示的图片。
192             if(this.childNodes[this.childNodes.length -2].folder){
193                 var _icon ;
194                 if(this.childNodes[this.childNodes.length -2].open){
195                   _icon = webFXTreeConfig.tMinusIcon;
196                 }else{
197                   _icon = webFXTreeConfig.tPlusIcon;
198                 }
199                 document.getElementById(this.childNodes[this.childNodes.length - 2].id + '-plus').src = _icon;
200             }else{
201               document.getElementById(this.childNodes[this.childNodes.length - 2].id + '-plus').src = webFXTreeConfig.tIcon;
202             }
203 
204             this.childNodes[this.childNodes.length - 2].plusIcon = webFXTreeConfig.tPlusIcon;
205             this.childNodes[this.childNodes.length - 2].minusIcon = webFXTreeConfig.tMinusIcon;
206             this.childNodes[this.childNodes.length - 2]._last = false;
207         }
208         this._last = true;
209         // 本节点赋予 foo对象
210         var foo = this;
211         while (foo.parentNode) {
212             for (var i = 0; i < foo.parentNode.childNodes.length; i++) {
213                 if (foo.id == foo.parentNode.childNodes[i].id) { 
214                     break;
215               }
216             }
217             if (i == foo.parentNode.childNodes.length - 1) { 
218                 foo.parentNode._last = true
219             }
220             else { 
221                 foo.parentNode._last = false
222             }
223             foo = foo.parentNode;
224         }
225         webFXTreeHandler.insertHTMLBeforeEnd(document.getElementById(this.id + '-cont'), node.toString());
226         
227         if ((!this.folder) && (!this.openIcon)) {
228             this.icon = webFXTreeConfig.folderIcon;
229             this.openIcon = webFXTreeConfig.openFolderIcon;
230         }
231         if (!this.folder) { 
232             this.folder = true
233             this.collapse(true); 
234         }
235         if (!bNoIdent) { 
236             this.indent(); 
237         }
238     }
239     return node;
240 }
241 /**
242  *@function 扩展/折叠 方法
243  *1.判断文件是否 折叠
244  *2.如果状态是打开,执行 collapse ()方法 ,将其折叠
245  *3.如果状态是关闭,执行 expand()  方法,将其打开
246  */
247 WebFXTreeAbstractNode.prototype.toggle = function() {
248     if (this.folder) {
249         if (this.open) {
250              this.collapse();
251       }
252         else {
253              this.expand(); 
254         }
255     }
256 }
257 /**
258  *@function 节点选择方法
259  *当选择时此对象得到焦点
260  */
261 WebFXTreeAbstractNode.prototype.select = function() {
262     document.getElementById(this.id + '-anchor').focus();
263 }
264 /**
265  *@function 取消选择方法
266  *1.节点的className  为空
267  *2.管理表示此节点未选择
268  */
269 WebFXTreeAbstractNode.prototype.deSelect = function() {
270     document.getElementById(this.id + '-anchor').className = '';
271     webFXTreeHandler.selected = null;
272 }
273 /**
274  *@function 当节点被选中时,执行此得到焦点方法
275  */
276 WebFXTreeAbstractNode.prototype.focus = function() {
277     // 如果选中为空,或者选中的不是本节点,则执行取消选择方法。
278     if ((webFXTreeHandler.selected) && (webFXTreeHandler.selected != this)) { 
279          webFXTreeHandler.selected.deSelect(); 
280     }
281     //选择值赋予本节点。
282     webFXTreeHandler.selected = this;
283     //改变图标
284     if ((this.openIcon) && (webFXTreeHandler.behavior != 'classic')) { 
285         document.getElementById(this.id + '-icon').src = this.openIcon; 
286     }
287     document.getElementById(this.id + '-anchor').className = 'selected';
288     document.getElementById(this.id + '-anchor').focus();
289     // 如果 onSelect 存在,则执行本节点的  onSelect 方法。猜想:一种扩展方法吗???
290     if (webFXTreeHandler.onSelect) { 
291         webFXTreeHandler.onSelect(this); 
292     }
293 }
294 
295 WebFXTreeAbstractNode.prototype.blur = function() {
296     if ((this.openIcon) && (webFXTreeHandler.behavior != 'classic')) { document.getElementById(this.id + '-icon').src = this.icon; }
297     document.getElementById(this.id + '-anchor').className = 'selected-inactive';
298 }
299 
300 /**
301  * @function 节点扩张方法的据体实体。
302  */
303 WebFXTreeAbstractNode.prototype.doExpand = function() {
304     //改变节点的显示图标。
305     if (webFXTreeHandler.behavior == 'classic') { 
306           document.getElementById(this.id + '-icon').src = this.openIcon; 
307     }
308     // 节点下的 div  层状态为显示
309     if (this.childNodes.length) {  
310           document.getElementById(this.id + '-cont').style.display = 'block';
311   }
312   // 改变节点的状态为:打开
313     this.open = true;
314     //设定 存储在 cookie 上id为 '1'
315     if (webFXTreeConfig.usePersistence) {
316         webFXTreeHandler.cookies.setCookie(this.id.substr(18,this.id.length - 18), '1');
317      }
318 }
319 
320 /**
321  *@function 节点收缩的据体操作
322  */
323 WebFXTreeAbstractNode.prototype.doCollapse = function() {
324     //改变节点的图标
325     if (webFXTreeHandler.behavior == 'classic') { 
326          document.getElementById(this.id + '-icon').src = this.icon; 
327     }
328     //改变 div 状态为隐藏
329     if (this.childNodes.length) { 
330          document.getElementById(this.id + '-cont').style.display = 'none'; 
331     }
332     //改变节点当前状态是:关闭
333     this.open = false;
334     //设定 存储在  cookie 上的id为‘0’
335     if (webFXTreeConfig.usePersistence) {
336         webFXTreeHandler.cookies.setCookie(this.id.substr(18,this.id.length - 18), '0');
337     }    
338 }
339 /**
340  *@function 打开所有的子节点 
341  */
342 WebFXTreeAbstractNode.prototype.expandAll = function() {
343     this.expandChildren();
344     if ((this.folder) && (!this.open)) {
345          this.expand();
346     }
347 }
348 /**
349  *@function 打开本节点的子节点。跟 expandAll() 方法合用
350  */
351 WebFXTreeAbstractNode.prototype.expandChildren = function() {
352     for (var i = 0; i < this.childNodes.length; i++) {
353         this.childNodes[i].expandAll();
354     } 
355 }
356 /**
357  *@function 关闭所有的节点。
358  */
359 WebFXTreeAbstractNode.prototype.collapseAll = function() {
360     this.collapseChildren();
361     if ((this.folder) && (this.open)) { 
362          //有值,表示关闭时,不获得焦点
363          this.collapse(true); 
364     }
365 }
366 /**
367  *@function 关闭本节点的子节点,跟 collapseAll()  方法合用。
368  */
369 WebFXTreeAbstractNode.prototype.collapseChildren = function() {
370     for (var i = 0; i < this.childNodes.length; i++) {
371         this.childNodes[i].collapseAll();
372     }
373 }
374 
375 
376 WebFXTreeAbstractNode.prototype.indent = function(lvl, del, last, level, nodesLeft) {
377     /*
378      * Since we only want to modify items one level below ourself,
379      * and since the rightmost indentation position is occupied by
380      * the plus icon we set this to -2
381      */
382     if (lvl == null) { 
383         lvl = -2
384     }
385     var state = 0;
386     for (var i = this.childNodes.length - 1; i >= 0 ; i--) {
387         state = this.childNodes[i].indent(lvl + 1, del, last, level);
388         if (state) { 
389             return
390         }
391     }
392     if (del) {
393         if ((level >= this._level) && (document.getElementById(this.id + '-plus'))) {
394             if (this.folder) {
395                 document.getElementById(this.id + '-plus').src = (this.open)?webFXTreeConfig.lMinusIcon:webFXTreeConfig.lPlusIcon;
396                 this.plusIcon = webFXTreeConfig.lPlusIcon;
397                 this.minusIcon = webFXTreeConfig.lMinusIcon;
398             }else if (nodesLeft) { 
399                 document.getElementById(this.id + '-plus').src = webFXTreeConfig.lIcon; 
400             }
401             return 1;
402       }    
403     }
404     var foo = document.getElementById(this.id + '-indent-+ lvl);
405     if (foo) {
406         if ((foo._last) || ((del) && (last))) { 
407             foo.src =  webFXTreeConfig.blankIcon; 
408         } else { 
409             foo.src =  webFXTreeConfig.iIcon;
410         }
411     }
412     return 0;
413 }
414 
415 
416 /*
417  * WebFXTree class
418  */
419 
420 function WebFXTree(sText, sAction, sBehavior, sIcon, sOpenIcon) {
421     //抽象节点操作,将 sText ,sAction 添加到树节点中
422     this.base = WebFXTreeAbstractNode;
423     this.base(sText, sAction);
424     
425     //OR 逻辑运算符特性,如果 sIcon 字符串不为 空,那么在 Boolean 中表示 true,返回 sIcon,
426     //如果为空,则返回 webFXTreeConfig.rootIcon 字符串。
427     this.icon      = sIcon || webFXTreeConfig.rootIcon;
428     this.openIcon  = sOpenIcon || webFXTreeConfig.openRootIcon;
429 
430     /* Defaults to open */
431     if (webFXTreeConfig.usePersistence) {
432         this.open  = (webFXTreeHandler.cookies.getCookie(this.id.substr(18,this.id.length - 18)) == '0')?false:true;
433     } else { 
434         this.open  = true
435     }
436     // 是否折叠
437     this.folder    = true;
438     // 是否已经浏览
439     this.rendered  = false;
440     // 是否选择
441     this.onSelect  = null;
442     if (!webFXTreeHandler.behavior) {  
443          webFXTreeHandler.behavior = sBehavior || webFXTreeConfig.defaultBehavior;
444     }
445 }
446 // 继承: WebFXTree 继承 WebFXTreeAbstractNode 所有的方法和属性。
447 WebFXTree.prototype = new WebFXTreeAbstractNode;
448 
449 WebFXTree.prototype.setBehavior = function (sBehavior) {
450     webFXTreeHandler.behavior =  sBehavior;
451 };
452 
453 WebFXTree.prototype.getBehavior = function (sBehavior) {
454     return webFXTreeHandler.behavior;
455 };
456 
457 /**
458  *@function 树得到焦点时,返回得到焦点的节点信息
459  */
460 WebFXTree.prototype.getSelected = function() {
461     if (webFXTreeHandler.selected) { 
462         return webFXTreeHandler.selected; 
463     }
464     else { 
465         return null;
466     }
467 }
468 /**
469  * @function 根节点 remove 方法为空,不能删除根节点吧。
470  */
471 WebFXTree.prototype.remove = function() { }
472 
473 /**
474  * @function 扩张方法,即打开根节点下的叶节点。
475  */
476 WebFXTree.prototype.expand = function() {
477     this.doExpand();
478 }
479 /**
480  *@function 收缩方法,即关闭根节点下的所有叶节点。
481  *对象得到焦点
482  */
483 WebFXTree.prototype.collapse = function(b) {
484     if (!b) { 
485         this.focus(); 
486     }
487     this.doCollapse();
488 }
489 /*
490 WebFXTree.prototype.getFirst = function() {
491     return null;
492 }
493 
494 WebFXTree.prototype.getLast = function() {
495     return null;
496 }
497 
498 WebFXTree.prototype.getNextSibling = function() {
499     return null;
500 }
501 
502 WebFXTree.prototype.getPreviousSibling = function() {
503     return null;
504 }
505 */
506 WebFXTree.prototype.keydown = function(key) {
507     if (key == 39) {
508         if (!this.open) { this.expand(); }
509         else if (this.childNodes.length) { this.childNodes[0].select(); }
510         return false;
511     }
512     if (key == 37) { this.collapse(); return false; }
513     if ((key == 40&& (this.open) && (this.childNodes.length)) { this.childNodes[0].select(); return false; }
514     return true;
515 }
516 
517 WebFXTree.prototype.toString = function() {
518     var str = "<div id=\"" + this.id + "\" ondblclick=\"webFXTreeHandler.toggle(this);\" class=\"webfx-tree-item\" onkeydown=\"return webFXTreeHandler.keydown(this, event)\">" +
519         "<img id=\"" + this.id + "-icon\" class=\"webfx-tree-icon\" src=\"" + ((webFXTreeHandler.behavior == 'classic' && this.open)?this.openIcon:this.icon) + "\" onclick=\"webFXTreeHandler.select(this);\">" +
520         "<a href=\"" + this.action + "\" id=\"" + this.id + "-anchor\" onfocus=\"webFXTreeHandler.focus(this);\" onblur=\"webFXTreeHandler.blur(this);\"" +
521         (this.target ? " target=\"" + this.target + "\"" : ""+
522         ">" + this.text + "</a></div>" +
523         "<div id=\"" + this.id + "-cont\" class=\"webfx-tree-container\" style=\"display: " + ((this.open)?'block':'none') + ";\">";
524     var sb = [];
525     for (var i = 0; i < this.childNodes.length; i++) {
526         sb[i] = this.childNodes[i].toString(i, this.childNodes.length);
527     }
528     this.rendered = true;
529     // 返回字符串值,其中包含了连接到一起的数组的所有元素,元素由指定分隔符分隔开来.
530     return str + sb.join(""+ "</div>";
531 };
532 
533 /*
534  * WebFXTreeItem class
535  */
536 
537 function WebFXTreeItem(sText, sAction, eParent, sIcon, sOpenIcon) {
538     this.base = WebFXTreeAbstractNode;
539     this.base(sText, sAction);
540     /* Defaults to close */
541     if (webFXTreeConfig.usePersistence) {
542         this.open = (webFXTreeHandler.cookies.getCookie(this.id.substr(18,this.id.length - 18)) == '1')?true:false;
543     } else { 
544         this.open = false
545     }
546     if (sIcon) { 
547         this.icon = sIcon;
548     }
549     if (sOpenIcon) { 
550         this.openIcon = sOpenIcon; 
551     }
552     if (eParent) { 
553          eParent.add(this); 
554     }
555 }
556 
557 // WebFXTreeItem 类继承  WebFXTreeAbstractNode 抽象类所有的属性和方法。
558 WebFXTreeItem.prototype = new WebFXTreeAbstractNode;
559 
560 /**
561  *@function WebFXTreeItem 节点删除方法
562  */
563 WebFXTreeItem.prototype.remove = function() {
564     var iconSrc = document.getElementById(this.id + '-plus').src;
565     // 父节点
566     var parentNode = this.parentNode;
567     // 上一个兄弟节点
568     var prevSibling = this.getPreviousSibling(true);
569     // 下一个兄弟节点
570     var nextSibling = this.getNextSibling(true);
571     // 父节点的折叠属性
572     var folder = this.parentNode.folder;
573     // 判断本节点是不是父节点的最后一个子节点。
574     var last = ((nextSibling) && (nextSibling.parentNode) && (nextSibling.parentNode.id == parentNode.id))?false:true;
575     // 本节点的上一个兄弟节点得到焦点。
576     this.getPreviousSibling().focus();
577     
578     this._remove();
579     
580     if (parentNode.childNodes.length == 0) {
581         document.getElementById(parentNode.id + '-cont').style.display = 'none';
582         parentNode.doCollapse();
583         parentNode.folder = false;
584         parentNode.open = false;
585     }
586     if (!nextSibling || last) { parentNode.indent(nulltrue, last, this._level, parentNode.childNodes.length); }
587     if ((prevSibling == parentNode) && !(parentNode.childNodes.length)) {
588         prevSibling.folder = false;
589         prevSibling.open = false;
590         iconSrc = document.getElementById(prevSibling.id + '-plus').src;
591         iconSrc = iconSrc.replace('minus', '').replace('plus', '');
592         document.getElementById(prevSibling.id + '-plus').src = iconSrc;
593         document.getElementById(prevSibling.id + '-icon').src = webFXTreeConfig.fileIcon;
594     }
595     if (document.getElementById(prevSibling.id + '-plus')) {
596         if (parentNode == prevSibling.parentNode) {
597             iconSrc = iconSrc.replace('minus', '').replace('plus', '');
598             document.getElementById(prevSibling.id + '-plus').src = iconSrc;
599 }    }    }
600 
601 /**
602  *@function 删除方法的据体操作
603  */
604 WebFXTreeItem.prototype._remove = function() {
605      //递归删除节点下的所有子节点
606     for (var i = this.childNodes.length - 1; i >= 0; i--) {
607         this.childNodes[i]._remove();
608      }
609      /*
610      * 循环查询所有的子节点,找到本节点在子节点的位置,将本节点后的节点分别向前占位,并使父节点的节点总量减一。
611      * 如果节点的位置 +1 等于父节点的子节点总数,那么设置父节点的_last 为 true,即最后一个节点。
612      */
613     for (var i = 0; i < this.parentNode.childNodes.length; i++) {
614         if (this == this.parentNode.childNodes[i]) {
615             for (var j = i; j < this.parentNode.childNodes.length; j++) {
616                 this.parentNode.childNodes[j] = this.parentNode.childNodes[j+1];
617             }
618             this.parentNode.childNodes.length -= 1;
619             if (i + 1 == this.parentNode.childNodes.length) { 
620                  this.parentNode._last = true
621             }
622             break;
623       }    
624     }
625     //本ID节点为NULL
626     webFXTreeHandler.all[this.id] = null;
627     //得到本节点元素,如果存在让父元素删除,
628     var tmp = document.getElementById(this.id);
629     if (tmp) { 
630         tmp.parentNode.removeChild(tmp); 
631     }
632     //得到本节点元素的 子空间,如果存在,删除。
633     tmp = document.getElementById(this.id + '-cont');
634     if (tmp) { 
635         tmp.parentNode.removeChild(tmp); 
636     }
637 }
638 
639 /**
640  *@function  扩张方法
641  */
642 WebFXTreeItem.prototype.expand = function() {
643     this.doExpand();
644     document.getElementById(this.id + '-plus').src = this.minusIcon;
645 }
646 /**
647  *@function   收缩方法 
648  */
649 WebFXTreeItem.prototype.collapse = function(b) {
650     if (!b) { this.focus(); }
651     this.doCollapse();
652     document.getElementById(this.id + '-plus').src = this.plusIcon;
653 }
654 /**
655  *@function 返回第一个节点
656  */
657 WebFXTreeItem.prototype.getFirst = function() {
658     return this.childNodes[0];
659 }
660 
661 /*
662  *@function 返回上一个最后的子节点
663  */
664 WebFXTreeItem.prototype.getLast = function() {
665     //如果节点是打开,那么递归得到最后一个节点;否则返回这个节点。
666     if (this.childNodes[this.childNodes.length - 1].open) { 
667          return this.childNodes[this.childNodes.length - 1].getLast(); 
668     }else { 
669         return this.childNodes[this.childNodes.length - 1]; 
670     }
671 }
672 /**
673  *@function 获得本节点的下一个子节点。
674  */
675 WebFXTreeItem.prototype.getNextSibling = function() {
676     for (var i = 0; i < this.parentNode.childNodes.length; i++) {
677         if (this == this.parentNode.childNodes[i]) { break; }
678     }
679     if (++== this.parentNode.childNodes.length) { return this.parentNode.getNextSibling(); }
680     else { return this.parentNode.childNodes[i]; }
681 }
682 
683 /**
684  *@function 获得本节点的前一个兄弟节点
685  */
686 WebFXTreeItem.prototype.getPreviousSibling = function(b) {
687     //判断兄弟节点中,本节点所占的下标。
688     for (var i = 0; i < this.parentNode.childNodes.length; i++) {
689         if (this == this.parentNode.childNodes[i]) { 
690             break
691         }
692     }
693     //如果下标 i  为零,即父节点只有一个子节点,反回父节点。 
694     if (i == 0) { 
695         return this.parentNode; 
696     } else {
697         if ((this.parentNode.childNodes[--i].open) || (b && this.parentNode.childNodes[i].folder)) { 
698              return this.parentNode.childNodes[i].getLast(); 
699         }    else { 
700             return this.parentNode.childNodes[i];
701       }
702     } 
703 }
704 
705 WebFXTreeItem.prototype.keydown = function(key) {
706     if ((key == 39&& (this.folder)) {
707         if (!this.open) { this.expand(); }
708         else { this.getFirst().select(); }
709         return false;
710     }
711     else if (key == 37) {
712         if (this.open) { this.collapse(); }
713         else { this.parentNode.select(); }
714         return false;
715     }
716     else if (key == 40) {
717         if (this.open) { this.getFirst().select(); }
718         else {
719             var sib = this.getNextSibling();
720             if (sib) { sib.select(); }
721         }
722         return false;
723     }
724     else if (key == 38) { this.getPreviousSibling().select(); return false; }
725     return true;
726 }
727 /**
728  *@function 返回该对象的字符串表达
729  */
730 WebFXTreeItem.prototype.toString = function (nItem, nItemCount) {
731     var foo = this.parentNode;
732     var indent = '';
733     if (nItem + 1 == nItemCount) { this.parentNode._last = true; }
734     var i = 0;
735     while (foo.parentNode) {
736         foo = foo.parentNode;
737         indent = "<img id=\"" + this.id + "-indent-" + i + "\" src=\"" + ((foo._last)?webFXTreeConfig.blankIcon:webFXTreeConfig.iIcon) + "\">" + indent;
738         i++;
739     }
740     this._level = i;
741     if (this.childNodes.length) { this.folder = 1; }
742     else { this.open = false; }
743     if ((this.folder) || (webFXTreeHandler.behavior != 'classic')) {
744         if (!this.icon) { this.icon = webFXTreeConfig.folderIcon; }
745         if (!this.openIcon) { this.openIcon = webFXTreeConfig.openFolderIcon; }
746     }
747     else if (!this.icon) { this.icon = webFXTreeConfig.fileIcon; }
748     var label = this.text.replace(/</g, '&lt;').replace(/>/g, '&gt;');
749     var str = "<div id=\"" + this.id + "\" ondblclick=\"webFXTreeHandler.toggle(this);\" class=\"webfx-tree-item\" onkeydown=\"return webFXTreeHandler.keydown(this, event)\">" +
750         indent +
751         "<img id=\"" + this.id + "-plus\" src=\"" + ((this.folder)?((this.open)?((this.parentNode._last)?webFXTreeConfig.lMinusIcon:webFXTreeConfig.tMinusIcon):((this.parentNode._last)?webFXTreeConfig.lPlusIcon:webFXTreeConfig.tPlusIcon)):((this.parentNode._last)?webFXTreeConfig.lIcon:webFXTreeConfig.tIcon)) + "\" onclick=\"webFXTreeHandler.toggle(this);\">" +
752         "<img id=\"" + this.id + "-icon\" class=\"webfx-tree-icon\" src=\"" + ((webFXTreeHandler.behavior == 'classic' && this.open)?this.openIcon:this.icon) + "\" onclick=\"webFXTreeHandler.select(this);\">" +
753         "<a href=\"" + this.action + "\" id=\"" + this.id + "-anchor\" onfocus=\"webFXTreeHandler.focus(this);\" onblur=\"webFXTreeHandler.blur(this);\"" +
754         (this.target ? " target=\"" + this.target + "\"" : ""+
755         ">" + label + "</a></div>" +
756         "<div id=\"" + this.id + "-cont\" class=\"webfx-tree-container\" style=\"display: " + ((this.open)?'block':'none') + ";\">";
757     var sb = [];
758     for (var i = 0; i < this.childNodes.length; i++) {
759         sb[i] = this.childNodes[i].toString(i,this.childNodes.length);
760     }
761     this.plusIcon = ((this.parentNode._last)?webFXTreeConfig.lPlusIcon:webFXTreeConfig.tPlusIcon);
762     this.minusIcon = ((this.parentNode._last)?webFXTreeConfig.lMinusIcon:webFXTreeConfig.tMinusIcon);
763     return str + sb.join(""+ "</div>";
764 }
765 
766 
767         面向对象的思想来编写 javascript  语言,运用很多让人容易忽略的js语言知识,有着 DOM 方式,使整个框架看起来让人惊叹。
768 框架原来如此简单!
769 
下载框架

posted on 2009-07-09 09:44 星期五 阅读(1198) 评论(0)  编辑  收藏 所属分类: WEB FX


只有注册用户登录后才能发表评论。


网站导航: