source: sandbox/expressoMail1_2/MailArchiver/2.2/phpgwapi/js/dftree/dftree.js @ 4713

Revision 4713, 16.8 KB checked in by fernando-alberto, 13 years ago (diff)

Ticket #1269 - Desenvolvimento da nova solucao de arquivamento local MailArchiver?, tree pref sem arquivamento

  • Property svn:eol-style set to native
  • Property svn:executable set to *
Line 
1/* Dynamic Folder Tree
2 * Generates DHTML tree dynamically (on the fly).
3 * License: GNU LGPL
4 *
5 * Copyright (c) 2004, Vinicius Cubas Brand, Raphael Derosso Pereira
6 * {viniciuscb,raphaelpereira} at users.sourceforge.net
7 * All rights reserved.
8 *
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24/*
25 * Chanded by Joao Alfredo Knopik Junior
26 * joao.alfredo at gmail.com
27 */
28
29// NODE
30//Usage: a = new dNode({id:2, caption:'tree root', url:'http://www.w3.org'});
31function dNode(arrayProps) {
32        //mandatory fields
33        this.id;          //node id
34        this.caption;     //node caption
35
36        //optional fields
37        this.url;         //url to open
38        this.target;      //target to open url
39        this.onClick;     //javascript to execute onclick
40        this.onOpen;      //javascript to execute when a node of the tree opens
41        this.onClose;     //javascript to execute when a node of the tree closes
42        this.onFirstOpen; //javascript to execute only on the first open
43        this.iconClosed;  //img.src of closed icon
44        this.iconOpen;    //img.src of open icon
45        this.runJS = true;       //(bool) if true, runs the on* props defined above
46        this.plusSign = true;    //(bool) if the plus sign will appear or not
47        this.captionClass = 'l'; //(string) the class for this node's caption
48
49
50        //The parameters below are private
51        this._opened = false; //already opened
52        this._io = false; //is opened
53
54        this._children = []; //references to children
55        this._parent; //pointer to parent
56        this._myTree; //pointer to myTree
57        this._drawn = false;
58
59        for (var i in arrayProps)
60        {
61                if (i.charAt(0) != '_')
62                {
63                        eval('this.'+i+' = arrayProps[\''+i+'\'];');
64                }
65        }
66}
67
68//changes node state from open to closed, and vice-versa
69dNode.prototype.changeState = function()
70{
71        if (this._io)
72        {
73                this.close();
74        }
75        else
76        {
77                this.open();
78        }
79
80        //cons = COokie of Node Status
81        //setCookie("cons"+this.id,this._io);
82}
83
84dNode.prototype.open = function () {
85        //window.alert('em dNode.prototype.open\n\nname = ' + this.id + '\nopened = ' + this._opened + '\nis opened = ' + this._io + '\ncaptionClass = ' + this.captionClass + '\nmyTree = ' + this._myTree.name);
86       
87        if(typeof(expresso_mail_archive) != 'undefined')
88            if (expresso_mail_archive.enabled)
89                expresso_mail_archive.drawdata.treeName = this._myTree.name;
90       
91        if (!this._io)
92        {
93                if (!this._opened && this.runJS && this.onFirstOpen != null)
94                {
95                        alert('onfirstopen');
96                        eval(this.onFirstOpen);
97                }
98                else if (this.runJS && this.onOpen != null)
99                {
100                        alert('onOpen');
101                        eval(this.onOpen);
102                }
103                else if((this.id.substr(0,5) == 'local') && (!this._opened) && (!this._io) && (expresso_mail_archive.enabled)){
104                    if (this.id != 'local_root')
105                        expresso_mail_archive.getFoldersList(this.id.substr(6));
106                    else
107                        expresso_mail_archive.getFoldersList("");
108                }
109               
110                this._debug = true;
111                this._opened = true;
112                this._io = true;
113                this._refresh();
114        }
115}
116
117
118dNode.prototype.close = function() {
119        if (this._io)
120        {
121                if (this.runJS && this.onClose != null)
122                {
123                        eval(this.onClose);
124                }
125                this._io = false;
126                this._refresh();
127        }
128}
129
130//alter node label and other properties
131dNode.prototype.alter = function(arrayProps)
132{
133        for (var i in arrayProps)
134        {
135                if (i != 'id' && i.charAt(0) != '_')
136                {
137                        eval('this.'+i+' = arrayProps[\''+i+'\'];');
138                }
139        }
140}
141
142//css and dhtml refresh part
143dNode.prototype._refresh = function() {
144        var nodeDiv      = getObjectById("n"+this.id+this._myTree.name);
145        var plusSpan     = getObjectById("p"+this.id+this._myTree.name);
146        var captionSpan  = getObjectById("l"+this.id+this._myTree.name);
147        var childrenDiv  = getObjectById("ch"+this.id+this._myTree.name);
148
149        if (nodeDiv != null)
150        {
151                //Handling open and close: checks this._io and changes class as needed
152                if (!this._io) //just closed
153                {
154                        childrenDiv.className = "closed";
155                }
156                else //just opened
157                {
158                        //prevents IE undesired behaviour when displaying empty DIVs
159/*                      if (this._children.length > 0)
160                        {*/
161                                childrenDiv.className = "opened";
162                //      }
163                }
164
165                plusSpan.innerHTML = this._properPlus();
166
167                captionSpan.innerHTML = this.caption;
168        }
169
170//alter onLoad, etc
171
172}
173
174//gets the proper plus for this moment
175dNode.prototype._properPlus = function()
176{
177       
178        if (!this._io)
179        {
180                if (this._myTree.useIcons)
181                {
182                        return (this.plusSign)?imageHTML(this._myTree.icons.plus):"";
183                }
184                else
185                {
186                        return (this.plusSign)?"+":" ";
187                }
188        }
189        else
190        {
191                if (this._myTree.useIcons)
192                {
193                        return (this.plusSign)?imageHTML(this._myTree.icons.minus):"";
194                }
195                else
196                {
197                        return (this.plusSign)?"-":" ";
198                }
199        }
200}
201
202//changes node to selected style class. Perform further actions.
203dNode.prototype._select = function()
204{
205        var captionSpan;
206
207        if (this._myTree._selected)
208        {
209                this._myTree._selected._unselect();
210        }
211        this._myTree._selected = this;
212       
213        captionSpan  = getObjectById("l"+this.id+this._myTree.name);
214       
215        if(document.getElementById("div_tree") != null){
216                if(ttree.FOLDER != ""){
217                        ttree.FOLDER = "";
218                }
219                ttree.FOLDER = this.id;
220        }
221       
222        if(document.getElementById("div_folders_search") != null){
223                if(EsearchE.name_box_search != ""){
224                        EsearchE.name_box_search = "";
225                }
226                EsearchE.name_box_search = this.id;
227        }
228
229        //changes class to selected link
230        if (captionSpan)
231        {
232                captionSpan.className = 'sl';
233        }
234
235}
236
237//changes node background color.
238dNode.prototype._onMouseOver = function()
239{
240        var captionSpan;
241        if ((this.id != 'root') && (this.id != 'user') && (this.id !='local_root')){
242                captionSpan = getObjectById("l"+this.id+this._myTree.name);
243                captionSpan.style.backgroundColor = 'white';
244                captionSpan.style.border = '1px solid black';
245                captionSpan.style.paddingTop = '0px';
246                captionSpan.style.paddingBottom = '0px';
247        }
248}
249//changes node background color.
250dNode.prototype._onMouseOut = function()
251{
252        var captionSpan;
253        if ((this.id != 'root') && (this.id != 'user') && (this.id !='local_root')){
254                captionSpan = getObjectById("l"+this.id+this._myTree.name);
255                captionSpan.style.backgroundColor = '';
256                captionSpan.style.border = '0px';
257                captionSpan.style.paddingTop = '1px';
258                captionSpan.style.paddingBottom = '1px';
259        }
260}
261
262//changes node to unselected style class. Perform further actions.
263dNode.prototype._unselect = function()
264{
265        var captionSpan  = getObjectById("l"+this.id+this._myTree.name);
266
267        this._myTree._lastSelected = this._myTree._selected;
268        this._myTree._selected = null;
269
270        //changes class to selected link
271        if (captionSpan)
272        {
273                captionSpan.className = this.captionClass;
274        }
275}
276
277
278//state can be open or closed
279//warning: if drawed node is not child or root, bugs will happen
280dNode.prototype._draw = function()
281{
282        var str;
283        var _this = this;
284        var divN, divCH, spanP, spanL, parentChildrenDiv;
285        var myClass = (this._io)? "opened" : "closed";
286        var myPlus = this._properPlus();
287        var append = true;
288        var captionOnClickEvent = null;
289//      var cook;
290
291        var plusEventHandler = function(){
292                _this.changeState();
293        }
294
295        var captionEventHandler = function(){
296                eval(captionOnClickEvent);
297        }
298
299/*      if (this.myTree.followCookies)
300        {
301                this._io = getCookie("cons"+this.id);
302        }*/
303
304        //FIXME put this in a separate function, as this will be necessary in
305        //various parts
306       
307        //window.alert('this.onclick = ' + _this.onClick);
308
309        if (this.onClick) //FIXME when onclick && url
310        {
311                captionEventHandler = function () { _this._select(); typeof(_this.onClick) == 'function' ? _this.onClick() : eval(_this.onClick); };
312        }
313        else if (this.url && this.target)
314        {
315                captionEventHandler = function () { _this._select(); window.open(_this.url,_this.target); };
316        }
317        else if (this.url)
318        {
319                captionEventHandler = function () { _this._select(); window.location=_this.url; };
320        }
321        else //Nao tem onClick
322        {
323                if ((this.id != 'root') && (this.id != 'user') && (this.id !='local_root')) //e nao seja raiz(root) ou pastas compartilhadas(user).
324                        captionEventHandler = function () { _this._select();};
325        }
326       
327        //The div of this node
328        divN = document.createElement('div');
329        divN.id = 'n'+this.id+this._myTree.name;
330        //divN.className = 'son';
331        divN.className = (!this._parent) ? 'root' : 'son';
332        //divN.style.border = '1px solid black';
333       
334        //The span that holds the plus/minus sign
335        spanP = document.createElement('span');
336        spanP.id = 'p'+this.id+this._myTree.name;
337        spanP.className = 'plus';
338        spanP.onclick = plusEventHandler;
339        spanP.innerHTML = myPlus;
340        //spanP.style.border = '1px solid green';
341
342        //The span that holds the label/caption
343        spanL = document.createElement('span');
344        spanL.id = 'l'+this.id+this._myTree.name;
345        spanL.className = this.captionClass;
346        spanL.onclick = captionEventHandler;
347        spanL.onmouseover = function () { _this._onMouseOver(); };
348        spanL.onmouseout = function () { _this._onMouseOut(); };
349//      spanL.style.border = '1px solid #f7f7f7';
350        spanL.innerHTML = this.caption;
351        //spanL.style.border = '1px solid red';
352
353        //The div that holds the children
354        divCH = document.createElement('div');
355        divCH.id = 'ch'+this.id+this._myTree.name;
356        divCH.className = myClass;
357        //divCH.style.border = '1px solid blue';
358       
359//      div.innerHTML = str;
360        divN.appendChild(spanP);
361        divN.appendChild(spanL);
362        divN.appendChild(divCH);
363       
364       
365        if (this._parent != null)
366        {
367        parentChildrenDiv = getObjectById("ch"+this._parent.id+this._myTree.name);
368        }
369        else //is root
370        {
371        parentChildrenDiv = getObjectById("dftree_"+this._myTree.name);
372        }
373       
374        if (parentChildrenDiv)
375        {
376        parentChildrenDiv.appendChild(divN);
377        }
378}
379
380// TREE
381//Usage: t = new dFTree({name:t, caption:'tree root', url:'http://www.w3.org'});
382function dFTree(arrayProps) {
383        //mandatory fields
384        this.name;      //the value of this must be the name of the object
385
386        //optional fields
387        this.is_dynamic = true;   //tree is dynamic, i.e. updated on the fly
388        this.followCookies = true;//use previous state (o/c) of nodes
389        this.useIcons = false;     //use icons or not
390       
391
392        //arrayProps[icondir]: Icons Directory
393        iconPath = (arrayProps['icondir'] != null)? arrayProps['icondir'] : '';
394
395        this.icons = {
396                root        : iconPath+'/foldertree_base.gif',
397                folder      : iconPath+'/foldertree_folder.gif',
398                folderOpen  : iconPath+'/foldertree_folderopen.gif',
399                node        : iconPath+'/foldertree_folder.gif',
400                empty       : iconPath+'/foldertree_empty.gif',
401                line        : iconPath+'/foldertree_line.gif',
402                join        : iconPath+'/foldertree_join.gif',
403                joinBottom  : iconPath+'/foldertree_joinbottom.gif',
404                plus        : iconPath+'/foldertree_plus.gif',
405                plusBottom  : iconPath+'/foldertree_plusbottom.gif',
406                minus       : iconPath+'/foldertree_minus.gif',
407                minusBottom : iconPath+'/foldertree_minusbottom.gif',
408                nlPlus      : iconPath+'/foldertree_nolines_plus.gif',
409                nlMinus     : iconPath+'/foldertree_nolines_minus.gif'
410        };
411
412        //private
413        this._root = false; //reference to root node
414        this._aNodes = [];
415        this._lastSelected; //The last selected node
416        this._selected; //The actual selected node
417        this._folderPr = [];
418
419        for (var i in arrayProps)
420        {
421                if (i.charAt(0) != '_')
422                {
423                        eval('this.'+i+' = arrayProps[\''+i+'\'];');
424                }
425        }
426}
427
428dFTree.prototype.draw = function(dest_element) {
429        var main_div;
430       
431        if (!getObjectById("dftree_"+this.name) && dest_element)
432        {
433                main_div = document.createElement('div');
434                main_div.id = 'dftree_'+this.name;
435                dest_element.appendChild(main_div);
436                this._drawn = true;
437        }
438
439        if (this._root != false)
440        {
441                this._root._draw();
442                this._drawBranch(this._root._children);
443        }
444
445}
446
447//Transforms tree in HTML code
448dFTree.prototype.toString = function() {
449        var str = '';
450
451        if (!getObjectById("dftree_"+this.name))
452        {
453                str = '<div id="dftree_'+this.name+'"></div>';
454        }
455        return str;
456
457/*      if (this.root != false)
458        {
459                this.root._draw();
460                this._drawBranch(this.root.children);
461        }*/
462}
463
464//Recursive function, draws children
465dFTree.prototype._drawBranch = function(childrenArray) {
466        var a=0;
467        for (a;a<childrenArray.length;a++)
468        {
469                childrenArray[a]._draw();
470                this._drawBranch(childrenArray[a]._children);
471        }
472}
473
474//add into a position
475dFTree.prototype.add = function(node,pid) {
476        var auxPos;
477        var addNode = false;
478        if (typeof (auxPos = this._searchNode(node.id)) != "number")
479        {
480                // if parent exists, add node as its child
481                if (typeof (auxPos = this._searchNode(pid)) == "number")
482                {
483                        node._parent = this._aNodes[auxPos];
484                        this._aNodes[auxPos]._children[this._aNodes[auxPos]._children.length] = node;
485                        addNode = true;
486                }
487                else //if parent cannot be found and there is a tree root, ignores node
488                {
489                        if (!this._root)
490                        {
491                                this._root = node;
492                                addNode = true;
493                        }
494                }
495                if (addNode)
496                {
497                        this._aNodes[this._aNodes.length] = node;
498                        node._myTree = this;
499                        if (this.is_dynamic && this._drawn)
500                        {
501                                node._draw();
502                        }
503                }
504                else
505                {
506                        this._folderPr[this._folderPr.length] = node.id ;
507                }
508               
509        }
510        else {
511                var arrayProps = new Array();
512
513                arrayProps['id'] = node.id;
514                arrayProps['caption'] = node.caption;
515
516                arrayProps['url'] = node.url;
517                arrayProps['target'] = node.target;
518                arrayProps['onClick'] = node.onClick;
519                arrayProps['onOpen'] = node.onOpen;
520                arrayProps['onClose'] = node.onClose;
521                arrayProps['onFirstOpen'] = node.onFirstOpen;
522                arrayProps['iconClosed'] = node.iconClosed;
523                arrayProps['iconOpen'] = node.iconOpen;
524                arrayProps['runJS'] = node.runJS;
525                arrayProps['plusSign'] = node.plusSign;
526                arrayProps['captionClass'] = node.captionClass;
527
528                delete node;
529
530                this.alter(arrayProps);
531        }
532
533}
534
535//arrayProps: same properties of Node
536dFTree.prototype.alter = function(arrayProps) {
537        this.getNodeById(arrayProps['id']).alter(arrayProps);
538}
539
540dFTree.prototype.getNodeById = function(nodeid) {
541        return this._aNodes[this._searchNode(nodeid)];
542}
543
544dFTree.prototype.openTo = function(nodeid)
545{
546        var node = this.getNodeById(nodeid);
547
548        if (node && node._parent)
549        {
550                node._parent.open();
551                this.openTo(node._parent.id);
552        }
553}
554
555//Searches for a node in the node array, returning the position of the array 4it
556dFTree.prototype._searchNode = function(id) {
557        var a=0;
558        for (a;a<this._aNodes.length;a++)
559        {
560                if (this._aNodes[a].id == id)
561                {
562                        return a;
563                }
564        }
565        return false;
566}
567// By jakjr, retorna um array com os ids de todas as pastas (nodes)
568dFTree.prototype.getNodesList = function(imapDelimiter) {
569        var a=0;
570        var nodes=[];
571        for (a;a<this._aNodes.length;a++)
572        {
573                var node = this.getNodeById(this._aNodes[a].id);
574                nodes[a]=[];
575                nodes[a].id = node.id;
576                nodes[a].parent = node._parent ? node._parent.id : 'root';             
577                var tmp = node.id.split(imapDelimiter);
578                var tmp_caption = node.caption.split("<");
579
580                if (node.id == 'INBOX')
581                        nodes[a].caption = get_lang('Inbox');
582                else if (node.id == 'user')
583                        nodes[a].caption = get_lang("Shared Folders");
584                else
585                        nodes[a].caption = tmp_caption[0];
586                //nodes[a].caption = tmp[tmp.length-1] == 'INBOX' ? get_lang('Inbox') : tmp[tmp.length-1];
587                nodes[a].plusSign = node.plusSign;
588        }
589        return nodes;
590}
591
592//Auxiliar functions
593//For multi-browser compatibility
594function getObjectById(name)
595{   
596    if (document.getElementById)
597    {
598        return document.getElementById(name);
599    }
600    else if (document.all)
601    {
602        return document.all[name];
603    }
604    else if (document.layers)
605    {
606        return document.layers[name];
607    }
608    return false;
609}
610
611// [Cookie] Clears a cookie
612function clearCookie(cookieName) {
613        var now = new Date();
614        var yesterday = new Date(now.getTime() - 1000 * 60 * 60 * 24);
615        this.setCookie(cookieName, 'cookieValue', yesterday);
616        this.setCookie(cookieName, 'cookieValue', yesterday);
617};
618
619// [Cookie] Sets value in a cookie
620function setCookie(cookieName, cookieValue, expires, path, domain, secure) {
621        document.cookie =
622                escape(cookieName) + '=' + escape(cookieValue)
623                + (expires ? '; expires=' + expires.toGMTString() : '')
624                + (path ? '; path=' + path : '')
625                + (domain ? '; domain=' + domain : '')
626                + (secure ? '; secure' : '');
627};
628
629// [Cookie] Gets a value from a cookie
630function getCookie(cookieName) {
631        var cookieValue = '';
632        var posName = document.cookie.indexOf(escape(cookieName) + '=');
633        if (posName != -1) {
634                var posValue = posName + (escape(cookieName) + '=').length;
635                var endPos = document.cookie.indexOf(';', posValue);
636                if (endPos != -1)
637                {
638                        cookieValue = unescape(document.cookie.substring(posValue, endPos));
639                }
640                else
641                {
642                        cookieValue = unescape(document.cookie.substring(posValue));
643                }
644        }
645        return (cookieValue);
646};
647
648
649function imageHTML(src,attributes) {
650        if (attributes != null)
651        {
652                attributes = '';
653        }
654        return "<img "+attributes+" src=\""+src+"\">";
655}
Note: See TracBrowser for help on using the repository browser.