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