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