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