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