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