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