]> err.no Git - scalable-opengroupware.org/blob - UI/WebServerResources/MailerUI.js
df32f1d746819e4a7373c0e46daa4961e91a8b81
[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 onPrintCurrentMessage(event) {
324   var rowIds = $("messageList").getSelectedRowsId();
325   if (rowIds.length == 0) {
326     window.alert(labels["Please select a message to print."].decodeEntities());
327   }
328   else if (rowIds.length > 1) {
329     window.alert(labels["Please select only one message to print."].decodeEntities());
330   }
331   else
332     window.print();
333
334   preventDefault(event);
335 }
336
337 function onMailboxTreeItemClick(event) {
338   var topNode = $("mailboxTree");
339   var mailbox = this.parentNode.getAttribute("dataname");
340
341   if (topNode.selectedEntry)
342     topNode.selectedEntry.deselect();
343   this.select();
344   topNode.selectedEntry = this;
345
346   search = {};
347   sorting = {};
348   $("searchValue").value = "";
349   initCriteria();
350
351   var datatype = this.parentNode.getAttribute("datatype");
352   if (datatype == "account" || datatype == "additional") {
353     currentMailbox = mailbox;
354     $("messageContent").innerHTML = "";
355     var body = $("messageList").tBodies[0];
356     for (var i = body.rows.length - 1; i > 0; i--)
357       body.deleteRow(i);
358   }
359   else
360     openMailbox(mailbox);
361    
362   preventDefault(event);
363 }
364
365 function onMailboxMenuMove() {
366   window.alert("unimplemented");
367 }
368
369 function onMailboxMenuCopy() {
370   window.alert("unimplemented");
371 }
372
373 function refreshMailbox() {
374   var topWindow = getTopWindow();
375   if (topWindow)
376     topWindow.refreshCurrentFolder();
377
378   return false;
379 }
380
381 function openMailbox(mailbox, reload, idx) {
382   if (mailbox != currentMailbox || reload) {
383     currentMailbox = mailbox;
384     var url = ApplicationBaseURL + mailbox + "/view?noframe=1";
385     var messageContent = $("messageContent");
386     messageContent.innerHTML = '';
387       
388     if (currentMessages[mailbox]) {
389       loadMessage(currentMessages[mailbox]);
390       url += '&pageforuid=' + currentMessages[mailbox];
391     }
392
393     var searchValue = search["value"];
394     if (searchValue && searchValue.length > 0)
395       url += ("&search=" + search["criteria"]
396               + "&value=" + searchValue);
397     var sortAttribute = sorting["attribute"];
398     if (sortAttribute && sortAttribute.length > 0)
399       url += ("&sort=" + sorting["attribute"]
400               + "&asc=" + sorting["ascending"]);
401     if (idx)
402       url += "&idx=" + idx;
403
404     if (document.messageListAjaxRequest) {
405       document.messageListAjaxRequest.aborted = true;
406       document.messageListAjaxRequest.abort();
407     }
408
409     var mailboxContent = $("mailboxContent");
410     if (mailboxContent.getStyle('visibility') == "hidden") {
411       mailboxContent.setStyle({ visibility: "visible" });
412       var rightDragHandle = $("rightDragHandle");
413       rightDragHandle.setStyle({ visibility: "visible" });
414       messageContent.setStyle({ top: (rightDragHandle.offsetTop
415                                       + rightDragHandle.offsetHeight
416                                       + 'px') });
417     }
418
419     document.messageListAjaxRequest
420       = triggerAjaxRequest(url, messageListCallback,
421                            currentMessages[mailbox]);
422
423     var quotasUrl = ApplicationBaseURL + mailbox + "/quotas";
424     document.quotasAjaxRequest
425       = triggerAjaxRequest(quotasUrl, quotasCallback);
426   }
427 }
428
429 function openMailboxAtIndex(event) {
430   openMailbox(currentMailbox, true, this.getAttribute("idx"));
431
432   preventDefault(event);
433 }
434
435 function messageListCallback(http) {
436   var div = $('mailboxContent');
437    
438   if (http.readyState == 4
439       && http.status == 200) {
440     document.messageListAjaxRequest = null;
441     div.innerHTML = http.responseText;
442     var selected = http.callbackData;
443     if (selected) {
444       var row = $("row_" + selected);
445       if (row)
446         row.select();
447     }
448     configureMessageListEvents();
449     if (sorting["attribute"] && sorting["attribute"].length > 0) {
450       var sortHeader;
451       if (sorting["attribute"] == "subject")
452         sortHeader = $("subjectHeader");
453       else if (sorting["attribute"] == "from")
454         sortHeader = $("fromHeader");
455       else if (sorting["attribute"] == "date")
456         sortHeader = $("dateHeader");
457       else
458         sortHeader = null;
459
460       if (sortHeader) {
461         var sortImage = createElement("img", "messageSortImage", "sortImage");
462         sortHeader.insertBefore(sortImage, sortHeader.firstChild);
463         if (sorting["ascending"])
464           sortImage.src = ResourcesURL + "/title_sortdown_12x12.png";
465         else
466           sortImage.src = ResourcesURL + "/title_sortup_12x12.png";
467       }
468     }
469   }
470   else
471     log("messageListCallback: problem during ajax request (readyState = " + http.readyState + ", status = " + http.status + ")");
472 }
473
474 function quotasCallback(http) {
475   if (http.readyState == 4
476       && http.status == 200) {
477     var hasQuotas = false;
478
479     var quotas = http.responseText.evalJSON(true);
480     for (var i in quotas) {
481       hasQuotas = true;
482       break;
483     }
484
485     if (hasQuotas) {
486       var treePath = currentMailbox.split("/");
487       var mbQuotas = quotas["/" + treePath[2]];
488       var used = mbQuotas["usedSpace"];
489       var max = mbQuotas["maxQuota"];
490       var percents = (Math.round(used * 10000 / max) / 100);
491       var format = labels["quotasFormat"].decodeEntities();
492       var text = format.formatted(used, max, percents);
493       window.status = text;
494     }
495   }
496 }
497
498 function onMessageContextMenu(event) {
499   var menu = $('messageListMenu');
500   Event.observe(menu, "hideMenu", onMessageContextMenuHide);
501   popupMenu(event, "messageListMenu", this);
502
503   var topNode = $('messageList');
504   var selectedNodes = topNode.getSelectedRows();
505   for (var i = 0; i < selectedNodes.length; i++)
506     selectedNodes[i].deselect();
507   topNode.menuSelectedRows = selectedNodes;
508   topNode.menuSelectedEntry = this;
509   this.select();
510 }
511
512 function onMessageContextMenuHide(event) {
513   var topNode = $('messageList');
514
515   if (topNode.menuSelectedEntry) {
516     topNode.menuSelectedEntry.deselect();
517     topNode.menuSelectedEntry = null;
518   }
519   if (topNode.menuSelectedRows) {
520     var nodes = topNode.menuSelectedRows;
521     for (var i = 0; i < nodes.length; i++)
522       nodes[i].select();
523     topNode.menuSelectedRows = null;
524   }
525 }
526
527 function onFolderMenuClick(event) {
528   var onhide, menuName;
529    
530   var menutype = this.parentNode.getAttribute("datatype");
531   if (menutype) {
532     if (menutype == "inbox") {
533       menuName = "inboxIconMenu";
534     } else if (menutype == "account") {
535       menuName = "accountIconMenu";
536     } else if (menutype == "trash") {
537       menuName = "trashIconMenu";
538     } else {
539       menuName = "mailboxIconMenu";
540     }
541   } else {
542     menuName = "mailboxIconMenu";
543   }
544
545   var menu = $(menuName);
546   Event.observe(menu, "hideMenu", onFolderMenuHide);
547   popupMenu(event, menuName, this.parentNode);
548
549   var topNode = $("mailboxTree");
550   if (topNode.selectedEntry)
551     topNode.selectedEntry.deselect();
552   if (topNode.menuSelectedEntry)
553     topNode.menuSelectedEntry.deselect();
554   topNode.menuSelectedEntry = this;
555   this.select();
556
557   preventDefault(event);
558 }
559
560 function onFolderMenuHide(event) {
561   var topNode = $("mailboxTree");
562
563   if (topNode.menuSelectedEntry) {
564     topNode.menuSelectedEntry.deselect();
565     topNode.menuSelectedEntry = null;
566   }
567   if (topNode.selectedEntry)
568     topNode.selectedEntry.select();
569 }
570
571 function deleteCachedMessage(messageId) {
572   var done = false;
573   var counter = 0;
574
575   while (counter < cachedMessages.length
576          && !done)
577     if (cachedMessages[counter]
578         && cachedMessages[counter]['idx'] == messageId) {
579       cachedMessages.splice(counter, 1);
580       done = true;
581     }
582     else
583       counter++;
584 }
585
586 function getCachedMessage(idx) {
587   var message = null;
588   var counter = 0;
589
590   while (counter < cachedMessages.length
591          && message == null)
592     if (cachedMessages[counter]
593         && cachedMessages[counter]['idx'] == currentMailbox + '/' + idx)
594       message = cachedMessages[counter];
595     else
596       counter++;
597
598   return message;
599 }
600
601 function storeCachedMessage(cachedMessage) {
602   var oldest = -1;
603   var timeOldest = -1;
604   var counter = 0;
605
606   if (cachedMessages.length < maxCachedMessages)
607     oldest = cachedMessages.length;
608   else {
609     while (cachedMessages[counter]) {
610       if (oldest == -1
611           || cachedMessages[counter]['time'] < timeOldest) {
612         oldest = counter;
613         timeOldest = cachedMessages[counter]['time'];
614       }
615       counter++;
616     }
617
618     if (oldest == -1)
619       oldest = 0;
620   }
621
622   cachedMessages[oldest] = cachedMessage;
623 }
624
625 function onMessageSelectionChange() {
626   var rows = this.getSelectedRowsId();
627
628   if (rows.length == 1) {
629     var idx = rows[0].substr(4);
630
631     if (currentMessages[currentMailbox] != idx) {
632       currentMessages[currentMailbox] = idx;
633       loadMessage(idx);
634     }
635   }
636 }
637
638 function loadMessage(idx) {
639   if (document.messageAjaxRequest) {
640     document.messageAjaxRequest.aborted = true;
641     document.messageAjaxRequest.abort();
642   }
643
644   var cachedMessage = getCachedMessage(idx);
645
646   if (cachedMessage == null) {
647     var url = (ApplicationBaseURL + currentMailbox + "/"
648                + idx + "/view?noframe=1");
649     document.messageAjaxRequest
650       = triggerAjaxRequest(url, messageCallback, idx);
651     markMailInWindow(window, idx, true);
652   } else {
653     var div = $('messageContent');
654     div.innerHTML = cachedMessage['text'];
655     cachedMessage['time'] = (new Date()).getTime();
656     document.messageAjaxRequest = null;
657     configureLinksInMessage();
658   }
659 }
660
661 function configureLinksInMessage() {
662   var messageDiv = $('messageContent');
663   var mailContentDiv = document.getElementsByClassName('mailer_mailcontent',
664                                                        messageDiv)[0];
665   Event.observe(mailContentDiv, "contextmenu",
666                 onMessageContentMenu.bindAsEventListener(mailContentDiv));
667   var anchors = messageDiv.getElementsByTagName('a');
668   for (var i = 0; i < anchors.length; i++)
669     if (anchors[i].href.substring(0,7) == "mailto:") {
670       Event.observe(anchors[i], "click",
671                     onEmailAddressClick.bindAsEventListener(anchors[i]));
672       Event.observe(anchors[i], "contextmenu",
673                     onEmailAddressClick.bindAsEventListener(anchors[i]));
674     }
675     else
676       Event.observe(anchors[i], "click",
677                     onMessageAnchorClick);
678 }
679
680 function onMessageContentMenu(event) {
681   popupMenu(event, 'messageContentMenu', this);
682 }
683
684 function onEmailAddressClick(event) {
685   popupMenu(event, 'addressMenu', this);
686 }
687
688 function onMessageAnchorClick (event) {
689   window.open(this.href);
690   preventDefault(event);
691 }
692
693 function messageCallback(http) {
694   var div = $('messageContent');
695
696   if (http.readyState == 4
697       && http.status == 200) {
698     document.messageAjaxRequest = null;
699     div.innerHTML = http.responseText;
700     configureLinksInMessage();
701       
702     if (http.callbackData) {
703       var cachedMessage = new Array();
704       cachedMessage['idx'] = currentMailbox + '/' + http.callbackData;
705       cachedMessage['time'] = (new Date()).getTime();
706       cachedMessage['text'] = http.responseText;
707       if (cachedMessage['text'].length < 30000)
708         storeCachedMessage(cachedMessage);
709     }
710   }
711   else
712     log("messageCallback: problem during ajax request: " + http.status);
713 }
714
715 function processMailboxMenuAction(mailbox) {
716   var currentNode, upperNode;
717   var mailboxName;
718   var action;
719
720   mailboxName = mailbox.getAttribute('mailboxname');
721   currentNode = mailbox;
722   upperNode = null;
723
724   while (currentNode
725          && !currentNode.hasAttribute('mailboxaction'))
726     currentNode = currentNode.parentNode.parentNode.parentMenuItem;
727
728   if (currentNode)
729     {
730       action = currentNode.getAttribute('mailboxaction');
731       //       var rows  = collectSelectedRows();
732       //       var rString = rows.join(', ');
733       //       alert("performing '" + action + "' on " + rString
734       //             + " to " + mailboxName);
735     }
736 }
737
738 var rowSelectionCount = 0;
739
740 validateControls();
741
742 function showElement(e, shouldShow) {
743   e.style.display = shouldShow ? "" : "none";
744 }
745
746 function enableElement(e, shouldEnable) {
747   if(!e)
748     return;
749   if(shouldEnable) {
750     if(e.hasAttribute("disabled"))
751       e.removeAttribute("disabled");
752   }
753   else {
754     e.setAttribute("disabled", "1");
755   }
756 }
757
758 function validateControls() {
759   var e = $("moveto");
760   this.enableElement(e, rowSelectionCount > 0);
761 }
762
763 function moveTo(uri) {
764   alert("MoveTo: " + uri);
765 }
766
767 function deleteSelectedMails() {
768 }
769
770 /* message menu entries */
771 function onMenuOpenMessage(event) {
772   return openMessageWindowsForSelection('popupview');
773 }
774
775 function onMenuReplyToSender(event) {
776   return openMessageWindowsForSelection('reply');
777 }
778
779 function onMenuReplyToAll(event) {
780   return openMessageWindowsForSelection('replyall');
781 }
782
783 function onMenuForwardMessage(event) {
784   return openMessageWindowsForSelection('forward');
785 }
786
787 function onMenuViewMessageSource(event) {
788   var messageList = $("messageList");
789   var rows = messageList.getSelectedRowsId();
790
791   if (rows.length > 0) {
792     var url = (ApplicationBaseURL + currentMailbox + "/"
793                + rows[0].substr(4) + "/viewsource");
794     window.open(url, "",
795                 "width=680,height=520,resizable=1,scrollbars=1,toolbar=0,"
796                 + "location=0,directories=0,status=0,menubar=0,copyhistory=0");
797   }
798
799   preventDefault(event);
800 }
801
802 /* contacts */
803 function newContactFromEmail(event) {
804   var mailto = document.menuTarget.innerHTML;
805
806   var email = extractEmailAddress(mailto);
807   var c_name = extractEmailName(mailto);
808   if (email.length > 0)
809     {
810       var url = UserFolderURL + "Contacts/new?contactEmail=" + email;
811       if (c_name)
812         url += "&contactFN=" + c_name;
813       w = window.open(url, null,
814                       "width=546,height=490,resizable=1,scrollbars=1,toolbar=0,"
815                       + "location=0,directories=0,status=0,menubar=0,copyhistory=0");
816       w.focus();
817     }
818
819   return false; /* stop following the link */
820 }
821
822 function newEmailTo(sender) {
823   return openMailTo(document.menuTarget.innerHTML);
824 }
825
826 function expandUpperTree(node) {
827   var currentNode = node.parentNode;
828
829   while (currentNode.className != "dtree") {
830     if (currentNode.className == 'clip') {
831       var id = currentNode.getAttribute("id");
832       var number = parseInt(id.substr(2));
833       if (number > 0) {
834         var cn = mailboxTree.aNodes[number];
835         mailboxTree.nodeStatus(1, number, cn._ls);
836       }
837     }
838     currentNode = currentNode.parentNode;
839   }
840 }
841
842 function onHeaderClick(event) {
843   var headerId = this.getAttribute("id");
844   var newSortAttribute;
845   if (headerId == "subjectHeader")
846     newSortAttribute = "subject";
847   else if (headerId == "fromHeader")
848     newSortAttribute = "from";
849   else if (headerId == "dateHeader")
850     newSortAttribute = "date";
851   else
852     newSortAttribute = "arrival";
853
854   if (sorting["attribute"] == newSortAttribute)
855     sorting["ascending"] = !sorting["ascending"];
856   else {
857     sorting["attribute"] = newSortAttribute;
858     sorting["ascending"] = true;
859   }
860
861   refreshCurrentFolder();
862
863   preventDefault(event);
864 }
865
866 function refreshCurrentFolder() {
867   openMailbox(currentMailbox, true);
868 }
869
870 function pouetpouet(event) {
871   window.alert("pouet pouet");
872 }
873
874 var mailboxSpanAcceptType = function(type) {
875   return (type == "mailRow");
876 }
877
878 var mailboxSpanEnter = function() {
879   this.addClassName("_dragOver");
880 }
881
882 var mailboxSpanExit = function() {
883   this.removeClassName("_dragOver");
884 }
885
886 var mailboxSpanDrop = function(data) {
887   var success = false;
888
889   if (data) {
890     var folder = this.parentNode.parentNode.getAttribute("dataname");
891     if (folder != currentMailbox)
892       success = (moveMessages(data, folder) == 0);
893   }
894   else
895     success = false;
896   
897   return success;
898 }
899     
900 var plusSignEnter = function() {
901   var nodeNr = parseInt(this.id.substr(2));
902   if (!mailboxTree.aNodes[nodeNr]._io)
903     this.plusSignTimer = setTimeout("openPlusSign('" + nodeNr + "');", 1000);
904 }
905       
906 var plusSignExit = function() {
907   if (this.plusSignTimer) {
908     clearTimeout(this.plusSignTimer);
909     this.plusSignTimer = null;
910   }
911 }
912         
913 function openPlusSign(nodeNr) {
914   mailboxTree.nodeStatus(1, nodeNr, mailboxTree.aNodes[nodeNr]._ls);
915   mailboxTree.aNodes[nodeNr]._io = 1;
916   this.plusSignTimer = null;
917 }
918
919 var messageListGhost = function () {
920   var newDiv = document.createElement("div");
921   //   newDiv.style.width = "25px;";
922   //   newDiv.style.height = "25px;";
923   newDiv.style.backgroundColor = "#aae;";
924   newDiv.style.border = "2px solid #a3a;";
925   newDiv.style.padding = "5px;";
926   newDiv.ghostOffsetX = 10;
927   newDiv.ghostOffsetY = 5;
928
929   var newImg = document.createElement("img");
930   newImg.src = ResourcesURL + "/message-mail.png";
931
932   var list = $("messageList");
933   var count = list.getSelectedRows().length;
934   newDiv.appendChild(newImg);
935   newDiv.appendChild(document.createElement("br"));
936   newDiv.appendChild(document.createTextNode(count + " messages..."));
937
938   return newDiv;
939 }
940
941 var messageListData = function(type) {
942   var rows = this.parentNode.parentNode.getSelectedRowsId();
943   var msgIds = new Array();
944   for (var i = 0; i < rows.length; i++)
945     msgIds.push(rows[i].substr(4));
946
947   return msgIds;
948 }
949
950 /* a model for a futur refactoring of the sortable table headers mechanism */
951
952 function configureMessageListHeaders(cells) {
953   for (var i = 0; i < cells.length; i++) {
954     var currentCell = $(cells[i]);
955     Event.observe(currentCell, "click",
956                   onHeaderClick.bindAsEventListener(currentCell));
957     Event.observe(currentCell, "mousedown", listRowMouseDownHandler);
958   }
959 }
960
961 function configureMessageListEvents() {
962   var messageList = $("messageList");
963   if (messageList) {
964     Event.observe(messageList, "mousedown",
965                   onMessageSelectionChange.bindAsEventListener(messageList));
966
967     configureMessageListHeaders(messageList.tHead.rows[0].cells);
968     var cell = messageList.tHead.rows[1].cells[0];
969     if ($(cell).hasClassName("tbtv_navcell")) {
970       var anchors = $(cell).childNodesWithTag("a");
971       for (var i = 0; i < anchors.length; i++)
972         Event.observe(anchors[i], "click", openMailboxAtIndex.bindAsEventListener(anchors[i]));
973     }
974
975     rows = messageList.tBodies[0].rows;
976     for (var i = 0; i < rows.length; i++) {
977       Event.observe(rows[i], "mousedown", onRowClick);
978       Event.observe(rows[i], "contextmenu", onMessageContextMenu.bindAsEventListener(rows[i]));
979          
980       rows[i].dndTypes = function() { return new Array("mailRow"); };
981       rows[i].dndGhost = messageListGhost;
982       rows[i].dndDataForType = messageListData;
983       document.DNDManager.registerSource(rows[i]);
984
985       for (var j = 0; j < rows[i].cells.length; j++) {
986         var cell = rows[i].cells[j];
987         Event.observe(cell, "mousedown", listRowMouseDownHandler);
988         if (j == 2 || j == 3 || j == 5)
989           Event.observe(cell, "dblclick", onMessageDoubleClick.bindAsEventListener(cell));
990         else if (j == 4) {
991           var img = cell.childNodesWithTag("img")[0];
992           Event.observe(img, "click", mailListMarkMessage);
993         }
994       }
995     }
996   }
997 }
998
999 function configureDragHandles() {
1000   var handle = $("verticalDragHandle");
1001   if (handle) {
1002     handle.addInterface(SOGoDragHandlesInterface);
1003     handle.leftBlock=$("leftPanel");
1004     handle.rightBlock=$("rightPanel");
1005   }
1006
1007   handle = $("rightDragHandle");
1008   if (handle) {
1009     handle.addInterface(SOGoDragHandlesInterface);
1010     handle.upperBlock=$("mailboxContent");
1011     handle.lowerBlock=$("messageContent");
1012   }
1013 }
1014
1015 /* dnd */
1016 function initDnd() {
1017   //   log("MailerUI initDnd");
1018
1019   var tree = $("mailboxTree");
1020   if (tree) {
1021     var images = tree.getElementsByTagName("img");
1022     for (var i = 0; i < images.length; i++) {
1023       if (images[i].id[0] == 'j') {
1024         images[i].dndAcceptType = mailboxSpanAcceptType;
1025         images[i].dndEnter = plusSignEnter;
1026         images[i].dndExit = plusSignExit;
1027         document.DNDManager.registerDestination(images[i]);
1028       }
1029     }
1030     var nodes = document.getElementsByClassName("nodeName", tree);
1031     for (var i = 0; i < nodes.length; i++) {
1032       nodes[i].dndAcceptType = mailboxSpanAcceptType;
1033       nodes[i].dndEnter = mailboxSpanEnter;
1034       nodes[i].dndExit = mailboxSpanExit;
1035       nodes[i].dndDrop = mailboxSpanDrop;
1036       document.DNDManager.registerDestination(nodes[i]);
1037     }
1038   }
1039 }
1040
1041 /* stub */
1042
1043 function refreshContacts() {
1044 }
1045
1046 function openInbox(node) {
1047   var done = false;
1048   openMailbox(node.parentNode.getAttribute("dataname"));
1049   var tree = $("mailboxTree");
1050   tree.selectedEntry = node;
1051   node.select();
1052   mailboxTree.o(1);
1053 }
1054
1055 function initMailer(event) {
1056   if (!document.body.hasClassName("popup")) {
1057     configureMessageListEvents();
1058     initDnd();
1059     currentMailbox = "/" + accounts[0] + "/folderINBOX";
1060     initMailboxTree();
1061   }
1062 }
1063
1064 function initMailboxTree() {
1065   mailboxTree = new dTree("mailboxTree");
1066   mailboxTree.config.folderLinks = true;
1067   mailboxTree.config.hideRoot = true;
1068
1069   mailboxTree.icon.root = ResourcesURL + "/tbtv_account_17x17.gif";
1070   mailboxTree.icon.folder = ResourcesURL + "/tbtv_leaf_corner_17x17.gif";
1071   mailboxTree.icon.folderOpen   = ResourcesURL + "/tbtv_leaf_corner_17x17.gif";
1072   mailboxTree.icon.node = ResourcesURL + "/tbtv_leaf_corner_17x17.gif";
1073   mailboxTree.icon.line = ResourcesURL + "/tbtv_line_17x17.gif";
1074   mailboxTree.icon.join = ResourcesURL + "/tbtv_junction_17x17.gif";
1075   mailboxTree.icon.joinBottom   = ResourcesURL + "/tbtv_corner_17x17.gif";
1076   mailboxTree.icon.plus = ResourcesURL + "/tbtv_plus_17x17.gif";
1077   mailboxTree.icon.plusBottom   = ResourcesURL + "/tbtv_corner_plus_17x17.gif";
1078   mailboxTree.icon.minus = ResourcesURL + "/tbtv_minus_17x17.gif";
1079   mailboxTree.icon.minusBottom = ResourcesURL + "/tbtv_corner_minus_17x17.gif";
1080   mailboxTree.icon.nlPlus = ResourcesURL + "/tbtv_corner_plus_17x17.gif";
1081   mailboxTree.icon.nlMinus = ResourcesURL + "/tbtv_corner_minus_17x17.gif";
1082   mailboxTree.icon.empty = ResourcesURL + "/empty.gif";
1083
1084   mailboxTree.add(0, -1, '');
1085
1086   mailboxTree.pendingRequests = mailAccounts.length;
1087   for (var i = 0; i < mailAccounts.length; i++) {
1088     var url = ApplicationBaseURL + "/" + mailAccounts[i] + "/mailboxes";
1089     triggerAjaxRequest(url, onLoadMailboxesCallback, mailAccounts[i]);
1090   }
1091 }
1092
1093 function updateMailboxTreeInPage() {
1094   $("folderTreeContent").innerHTML = mailboxTree;
1095
1096   var inboxFound = false;
1097   var tree = $("mailboxTree");
1098   var nodes = document.getElementsByClassName("node", tree);
1099   for (i = 0; i < nodes.length; i++) {
1100     Event.observe(nodes[i], "click", onMailboxTreeItemClick.bindAsEventListener(nodes[i]));
1101     Event.observe(nodes[i], "contextmenu", onFolderMenuClick.bindAsEventListener(nodes[i]));
1102     if (!inboxFound
1103         && nodes[i].parentNode.getAttribute("datatype") == "inbox") {
1104       openInbox(nodes[i]);
1105       inboxFound = true;
1106     }
1107   }
1108 }
1109
1110 function mailboxMenuNode(type, name) {
1111   var newNode = document.createElement("li");
1112   var icon = MailerUIdTreeExtension.folderIcons[type];
1113   if (!icon)
1114     icon = "tbtv_leaf_corner_17x17.gif";
1115   var image = document.createElement("img");
1116   image.src = ResourcesURL + "/" + icon;
1117   newNode.appendChild(image);
1118   newNode.appendChild(document.createTextNode(" " + name));
1119
1120   return newNode;
1121 }
1122
1123 function generateMenuForMailbox(mailbox, prefix, callback) {
1124   var menuDIV = document.createElement("div");
1125   $(menuDIV).addClassName("menu");
1126   menuDIV.setAttribute("id", prefix + "Submenu");
1127   var menu = document.createElement("ul");
1128   menuDIV.appendChild(menu);
1129
1130   var callbacks = new Array();
1131   if (mailbox.type != "account") {
1132     var newNode = document.createElement("li");
1133     newNode.mailbox = mailbox;
1134     newNode.appendChild(document.createTextNode("coucou"));
1135     menu.appendChild(newNode);
1136     menu.appendChild(document.createElement("li"));
1137     callbacks.push(callback);
1138     callbacks.push("-");
1139   }
1140
1141   var submenuCount = 0;
1142   for (var i = 0; i < mailbox.children.length; i++) {
1143     var child = mailbox.children[i];
1144     var newNode = mailboxMenuNode(child.type, child.name);
1145     menu.appendChild(newNode);
1146     if (child.children.length > 0) {
1147       var newPrefix = prefix + submenuCount;
1148       var newSubmenu = generateMenuForMailbox(child,
1149                                               newPrefix,
1150                                               callback);
1151       document.body.appendChild(newSubmenu);
1152       callbacks.push(newPrefix + "Submenu");
1153       submenuCount++;
1154     }
1155     else {
1156       newNode.mailbox = child;
1157       callbacks.push(callback);
1158     }
1159   }
1160   initMenu(menuDIV, callbacks);
1161
1162   return menuDIV;
1163 }
1164
1165 function updateMailboxMenus() {
1166   var mailboxActions = { move: onMailboxMenuMove,
1167                          copy: onMailboxMenuCopy };
1168
1169   for (key in mailboxActions) {
1170     var menuId = key + "MailboxMenu";
1171     var menuDIV = $(menuId);
1172     if (menuDIV)
1173       menuDIV.parentNode.removeChild(menuDIV);
1174
1175     menuDIV = document.createElement("div");
1176     document.body.appendChild(menuDIV);
1177
1178     var menu = document.createElement("ul");
1179     menuDIV.appendChild(menu);
1180
1181     $(menuDIV).addClassName("menu");
1182     menuDIV.setAttribute("id", menuId);
1183       
1184     var submenuIds = new Array();
1185     for (var i = 0; i < mailAccounts.length; i++) {
1186       var menuEntry = mailboxMenuNode("account", mailAccounts[i]);
1187       menu.appendChild(menuEntry);
1188       var mailbox = accounts[mailAccounts[i]];
1189       var newSubmenu = generateMenuForMailbox(mailbox,
1190                                               key, mailboxActions[key]);
1191       document.body.appendChild(newSubmenu);
1192       submenuIds.push(newSubmenu.getAttribute("id"));
1193     }
1194     initMenu(menuDIV, submenuIds);
1195   }
1196 }
1197
1198 function onLoadMailboxesCallback(http) {
1199   if (http.readyState == 4
1200       && http.status == 200) {
1201     var newAccount = buildMailboxes(http.callbackData,
1202                                     http.responseText);
1203     accounts[http.callbackData] = newAccount;
1204     mailboxTree.addMailAccount(newAccount);
1205     mailboxTree.pendingRequests--;
1206     if (!mailboxTree.pendingRequests) {
1207       updateMailboxTreeInPage();
1208       updateMailboxMenus();
1209     }
1210   }
1211
1212   //       var tree = $("mailboxTree");
1213   //       var treeNodes = document.getElementsByClassName("dTreeNode", tree);
1214   //       var i = 0;
1215   //       while (i < treeNodes.length
1216   //         && treeNodes[i].getAttribute("dataname") != currentMailbox)
1217   //     i++;
1218   //       if (i < treeNodes.length) {
1219   //     //     log("found mailbox");
1220   //     var links = document.getElementsByClassName("node", treeNodes[i]);
1221   //     if (tree.selectedEntry)
1222   //        tree.selectedEntry.deselect();
1223   //     links[0].select();
1224   //     tree.selectedEntry = links[0];
1225   //     expandUpperTree(links[0]);
1226   //       }
1227 }
1228
1229 function buildMailboxes(accountName, encoded) {
1230   var account = new Mailbox("account", accountName);
1231   var data = encoded.evalJSON(true);
1232   for (var i = 0; i < data.length; i++) {
1233     var currentNode = account;
1234     var names = data[i].path.split("/");
1235     for (var j = 1; j < (names.length - 1); j++) {
1236       var node = currentNode.findMailboxByName(names[j]);
1237       if (!node) {
1238         node = new Mailbox("additional", names[j]);
1239         currentNode.addMailbox(node);
1240       }
1241       currentNode = node;
1242     }
1243     var basename = names[names.length-1];
1244     var leaf = currentNode.findMailboxByName(basename);
1245     if (leaf)
1246       leaf.type = data[i].type;
1247     else {
1248       leaf = new Mailbox(data[i].type, basename);
1249       currentNode.addMailbox(leaf);
1250     }
1251   }
1252
1253   return account;
1254 }
1255
1256 function onMenuCreateFolder(event) {
1257   var name = window.prompt(labels["Name :"].decodeEntities(), "");
1258   if (name && name.length > 0) {
1259     var folderID = document.menuTarget.getAttribute("dataname");
1260     var urlstr = URLForFolderID(folderID) + "/createFolder?name=" + name;
1261     triggerAjaxRequest(urlstr, folderOperationCallback);
1262   }
1263 }
1264
1265 function onMenuRenameFolder(event) {
1266   var name = window.prompt(labels["Enter the new name of your folder :"]
1267                            .decodeEntities(),
1268                            "");
1269   if (name && name.length > 0) {
1270     var folderID = document.menuTarget.getAttribute("dataname");
1271     var urlstr = URLForFolderID(folderID) + "/renameFolder?name=" + name;
1272     triggerAjaxRequest(urlstr, folderOperationCallback);
1273   }
1274 }
1275
1276 function onMenuDeleteFolder(event) {
1277   var answer = window.confirm(labels["Do you really want to move this folder into the trash ?"].decodeEntities());
1278   if (answer) {
1279     var folderID = document.menuTarget.getAttribute("dataname");
1280     var urlstr = URLForFolderID(folderID) + "/deleteFolder";
1281     triggerAjaxRequest(urlstr, folderOperationCallback);
1282   }
1283 }
1284
1285 function onMenuEmptyTrash(event) {
1286   var folderID = document.menuTarget.getAttribute("dataname");
1287   var urlstr = URLForFolderID(folderID) + "/emptyTrash";
1288   triggerAjaxRequest(urlstr, folderOperationCallback);
1289 }
1290
1291 function folderOperationCallback(http) {
1292   if (http.readyState == 4
1293       && http.status == 204)
1294     initMailboxTree();
1295   else
1296     window.alert(labels["Operation failed"].decodeEntities());
1297 }
1298
1299 function getMenus() {
1300   var menus = {}
1301   menus["accountIconMenu"] = new Array(null, null, onMenuCreateFolder, null,
1302                                        null, null);
1303   menus["inboxIconMenu"] = new Array(null, null, null, "-", null,
1304                                      onMenuCreateFolder, null, "-", null,
1305                                      onMenuSharing);
1306   menus["trashIconMenu"] = new Array(null, null, null, "-", null,
1307                                      onMenuCreateFolder, null,
1308                                      onMenuEmptyTrash, "-", null,
1309                                      onMenuSharing);
1310   menus["mailboxIconMenu"] = new Array(null, null, null, "-", null,
1311                                        onMenuCreateFolder,
1312                                        onMenuRenameFolder,
1313                                        null, onMenuDeleteFolder, "-", null,
1314                                        onMenuSharing);
1315   menus["addressMenu"] = new Array(newContactFromEmail, newEmailTo, null);
1316   menus["messageListMenu"] = new Array(onMenuOpenMessage, "-",
1317                                        onMenuReplyToSender,
1318                                        onMenuReplyToAll,
1319                                        onMenuForwardMessage, null,
1320                                        "-", "moveMailboxMenu",
1321                                        "copyMailboxMenu", "label-menu",
1322                                        "mark-menu", "-", null,
1323                                        onMenuViewMessageSource, null,
1324                                        null, onMenuDeleteMessage);
1325   menus["messageContentMenu"] = new Array(onMenuReplyToSender,
1326                                           onMenuReplyToAll,
1327                                           onMenuForwardMessage,
1328                                           null, "moveMailboxMenu",
1329                                           "copyMailboxMenu",
1330                                           "-", "label-menu", "mark-menu",
1331                                           "-",
1332                                           null, onMenuViewMessageSource,
1333                                           null, onPrintCurrentMessage,
1334                                           onMenuDeleteMessage);
1335   menus["label-menu"] = new Array(null, "-", null , null, null, null , null,
1336                                   null);
1337   menus["mark-menu"] = new Array(null, null, null, null, "-", null, "-",
1338                                  null, null, null);
1339   menus["searchMenu"] = new Array(setSearchCriteria, setSearchCriteria,
1340                                   setSearchCriteria, setSearchCriteria,
1341                                   setSearchCriteria);
1342
1343   return menus;
1344 }
1345
1346 addEvent(window, 'load', initMailer);
1347
1348 function Mailbox(type, name) {
1349   this.type = type;
1350   this.name = name;
1351   this.parentFolder = null;
1352   this.children = new Array();
1353   return this;
1354 }
1355
1356 Mailbox.prototype.dump = function(indent) {
1357   if (!indent)
1358     indent = 0;
1359   log(" ".repeat(indent) + this.name);
1360   for (var i = 0; i < this.children.length; i++) {
1361     this.children[i].dump(indent + 2);
1362   }
1363 }
1364
1365 Mailbox.prototype.findMailboxByName = function(name) {
1366   var mailbox = null;
1367
1368   var i = 0;
1369   while (!mailbox && i < this.children.length)
1370     if (this.children[i].name == name)
1371       mailbox = this.children[i];
1372     else
1373       i++;
1374
1375   return mailbox;
1376 }
1377
1378 Mailbox.prototype.addMailbox = function(mailbox) {
1379   mailbox.parentFolder = this;
1380   this.children.push(mailbox);
1381 }