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