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