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