]> err.no Git - scalable-opengroupware.org/blob - UI/WebServerResources/MailerUI.js
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1150 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / UI / WebServerResources / MailerUI.js
1 /* JavaScript for SOGoMail */
2 var accounts = {};
3 var mailboxTree;
4
5 var currentMessages = new Array();
6 var maxCachedMessages = 20;
7 var cachedMessages = new Array();
8 var currentMailbox = null;
9 var currentMailboxType = "";
10
11 var usersRightsWindowHeight = 320;
12 var usersRightsWindowWidth = 400;
13
14 /* mail list */
15
16 function openMessageWindow(msguid, url) {
17   var wId = '';
18   if (msguid) {
19     wId += "SOGo_msg_" + msguid;
20     markMailReadInWindow(window, msguid);
21   }
22   var msgWin = window.open(url, wId,
23                            "width=680,height=520,resizable=1,scrollbars=1,toolbar=0,"
24                            + "location=0,directories=0,status=0,menubar=0,copyhistory=0");
25   if (msguid) {
26     msgWin.messageId = msguid;
27     msgWin.messageURL = ApplicationBaseURL + currentMailbox + "/" + msguid;
28   }
29   msgWin.focus();
30
31   return false;
32 }
33
34 function onMessageDoubleClick(event) {
35   var action;
36
37   if (currentMailboxType == "draft")
38     action = "edit";
39   else
40     action = "popupview";
41
42   return openMessageWindowsForSelection(action, true);
43 }
44
45 function toggleMailSelect(sender) {
46   var row;
47   row = $(sender.name);
48   row.className = sender.checked ? "tableview_selected" : "tableview";
49 }
50
51 function openAddressbook(sender) {
52   var urlstr;
53    
54   urlstr = ApplicationBaseURL + "/../Contacts/?popup=YES";
55   var w = window.open(urlstr, "Addressbook",
56                       "width=640,height=400,resizable=1,scrollbars=1,toolbar=0,"
57                       + "location=0,directories=0,status=0,menubar=0,copyhistory=0");
58   w.focus();
59
60   return false;
61 }
62
63 function onMenuSharing(event) {
64   var folderID = document.menuTarget.getAttribute("dataname");
65   var urlstr = URLForFolderID(folderID) + "/acls";
66   preventDefault(event);
67
68   openAclWindow(urlstr);
69 }
70
71 /* mail list DOM changes */
72
73 function markMailInWindow(win, msguid, markread) {
74   var msgDiv;
75
76   msgDiv = win.$("div_" + msguid);
77   if (msgDiv) {
78     if (markread) {
79       msgDiv.removeClassName("mailer_unreadmailsubject");
80       msgDiv.addClassName("mailer_readmailsubject");
81       msgDiv = win.$("unreaddiv_" + msguid);
82       if (msgDiv)
83         {
84           msgDiv.setAttribute("class", "mailerUnreadIcon");
85           msgDiv.setAttribute("id", "readdiv_" + msguid);
86           msgDiv.setAttribute("src", ResourcesURL + "/icon_read.gif");
87           msgDiv.setAttribute("onclick", "mailListMarkMessage(this,"
88                               + " 'markMessageUnread', " + msguid
89                               + ", false);"
90                               +" return false;");
91           var title = msgDiv.getAttribute("title-markunread");
92           if (title)
93             msgDiv.setAttribute("title", title);
94         }
95     }
96     else {
97       msgDiv.removeClassName('mailer_readmailsubject');
98       msgDiv.addClassName('mailer_unreadmailsubject');
99       msgDiv = win.$("readdiv_" + msguid);
100       if (msgDiv)
101         {
102           msgDiv.setAttribute("class", "mailerReadIcon");
103           msgDiv.setAttribute("id", "unreaddiv_" + msguid);
104           msgDiv.setAttribute("src", ResourcesURL + "/icon_unread.gif");
105           msgDiv.setAttribute("onclick", "mailListMarkMessage(this,"
106                               + " 'markMessageRead', " + msguid
107                               + ", true);"
108                               +" return false;");
109           var title = msgDiv.getAttribute("title-markread");
110           if (title)
111             msgDiv.setAttribute("title", title);
112         }
113     }
114     return true;
115   }
116   else
117     return false;
118 }
119
120 function markMailReadInWindow(win, msguid) {
121   /* this is called by UIxMailView with window.opener */
122   return markMailInWindow(win, msguid, true);
123 }
124
125 /* main window */
126
127 function reopenToRemoveLocationBar() {
128   // we cannot really use this, see below at the close comment
129   if (window.locationbar && window.locationbar.visible) {
130     newwin = window.open(window.location.href, "SOGo",
131                          "width=800,height=600,resizable=1,scrollbars=1," +
132                          "toolbar=0,location=0,directories=0,status=0," + 
133                          "menubar=0,copyhistory=0");
134     if (newwin) {
135       window.close(); // this does only work for windows opened by scripts!
136       newwin.focus();
137       return true;
138     }
139     return false;
140   }
141   return true;
142 }
143
144 /* mail list reply */
145
146 function openMessageWindowsForSelection(action, firstOnly) {
147   if (document.body.hasClassName("popup"))
148     win = openMessageWindow(window.messageId,
149                             window.messageURL + "/" + action);
150   else {
151     var messageList = $("messageList");
152     var rows = messageList.getSelectedRowsId();
153     if (rows.length > 0) {
154       if (firstOnly)
155         openMessageWindow(rows[0].substr(4),
156                           ApplicationBaseURL + currentMailbox
157                           + "/" + rows[0].substr(4)
158                           + "/" + action);
159       else
160         for (var i = 0; i < rows.length; i++)
161           openMessageWindow(rows[i].substr(4),
162                             ApplicationBaseURL + currentMailbox
163                             + "/" + rows[i].substr(4)
164                             + "/" + action);
165     }
166   }
167
168   return false;
169 }
170
171 function mailListMarkMessage(event) {
172   var http = createHTTPClient();
173   var url = ApplicationBaseURL + currentMailbox + "/" + action + "?uid=" + msguid;
174
175   if (http) {
176     // TODO: add parameter to signal that we are only interested in OK
177     http.open("POST", url + "&jsonly=1", false /* not async */);
178     http.send("");
179     if (http.status != 200) {
180       // TODO: refresh page?
181       alert("Message Mark Failed: " + http.statusText);
182       window.location.reload();
183     }
184     else {
185       markMailInWindow(window, msguid, markread);
186     }
187   }
188   else {
189     window.location.href = url;
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 /* folder operations */
215
216 function ctxFolderAdd(sender) {
217   var folderName;
218    
219   folderName = prompt("Foldername: ");
220   if (folderName == undefined)
221     return false;
222   if (folderName == "")
223     return false;
224    
225   // TODO: should use a form-POST or AJAX
226   window.location.href = "createFolder?name=" + escape(folderName);
227   return false;
228 }
229
230 function ctxFolderDelete(sender) {
231   if (!confirm("Delete current folder?").decodeEntities())
232     return false;
233    
234   // TODO: should use a form-POST or AJAX
235   window.location.href = "deleteFolder";
236   return false;
237 }
238
239 /* bulk delete of messages */
240
241 function uixDeleteSelectedMessages(sender) {
242   var failCount = 0;
243    
244   var messageList = $("messageList");
245   var rowIds = messageList.getSelectedRowsId();
246
247   for (var i = 0; i < rowIds.length; i++) {
248     var url, http;
249     var rowId = rowIds[i].substr(4);
250     /* send AJAX request (synchronously) */
251
252     var messageId = currentMailbox + "/" + rowId;
253     url = ApplicationBaseURL + messageId + "/trash?jsonly=1";
254     http = createHTTPClient();
255     http.open("POST", url, false /* not async */);
256     http.send("");
257     if (http.status != 200) { /* request failed */
258       failCount++;
259       http = null;
260       continue;
261     } else {
262       deleteCachedMessage(messageId);
263       if (currentMessages[currentMailbox] == rowId) {
264         var div = $('messageContent');
265         div.innerHTML = "";
266         currentMessages[currentMailbox] = null;
267       }
268     }
269     http = null;
270
271     /* remove from page */
272
273     /* line-through would be nicer, but hiding is OK too */
274     var row = $(rowIds[i]);
275     row.parentNode.removeChild(row);
276   }
277
278   if (failCount > 0)
279     alert("Could not delete " + failCount + " messages!");
280    
281   return false;
282 }
283
284 function moveMessages(rowIds, folder) {
285   var failCount = 0;
286
287   for (var i = 0; i < rowIds.length; i++) {
288     var url, http;
289
290     /* send AJAX request (synchronously) */
291           
292     var messageId = currentMailbox + "/" + rowIds[i];
293     url = (ApplicationBaseURL + messageId
294            + "/move?jsonly=1&tofolder=" + folder);
295     http = createHTTPClient();
296     http.open("GET", url, false /* not async */);
297     http.send("");
298     if (http.status == 200) {
299       var row = $("row_" + rowIds[i]);
300       row.parentNode.removeChild(row);
301       deleteCachedMessage(messageId);
302       if (currentMessages[currentMailbox] == rowIds[i]) {
303         var div = $('messageContent');
304         div.innerHTML = "";
305         currentMessages[currentMailbox] = null;
306       }
307     }
308     else /* request failed */
309       failCount++;
310
311     /* remove from page */
312
313     /* line-through would be nicer, but hiding is OK too */
314   }
315
316   if (failCount > 0)
317     alert("Could not move " + failCount + " messages!");
318    
319   return failCount;
320 }
321
322 function onMenuDeleteMessage(event) {
323   uixDeleteSelectedMessages();
324   preventDefault(event);
325 }
326
327 function onPrintCurrentMessage(event) {
328   var rowIds = $("messageList").getSelectedRowsId();
329   if (rowIds.length == 0) {
330     window.alert(labels["Please select a message to print."].decodeEntities());
331   }
332   else if (rowIds.length > 1) {
333     window.alert(labels["Please select only one message to print."].decodeEntities());
334   }
335   else
336     window.print();
337
338   preventDefault(event);
339 }
340
341 function onMailboxTreeItemClick(event) {
342   var topNode = $("mailboxTree");
343   var mailbox = this.parentNode.getAttribute("dataname");
344
345   if (topNode.selectedEntry)
346     topNode.selectedEntry.deselect();
347   this.select();
348   topNode.selectedEntry = this;
349
350   search = {};
351   sorting = {};
352   $("searchValue").value = "";
353   initCriteria();
354
355   currentMailboxType = this.parentNode.getAttribute("datatype");
356   if (currentMailboxType == "account" || currentMailboxType == "additional") {
357     currentMailbox = mailbox;
358     $("messageContent").innerHTML = "";
359     var body = $("messageList").tBodies[0];
360     for (var i = body.rows.length; i > 0; i--)
361       body.deleteRow(i-1);
362   }
363   else
364     openMailbox(mailbox);
365    
366   preventDefault(event);
367 }
368
369 function onMailboxMenuMove() {
370   window.alert("unimplemented");
371 }
372
373 function onMailboxMenuCopy() {
374   window.alert("unimplemented");
375 }
376
377 function refreshMailbox() {
378   var topWindow = getTopWindow();
379   if (topWindow)
380     topWindow.refreshCurrentFolder();
381
382   return false;
383 }
384
385 function onComposeMessage() {
386   var topWindow = getTopWindow();
387   if (topWindow)
388     topWindow.composeNewMessage();
389
390   return false;
391 }
392
393 function composeNewMessage() {
394   var account = currentMailbox.split("/")[1];
395   var url = ApplicationBaseURL + "/" + account + "/compose";
396   window.open(url, null,
397               "width=680,height=520,resizable=1,scrollbars=1,toolbar=0,"
398               + "location=0,directories=0,status=0,menubar=0,copyhistory=0");
399 }
400
401 function openMailbox(mailbox, reload, idx) {
402   if (mailbox != currentMailbox || reload) {
403     currentMailbox = mailbox;
404     var url = ApplicationBaseURL + mailbox + "/view?noframe=1";
405     var messageContent = $("messageContent");
406     messageContent.innerHTML = '';
407
408     var currentMessage;
409     if (!idx) {
410       currentMessage = currentMessages[mailbox];
411       if (currentMessage) {
412         loadMessage(currentMessage);
413         url += '&pageforuid=' + currentMessage;
414       }
415     }
416
417     var searchValue = search["value"];
418     if (searchValue && searchValue.length > 0)
419       url += ("&search=" + search["criteria"]
420               + "&value=" + escape(searchValue));
421     var sortAttribute = sorting["attribute"];
422     if (sortAttribute && sortAttribute.length > 0)
423       url += ("&sort=" + sorting["attribute"]
424               + "&asc=" + sorting["ascending"]);
425     if (idx)
426       url += "&idx=" + idx;
427
428     if (document.messageListAjaxRequest) {
429       document.messageListAjaxRequest.aborted = true;
430       document.messageListAjaxRequest.abort();
431     }
432
433     var mailboxContent = $("mailboxContent");
434     if (mailboxContent.getStyle('visibility') == "hidden") {
435       mailboxContent.setStyle({ visibility: "visible" });
436       var rightDragHandle = $("rightDragHandle");
437       rightDragHandle.setStyle({ visibility: "visible" });
438       messageContent.setStyle({ top: (rightDragHandle.offsetTop
439                                       + rightDragHandle.offsetHeight
440                                       + 'px') });
441     }
442
443     document.messageListAjaxRequest
444       = triggerAjaxRequest(url, messageListCallback,
445                            currentMessage);
446
447     var quotasUrl = ApplicationBaseURL + mailbox + "/quotas";
448     document.quotasAjaxRequest
449       = triggerAjaxRequest(quotasUrl, quotasCallback);
450   }
451 }
452
453 function openMailboxAtIndex(event) {
454   openMailbox(currentMailbox, true, this.getAttribute("idx"));
455
456   preventDefault(event);
457 }
458
459 function messageListCallback(http) {
460   var div = $('mailboxContent');
461    
462   if (http.readyState == 4
463       && http.status == 200) {
464     document.messageListAjaxRequest = null;
465     div.innerHTML = http.responseText;
466     var selected = http.callbackData;
467     if (selected) {
468       var row = $("row_" + selected);
469       if (row)
470         row.select();
471     }
472     configureMessageListEvents();
473     if (sorting["attribute"] && sorting["attribute"].length > 0) {
474       var sortHeader;
475       if (sorting["attribute"] == "subject")
476         sortHeader = $("subjectHeader");
477       else if (sorting["attribute"] == "from")
478         sortHeader = $("fromHeader");
479       else if (sorting["attribute"] == "date")
480         sortHeader = $("dateHeader");
481       else
482         sortHeader = null;
483
484       if (sortHeader) {
485         var sortImage = createElement("img", "messageSortImage", "sortImage");
486         sortHeader.insertBefore(sortImage, sortHeader.firstChild);
487         if (sorting["ascending"])
488           sortImage.src = ResourcesURL + "/title_sortdown_12x12.png";
489         else
490           sortImage.src = ResourcesURL + "/title_sortup_12x12.png";
491       }
492     }
493   }
494   else
495     log("messageListCallback: problem during ajax request (readyState = " + http.readyState + ", status = " + http.status + ")");
496 }
497
498 function quotasCallback(http) {
499   if (http.readyState == 4
500       && http.status == 200) {
501     var hasQuotas = false;
502
503     var quotas = http.responseText.evalJSON(true);
504     for (var i in quotas) {
505       hasQuotas = true;
506       break;
507     }
508
509     if (hasQuotas) {
510       var treePath = currentMailbox.split("/");
511       var mbQuotas = quotas["/" + treePath[2]];
512       var used = mbQuotas["usedSpace"];
513       var max = mbQuotas["maxQuota"];
514       var percents = (Math.round(used * 10000 / max) / 100);
515       var format = labels["quotasFormat"].decodeEntities();
516       var text = format.formatted(used, max, percents);
517       window.status = text;
518     }
519   }
520 }
521
522 function onMessageContextMenu(event) {
523   var menu = $('messageListMenu');
524   Event.observe(menu, "hideMenu", onMessageContextMenuHide);
525   popupMenu(event, "messageListMenu", this);
526
527   var topNode = $('messageList');
528   var selectedNodes = topNode.getSelectedRows();
529   for (var i = 0; i < selectedNodes.length; i++)
530     selectedNodes[i].deselect();
531   topNode.menuSelectedRows = selectedNodes;
532   topNode.menuSelectedEntry = this;
533   this.select();
534 }
535
536 function onMessageContextMenuHide(event) {
537   var topNode = $('messageList');
538
539   if (topNode.menuSelectedEntry) {
540     topNode.menuSelectedEntry.deselect();
541     topNode.menuSelectedEntry = null;
542   }
543   if (topNode.menuSelectedRows) {
544     var nodes = topNode.menuSelectedRows;
545     for (var i = 0; i < nodes.length; i++)
546       nodes[i].select();
547     topNode.menuSelectedRows = null;
548   }
549 }
550
551 function onFolderMenuClick(event) {
552   var onhide, menuName;
553    
554   var menutype = this.parentNode.getAttribute("datatype");
555   if (menutype) {
556     if (menutype == "inbox") {
557       menuName = "inboxIconMenu";
558     } else if (menutype == "account") {
559       menuName = "accountIconMenu";
560     } else if (menutype == "trash") {
561       menuName = "trashIconMenu";
562     } else {
563       menuName = "mailboxIconMenu";
564     }
565   } else {
566     menuName = "mailboxIconMenu";
567   }
568
569   var menu = $(menuName);
570   Event.observe(menu, "hideMenu", onFolderMenuHide);
571   popupMenu(event, menuName, this.parentNode);
572
573   var topNode = $("mailboxTree");
574   if (topNode.selectedEntry)
575     topNode.selectedEntry.deselect();
576   if (topNode.menuSelectedEntry)
577     topNode.menuSelectedEntry.deselect();
578   topNode.menuSelectedEntry = this;
579   this.select();
580
581   preventDefault(event);
582 }
583
584 function onFolderMenuHide(event) {
585   var topNode = $("mailboxTree");
586
587   if (topNode.menuSelectedEntry) {
588     topNode.menuSelectedEntry.deselect();
589     topNode.menuSelectedEntry = null;
590   }
591   if (topNode.selectedEntry)
592     topNode.selectedEntry.select();
593 }
594
595 function deleteCachedMessage(messageId) {
596   var done = false;
597   var counter = 0;
598
599   while (counter < cachedMessages.length
600          && !done)
601     if (cachedMessages[counter]
602         && cachedMessages[counter]['idx'] == messageId) {
603       cachedMessages.splice(counter, 1);
604       done = true;
605     }
606     else
607       counter++;
608 }
609
610 function getCachedMessage(idx) {
611   var message = null;
612   var counter = 0;
613
614   while (counter < cachedMessages.length
615          && message == null)
616     if (cachedMessages[counter]
617         && cachedMessages[counter]['idx'] == currentMailbox + '/' + idx)
618       message = cachedMessages[counter];
619     else
620       counter++;
621
622   return message;
623 }
624
625 function storeCachedMessage(cachedMessage) {
626   var oldest = -1;
627   var timeOldest = -1;
628   var counter = 0;
629
630   if (cachedMessages.length < maxCachedMessages)
631     oldest = cachedMessages.length;
632   else {
633     while (cachedMessages[counter]) {
634       if (oldest == -1
635           || cachedMessages[counter]['time'] < timeOldest) {
636         oldest = counter;
637         timeOldest = cachedMessages[counter]['time'];
638       }
639       counter++;
640     }
641
642     if (oldest == -1)
643       oldest = 0;
644   }
645
646   cachedMessages[oldest] = cachedMessage;
647 }
648
649 function onMessageSelectionChange() {
650   var rows = this.getSelectedRowsId();
651
652   if (rows.length == 1) {
653     var idx = rows[0].substr(4);
654
655     if (currentMessages[currentMailbox] != idx) {
656       currentMessages[currentMailbox] = idx;
657       loadMessage(idx);
658     }
659   }
660 }
661
662 function loadMessage(idx) {
663   if (document.messageAjaxRequest) {
664     document.messageAjaxRequest.aborted = true;
665     document.messageAjaxRequest.abort();
666   }
667
668   var cachedMessage = getCachedMessage(idx);
669
670   if (cachedMessage == null) {
671     var url = (ApplicationBaseURL + currentMailbox + "/"
672                + idx + "/view?noframe=1");
673     document.messageAjaxRequest
674       = triggerAjaxRequest(url, messageCallback, idx);
675     markMailInWindow(window, idx, true);
676   } else {
677     var div = $('messageContent');
678     div.innerHTML = cachedMessage['text'];
679     cachedMessage['time'] = (new Date()).getTime();
680     document.messageAjaxRequest = null;
681     configureLinksInMessage();
682   }
683 }
684
685 function configureLinksInMessage() {
686   var messageDiv = $('messageContent');
687   var mailContentDiv = document.getElementsByClassName('mailer_mailcontent',
688                                                        messageDiv)[0];
689   Event.observe(mailContentDiv, "contextmenu",
690                 onMessageContentMenu.bindAsEventListener(mailContentDiv));
691   var anchors = messageDiv.getElementsByTagName('a');
692   for (var i = 0; i < anchors.length; i++)
693     if (anchors[i].href.substring(0,7) == "mailto:") {
694       Event.observe(anchors[i], "click",
695                     onEmailAddressClick.bindAsEventListener(anchors[i]));
696       Event.observe(anchors[i], "contextmenu",
697                     onEmailAddressClick.bindAsEventListener(anchors[i]));
698     }
699     else
700       Event.observe(anchors[i], "click",
701                     onMessageAnchorClick);
702
703   var editDraftButton = $("editDraftButton");
704   if (editDraftButton)
705     Event.observe(editDraftButton, "click", onMessageEditDraft);
706 }
707
708 function onMessageContentMenu(event) {
709   popupMenu(event, 'messageContentMenu', this);
710 }
711
712 function onMessageEditDraft(event) {
713   return openMessageWindowsForSelection("edit", true);
714 }
715
716 function onEmailAddressClick(event) {
717   popupMenu(event, 'addressMenu', this);
718 }
719
720 function onMessageAnchorClick (event) {
721   window.open(this.href);
722   preventDefault(event);
723 }
724
725 function messageCallback(http) {
726   var div = $('messageContent');
727
728   if (http.readyState == 4
729       && http.status == 200) {
730     document.messageAjaxRequest = null;
731     div.innerHTML = http.responseText;
732     configureLinksInMessage();
733       
734     if (http.callbackData) {
735       var cachedMessage = new Array();
736       cachedMessage['idx'] = currentMailbox + '/' + http.callbackData;
737       cachedMessage['time'] = (new Date()).getTime();
738       cachedMessage['text'] = http.responseText;
739       if (cachedMessage['text'].length < 30000)
740         storeCachedMessage(cachedMessage);
741     }
742   }
743   else
744     log("messageCallback: problem during ajax request: " + http.status);
745 }
746
747 function processMailboxMenuAction(mailbox) {
748   var currentNode, upperNode;
749   var mailboxName;
750   var action;
751
752   mailboxName = mailbox.getAttribute('mailboxname');
753   currentNode = mailbox;
754   upperNode = null;
755
756   while (currentNode
757          && !currentNode.hasAttribute('mailboxaction'))
758     currentNode = currentNode.parentNode.parentNode.parentMenuItem;
759
760   if (currentNode)
761     {
762       action = currentNode.getAttribute('mailboxaction');
763       //       var rows  = collectSelectedRows();
764       //       var rString = rows.join(', ');
765       //       alert("performing '" + action + "' on " + rString
766       //             + " to " + mailboxName);
767     }
768 }
769
770 var rowSelectionCount = 0;
771
772 validateControls();
773
774 function showElement(e, shouldShow) {
775   e.style.display = shouldShow ? "" : "none";
776 }
777
778 function enableElement(e, shouldEnable) {
779   if(!e)
780     return;
781   if(shouldEnable) {
782     if(e.hasAttribute("disabled"))
783       e.removeAttribute("disabled");
784   }
785   else {
786     e.setAttribute("disabled", "1");
787   }
788 }
789
790 function validateControls() {
791   var e = $("moveto");
792   this.enableElement(e, rowSelectionCount > 0);
793 }
794
795 function moveTo(uri) {
796   alert("MoveTo: " + uri);
797 }
798
799 function deleteSelectedMails() {
800 }
801
802 /* message menu entries */
803 function onMenuOpenMessage(event) {
804   return openMessageWindowsForSelection('popupview');
805 }
806
807 function onMenuReplyToSender(event) {
808   return openMessageWindowsForSelection('reply');
809 }
810
811 function onMenuReplyToAll(event) {
812   return openMessageWindowsForSelection('replyall');
813 }
814
815 function onMenuForwardMessage(event) {
816   return openMessageWindowsForSelection('forward');
817 }
818
819 function onMenuViewMessageSource(event) {
820   var messageList = $("messageList");
821   var rows = messageList.getSelectedRowsId();
822
823   if (rows.length > 0) {
824     var url = (ApplicationBaseURL + currentMailbox + "/"
825                + rows[0].substr(4) + "/viewsource");
826     window.open(url, "",
827                 "width=680,height=520,resizable=1,scrollbars=1,toolbar=0,"
828                 + "location=0,directories=0,status=0,menubar=0,copyhistory=0");
829   }
830
831   preventDefault(event);
832 }
833
834 /* contacts */
835 function newContactFromEmail(event) {
836   var mailto = document.menuTarget.innerHTML;
837
838   var email = extractEmailAddress(mailto);
839   var c_name = extractEmailName(mailto);
840   if (email.length > 0)
841     {
842       var url = UserFolderURL + "Contacts/new?contactEmail=" + email;
843       if (c_name)
844         url += "&contactFN=" + c_name;
845       w = window.open(url, null,
846                       "width=546,height=490,resizable=1,scrollbars=1,toolbar=0,"
847                       + "location=0,directories=0,status=0,menubar=0,copyhistory=0");
848       w.focus();
849     }
850
851   return false; /* stop following the link */
852 }
853
854 function newEmailTo(sender) {
855   return openMailTo(document.menuTarget.innerHTML);
856 }
857
858 function expandUpperTree(node) {
859   var currentNode = node.parentNode;
860
861   while (currentNode.className != "dtree") {
862     if (currentNode.className == 'clip') {
863       var id = currentNode.getAttribute("id");
864       var number = parseInt(id.substr(2));
865       if (number > 0) {
866         var cn = mailboxTree.aNodes[number];
867         mailboxTree.nodeStatus(1, number, cn._ls);
868       }
869     }
870     currentNode = currentNode.parentNode;
871   }
872 }
873
874 function onHeaderClick(event) {
875   var headerId = this.getAttribute("id");
876   var newSortAttribute;
877   if (headerId == "subjectHeader")
878     newSortAttribute = "subject";
879   else if (headerId == "fromHeader")
880     newSortAttribute = "from";
881   else if (headerId == "dateHeader")
882     newSortAttribute = "date";
883   else
884     newSortAttribute = "arrival";
885
886   if (sorting["attribute"] == newSortAttribute)
887     sorting["ascending"] = !sorting["ascending"];
888   else {
889     sorting["attribute"] = newSortAttribute;
890     sorting["ascending"] = true;
891   }
892
893   refreshCurrentFolder();
894
895   preventDefault(event);
896 }
897
898 function refreshCurrentFolder() {
899   openMailbox(currentMailbox, true);
900 }
901
902 function pouetpouet(event) {
903   window.alert("pouet pouet");
904 }
905
906 var mailboxSpanAcceptType = function(type) {
907   return (type == "mailRow");
908 }
909
910 var mailboxSpanEnter = function() {
911   this.addClassName("_dragOver");
912 }
913
914 var mailboxSpanExit = function() {
915   this.removeClassName("_dragOver");
916 }
917
918 var mailboxSpanDrop = function(data) {
919   var success = false;
920
921   if (data) {
922     var folder = this.parentNode.parentNode.getAttribute("dataname");
923     if (folder != currentMailbox)
924       success = (moveMessages(data, folder) == 0);
925   }
926   else
927     success = false;
928   
929   return success;
930 }
931     
932 var plusSignEnter = function() {
933   var nodeNr = parseInt(this.id.substr(2));
934   if (!mailboxTree.aNodes[nodeNr]._io)
935     this.plusSignTimer = setTimeout("openPlusSign('" + nodeNr + "');", 1000);
936 }
937       
938 var plusSignExit = function() {
939   if (this.plusSignTimer) {
940     clearTimeout(this.plusSignTimer);
941     this.plusSignTimer = null;
942   }
943 }
944         
945 function openPlusSign(nodeNr) {
946   mailboxTree.nodeStatus(1, nodeNr, mailboxTree.aNodes[nodeNr]._ls);
947   mailboxTree.aNodes[nodeNr]._io = 1;
948   this.plusSignTimer = null;
949 }
950
951 var messageListGhost = function () {
952   var newDiv = document.createElement("div");
953   //   newDiv.style.width = "25px;";
954   //   newDiv.style.height = "25px;";
955   newDiv.style.backgroundColor = "#aae;";
956   newDiv.style.border = "2px solid #a3a;";
957   newDiv.style.padding = "5px;";
958   newDiv.ghostOffsetX = 10;
959   newDiv.ghostOffsetY = 5;
960
961   var newImg = document.createElement("img");
962   newImg.src = ResourcesURL + "/message-mail.png";
963
964   var list = $("messageList");
965   var count = list.getSelectedRows().length;
966   newDiv.appendChild(newImg);
967   newDiv.appendChild(document.createElement("br"));
968   newDiv.appendChild(document.createTextNode(count + " messages..."));
969
970   return newDiv;
971 }
972
973 var messageListData = function(type) {
974   var rows = this.parentNode.parentNode.getSelectedRowsId();
975   var msgIds = new Array();
976   for (var i = 0; i < rows.length; i++)
977     msgIds.push(rows[i].substr(4));
978
979   return msgIds;
980 }
981
982 /* a model for a futur refactoring of the sortable table headers mechanism */
983
984 function configureMessageListHeaders(cells) {
985   for (var i = 0; i < cells.length; i++) {
986     var currentCell = $(cells[i]);
987     Event.observe(currentCell, "click",
988                   onHeaderClick.bindAsEventListener(currentCell));
989     Event.observe(currentCell, "mousedown", listRowMouseDownHandler);
990   }
991 }
992
993 function configureMessageListEvents() {
994   var messageList = $("messageList");
995   if (messageList) {
996     Event.observe(messageList, "mousedown",
997                   onMessageSelectionChange.bindAsEventListener(messageList));
998
999     configureMessageListHeaders(messageList.tHead.rows[0].cells);
1000     var cell = messageList.tHead.rows[1].cells[0];
1001     if ($(cell).hasClassName("tbtv_navcell")) {
1002       var anchors = $(cell).childNodesWithTag("a");
1003       for (var i = 0; i < anchors.length; i++)
1004         Event.observe(anchors[i], "click", openMailboxAtIndex.bindAsEventListener(anchors[i]));
1005     }
1006
1007     rows = messageList.tBodies[0].rows;
1008     for (var i = 0; i < rows.length; i++) {
1009       Event.observe(rows[i], "mousedown", onRowClick);
1010       Event.observe(rows[i], "contextmenu", onMessageContextMenu.bindAsEventListener(rows[i]));
1011          
1012       rows[i].dndTypes = function() { return new Array("mailRow"); };
1013       rows[i].dndGhost = messageListGhost;
1014       rows[i].dndDataForType = messageListData;
1015       document.DNDManager.registerSource(rows[i]);
1016
1017       for (var j = 0; j < rows[i].cells.length; j++) {
1018         var cell = rows[i].cells[j];
1019         Event.observe(cell, "mousedown", listRowMouseDownHandler);
1020         if (j == 2 || j == 3 || j == 5)
1021           Event.observe(cell, "dblclick", onMessageDoubleClick.bindAsEventListener(cell));
1022         else if (j == 4) {
1023           var img = cell.childNodesWithTag("img")[0];
1024           Event.observe(img, "click", mailListMarkMessage);
1025         }
1026       }
1027     }
1028   }
1029 }
1030
1031 function configureDragHandles() {
1032   var handle = $("verticalDragHandle");
1033   if (handle) {
1034     handle.addInterface(SOGoDragHandlesInterface);
1035     handle.leftMargin = 1;
1036     handle.leftBlock=$("leftPanel");
1037     handle.rightBlock=$("rightPanel");
1038   }
1039
1040   handle = $("rightDragHandle");
1041   if (handle) {
1042     handle.addInterface(SOGoDragHandlesInterface);
1043     handle.upperBlock=$("mailboxContent");
1044     handle.lowerBlock=$("messageContent");
1045   }
1046 }
1047
1048 /* dnd */
1049 function initDnd() {
1050   //   log("MailerUI initDnd");
1051
1052   var tree = $("mailboxTree");
1053   if (tree) {
1054     var images = tree.getElementsByTagName("img");
1055     for (var i = 0; i < images.length; i++) {
1056       if (images[i].id[0] == 'j') {
1057         images[i].dndAcceptType = mailboxSpanAcceptType;
1058         images[i].dndEnter = plusSignEnter;
1059         images[i].dndExit = plusSignExit;
1060         document.DNDManager.registerDestination(images[i]);
1061       }
1062     }
1063     var nodes = document.getElementsByClassName("nodeName", tree);
1064     for (var i = 0; i < nodes.length; i++) {
1065       nodes[i].dndAcceptType = mailboxSpanAcceptType;
1066       nodes[i].dndEnter = mailboxSpanEnter;
1067       nodes[i].dndExit = mailboxSpanExit;
1068       nodes[i].dndDrop = mailboxSpanDrop;
1069       document.DNDManager.registerDestination(nodes[i]);
1070     }
1071   }
1072 }
1073
1074 /* stub */
1075
1076 function refreshContacts() {
1077 }
1078
1079 function openInbox(node) {
1080   var done = false;
1081   openMailbox(node.parentNode.getAttribute("dataname"));
1082   var tree = $("mailboxTree");
1083   tree.selectedEntry = node;
1084   node.select();
1085   mailboxTree.o(1);
1086 }
1087
1088 function initMailer(event) {
1089   if (!document.body.hasClassName("popup")) {
1090     configureMessageListEvents();
1091     initDnd();
1092     currentMailbox = "/" + accounts[0] + "/folderINBOX";
1093     initMailboxTree();
1094   }
1095 }
1096
1097 function initMailboxTree() {
1098   mailboxTree = new dTree("mailboxTree");
1099   mailboxTree.config.folderLinks = true;
1100   mailboxTree.config.hideRoot = true;
1101
1102   mailboxTree.icon.root = ResourcesURL + "/tbtv_account_17x17.gif";
1103   mailboxTree.icon.folder = ResourcesURL + "/tbtv_leaf_corner_17x17.gif";
1104   mailboxTree.icon.folderOpen   = ResourcesURL + "/tbtv_leaf_corner_17x17.gif";
1105   mailboxTree.icon.node = ResourcesURL + "/tbtv_leaf_corner_17x17.gif";
1106   mailboxTree.icon.line = ResourcesURL + "/tbtv_line_17x17.gif";
1107   mailboxTree.icon.join = ResourcesURL + "/tbtv_junction_17x17.gif";
1108   mailboxTree.icon.joinBottom   = ResourcesURL + "/tbtv_corner_17x17.gif";
1109   mailboxTree.icon.plus = ResourcesURL + "/tbtv_plus_17x17.gif";
1110   mailboxTree.icon.plusBottom   = ResourcesURL + "/tbtv_corner_plus_17x17.gif";
1111   mailboxTree.icon.minus = ResourcesURL + "/tbtv_minus_17x17.gif";
1112   mailboxTree.icon.minusBottom = ResourcesURL + "/tbtv_corner_minus_17x17.gif";
1113   mailboxTree.icon.nlPlus = ResourcesURL + "/tbtv_corner_plus_17x17.gif";
1114   mailboxTree.icon.nlMinus = ResourcesURL + "/tbtv_corner_minus_17x17.gif";
1115   mailboxTree.icon.empty = ResourcesURL + "/empty.gif";
1116
1117   mailboxTree.add(0, -1, '');
1118
1119   mailboxTree.pendingRequests = mailAccounts.length;
1120   for (var i = 0; i < mailAccounts.length; i++) {
1121     var url = ApplicationBaseURL + "/" + mailAccounts[i] + "/mailboxes";
1122     triggerAjaxRequest(url, onLoadMailboxesCallback, mailAccounts[i]);
1123   }
1124 }
1125
1126 function updateMailboxTreeInPage() {
1127   $("folderTreeContent").innerHTML = mailboxTree;
1128
1129   var inboxFound = false;
1130   var tree = $("mailboxTree");
1131   var nodes = document.getElementsByClassName("node", tree);
1132   for (i = 0; i < nodes.length; i++) {
1133     Event.observe(nodes[i], "click", onMailboxTreeItemClick.bindAsEventListener(nodes[i]));
1134     Event.observe(nodes[i], "contextmenu", onFolderMenuClick.bindAsEventListener(nodes[i]));
1135     if (!inboxFound
1136         && nodes[i].parentNode.getAttribute("datatype") == "inbox") {
1137       openInbox(nodes[i]);
1138       inboxFound = true;
1139     }
1140   }
1141 }
1142
1143 function mailboxMenuNode(type, name) {
1144   var newNode = document.createElement("li");
1145   var icon = MailerUIdTreeExtension.folderIcons[type];
1146   if (!icon)
1147     icon = "tbtv_leaf_corner_17x17.gif";
1148   var image = document.createElement("img");
1149   image.src = ResourcesURL + "/" + icon;
1150   newNode.appendChild(image);
1151   newNode.appendChild(document.createTextNode(" " + name));
1152
1153   return newNode;
1154 }
1155
1156 function generateMenuForMailbox(mailbox, prefix, callback) {
1157   var menuDIV = document.createElement("div");
1158   $(menuDIV).addClassName("menu");
1159   menuDIV.setAttribute("id", prefix + "Submenu");
1160   var menu = document.createElement("ul");
1161   menuDIV.appendChild(menu);
1162
1163   var callbacks = new Array();
1164   if (mailbox.type != "account") {
1165     var newNode = document.createElement("li");
1166     newNode.mailbox = mailbox;
1167     newNode.appendChild(document.createTextNode("coucou"));
1168     menu.appendChild(newNode);
1169     menu.appendChild(document.createElement("li"));
1170     callbacks.push(callback);
1171     callbacks.push("-");
1172   }
1173
1174   var submenuCount = 0;
1175   for (var i = 0; i < mailbox.children.length; i++) {
1176     var child = mailbox.children[i];
1177     var newNode = mailboxMenuNode(child.type, child.name);
1178     menu.appendChild(newNode);
1179     if (child.children.length > 0) {
1180       var newPrefix = prefix + submenuCount;
1181       var newSubmenu = generateMenuForMailbox(child,
1182                                               newPrefix,
1183                                               callback);
1184       document.body.appendChild(newSubmenu);
1185       callbacks.push(newPrefix + "Submenu");
1186       submenuCount++;
1187     }
1188     else {
1189       newNode.mailbox = child;
1190       callbacks.push(callback);
1191     }
1192   }
1193   initMenu(menuDIV, callbacks);
1194
1195   return menuDIV;
1196 }
1197
1198 function updateMailboxMenus() {
1199   var mailboxActions = { move: onMailboxMenuMove,
1200                          copy: onMailboxMenuCopy };
1201
1202   for (key in mailboxActions) {
1203     var menuId = key + "MailboxMenu";
1204     var menuDIV = $(menuId);
1205     if (menuDIV)
1206       menuDIV.parentNode.removeChild(menuDIV);
1207
1208     menuDIV = document.createElement("div");
1209     document.body.appendChild(menuDIV);
1210
1211     var menu = document.createElement("ul");
1212     menuDIV.appendChild(menu);
1213
1214     $(menuDIV).addClassName("menu");
1215     menuDIV.setAttribute("id", menuId);
1216       
1217     var submenuIds = new Array();
1218     for (var i = 0; i < mailAccounts.length; i++) {
1219       var menuEntry = mailboxMenuNode("account", mailAccounts[i]);
1220       menu.appendChild(menuEntry);
1221       var mailbox = accounts[mailAccounts[i]];
1222       var newSubmenu = generateMenuForMailbox(mailbox,
1223                                               key, mailboxActions[key]);
1224       document.body.appendChild(newSubmenu);
1225       submenuIds.push(newSubmenu.getAttribute("id"));
1226     }
1227     initMenu(menuDIV, submenuIds);
1228   }
1229 }
1230
1231 function onLoadMailboxesCallback(http) {
1232   if (http.readyState == 4
1233       && http.status == 200) {
1234     var newAccount = buildMailboxes(http.callbackData,
1235                                     http.responseText);
1236     accounts[http.callbackData] = newAccount;
1237     mailboxTree.addMailAccount(newAccount);
1238     mailboxTree.pendingRequests--;
1239     if (!mailboxTree.pendingRequests) {
1240       updateMailboxTreeInPage();
1241       updateMailboxMenus();
1242     }
1243   }
1244
1245   //       var tree = $("mailboxTree");
1246   //       var treeNodes = document.getElementsByClassName("dTreeNode", tree);
1247   //       var i = 0;
1248   //       while (i < treeNodes.length
1249   //         && treeNodes[i].getAttribute("dataname") != currentMailbox)
1250   //     i++;
1251   //       if (i < treeNodes.length) {
1252   //     //     log("found mailbox");
1253   //     var links = document.getElementsByClassName("node", treeNodes[i]);
1254   //     if (tree.selectedEntry)
1255   //        tree.selectedEntry.deselect();
1256   //     links[0].select();
1257   //     tree.selectedEntry = links[0];
1258   //     expandUpperTree(links[0]);
1259   //       }
1260 }
1261
1262 function buildMailboxes(accountName, encoded) {
1263   var account = new Mailbox("account", accountName);
1264   var data = encoded.evalJSON(true);
1265   for (var i = 0; i < data.length; i++) {
1266     var currentNode = account;
1267     var names = data[i].path.split("/");
1268     for (var j = 1; j < (names.length - 1); j++) {
1269       var node = currentNode.findMailboxByName(names[j]);
1270       if (!node) {
1271         node = new Mailbox("additional", names[j]);
1272         currentNode.addMailbox(node);
1273       }
1274       currentNode = node;
1275     }
1276     var basename = names[names.length-1];
1277     var leaf = currentNode.findMailboxByName(basename);
1278     if (leaf)
1279       leaf.type = data[i].type;
1280     else {
1281       leaf = new Mailbox(data[i].type, basename);
1282       currentNode.addMailbox(leaf);
1283     }
1284   }
1285
1286   return account;
1287 }
1288
1289 function onMenuCreateFolder(event) {
1290   var name = window.prompt(labels["Name :"].decodeEntities(), "");
1291   if (name && name.length > 0) {
1292     var folderID = document.menuTarget.getAttribute("dataname");
1293     var urlstr = URLForFolderID(folderID) + "/createFolder?name=" + name;
1294     triggerAjaxRequest(urlstr, folderOperationCallback);
1295   }
1296 }
1297
1298 function onMenuRenameFolder(event) {
1299   var name = window.prompt(labels["Enter the new name of your folder :"]
1300                            .decodeEntities(),
1301                            "");
1302   if (name && name.length > 0) {
1303     var folderID = document.menuTarget.getAttribute("dataname");
1304     var urlstr = URLForFolderID(folderID) + "/renameFolder?name=" + name;
1305     triggerAjaxRequest(urlstr, folderOperationCallback);
1306   }
1307 }
1308
1309 function onMenuDeleteFolder(event) {
1310   var answer = window.confirm(labels["Do you really want to move this folder into the trash ?"].decodeEntities());
1311   if (answer) {
1312     var folderID = document.menuTarget.getAttribute("dataname");
1313     var urlstr = URLForFolderID(folderID) + "/deleteFolder";
1314     triggerAjaxRequest(urlstr, folderOperationCallback);
1315   }
1316 }
1317
1318 function onMenuExpungeFolder(event) {
1319   var folderID = document.menuTarget.getAttribute("dataname");
1320   var urlstr = URLForFolderID(folderID) + "/expunge";
1321
1322   triggerAjaxRequest(urlstr, folderRefreshCallback, folderID);
1323 }
1324
1325 function onMenuEmptyTrash(event) {
1326   var folderID = document.menuTarget.getAttribute("dataname");
1327   var urlstr = URLForFolderID(folderID) + "/emptyTrash";
1328
1329   triggerAjaxRequest(urlstr, folderRefreshCallback, folderID);
1330 }
1331
1332 function folderOperationCallback(http) {
1333   if (http.readyState == 4
1334       && http.status == 204)
1335     initMailboxTree();
1336   else
1337     window.alert(labels["Operation failed"].decodeEntities());
1338 }
1339
1340 function folderRefreshCallback(http) {
1341   if (http.readyState == 4
1342       && http.status == 204) {
1343     var oldMailbox = http.callbackData;
1344     if (oldMailbox == currentMailbox)
1345       refreshCurrentFolder();
1346   }
1347   else
1348     window.alert(labels["Operation failed"].decodeEntities());
1349 }
1350
1351 function getMenus() {
1352   var menus = {}
1353   menus["accountIconMenu"] = new Array(null, null, onMenuCreateFolder, null,
1354                                        null, null);
1355   menus["inboxIconMenu"] = new Array(null, null, null, "-", null,
1356                                      onMenuCreateFolder, onMenuExpungeFolder,
1357                                      "-", null,
1358                                      onMenuSharing);
1359   menus["trashIconMenu"] = new Array(null, null, null, "-", null,
1360                                      onMenuCreateFolder, onMenuExpungeFolder,
1361                                      onMenuEmptyTrash, "-", null,
1362                                      onMenuSharing);
1363   menus["mailboxIconMenu"] = new Array(null, null, null, "-", null,
1364                                        onMenuCreateFolder,
1365                                        onMenuRenameFolder,
1366                                        onMenuExpungeFolder,
1367                                        onMenuDeleteFolder, "-", null,
1368                                        onMenuSharing);
1369   menus["addressMenu"] = new Array(newContactFromEmail, newEmailTo, null);
1370   menus["messageListMenu"] = new Array(onMenuOpenMessage, "-",
1371                                        onMenuReplyToSender,
1372                                        onMenuReplyToAll,
1373                                        onMenuForwardMessage, null,
1374                                        "-", "moveMailboxMenu",
1375                                        "copyMailboxMenu", "label-menu",
1376                                        "mark-menu", "-", null,
1377                                        onMenuViewMessageSource, null,
1378                                        null, onMenuDeleteMessage);
1379   menus["messageContentMenu"] = new Array(onMenuReplyToSender,
1380                                           onMenuReplyToAll,
1381                                           onMenuForwardMessage,
1382                                           null, "moveMailboxMenu",
1383                                           "copyMailboxMenu",
1384                                           "-", "label-menu", "mark-menu",
1385                                           "-",
1386                                           null, onMenuViewMessageSource,
1387                                           null, onPrintCurrentMessage,
1388                                           onMenuDeleteMessage);
1389   menus["label-menu"] = new Array(null, "-", null , null, null, null , null,
1390                                   null);
1391   menus["mark-menu"] = new Array(null, null, null, null, "-", null, "-",
1392                                  null, null, null);
1393   menus["searchMenu"] = new Array(setSearchCriteria, setSearchCriteria,
1394                                   setSearchCriteria, setSearchCriteria,
1395                                   setSearchCriteria);
1396
1397   return menus;
1398 }
1399
1400 addEvent(window, 'load', initMailer);
1401
1402 function Mailbox(type, name) {
1403   this.type = type;
1404   this.name = name;
1405   this.parentFolder = null;
1406   this.children = new Array();
1407   return this;
1408 }
1409
1410 Mailbox.prototype.dump = function(indent) {
1411   if (!indent)
1412     indent = 0;
1413   log(" ".repeat(indent) + this.name);
1414   for (var i = 0; i < this.children.length; i++) {
1415     this.children[i].dump(indent + 2);
1416   }
1417 }
1418
1419 Mailbox.prototype.findMailboxByName = function(name) {
1420   var mailbox = null;
1421
1422   var i = 0;
1423   while (!mailbox && i < this.children.length)
1424     if (this.children[i].name == name)
1425       mailbox = this.children[i];
1426     else
1427       i++;
1428
1429   return mailbox;
1430 }
1431
1432 Mailbox.prototype.addMailbox = function(mailbox) {
1433   mailbox.parentFolder = this;
1434   this.children.push(mailbox);
1435 }