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