]> err.no Git - scalable-opengroupware.org/blob - UI/WebServerResources/MailerUI.js
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1131 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / UI / WebServerResources / MailerUI.js
1 /* JavaScript for SOGoMail */
2 var accounts = {};
3 var mailboxTree;
4
5 var currentMessages = new Array();
6 var maxCachedMessages = 20;
7 var cachedMessages = new Array();
8 var currentMailbox = null;
9
10 var usersRightsWindowHeight = 320;
11 var usersRightsWindowWidth = 400;
12
13 /* mail list */
14
15 function openMessageWindow(msguid, url) {
16   var wId = '';
17   if (msguid) {
18     wId += "SOGo_msg_" + msguid;
19     markMailReadInWindow(window, msguid);
20   }
21   var msgWin = window.open(url, wId,
22                            "width=680,height=520,resizable=1,scrollbars=1,toolbar=0,"
23                            + "location=0,directories=0,status=0,menubar=0,copyhistory=0");
24   if (msguid) {
25     msgWin.messageId = msguid;
26     msgWin.messageURL = ApplicationBaseURL + currentMailbox + "/" + msguid;
27   }
28   msgWin.focus();
29
30   return false;
31 }
32
33 function onMessageDoubleClick(event) {
34   resetSelection(window);
35   var msguid = this.parentNode.id.substr(4);
36    
37   return openMessageWindow(msguid,
38                            ApplicationBaseURL + currentMailbox + "/"
39                            + msguid + "/popupview");
40 }
41
42 function toggleMailSelect(sender) {
43   var row;
44   row = $(sender.name);
45   row.className = sender.checked ? "tableview_selected" : "tableview";
46 }
47
48 function clearSearch(sender) {
49   var searchField = window.$("search");
50   if (searchField) searchField.value="";
51   return true;
52 }
53
54 function openAddressbook(sender) {
55   var urlstr;
56    
57   urlstr = ApplicationBaseURL + "/../Contacts/?popup=YES";
58   var w = window.open(urlstr, "Addressbook",
59                       "width=640,height=400,resizable=1,scrollbars=1,toolbar=0,"
60                       + "location=0,directories=0,status=0,menubar=0,copyhistory=0");
61   w.focus();
62
63   return false;
64 }
65
66 function onMenuSharing(event) {
67   var folderID = document.menuTarget.getAttribute("dataname");
68   var urlstr = URLForFolderID(folderID) + "/acls";
69   preventDefault(event);
70
71   openAclWindow(urlstr);
72 }
73
74 /* mail list DOM changes */
75
76 function markMailInWindow(win, msguid, markread) {
77   var msgDiv;
78
79   msgDiv = win.$("div_" + msguid);
80   if (msgDiv) {
81     if (markread) {
82       msgDiv.removeClassName("mailer_unreadmailsubject");
83       msgDiv.addClassName("mailer_readmailsubject");
84       msgDiv = win.$("unreaddiv_" + msguid);
85       if (msgDiv)
86         {
87           msgDiv.setAttribute("class", "mailerUnreadIcon");
88           msgDiv.setAttribute("id", "readdiv_" + msguid);
89           msgDiv.setAttribute("src", ResourcesURL + "/icon_read.gif");
90           msgDiv.setAttribute("onclick", "mailListMarkMessage(this,"
91                               + " 'markMessageUnread', " + msguid
92                               + ", false);"
93                               +" return false;");
94           var title = msgDiv.getAttribute("title-markunread");
95           if (title)
96             msgDiv.setAttribute("title", title);
97         }
98     }
99     else {
100       msgDiv.removeClassName('mailer_readmailsubject');
101       msgDiv.addClassName('mailer_unreadmailsubject');
102       msgDiv = win.$("readdiv_" + msguid);
103       if (msgDiv)
104         {
105           msgDiv.setAttribute("class", "mailerReadIcon");
106           msgDiv.setAttribute("id", "unreaddiv_" + msguid);
107           msgDiv.setAttribute("src", ResourcesURL + "/icon_unread.gif");
108           msgDiv.setAttribute("onclick", "mailListMarkMessage(this,"
109                               + " 'markMessageRead', " + msguid
110                               + ", true);"
111                               +" return false;");
112           var title = msgDiv.getAttribute("title-markread");
113           if (title)
114             msgDiv.setAttribute("title", title);
115         }
116     }
117     return true;
118   }
119   else
120     return false;
121 }
122
123 function markMailReadInWindow(win, msguid) {
124   /* this is called by UIxMailView with window.opener */
125   return markMailInWindow(win, msguid, true);
126 }
127
128 /* main window */
129
130 function reopenToRemoveLocationBar() {
131   // we cannot really use this, see below at the close comment
132   if (window.locationbar && window.locationbar.visible) {
133     newwin = window.open(window.location.href, "SOGo",
134                          "width=800,height=600,resizable=1,scrollbars=1," +
135                          "toolbar=0,location=0,directories=0,status=0," + 
136                          "menubar=0,copyhistory=0");
137     if (newwin) {
138       window.close(); // this does only work for windows opened by scripts!
139       newwin.focus();
140       return true;
141     }
142     return false;
143   }
144   return true;
145 }
146
147 /* mail list reply */
148
149 function openMessageWindowsForSelection(action) {
150   if (document.body.hasClassName("popup"))
151     win = openMessageWindow(window.messageId,
152                             window.messageURL + "/" + action /* url */);
153   else {
154     var messageList = $("messageList");
155     var rows = messageList.getSelectedRowsId();
156     var idset = "";
157     for (var i = 0; i < rows.length; i++)
158       win = openMessageWindow(rows[i].substr(4)        /* msguid */,
159                               ApplicationBaseURL + currentMailbox
160                               + "/" + rows[i].substr(4)
161                               + "/" + action /* url */);
162   }
163
164   return false;
165 }
166
167 function mailListMarkMessage(event) {
168   var http = createHTTPClient();
169   var url = ApplicationBaseURL + currentMailbox + "/" + action + "?uid=" + msguid;
170
171   if (http) {
172     // TODO: add parameter to signal that we are only interested in OK
173     http.open("POST", url + "&jsonly=1", false /* not async */);
174     http.send("");
175     if (http.status != 200) {
176       // TODO: refresh page?
177       alert("Message Mark Failed: " + http.statusText);
178       window.location.reload();
179     }
180     else {
181       markMailInWindow(window, msguid, markread);
182     }
183   }
184   else {
185     window.location.href = url;
186   }
187 }
188
189 /* maillist row highlight */
190
191 var oldMaillistHighlight = null; // to remember deleted/selected style
192
193 function ml_highlight(sender) {
194   oldMaillistHighlight = sender.className;
195   if (oldMaillistHighlight == "tableview_highlight")
196     oldMaillistHighlight = null;
197   sender.className = "tableview_highlight";
198 }
199
200 function ml_lowlight(sender) {
201   if (oldMaillistHighlight) {
202     sender.className = oldMaillistHighlight;
203     oldMaillistHighlight = null;
204   }
205   else
206     sender.className = "tableview";
207 }
208
209
210 /* folder operations */
211
212 function ctxFolderAdd(sender) {
213   var folderName;
214    
215   folderName = prompt("Foldername: ");
216   if (folderName == undefined)
217     return false;
218   if (folderName == "")
219     return false;
220    
221   // TODO: should use a form-POST or AJAX
222   window.location.href = "createFolder?name=" + escape(folderName);
223   return false;
224 }
225
226 function ctxFolderDelete(sender) {
227   if (!confirm("Delete current folder?").decodeEntities())
228     return false;
229    
230   // TODO: should use a form-POST or AJAX
231   window.location.href = "deleteFolder";
232   return false;
233 }
234
235 /* bulk delete of messages */
236
237 function uixDeleteSelectedMessages(sender) {
238   var failCount = 0;
239    
240   var messageList = $("messageList");
241   var rowIds = messageList.getSelectedRowsId();
242
243   for (var i = 0; i < rowIds.length; i++) {
244     var url, http;
245     var rowId = rowIds[i].substr(4);
246     /* send AJAX request (synchronously) */
247
248     var messageId = currentMailbox + "/" + rowId;
249     url = ApplicationBaseURL + messageId + "/trash?jsonly=1";
250     http = createHTTPClient();
251     http.open("GET", url, false /* not async */);
252     http.send("");
253     if (http.status != 200) { /* request failed */
254       failCount++;
255       http = null;
256       continue;
257     } else {
258       deleteCachedMessage(messageId);
259       if (currentMessages[currentMailbox] == rowId) {
260         var div = $('messageContent');
261         div.innerHTML = "";
262         currentMessages[currentMailbox] = null;
263       }
264     }
265     http = null;
266
267     /* remove from page */
268
269     /* line-through would be nicer, but hiding is OK too */
270     var row = $(rowIds[i]);
271     row.parentNode.removeChild(row);
272   }
273
274   if (failCount > 0)
275     alert("Could not delete " + failCount + " messages!");
276    
277   return false;
278 }
279
280 function moveMessages(rowIds, folder) {
281   var failCount = 0;
282
283   for (var i = 0; i < rowIds.length; i++) {
284     var url, http;
285
286     /* send AJAX request (synchronously) */
287           
288     var messageId = currentMailbox + "/" + rowIds[i];
289     url = (ApplicationBaseURL + messageId
290            + "/move?jsonly=1&tofolder=" + folder);
291     http = createHTTPClient();
292     http.open("GET", url, false /* not async */);
293     http.send("");
294     if (http.status == 200) {
295       var row = $("row_" + rowIds[i]);
296       row.parentNode.removeChild(row);
297       deleteCachedMessage(messageId);
298       if (currentMessages[currentMailbox] == rowIds[i]) {
299         var div = $('messageContent');
300         div.innerHTML = "";
301         currentMessages[currentMailbox] = null;
302       }
303     }
304     else /* request failed */
305       failCount++;
306
307     /* remove from page */
308
309     /* line-through would be nicer, but hiding is OK too */
310   }
311
312   if (failCount > 0)
313     alert("Could not move " + failCount + " messages!");
314    
315   return failCount;
316 }
317
318 function onMenuDeleteMessage(event) {
319   uixDeleteSelectedMessages();
320   preventDefault(event);
321 }
322
323 function onMailboxTreeItemClick(event) {
324   var topNode = $("mailboxTree");
325   var mailbox = this.parentNode.getAttribute("dataname");
326
327   if (topNode.selectedEntry)
328     topNode.selectedEntry.deselect();
329   this.select();
330   topNode.selectedEntry = this;
331
332   search = {};
333   sorting = {};
334   $("searchValue").value = "";
335   initCriteria();
336
337   var datatype = this.parentNode.getAttribute("datatype");
338   if (datatype == "account" || datatype == "additional") {
339     currentMailbox = mailbox;
340     $("messageContent").innerHTML = "";
341     var body = $("messageList").tBodies[0];
342     for (var i = body.rows.length - 1; i > 0; i--)
343       body.deleteRow(i);
344   }
345   else
346     openMailbox(mailbox);
347    
348   preventDefault(event);
349 }
350
351 function onMailboxMenuMove() {
352   window.alert("unimplemented");
353 }
354
355 function onMailboxMenuCopy() {
356   window.alert("unimplemented");
357 }
358
359 function refreshMailbox() {
360   var topWindow = getTopWindow();
361   if (topWindow)
362     topWindow.refreshCurrentFolder();
363
364   return false;
365 }
366
367 function openMailbox(mailbox, reload, idx) {
368   if (mailbox != currentMailbox || reload) {
369     currentMailbox = mailbox;
370     var url = ApplicationBaseURL + mailbox + "/view?noframe=1";
371     var messageContent = $("messageContent");
372     messageContent.innerHTML = '';
373       
374     if (currentMessages[mailbox]) {
375       loadMessage(currentMessages[mailbox]);
376       url += '&pageforuid=' + currentMessages[mailbox];
377     }
378
379     var searchValue = search["value"];
380     if (searchValue && searchValue.length > 0)
381       url += ("&search=" + search["criteria"]
382               + "&value=" + searchValue);
383     var sortAttribute = sorting["attribute"];
384     if (sortAttribute && sortAttribute.length > 0)
385       url += ("&sort=" + sorting["attribute"]
386               + "&asc=" + sorting["ascending"]);
387     if (idx)
388       url += "&idx=" + idx;
389
390     if (document.messageListAjaxRequest) {
391       document.messageListAjaxRequest.aborted = true;
392       document.messageListAjaxRequest.abort();
393     }
394
395     var mailboxContent = $("mailboxContent");
396     if (mailboxContent.getStyle('visibility') == "hidden") {
397       mailboxContent.setStyle({ visibility: "visible" });
398       var rightDragHandle = $("rightDragHandle");
399       rightDragHandle.setStyle({ visibility: "visible" });
400       messageContent.setStyle({ top: (rightDragHandle.offsetTop
401                                       + rightDragHandle.offsetHeight
402                                       + 'px') });
403     }
404
405     document.messageListAjaxRequest
406       = triggerAjaxRequest(url, messageListCallback,
407                            currentMessages[mailbox]);
408
409     var quotasUrl = ApplicationBaseURL + mailbox + "/quotas";
410     document.quotasAjaxRequest
411       = triggerAjaxRequest(quotasUrl, quotasCallback);
412   }
413 }
414
415 function openMailboxAtIndex(event) {
416   openMailbox(currentMailbox, true, this.getAttribute("idx"));
417
418   preventDefault(event);
419 }
420
421 function messageListCallback(http) {
422   var div = $('mailboxContent');
423    
424   if (http.readyState == 4
425       && http.status == 200) {
426     document.messageListAjaxRequest = null;
427     div.innerHTML = http.responseText;
428     var selected = http.callbackData;
429     if (selected) {
430       var row = $("row_" + selected);
431       if (row)
432         row.select();
433     }
434     configureMessageListEvents();
435     if (sorting["attribute"] && sorting["attribute"].length > 0) {
436       var sortHeader;
437       if (sorting["attribute"] == "subject")
438         sortHeader = $("subjectHeader");
439       else if (sorting["attribute"] == "from")
440         sortHeader = $("fromHeader");
441       else if (sorting["attribute"] == "date")
442         sortHeader = $("dateHeader");
443       else
444         sortHeader = null;
445
446       if (sortHeader) {
447         var sortImage = createElement("img", "messageSortImage", "sortImage");
448         sortHeader.insertBefore(sortImage, sortHeader.firstChild);
449         if (sorting["ascending"])
450           sortImage.src = ResourcesURL + "/title_sortdown_12x12.png";
451         else
452           sortImage.src = ResourcesURL + "/title_sortup_12x12.png";
453       }
454     }
455   }
456   else
457     log("messageListCallback: problem during ajax request (readyState = " + http.readyState + ", status = " + http.status + ")");
458 }
459
460 function quotasCallback(http) {
461   if (http.readyState == 4
462       && http.status == 200) {
463     var hasQuotas = false;
464
465     var quotas = http.responseText.evalJSON(true);
466     for (var i in quotas) {
467       hasQuotas = true;
468       break;
469     }
470
471     if (hasQuotas) {
472       var treePath = currentMailbox.split("/");
473       var mbQuotas = quotas["/" + treePath[2]];
474       var used = mbQuotas["usedSpace"];
475       var max = mbQuotas["maxQuota"];
476       var percents = (Math.round(used * 10000 / max) / 100);
477       var format = labels["quotasFormat"].decodeEntities();
478       var text = format.formatted(used, max, percents);
479       window.status = text;
480     }
481   }
482 }
483
484 function onMessageContextMenu(event) {
485   var menu = $('messageListMenu');
486   Event.observe(menu, "hideMenu", onMessageContextMenuHide);
487   popupMenu(event, "messageListMenu", this);
488
489   var topNode = $('messageList');
490   var selectedNodes = topNode.getSelectedRows();
491   for (var i = 0; i < selectedNodes.length; i++)
492     selectedNodes[i].deselect();
493   topNode.menuSelectedRows = selectedNodes;
494   topNode.menuSelectedEntry = this;
495   this.select();
496 }
497
498 function onMessageContextMenuHide(event) {
499   var topNode = $('messageList');
500
501   if (topNode.menuSelectedEntry) {
502     topNode.menuSelectedEntry.deselect();
503     topNode.menuSelectedEntry = null;
504   }
505   if (topNode.menuSelectedRows) {
506     var nodes = topNode.menuSelectedRows;
507     for (var i = 0; i < nodes.length; i++)
508       nodes[i].select();
509     topNode.menuSelectedRows = null;
510   }
511 }
512
513 function onFolderMenuClick(event) {
514   var onhide, menuName;
515    
516   var menutype = this.parentNode.getAttribute("datatype");
517   if (menutype) {
518     if (menutype == "inbox") {
519       menuName = "inboxIconMenu";
520     } else if (menutype == "account") {
521       menuName = "accountIconMenu";
522     } else if (menutype == "trash") {
523       menuName = "trashIconMenu";
524     } else {
525       menuName = "mailboxIconMenu";
526     }
527   } else {
528     menuName = "mailboxIconMenu";
529   }
530
531   var menu = $(menuName);
532   Event.observe(menu, "hideMenu", onFolderMenuHide);
533   popupMenu(event, menuName, this.parentNode);
534
535   var topNode = $("mailboxTree");
536   if (topNode.selectedEntry)
537     topNode.selectedEntry.deselect();
538   if (topNode.menuSelectedEntry)
539     topNode.menuSelectedEntry.deselect();
540   topNode.menuSelectedEntry = this;
541   this.select();
542
543   preventDefault(event);
544 }
545
546 function onFolderMenuHide(event) {
547   var topNode = $("mailboxTree");
548
549   if (topNode.menuSelectedEntry) {
550     topNode.menuSelectedEntry.deselect();
551     topNode.menuSelectedEntry = null;
552   }
553   if (topNode.selectedEntry)
554     topNode.selectedEntry.select();
555 }
556
557 function deleteCachedMessage(messageId) {
558   var done = false;
559   var counter = 0;
560
561   while (counter < cachedMessages.length
562          && !done)
563     if (cachedMessages[counter]
564         && cachedMessages[counter]['idx'] == messageId) {
565       cachedMessages.splice(counter, 1);
566       done = true;
567     }
568     else
569       counter++;
570 }
571
572 function getCachedMessage(idx) {
573   var message = null;
574   var counter = 0;
575
576   while (counter < cachedMessages.length
577          && message == null)
578     if (cachedMessages[counter]
579         && cachedMessages[counter]['idx'] == currentMailbox + '/' + idx)
580       message = cachedMessages[counter];
581     else
582       counter++;
583
584   return message;
585 }
586
587 function storeCachedMessage(cachedMessage) {
588   var oldest = -1;
589   var timeOldest = -1;
590   var counter = 0;
591
592   if (cachedMessages.length < maxCachedMessages)
593     oldest = cachedMessages.length;
594   else {
595     while (cachedMessages[counter]) {
596       if (oldest == -1
597           || cachedMessages[counter]['time'] < timeOldest) {
598         oldest = counter;
599         timeOldest = cachedMessages[counter]['time'];
600       }
601       counter++;
602     }
603
604     if (oldest == -1)
605       oldest = 0;
606   }
607
608   cachedMessages[oldest] = cachedMessage;
609 }
610
611 function onMessageSelectionChange() {
612   var rows = this.getSelectedRowsId();
613
614   if (rows.length == 1) {
615     var idx = rows[0].substr(4);
616
617     if (currentMessages[currentMailbox] != idx) {
618       currentMessages[currentMailbox] = idx;
619       loadMessage(idx);
620     }
621   }
622 }
623
624 function loadMessage(idx) {
625   if (document.messageAjaxRequest) {
626     document.messageAjaxRequest.aborted = true;
627     document.messageAjaxRequest.abort();
628   }
629
630   var cachedMessage = getCachedMessage(idx);
631
632   if (cachedMessage == null) {
633     var url = (ApplicationBaseURL + currentMailbox + "/"
634                + idx + "/view?noframe=1");
635     document.messageAjaxRequest
636       = triggerAjaxRequest(url, messageCallback, idx);
637     markMailInWindow(window, idx, true);
638   } else {
639     var div = $('messageContent');
640     div.innerHTML = cachedMessage['text'];
641     cachedMessage['time'] = (new Date()).getTime();
642     document.messageAjaxRequest = null;
643     configureLinksInMessage();
644   }
645 }
646
647 function configureLinksInMessage() {
648   var messageDiv = $('messageContent');
649   var mailContentDiv = document.getElementsByClassName('mailer_mailcontent',
650                                                        messageDiv)[0];
651   Event.observe(mailContentDiv, "contextmenu",
652                 onMessageContentMenu.bindAsEventListener(mailContentDiv));
653   var anchors = messageDiv.getElementsByTagName('a');
654   for (var i = 0; i < anchors.length; i++)
655     if (anchors[i].href.substring(0,7) == "mailto:") {
656       Event.observe(anchors[i], "click",
657                     onEmailAddressClick.bindAsEventListener(anchors[i]));
658       Event.observe(anchors[i], "contextmenu",
659                     onEmailAddressClick.bindAsEventListener(anchors[i]));
660     }
661     else
662       Event.observe(anchors[i], "click",
663                     onMessageAnchorClick);
664 }
665
666 function onMessageContentMenu(event) {
667   popupMenu(event, 'messageContentMenu', this);
668 }
669
670 function onEmailAddressClick(event) {
671   popupMenu(event, 'addressMenu', this);
672 }
673
674 function onMessageAnchorClick (event) {
675   window.open(this.href);
676   preventDefault(event);
677 }
678
679 function messageCallback(http) {
680   var div = $('messageContent');
681
682   if (http.readyState == 4
683       && http.status == 200) {
684     document.messageAjaxRequest = null;
685     div.innerHTML = http.responseText;
686     configureLinksInMessage();
687       
688     if (http.callbackData) {
689       var cachedMessage = new Array();
690       cachedMessage['idx'] = currentMailbox + '/' + http.callbackData;
691       cachedMessage['time'] = (new Date()).getTime();
692       cachedMessage['text'] = http.responseText;
693       if (cachedMessage['text'].length < 30000)
694         storeCachedMessage(cachedMessage);
695     }
696   }
697   else
698     log("messageCallback: problem during ajax request: " + http.status);
699 }
700
701 function processMailboxMenuAction(mailbox) {
702   var currentNode, upperNode;
703   var mailboxName;
704   var action;
705
706   mailboxName = mailbox.getAttribute('mailboxname');
707   currentNode = mailbox;
708   upperNode = null;
709
710   while (currentNode
711          && !currentNode.hasAttribute('mailboxaction'))
712     currentNode = currentNode.parentNode.parentNode.parentMenuItem;
713
714   if (currentNode)
715     {
716       action = currentNode.getAttribute('mailboxaction');
717       //       var rows  = collectSelectedRows();
718       //       var rString = rows.join(', ');
719       //       alert("performing '" + action + "' on " + rString
720       //             + " to " + mailboxName);
721     }
722 }
723
724 var rowSelectionCount = 0;
725
726 validateControls();
727
728 function showElement(e, shouldShow) {
729   e.style.display = shouldShow ? "" : "none";
730 }
731
732 function enableElement(e, shouldEnable) {
733   if(!e)
734     return;
735   if(shouldEnable) {
736     if(e.hasAttribute("disabled"))
737       e.removeAttribute("disabled");
738   }
739   else {
740     e.setAttribute("disabled", "1");
741   }
742 }
743
744 function validateControls() {
745   var e = $("moveto");
746   this.enableElement(e, rowSelectionCount > 0);
747 }
748
749 function moveTo(uri) {
750   alert("MoveTo: " + uri);
751 }
752
753 function deleteSelectedMails() {
754 }
755
756 /* message menu entries */
757 function onMenuOpenMessage(event) {
758   return openMessageWindowsForSelection('popupview');
759 }
760
761 function onMenuReplyToSender(event) {
762   return openMessageWindowsForSelection('reply');
763 }
764
765 function onMenuReplyToAll(event) {
766   return openMessageWindowsForSelection('replyall');
767 }
768
769 function onMenuForwardMessage(event) {
770   return openMessageWindowsForSelection('forward');
771 }
772
773 function onMenuViewMessageSource(event) {
774   var messageList = $("messageList");
775   var rows = messageList.getSelectedRowsId();
776
777   if (rows.length > 0) {
778     var url = (ApplicationBaseURL + currentMailbox + "/"
779                + rows[0].substr(4) + "/viewsource");
780     window.open(url, "",
781                 "width=680,height=520,resizable=1,scrollbars=1,toolbar=0,"
782                 + "location=0,directories=0,status=0,menubar=0,copyhistory=0");
783   }
784
785   preventDefault(event);
786 }
787
788 /* contacts */
789 function newContactFromEmail(event) {
790   var mailto = document.menuTarget.innerHTML;
791
792   var email = extractEmailAddress(mailto);
793   var c_name = extractEmailName(mailto);
794   if (email.length > 0)
795     {
796       var url = UserFolderURL + "Contacts/new?contactEmail=" + email;
797       if (c_name)
798         url += "&contactFN=" + c_name;
799       w = window.open(url, null,
800                       "width=546,height=490,resizable=1,scrollbars=1,toolbar=0,"
801                       + "location=0,directories=0,status=0,menubar=0,copyhistory=0");
802       w.focus();
803     }
804
805   return false; /* stop following the link */
806 }
807
808 function newEmailTo(sender) {
809   return openMailTo(document.menuTarget.innerHTML);
810 }
811
812 function expandUpperTree(node) {
813   var currentNode = node.parentNode;
814
815   while (currentNode.className != "dtree") {
816     if (currentNode.className == 'clip') {
817       var id = currentNode.getAttribute("id");
818       var number = parseInt(id.substr(2));
819       if (number > 0) {
820         var cn = mailboxTree.aNodes[number];
821         mailboxTree.nodeStatus(1, number, cn._ls);
822       }
823     }
824     currentNode = currentNode.parentNode;
825   }
826 }
827
828 function onHeaderClick(event) {
829   var headerId = this.getAttribute("id");
830   var newSortAttribute;
831   if (headerId == "subjectHeader")
832     newSortAttribute = "subject";
833   else if (headerId == "fromHeader")
834     newSortAttribute = "from";
835   else if (headerId == "dateHeader")
836     newSortAttribute = "date";
837   else
838     newSortAttribute = "arrival";
839
840   if (sorting["attribute"] == newSortAttribute)
841     sorting["ascending"] = !sorting["ascending"];
842   else {
843     sorting["attribute"] = newSortAttribute;
844     sorting["ascending"] = true;
845   }
846
847   refreshCurrentFolder();
848
849   preventDefault(event);
850 }
851
852 function refreshCurrentFolder() {
853   openMailbox(currentMailbox, true);
854 }
855
856 function pouetpouet(event) {
857   window.alert("pouet pouet");
858 }
859
860 var mailboxSpanAcceptType = function(type) {
861   return (type == "mailRow");
862 }
863
864 var mailboxSpanEnter = function() {
865   this.addClassName("_dragOver");
866 }
867
868 var mailboxSpanExit = function() {
869   this.removeClassName("_dragOver");
870 }
871
872 var mailboxSpanDrop = function(data) {
873   var success = false;
874
875   if (data) {
876     var folder = this.parentNode.parentNode.getAttribute("dataname");
877     if (folder != currentMailbox)
878       success = (moveMessages(data, folder) == 0);
879   }
880   else
881     success = false;
882   
883   return success;
884 }
885     
886 var plusSignEnter = function() {
887   var nodeNr = parseInt(this.id.substr(2));
888   if (!mailboxTree.aNodes[nodeNr]._io)
889     this.plusSignTimer = setTimeout("openPlusSign('" + nodeNr + "');", 1000);
890 }
891       
892 var plusSignExit = function() {
893   if (this.plusSignTimer) {
894     clearTimeout(this.plusSignTimer);
895     this.plusSignTimer = null;
896   }
897 }
898         
899 function openPlusSign(nodeNr) {
900   mailboxTree.nodeStatus(1, nodeNr, mailboxTree.aNodes[nodeNr]._ls);
901   mailboxTree.aNodes[nodeNr]._io = 1;
902   this.plusSignTimer = null;
903 }
904
905 var messageListGhost = function () {
906   var newDiv = document.createElement("div");
907   //   newDiv.style.width = "25px;";
908   //   newDiv.style.height = "25px;";
909   newDiv.style.backgroundColor = "#aae;";
910   newDiv.style.border = "2px solid #a3a;";
911   newDiv.style.padding = "5px;";
912   newDiv.ghostOffsetX = 10;
913   newDiv.ghostOffsetY = 5;
914
915   var newImg = document.createElement("img");
916   newImg.src = ResourcesURL + "/message-mail.png";
917
918   var list = $("messageList");
919   var count = list.getSelectedRows().length;
920   newDiv.appendChild(newImg);
921   newDiv.appendChild(document.createElement("br"));
922   newDiv.appendChild(document.createTextNode(count + " messages..."));
923
924   return newDiv;
925 }
926
927 var messageListData = function(type) {
928   var rows = this.parentNode.parentNode.getSelectedRowsId();
929   var msgIds = new Array();
930   for (var i = 0; i < rows.length; i++)
931     msgIds.push(rows[i].substr(4));
932
933   return msgIds;
934 }
935
936 /* a model for a futur refactoring of the sortable table headers mechanism */
937
938 function configureMessageListHeaders(cells) {
939   for (var i = 0; i < cells.length; i++) {
940     var currentCell = $(cells[i]);
941     Event.observe(currentCell, "click",
942                   onHeaderClick.bindAsEventListener(currentCell));
943     Event.observe(currentCell, "mousedown", listRowMouseDownHandler);
944   }
945 }
946
947 function configureMessageListEvents() {
948   var messageList = $("messageList");
949   if (messageList) {
950     Event.observe(messageList, "mousedown",
951                   onMessageSelectionChange.bindAsEventListener(messageList));
952
953     configureMessageListHeaders(messageList.tHead.rows[0].cells);
954     var cell = messageList.tHead.rows[1].cells[0];
955     if ($(cell).hasClassName("tbtv_navcell")) {
956       var anchors = $(cell).childNodesWithTag("a");
957       for (var i = 0; i < anchors.length; i++)
958         Event.observe(anchors[i], "click", openMailboxAtIndex.bindAsEventListener(anchors[i]));
959     }
960
961     rows = messageList.tBodies[0].rows;
962     for (var i = 0; i < rows.length; i++) {
963       Event.observe(rows[i], "mousedown", onRowClick);
964       Event.observe(rows[i], "contextmenu", onMessageContextMenu.bindAsEventListener(rows[i]));
965          
966       rows[i].dndTypes = function() { return new Array("mailRow"); };
967       rows[i].dndGhost = messageListGhost;
968       rows[i].dndDataForType = messageListData;
969       document.DNDManager.registerSource(rows[i]);
970
971       for (var j = 0; j < rows[i].cells.length; j++) {
972         var cell = rows[i].cells[j];
973         Event.observe(cell, "mousedown", listRowMouseDownHandler);
974         if (j == 2 || j == 3 || j == 5)
975           Event.observe(cell, "dblclick", onMessageDoubleClick.bindAsEventListener(cell));
976         else if (j == 4) {
977           var img = cell.childNodesWithTag("img")[0];
978           Event.observe(img, "click", mailListMarkMessage);
979         }
980       }
981     }
982   }
983 }
984
985 function configureDragHandles() {
986   var handle = $("verticalDragHandle");
987   if (handle) {
988     handle.addInterface(SOGoDragHandlesInterface);
989     handle.leftBlock=$("leftPanel");
990     handle.rightBlock=$("rightPanel");
991   }
992
993   handle = $("rightDragHandle");
994   if (handle) {
995     handle.addInterface(SOGoDragHandlesInterface);
996     handle.upperBlock=$("mailboxContent");
997     handle.lowerBlock=$("messageContent");
998   }
999 }
1000
1001 /* dnd */
1002 function initDnd() {
1003   //   log("MailerUI initDnd");
1004
1005   var tree = $("mailboxTree");
1006   if (tree) {
1007     var images = tree.getElementsByTagName("img");
1008     for (var i = 0; i < images.length; i++) {
1009       if (images[i].id[0] == 'j') {
1010         images[i].dndAcceptType = mailboxSpanAcceptType;
1011         images[i].dndEnter = plusSignEnter;
1012         images[i].dndExit = plusSignExit;
1013         document.DNDManager.registerDestination(images[i]);
1014       }
1015     }
1016     var nodes = document.getElementsByClassName("nodeName", tree);
1017     for (var i = 0; i < nodes.length; i++) {
1018       nodes[i].dndAcceptType = mailboxSpanAcceptType;
1019       nodes[i].dndEnter = mailboxSpanEnter;
1020       nodes[i].dndExit = mailboxSpanExit;
1021       nodes[i].dndDrop = mailboxSpanDrop;
1022       document.DNDManager.registerDestination(nodes[i]);
1023     }
1024   }
1025 }
1026
1027 /* stub */
1028
1029 function refreshContacts() {
1030 }
1031
1032 function openInbox(node) {
1033   var done = false;
1034   openMailbox(node.parentNode.getAttribute("dataname"));
1035   var tree = $("mailboxTree");
1036   tree.selectedEntry = node;
1037   node.select();
1038   mailboxTree.o(1);
1039 }
1040
1041 function initMailer(event) {
1042   if (!document.body.hasClassName("popup")) {
1043     configureMessageListEvents();
1044     initDnd();
1045     currentMailbox = "/" + accounts[0] + "/folderINBOX";
1046     initMailboxTree();
1047   }
1048 }
1049
1050 function initMailboxTree() {
1051   mailboxTree = new dTree("mailboxTree");
1052   mailboxTree.config.folderLinks = true;
1053   mailboxTree.config.hideRoot = true;
1054
1055   mailboxTree.icon.root = ResourcesURL + "/tbtv_account_17x17.gif";
1056   mailboxTree.icon.folder = ResourcesURL + "/tbtv_leaf_corner_17x17.gif";
1057   mailboxTree.icon.folderOpen   = ResourcesURL + "/tbtv_leaf_corner_17x17.gif";
1058   mailboxTree.icon.node = ResourcesURL + "/tbtv_leaf_corner_17x17.gif";
1059   mailboxTree.icon.line = ResourcesURL + "/tbtv_line_17x17.gif";
1060   mailboxTree.icon.join = ResourcesURL + "/tbtv_junction_17x17.gif";
1061   mailboxTree.icon.joinBottom   = ResourcesURL + "/tbtv_corner_17x17.gif";
1062   mailboxTree.icon.plus = ResourcesURL + "/tbtv_plus_17x17.gif";
1063   mailboxTree.icon.plusBottom   = ResourcesURL + "/tbtv_corner_plus_17x17.gif";
1064   mailboxTree.icon.minus = ResourcesURL + "/tbtv_minus_17x17.gif";
1065   mailboxTree.icon.minusBottom = ResourcesURL + "/tbtv_corner_minus_17x17.gif";
1066   mailboxTree.icon.nlPlus = ResourcesURL + "/tbtv_corner_plus_17x17.gif";
1067   mailboxTree.icon.nlMinus = ResourcesURL + "/tbtv_corner_minus_17x17.gif";
1068   mailboxTree.icon.empty = ResourcesURL + "/empty.gif";
1069
1070   mailboxTree.add(0, -1, '');
1071
1072   mailboxTree.pendingRequests = mailAccounts.length;
1073   for (var i = 0; i < mailAccounts.length; i++) {
1074     var url = ApplicationBaseURL + "/" + mailAccounts[i] + "/mailboxes";
1075     triggerAjaxRequest(url, onLoadMailboxesCallback, mailAccounts[i]);
1076   }
1077 }
1078
1079 function updateMailboxTreeInPage() {
1080   $("folderTreeContent").innerHTML = mailboxTree;
1081
1082   var inboxFound = false;
1083   var tree = $("mailboxTree");
1084   var nodes = document.getElementsByClassName("node", tree);
1085   for (i = 0; i < nodes.length; i++) {
1086     Event.observe(nodes[i], "click", onMailboxTreeItemClick.bindAsEventListener(nodes[i]));
1087     Event.observe(nodes[i], "contextmenu", onFolderMenuClick.bindAsEventListener(nodes[i]));
1088     if (!inboxFound
1089         && nodes[i].parentNode.getAttribute("datatype") == "inbox") {
1090       openInbox(nodes[i]);
1091       inboxFound = true;
1092     }
1093   }
1094 }
1095
1096 function mailboxMenuNode(type, name) {
1097   var newNode = document.createElement("li");
1098   var icon = MailerUIdTreeExtension.folderIcons[type];
1099   if (!icon)
1100     icon = "tbtv_leaf_corner_17x17.gif";
1101   var image = document.createElement("img");
1102   image.src = ResourcesURL + "/" + icon;
1103   newNode.appendChild(image);
1104   newNode.appendChild(document.createTextNode(" " + name));
1105
1106   return newNode;
1107 }
1108
1109 function generateMenuForMailbox(mailbox, prefix, callback) {
1110   var menuDIV = document.createElement("div");
1111   $(menuDIV).addClassName("menu");
1112   menuDIV.setAttribute("id", prefix + "Submenu");
1113   var menu = document.createElement("ul");
1114   menuDIV.appendChild(menu);
1115
1116   var callbacks = new Array();
1117   if (mailbox.type != "account") {
1118     var newNode = document.createElement("li");
1119     newNode.mailbox = mailbox;
1120     newNode.appendChild(document.createTextNode("coucou"));
1121     menu.appendChild(newNode);
1122     menu.appendChild(document.createElement("li"));
1123     callbacks.push(callback);
1124     callbacks.push("-");
1125   }
1126
1127   var submenuCount = 0;
1128   for (var i = 0; i < mailbox.children.length; i++) {
1129     var child = mailbox.children[i];
1130     var newNode = mailboxMenuNode(child.type, child.name);
1131     menu.appendChild(newNode);
1132     if (child.children.length > 0) {
1133       var newPrefix = prefix + submenuCount;
1134       var newSubmenu = generateMenuForMailbox(child,
1135                                               newPrefix,
1136                                               callback);
1137       document.body.appendChild(newSubmenu);
1138       callbacks.push(newPrefix + "Submenu");
1139       submenuCount++;
1140     }
1141     else {
1142       newNode.mailbox = child;
1143       callbacks.push(callback);
1144     }
1145   }
1146   initMenu(menuDIV, callbacks);
1147
1148   return menuDIV;
1149 }
1150
1151 function updateMailboxMenus() {
1152   var mailboxActions = { move: onMailboxMenuMove,
1153                          copy: onMailboxMenuCopy };
1154
1155   for (key in mailboxActions) {
1156     var menuId = key + "MailboxMenu";
1157     var menuDIV = $(menuId);
1158     if (menuDIV)
1159       menuDIV.parentNode.removeChild(menuDIV);
1160
1161     menuDIV = document.createElement("div");
1162     document.body.appendChild(menuDIV);
1163
1164     var menu = document.createElement("ul");
1165     menuDIV.appendChild(menu);
1166
1167     $(menuDIV).addClassName("menu");
1168     menuDIV.setAttribute("id", menuId);
1169       
1170     var submenuIds = new Array();
1171     for (var i = 0; i < mailAccounts.length; i++) {
1172       var menuEntry = mailboxMenuNode("account", mailAccounts[i]);
1173       menu.appendChild(menuEntry);
1174       var mailbox = accounts[mailAccounts[i]];
1175       var newSubmenu = generateMenuForMailbox(mailbox,
1176                                               key, mailboxActions[key]);
1177       document.body.appendChild(newSubmenu);
1178       submenuIds.push(newSubmenu.getAttribute("id"));
1179     }
1180     initMenu(menuDIV, submenuIds);
1181   }
1182 }
1183
1184 function onLoadMailboxesCallback(http) {
1185   if (http.readyState == 4
1186       && http.status == 200) {
1187     var newAccount = buildMailboxes(http.callbackData,
1188                                     http.responseText);
1189     accounts[http.callbackData] = newAccount;
1190     mailboxTree.addMailAccount(newAccount);
1191     mailboxTree.pendingRequests--;
1192     if (!mailboxTree.pendingRequests) {
1193       updateMailboxTreeInPage();
1194       updateMailboxMenus();
1195     }
1196   }
1197
1198   //       var tree = $("mailboxTree");
1199   //       var treeNodes = document.getElementsByClassName("dTreeNode", tree);
1200   //       var i = 0;
1201   //       while (i < treeNodes.length
1202   //         && treeNodes[i].getAttribute("dataname") != currentMailbox)
1203   //     i++;
1204   //       if (i < treeNodes.length) {
1205   //     //     log("found mailbox");
1206   //     var links = document.getElementsByClassName("node", treeNodes[i]);
1207   //     if (tree.selectedEntry)
1208   //        tree.selectedEntry.deselect();
1209   //     links[0].select();
1210   //     tree.selectedEntry = links[0];
1211   //     expandUpperTree(links[0]);
1212   //       }
1213 }
1214
1215 function buildMailboxes(accountName, encoded) {
1216   var account = new Mailbox("account", accountName);
1217   var data = encoded.evalJSON(true);
1218   for (var i = 0; i < data.length; i++) {
1219     var currentNode = account;
1220     var names = data[i].path.split("/");
1221     for (var j = 1; j < (names.length - 1); j++) {
1222       var node = currentNode.findMailboxByName(names[j]);
1223       if (!node) {
1224         node = new Mailbox("additional", names[j]);
1225         currentNode.addMailbox(node);
1226       }
1227       currentNode = node;
1228     }
1229     var basename = names[names.length-1];
1230     var leaf = currentNode.findMailboxByName(basename);
1231     if (leaf)
1232       leaf.type = data[i].type;
1233     else {
1234       leaf = new Mailbox(data[i].type, basename);
1235       currentNode.addMailbox(leaf);
1236     }
1237   }
1238
1239   return account;
1240 }
1241
1242 function onMenuCreateFolder(event) {
1243   var name = window.prompt(labels["Name :"].decodeEntities(), "");
1244   if (name && name.length > 0) {
1245     var folderID = document.menuTarget.getAttribute("dataname");
1246     var urlstr = URLForFolderID(folderID) + "/createFolder?name=" + name;
1247     triggerAjaxRequest(urlstr, folderOperationCallback);
1248   }
1249 }
1250
1251 function onMenuRenameFolder(event) {
1252   var name = window.prompt(labels["Enter the new name of your folder :"]
1253                            .decodeEntities(),
1254                            "");
1255   if (name && name.length > 0) {
1256     var folderID = document.menuTarget.getAttribute("dataname");
1257     var urlstr = URLForFolderID(folderID) + "/renameFolder?name=" + name;
1258     triggerAjaxRequest(urlstr, folderOperationCallback);
1259   }
1260 }
1261
1262 function onMenuDeleteFolder(event) {
1263   var answer = window.confirm(labels["Do you really want to move this folder into the trash ?"].decodeEntities());
1264   if (answer) {
1265     var folderID = document.menuTarget.getAttribute("dataname");
1266     var urlstr = URLForFolderID(folderID) + "/deleteFolder";
1267     triggerAjaxRequest(urlstr, folderOperationCallback);
1268   }
1269 }
1270
1271 function onMenuEmptyTrash(event) {
1272   var folderID = document.menuTarget.getAttribute("dataname");
1273   var urlstr = URLForFolderID(folderID) + "/emptyTrash";
1274   triggerAjaxRequest(urlstr, folderOperationCallback);
1275 }
1276
1277 function folderOperationCallback(http) {
1278   if (http.readyState == 4
1279       && http.status == 204)
1280     initMailboxTree();
1281   else
1282     window.alert(labels["Operation failed"].decodeEntities());
1283 }
1284
1285 function getMenus() {
1286   var menus = {}
1287   menus["accountIconMenu"] = new Array(null, null, onMenuCreateFolder, null,
1288                                        null, null);
1289   menus["inboxIconMenu"] = new Array(null, null, null, "-", null,
1290                                      onMenuCreateFolder, null, "-", null,
1291                                      onMenuSharing);
1292   menus["trashIconMenu"] = new Array(null, null, null, "-", null,
1293                                      onMenuCreateFolder, null,
1294                                      onMenuEmptyTrash, "-", null,
1295                                      onMenuSharing);
1296   menus["mailboxIconMenu"] = new Array(null, null, null, "-", null,
1297                                        onMenuCreateFolder,
1298                                        onMenuRenameFolder,
1299                                        null, onMenuDeleteFolder, "-", null,
1300                                        onMenuSharing);
1301   menus["addressMenu"] = new Array(newContactFromEmail, newEmailTo, null);
1302   menus["messageListMenu"] = new Array(onMenuOpenMessage, "-",
1303                                        onMenuReplyToSender,
1304                                        onMenuReplyToAll,
1305                                        onMenuForwardMessage, null,
1306                                        "-", "moveMailboxMenu",
1307                                        "copyMailboxMenu", "label-menu",
1308                                        "mark-menu", "-", null,
1309                                        onMenuViewMessageSource, null,
1310                                        null, onMenuDeleteMessage);
1311   menus["messageContentMenu"] = new Array(onMenuReplyToSender,
1312                                           onMenuReplyToAll,
1313                                           onMenuForwardMessage,
1314                                           null, "moveMailboxMenu",
1315                                           "copyMailboxMenu",
1316                                           "-", "label-menu", "mark-menu",
1317                                           "-",
1318                                           null, onMenuViewMessageSource,
1319                                           null, null,
1320                                           onMenuDeleteMessage);
1321   menus["label-menu"] = new Array(null, "-", null , null, null, null , null,
1322                                   null);
1323   menus["mark-menu"] = new Array(null, null, null, null, "-", null, "-",
1324                                  null, null, null);
1325   menus["searchMenu"] = new Array(setSearchCriteria, setSearchCriteria,
1326                                   setSearchCriteria, setSearchCriteria,
1327                                   setSearchCriteria);
1328
1329   return menus;
1330 }
1331
1332 addEvent(window, 'load', initMailer);
1333
1334 function Mailbox(type, name) {
1335   this.type = type;
1336   this.name = name;
1337   this.parentFolder = null;
1338   this.children = new Array();
1339   return this;
1340 }
1341
1342 Mailbox.prototype.dump = function(indent) {
1343   if (!indent)
1344     indent = 0;
1345   log(" ".repeat(indent) + this.name);
1346   for (var i = 0; i < this.children.length; i++) {
1347     this.children[i].dump(indent + 2);
1348   }
1349 }
1350
1351 Mailbox.prototype.findMailboxByName = function(name) {
1352   var mailbox = null;
1353
1354   var i = 0;
1355   while (!mailbox && i < this.children.length)
1356     if (this.children[i].name == name)
1357       mailbox = this.children[i];
1358     else
1359       i++;
1360
1361   return mailbox;
1362 }
1363
1364 Mailbox.prototype.addMailbox = function(mailbox) {
1365   mailbox.parentFolder = this;
1366   this.children.push(mailbox);
1367 }