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