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