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

Revision 5034, 17.6 KB checked in by fernando-alberto, 13 years ago (diff)

Ticket #1269 - Desenvolvimento da nova solucao de arquivamento local MailArchiver?, evolucao na api

  • 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            //alert('com !this._io e treeName = ' + this._myTree.name);
94                if (!this._opened && this.runJS && this.onFirstOpen != null)
95                {
96                        alert('onfirstopen');
97                        eval(this.onFirstOpen);
98                }
99                else if (this.runJS && this.onOpen != null)
100                {
101                        alert('onOpen');
102                        eval(this.onOpen);
103                }
104                else if(this.id.substr(0,5) == 'local'){
105                    //alert('on local data\nid = ' + this.id + '\nopened? ' + this._opened + '\nio?' + this._io);
106                    //this._io = false;
107                    //this._opened = false;
108                    //alert('... ajustado para:\nid = ' + this.id + '\nopened? ' + this._opened + '\nio?' + this._io);
109                    //if((!this._opened) && (!this._io) && (expresso_mail_archive.enabled)){
110                        //window.alert('NOCACHE INTENED TO LOCAL FOLDERS!\nok, com drawdata = ' + expresso_mail_archive.drawdata + '\n---\n' + print_r(expresso_mail_archive.drawdata.treeName));
111                        if (this.id != 'local_root')
112                            expresso_mail_archive.getFoldersList(this.id.substr(6));
113                        else
114                            expresso_mail_archive.getFoldersList("");
115                    //}
116                    //else{
117                    //    window.alert('else reached com _io = ' + this._io + ' e _opened = ' + this._opened);
118                    //}
119                }
120               
121                this._debug = true;
122                this._opened = true;
123                this._io = true;
124                //window.alert('sem refresh!');
125                this._refresh();
126        }
127}
128
129
130dNode.prototype.close = function() {
131        if (this._io)
132        {
133                if (this.runJS && this.onClose != null)
134                {
135                        eval(this.onClose);
136                }
137                this._io = false;
138                this._refresh();
139        }
140}
141
142//alter node label and other properties
143dNode.prototype.alter = function(arrayProps)
144{
145        for (var i in arrayProps)
146        {
147                if (i != 'id' && i.charAt(0) != '_')
148                {
149                        eval('this.'+i+' = arrayProps[\''+i+'\'];');
150                }
151        }
152}
153
154//css and dhtml refresh part
155dNode.prototype._refresh = function() {
156        var nodeDiv      = getObjectById("n"+this.id+this._myTree.name);
157        var plusSpan     = getObjectById("p"+this.id+this._myTree.name);
158        var captionSpan  = getObjectById("l"+this.id+this._myTree.name);
159        var childrenDiv  = getObjectById("ch"+this.id+this._myTree.name);
160
161        if (nodeDiv != null)
162        {
163                //Handling open and close: checks this._io and changes class as needed
164                if (!this._io) //just closed
165                {
166                        childrenDiv.className = "closed";
167                }
168                else //just opened
169                {
170                        //prevents IE undesired behaviour when displaying empty DIVs
171/*                      if (this._children.length > 0)
172                        {*/
173                                childrenDiv.className = "opened";
174                //      }
175                }
176
177                plusSpan.innerHTML = this._properPlus();
178
179                captionSpan.innerHTML = this.caption;
180        }
181
182//alter onLoad, etc
183
184}
185
186//gets the proper plus for this moment
187dNode.prototype._properPlus = function()
188{
189       
190        if (!this._io)
191        {
192                if (this._myTree.useIcons)
193                {
194                        return (this.plusSign)?imageHTML(this._myTree.icons.plus):"";
195                }
196                else
197                {
198                        return (this.plusSign)?"+":" ";
199                }
200        }
201        else
202        {
203                if (this._myTree.useIcons)
204                {
205                        return (this.plusSign)?imageHTML(this._myTree.icons.minus):"";
206                }
207                else
208                {
209                        return (this.plusSign)?"-":" ";
210                }
211        }
212}
213
214//changes node to selected style class. Perform further actions.
215dNode.prototype._select = function()
216{
217        var captionSpan;
218
219        if (this._myTree._selected)
220        {
221                this._myTree._selected._unselect();
222        }
223        this._myTree._selected = this;
224       
225        captionSpan  = getObjectById("l"+this.id+this._myTree.name);
226       
227        if(document.getElementById("div_tree") != null){
228                if(ttree.FOLDER != ""){
229                        ttree.FOLDER = "";
230                }
231                ttree.FOLDER = this.id;
232        }
233       
234        if(document.getElementById("div_folders_search") != null){
235                if(EsearchE.name_box_search != ""){
236                        EsearchE.name_box_search = "";
237                }
238                EsearchE.name_box_search = this.id;
239        }
240
241        //changes class to selected link
242        if (captionSpan)
243        {
244                captionSpan.className = 'sl';
245        }
246
247}
248
249//changes node background color.
250dNode.prototype._onMouseOver = 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 = 'white';
256                captionSpan.style.border = '1px solid black';
257                captionSpan.style.paddingTop = '0px';
258                captionSpan.style.paddingBottom = '0px';
259        }
260}
261//changes node background color.
262dNode.prototype._onMouseOut = function()
263{
264        var captionSpan;
265        if ((this.id != 'root') && (this.id != 'user') && (this.id !='local_root')){
266                captionSpan = getObjectById("l"+this.id+this._myTree.name);
267                captionSpan.style.backgroundColor = '';
268                captionSpan.style.border = '0px';
269                captionSpan.style.paddingTop = '1px';
270                captionSpan.style.paddingBottom = '1px';
271        }
272}
273
274//changes node to unselected style class. Perform further actions.
275dNode.prototype._unselect = function()
276{
277        var captionSpan  = getObjectById("l"+this.id+this._myTree.name);
278
279        this._myTree._lastSelected = this._myTree._selected;
280        this._myTree._selected = null;
281
282        //changes class to selected link
283        if (captionSpan)
284        {
285                captionSpan.className = this.captionClass;
286        }
287}
288
289
290//state can be open or closed
291//warning: if drawed node is not child or root, bugs will happen
292dNode.prototype._draw = function()
293{
294        var str;
295        var _this = this;
296        var divN, divCH, spanP, spanL, parentChildrenDiv;
297        var myClass = (this._io)? "opened" : "closed";
298        var myPlus = this._properPlus();
299        var append = true;
300        var captionOnClickEvent = null;
301//      var cook;
302
303        var plusEventHandler = function(){
304                _this.changeState();
305        }
306
307        var captionEventHandler = function(){
308                eval(captionOnClickEvent);
309        }
310
311/*      if (this.myTree.followCookies)
312        {
313                this._io = getCookie("cons"+this.id);
314        }*/
315
316        //FIXME put this in a separate function, as this will be necessary in
317        //various parts
318       
319        //window.alert('this.onclick = ' + _this.onClick);
320
321        if (this.onClick) //FIXME when onclick && url
322        {
323                captionEventHandler = function () { _this._select(); typeof(_this.onClick) == 'function' ? _this.onClick() : eval(_this.onClick); };
324        }
325        else if (this.url && this.target)
326        {
327                captionEventHandler = function () { _this._select(); window.open(_this.url,_this.target); };
328        }
329        else if (this.url)
330        {
331                captionEventHandler = function () { _this._select(); window.location=_this.url; };
332        }
333        else //Nao tem onClick
334        {
335                if ((this.id != 'root') && (this.id != 'user') && (this.id !='local_root')) //e nao seja raiz(root) ou pastas compartilhadas(user).
336                        captionEventHandler = function () { _this._select();};
337        }
338       
339        //The div of this node
340        divN = document.createElement('div');
341        divN.id = 'n'+this.id+this._myTree.name;
342        //divN.className = 'son';
343        divN.className = (!this._parent) ? 'root' : 'son';
344        //divN.style.border = '1px solid black';
345       
346        //The span that holds the plus/minus sign
347        spanP = document.createElement('span');
348        spanP.id = 'p'+this.id+this._myTree.name;
349        spanP.className = 'plus';
350        spanP.onclick = plusEventHandler;
351        spanP.innerHTML = myPlus;
352        //spanP.style.border = '1px solid green';
353
354        //The span that holds the label/caption
355        spanL = document.createElement('span');
356        spanL.id = 'l'+this.id+this._myTree.name;
357        spanL.className = this.captionClass;
358        spanL.onclick = captionEventHandler;
359        spanL.onmouseover = function () { _this._onMouseOver(); };
360        spanL.onmouseout = function () { _this._onMouseOut(); };
361//      spanL.style.border = '1px solid #f7f7f7';
362        spanL.innerHTML = this.caption;
363        //spanL.style.border = '1px solid red';
364
365        //The div that holds the children
366        divCH = document.createElement('div');
367        divCH.id = 'ch'+this.id+this._myTree.name;
368        divCH.className = myClass;
369        //divCH.style.border = '1px solid blue';
370       
371//      div.innerHTML = str;
372        divN.appendChild(spanP);
373        divN.appendChild(spanL);
374        divN.appendChild(divCH);
375       
376       
377        if (this._parent != null)
378        {
379        parentChildrenDiv = getObjectById("ch"+this._parent.id+this._myTree.name);
380        }
381        else //is root
382        {
383        parentChildrenDiv = getObjectById("dftree_"+this._myTree.name);
384        }
385       
386        if (parentChildrenDiv)
387        {
388        parentChildrenDiv.appendChild(divN);
389        }
390}
391
392// TREE
393//Usage: t = new dFTree({name:t, caption:'tree root', url:'http://www.w3.org'});
394function dFTree(arrayProps) {
395        //mandatory fields
396        this.name;      //the value of this must be the name of the object
397
398        //optional fields
399        this.is_dynamic = true;   //tree is dynamic, i.e. updated on the fly
400        this.followCookies = true;//use previous state (o/c) of nodes
401        this.useIcons = false;     //use icons or not
402       
403
404        //arrayProps[icondir]: Icons Directory
405        iconPath = (arrayProps['icondir'] != null)? arrayProps['icondir'] : '';
406
407        this.icons = {
408                root        : iconPath+'/foldertree_base.gif',
409                folder      : iconPath+'/foldertree_folder.gif',
410                folderOpen  : iconPath+'/foldertree_folderopen.gif',
411                node        : iconPath+'/foldertree_folder.gif',
412                empty       : iconPath+'/foldertree_empty.gif',
413                line        : iconPath+'/foldertree_line.gif',
414                join        : iconPath+'/foldertree_join.gif',
415                joinBottom  : iconPath+'/foldertree_joinbottom.gif',
416                plus        : iconPath+'/foldertree_plus.gif',
417                plusBottom  : iconPath+'/foldertree_plusbottom.gif',
418                minus       : iconPath+'/foldertree_minus.gif',
419                minusBottom : iconPath+'/foldertree_minusbottom.gif',
420                nlPlus      : iconPath+'/foldertree_nolines_plus.gif',
421                nlMinus     : iconPath+'/foldertree_nolines_minus.gif'
422        };
423
424        //private
425        this._root = false; //reference to root node
426        this._aNodes = [];
427        this._lastSelected; //The last selected node
428        this._selected; //The actual selected node
429        this._folderPr = [];
430
431        for (var i in arrayProps)
432        {
433                if (i.charAt(0) != '_')
434                {
435                        eval('this.'+i+' = arrayProps[\''+i+'\'];');
436                }
437        }
438}
439
440dFTree.prototype.draw = function(dest_element) {
441        var main_div;
442       
443        if (!getObjectById("dftree_"+this.name) && dest_element)
444        {
445                main_div = document.createElement('div');
446                main_div.id = 'dftree_'+this.name;
447                dest_element.appendChild(main_div);
448                this._drawn = true;
449        }
450
451        if (this._root != false)
452        {
453                this._root._draw();
454                this._drawBranch(this._root._children);
455        }
456
457}
458
459//Transforms tree in HTML code
460dFTree.prototype.toString = function() {
461        var str = '';
462
463        if (!getObjectById("dftree_"+this.name))
464        {
465                str = '<div id="dftree_'+this.name+'"></div>';
466        }
467        return str;
468
469/*      if (this.root != false)
470        {
471                this.root._draw();
472                this._drawBranch(this.root.children);
473        }*/
474}
475
476//Recursive function, draws children
477dFTree.prototype._drawBranch = function(childrenArray) {
478        var a=0;
479        for (a;a<childrenArray.length;a++)
480        {
481                childrenArray[a]._draw();
482                this._drawBranch(childrenArray[a]._children);
483        }
484}
485
486//add into a position
487dFTree.prototype.add = function(node,pid) {
488        var auxPos;
489        var addNode = false;
490        if (typeof (auxPos = this._searchNode(node.id)) != "number")
491        {
492                // if parent exists, add node as its child
493                if (typeof (auxPos = this._searchNode(pid)) == "number")
494                {
495                        node._parent = this._aNodes[auxPos];
496                        this._aNodes[auxPos]._children[this._aNodes[auxPos]._children.length] = node;
497                        addNode = true;
498                }
499                else //if parent cannot be found and there is a tree root, ignores node
500                {
501                        if (!this._root)
502                        {
503                                this._root = node;
504                                addNode = true;
505                        }
506                }
507                if (addNode)
508                {
509                        this._aNodes[this._aNodes.length] = node;
510                        node._myTree = this;
511                        if (this.is_dynamic && this._drawn)
512                        {
513                                node._draw();
514                        }
515                }
516                else
517                {
518                        this._folderPr[this._folderPr.length] = node.id ;
519                }
520               
521        }
522        else {
523                var arrayProps = new Array();
524
525                arrayProps['id'] = node.id;
526                arrayProps['caption'] = node.caption;
527
528                arrayProps['url'] = node.url;
529                arrayProps['target'] = node.target;
530                arrayProps['onClick'] = node.onClick;
531                arrayProps['onOpen'] = node.onOpen;
532                arrayProps['onClose'] = node.onClose;
533                arrayProps['onFirstOpen'] = node.onFirstOpen;
534                arrayProps['iconClosed'] = node.iconClosed;
535                arrayProps['iconOpen'] = node.iconOpen;
536                arrayProps['runJS'] = node.runJS;
537                arrayProps['plusSign'] = node.plusSign;
538                arrayProps['captionClass'] = node.captionClass;
539
540                delete node;
541
542                this.alter(arrayProps);
543        }
544
545}
546
547//arrayProps: same properties of Node
548dFTree.prototype.alter = function(arrayProps) {
549        this.getNodeById(arrayProps['id']).alter(arrayProps);
550}
551
552dFTree.prototype.getNodeById = function(nodeid) {
553        return this._aNodes[this._searchNode(nodeid)];
554}
555
556dFTree.prototype.openTo = function(nodeid)
557{
558        var node = this.getNodeById(nodeid);
559
560        if (node && node._parent)
561        {
562                node._parent.open();
563                this.openTo(node._parent.id);
564        }
565}
566
567//Searches for a node in the node array, returning the position of the array 4it
568dFTree.prototype._searchNode = function(id) {
569        var a=0;
570        for (a;a<this._aNodes.length;a++)
571        {
572                if (this._aNodes[a].id == id)
573                {
574                        return a;
575                }
576        }
577        return false;
578}
579// By jakjr, retorna um array com os ids de todas as pastas (nodes)
580dFTree.prototype.getNodesList = function(imapDelimiter) {
581        var a=0;
582        var nodes=[];
583        for (a;a<this._aNodes.length;a++)
584        {
585                var node = this.getNodeById(this._aNodes[a].id);
586                nodes[a]=[];
587                nodes[a].id = node.id;
588                nodes[a].parent = node._parent ? node._parent.id : 'root';             
589                var tmp = node.id.split(imapDelimiter);
590                var tmp_caption = node.caption.split("<");
591
592                if (node.id == 'INBOX')
593                        nodes[a].caption = get_lang('Inbox');
594                else if (node.id == 'user')
595                        nodes[a].caption = get_lang("Shared Folders");
596                else
597                        nodes[a].caption = tmp_caption[0];
598                //nodes[a].caption = tmp[tmp.length-1] == 'INBOX' ? get_lang('Inbox') : tmp[tmp.length-1];
599                nodes[a].plusSign = node.plusSign;
600        }
601        return nodes;
602}
603
604//Auxiliar functions
605//For multi-browser compatibility
606function getObjectById(name)
607{   
608    if (document.getElementById)
609    {
610        return document.getElementById(name);
611    }
612    else if (document.all)
613    {
614        return document.all[name];
615    }
616    else if (document.layers)
617    {
618        return document.layers[name];
619    }
620    return false;
621}
622
623// [Cookie] Clears a cookie
624function clearCookie(cookieName) {
625        var now = new Date();
626        var yesterday = new Date(now.getTime() - 1000 * 60 * 60 * 24);
627        this.setCookie(cookieName, 'cookieValue', yesterday);
628        this.setCookie(cookieName, 'cookieValue', yesterday);
629};
630
631// [Cookie] Sets value in a cookie
632function setCookie(cookieName, cookieValue, expires, path, domain, secure) {
633        document.cookie =
634                escape(cookieName) + '=' + escape(cookieValue)
635                + (expires ? '; expires=' + expires.toGMTString() : '')
636                + (path ? '; path=' + path : '')
637                + (domain ? '; domain=' + domain : '')
638                + (secure ? '; secure' : '');
639};
640
641// [Cookie] Gets a value from a cookie
642function getCookie(cookieName) {
643        var cookieValue = '';
644        var posName = document.cookie.indexOf(escape(cookieName) + '=');
645        if (posName != -1) {
646                var posValue = posName + (escape(cookieName) + '=').length;
647                var endPos = document.cookie.indexOf(';', posValue);
648                if (endPos != -1)
649                {
650                        cookieValue = unescape(document.cookie.substring(posValue, endPos));
651                }
652                else
653                {
654                        cookieValue = unescape(document.cookie.substring(posValue));
655                }
656        }
657        return (cookieValue);
658};
659
660
661function imageHTML(src,attributes) {
662        if (attributes != null)
663        {
664                attributes = '';
665        }
666        return "<img "+attributes+" src=\""+src+"\">";
667}
Note: See TracBrowser for help on using the repository browser.