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