]> err.no Git - scalable-opengroupware.org/blob - UI/WebServerResources/MailerUI.js
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1147 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("GET", 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     if (currentMessages[mailbox]) {
409       loadMessage(currentMessages[mailbox]);
410       url += '&pageforuid=' + currentMessages[mailbox];
411     }
412
413     var searchValue = search["value"];
414     if (searchValue && searchValue.length > 0)
415       url += ("&search=" + search["criteria"]
416               + "&value=" + escape(searchValue));
417     var sortAttribute = sorting["attribute"];
418     if (sortAttribute && sortAttribute.length > 0)
419       url += ("&sort=" + sorting["attribute"]
420               + "&asc=" + sorting["ascending"]);
421     if (idx)
422       url += "&idx=" + idx;
423
424     if (document.messageListAjaxRequest) {
425       document.messageListAjaxRequest.aborted = true;
426       document.messageListAjaxRequest.abort();
427     }
428
429     var mailboxContent = $("mailboxContent");
430     if (mailboxContent.getStyle('visibility') == "hidden") {
431       mailboxContent.setStyle({ visibility: "visible" });
432       var rightDragHandle = $("rightDragHandle");
433       rightDragHandle.setStyle({ visibility: "visible" });
434       messageContent.setStyle({ top: (rightDragHandle.offsetTop
435                                       + rightDragHandle.offsetHeight
436                                       + 'px') });
437     }
438
439     document.messageListAjaxRequest
440       = triggerAjaxRequest(url, messageListCallback,
441                            currentMessages[mailbox]);
442
443     var quotasUrl = ApplicationBaseURL + mailbox + "/quotas";
444     document.quotasAjaxRequest
445       = triggerAjaxRequest(quotasUrl, quotasCallback);
446   }
447 }
448
449 function openMailboxAtIndex(event) {
450   openMailbox(currentMailbox, true, this.getAttribute("idx"));
451
452   preventDefault(event);
453 }
454
455 function messageListCallback(http) {
456   var div = $('mailboxContent');
457    
458   if (http.readyState == 4
459       && http.status == 200) {
460     document.messageListAjaxRequest = null;
461     div.innerHTML = http.responseText;
462     var selected = http.callbackData;
463     if (selected) {
464       var row = $("row_" + selected);
465       if (row)
466         row.select();
467     }
468     configureMessageListEvents();
469     if (sorting["attribute"] && sorting["attribute"].length > 0) {
470       var sortHeader;
471       if (sorting["attribute"] == "subject")
472         sortHeader = $("subjectHeader");
473       else if (sorting["attribute"] == "from")
474         sortHeader = $("fromHeader");
475       else if (sorting["attribute"] == "date")
476         sortHeader = $("dateHeader");
477       else
478         sortHeader = null;
479
480       if (sortHeader) {
481         var sortImage = createElement("img", "messageSortImage", "sortImage");
482         sortHeader.insertBefore(sortImage, sortHeader.firstChild);
483         if (sorting["ascending"])
484           sortImage.src = ResourcesURL + "/title_sortdown_12x12.png";
485         else
486           sortImage.src = ResourcesURL + "/title_sortup_12x12.png";
487       }
488     }
489   }
490   else
491     log("messageListCallback: problem during ajax request (readyState = " + http.readyState + ", status = " + http.status + ")");
492 }
493
494 function quotasCallback(http) {
495   if (http.readyState == 4
496       && http.status == 200) {
497     var hasQuotas = false;
498
499     var quotas = http.responseText.evalJSON(true);
500     for (var i in quotas) {
501       hasQuotas = true;
502       break;
503     }
504
505     if (hasQuotas) {
506       var treePath = currentMailbox.split("/");
507       var mbQuotas = quotas["/" + treePath[2]];
508       var used = mbQuotas["usedSpace"];
509       var max = mbQuotas["maxQuota"];
510       var percents = (Math.round(used * 10000 / max) / 100);
511       var format = labels["quotasFormat"].decodeEntities();
512       var text = format.formatted(used, max, percents);
513       window.status = text;
514     }
515   }
516 }
517
518 function onMessageContextMenu(event) {
519   var menu = $('messageListMenu');
520   Event.observe(menu, "hideMenu", onMessageContextMenuHide);
521   popupMenu(event, "messageListMenu", this);
522
523   var topNode = $('messageList');
524   var selectedNodes = topNode.getSelectedRows();
525   for (var i = 0; i < selectedNodes.length; i++)
526     selectedNodes[i].deselect();
527   topNode.menuSelectedRows = selectedNodes;
528   topNode.menuSelectedEntry = this;
529   this.select();
530 }
531
532 function onMessageContextMenuHide(event) {
533   var topNode = $('messageList');
534
535   if (topNode.menuSelectedEntry) {
536     topNode.menuSelectedEntry.deselect();
537     topNode.menuSelectedEntry = null;
538   }
539   if (topNode.menuSelectedRows) {
540     var nodes = topNode.menuSelectedRows;
541     for (var i = 0; i < nodes.length; i++)
542       nodes[i].select();
543     topNode.menuSelectedRows = null;
544   }
545 }
546
547 function onFolderMenuClick(event) {
548   var onhide, menuName;
549    
550   var menutype = this.parentNode.getAttribute("datatype");
551   if (menutype) {
552     if (menutype == "inbox") {
553       menuName = "inboxIconMenu";
554     } else if (menutype == "account") {
555       menuName = "accountIconMenu";
556     } else if (menutype == "trash") {
557       menuName = "trashIconMenu";
558     } else {
559       menuName = "mailboxIconMenu";
560     }
561   } else {
562     menuName = "mailboxIconMenu";
563   }
564
565   var menu = $(menuName);
566   Event.observe(menu, "hideMenu", onFolderMenuHide);
567   popupMenu(event, menuName, this.parentNode);
568
569   var topNode = $("mailboxTree");
570   if (topNode.selectedEntry)
571     topNode.selectedEntry.deselect();
572   if (topNode.menuSelectedEntry)
573     topNode.menuSelectedEntry.deselect();
574   topNode.menuSelectedEntry = this;
575   this.select();
576
577   preventDefault(event);
578 }
579
580 function onFolderMenuHide(event) {
581   var topNode = $("mailboxTree");
582
583   if (topNode.menuSelectedEntry) {
584     topNode.menuSelectedEntry.deselect();
585     topNode.menuSelectedEntry = null;
586   }
587   if (topNode.selectedEntry)
588     topNode.selectedEntry.select();
589 }
590
591 function deleteCachedMessage(messageId) {
592   var done = false;
593   var counter = 0;
594
595   while (counter < cachedMessages.length
596          && !done)
597     if (cachedMessages[counter]
598         && cachedMessages[counter]['idx'] == messageId) {
599       cachedMessages.splice(counter, 1);
600       done = true;
601     }
602     else
603       counter++;
604 }
605
606 function getCachedMessage(idx) {
607   var message = null;
608   var counter = 0;
609
610   while (counter < cachedMessages.length
611          && message == null)
612     if (cachedMessages[counter]
613         && cachedMessages[counter]['idx'] == currentMailbox + '/' + idx)
614       message = cachedMessages[counter];
615     else
616       counter++;
617
618   return message;
619 }
620
621 function storeCachedMessage(cachedMessage) {
622   var oldest = -1;
623   var timeOldest = -1;
624   var counter = 0;
625
626   if (cachedMessages.length < maxCachedMessages)
627     oldest = cachedMessages.length;
628   else {
629     while (cachedMessages[counter]) {
630       if (oldest == -1
631           || cachedMessages[counter]['time'] < timeOldest) {
632         oldest = counter;
633         timeOldest = cachedMessages[counter]['time'];
634       }
635       counter++;
636     }
637
638     if (oldest == -1)
639       oldest = 0;
640   }
641
642   cachedMessages[oldest] = cachedMessage;
643 }
644
645 function onMessageSelectionChange() {
646   var rows = this.getSelectedRowsId();
647
648   if (rows.length == 1) {
649     var idx = rows[0].substr(4);
650
651     if (currentMessages[currentMailbox] != idx) {
652       currentMessages[currentMailbox] = idx;
653       loadMessage(idx);
654     }
655   }
656 }
657
658 function loadMessage(idx) {
659   if (document.messageAjaxRequest) {
660     document.messageAjaxRequest.aborted = true;
661     document.messageAjaxRequest.abort();
662   }
663
664   var cachedMessage = getCachedMessage(idx);
665
666   if (cachedMessage == null) {
667     var url = (ApplicationBaseURL + currentMailbox + "/"
668                + idx + "/view?noframe=1");
669     document.messageAjaxRequest
670       = triggerAjaxRequest(url, messageCallback, idx);
671     markMailInWindow(window, idx, true);
672   } else {
673     var div = $('messageContent');
674     div.innerHTML = cachedMessage['text'];
675     cachedMessage['time'] = (new Date()).getTime();
676     document.messageAjaxRequest = null;
677     configureLinksInMessage();
678   }
679 }
680
681 function configureLinksInMessage() {
682   var messageDiv = $('messageContent');
683   var mailContentDiv = document.getElementsByClassName('mailer_mailcontent',
684                                                        messageDiv)[0];
685   Event.observe(mailContentDiv, "contextmenu",
686                 onMessageContentMenu.bindAsEventListener(mailContentDiv));
687   var anchors = messageDiv.getElementsByTagName('a');
688   for (var i = 0; i < anchors.length; i++)
689     if (anchors[i].href.substring(0,7) == "mailto:") {
690       Event.observe(anchors[i], "click",
691                     onEmailAddressClick.bindAsEventListener(anchors[i]));
692       Event.observe(anchors[i], "contextmenu",
693                     onEmailAddressClick.bindAsEventListener(anchors[i]));
694     }
695     else
696       Event.observe(anchors[i], "click",
697                     onMessageAnchorClick);
698
699   var editDraftButton = $("editDraftButton");
700   if (editDraftButton)
701     Event.observe(editDraftButton, "click", onMessageEditDraft);
702 }
703
704 function onMessageContentMenu(event) {
705   popupMenu(event, 'messageContentMenu', this);
706 }
707
708 function onMessageEditDraft(event) {
709   return openMessageWindowsForSelection("edit", true);
710 }
711
712 function onEmailAddressClick(event) {
713   popupMenu(event, 'addressMenu', this);
714 }
715
716 function onMessageAnchorClick (event) {
717   window.open(this.href);
718   preventDefault(event);
719 }
720
721 function messageCallback(http) {
722   var div = $('messageContent');
723
724   if (http.readyState == 4
725       && http.status == 200) {
726     document.messageAjaxRequest = null;
727     div.innerHTML = http.responseText;
728     configureLinksInMessage();
729       
730     if (http.callbackData) {
731       var cachedMessage = new Array();
732       cachedMessage['idx'] = currentMailbox + '/' + http.callbackData;
733       cachedMessage['time'] = (new Date()).getTime();
734       cachedMessage['text'] = http.responseText;
735       if (cachedMessage['text'].length < 30000)
736         storeCachedMessage(cachedMessage);
737     }
738   }
739   else
740     log("messageCallback: problem during ajax request: " + http.status);
741 }
742
743 function processMailboxMenuAction(mailbox) {
744   var currentNode, upperNode;
745   var mailboxName;
746   var action;
747
748   mailboxName = mailbox.getAttribute('mailboxname');
749   currentNode = mailbox;
750   upperNode = null;
751
752   while (currentNode
753          && !currentNode.hasAttribute('mailboxaction'))
754     currentNode = currentNode.parentNode.parentNode.parentMenuItem;
755
756   if (currentNode)
757     {
758       action = currentNode.getAttribute('mailboxaction');
759       //       var rows  = collectSelectedRows();
760       //       var rString = rows.join(', ');
761       //       alert("performing '" + action + "' on " + rString
762       //             + " to " + mailboxName);
763     }
764 }
765
766 var rowSelectionCount = 0;
767
768 validateControls();
769
770 function showElement(e, shouldShow) {
771   e.style.display = shouldShow ? "" : "none";
772 }
773
774 function enableElement(e, shouldEnable) {
775   if(!e)
776     return;
777   if(shouldEnable) {
778     if(e.hasAttribute("disabled"))
779       e.removeAttribute("disabled");
780   }
781   else {
782     e.setAttribute("disabled", "1");
783   }
784 }
785
786 function validateControls() {
787   var e = $("moveto");
788   this.enableElement(e, rowSelectionCount > 0);
789 }
790
791 function moveTo(uri) {
792   alert("MoveTo: " + uri);
793 }
794
795 function deleteSelectedMails() {
796 }
797
798 /* message menu entries */
799 function onMenuOpenMessage(event) {
800   return openMessageWindowsForSelection('popupview');
801 }
802
803 function onMenuReplyToSender(event) {
804   return openMessageWindowsForSelection('reply');
805 }
806
807 function onMenuReplyToAll(event) {
808   return openMessageWindowsForSelection('replyall');
809 }
810
811 function onMenuForwardMessage(event) {
812   return openMessageWindowsForSelection('forward');
813 }
814
815 function onMenuViewMessageSource(event) {
816   var messageList = $("messageList");
817   var rows = messageList.getSelectedRowsId();
818
819   if (rows.length > 0) {
820     var url = (ApplicationBaseURL + currentMailbox + "/"
821                + rows[0].substr(4) + "/viewsource");
822     window.open(url, "",
823                 "width=680,height=520,resizable=1,scrollbars=1,toolbar=0,"
824                 + "location=0,directories=0,status=0,menubar=0,copyhistory=0");
825   }
826
827   preventDefault(event);
828 }
829
830 /* contacts */
831 function newContactFromEmail(event) {
832   var mailto = document.menuTarget.innerHTML;
833
834   var email = extractEmailAddress(mailto);
835   var c_name = extractEmailName(mailto);
836   if (email.length > 0)
837     {
838       var url = UserFolderURL + "Contacts/new?contactEmail=" + email;
839       if (c_name)
840         url += "&contactFN=" + c_name;
841       w = window.open(url, null,
842                       "width=546,height=490,resizable=1,scrollbars=1,toolbar=0,"
843                       + "location=0,directories=0,status=0,menubar=0,copyhistory=0");
844       w.focus();
845     }
846
847   return false; /* stop following the link */
848 }
849
850 function newEmailTo(sender) {
851   return openMailTo(document.menuTarget.innerHTML);
852 }
853
854 function expandUpperTree(node) {
855   var currentNode = node.parentNode;
856
857   while (currentNode.className != "dtree") {
858     if (currentNode.className == 'clip') {
859       var id = currentNode.getAttribute("id");
860       var number = parseInt(id.substr(2));
861       if (number > 0) {
862         var cn = mailboxTree.aNodes[number];
863         mailboxTree.nodeStatus(1, number, cn._ls);
864       }
865     }
866     currentNode = currentNode.parentNode;
867   }
868 }
869
870 function onHeaderClick(event) {
871   var headerId = this.getAttribute("id");
872   var newSortAttribute;
873   if (headerId == "subjectHeader")
874     newSortAttribute = "subject";
875   else if (headerId == "fromHeader")
876     newSortAttribute = "from";
877   else if (headerId == "dateHeader")
878     newSortAttribute = "date";
879   else
880     newSortAttribute = "arrival";
881
882   if (sorting["attribute"] == newSortAttribute)
883     sorting["ascending"] = !sorting["ascending"];
884   else {
885     sorting["attribute"] = newSortAttribute;
886     sorting["ascending"] = true;
887   }
888
889   refreshCurrentFolder();
890
891   preventDefault(event);
892 }
893
894 function refreshCurrentFolder() {
895   openMailbox(currentMailbox, true);
896 }
897
898 function pouetpouet(event) {
899   window.alert("pouet pouet");
900 }
901
902 var mailboxSpanAcceptType = function(type) {
903   return (type == "mailRow");
904 }
905
906 var mailboxSpanEnter = function() {
907   this.addClassName("_dragOver");
908 }
909
910 var mailboxSpanExit = function() {
911   this.removeClassName("_dragOver");
912 }
913
914 var mailboxSpanDrop = function(data) {
915   var success = false;
916
917   if (data) {
918     var folder = this.parentNode.parentNode.getAttribute("dataname");
919     if (folder != currentMailbox)
920       success = (moveMessages(data, folder) == 0);
921   }
922   else
923     success = false;
924   
925   return success;
926 }
927     
928 var plusSignEnter = function() {
929   var nodeNr = parseInt(this.id.substr(2));
930   if (!mailboxTree.aNodes[nodeNr]._io)
931     this.plusSignTimer = setTimeout("openPlusSign('" + nodeNr + "');", 1000);
932 }
933       
934 var plusSignExit = function() {
935   if (this.plusSignTimer) {
936     clearTimeout(this.plusSignTimer);
937     this.plusSignTimer = null;
938   }
939 }
940         
941 function openPlusSign(nodeNr) {
942   mailboxTree.nodeStatus(1, nodeNr, mailboxTree.aNodes[nodeNr]._ls);
943   mailboxTree.aNodes[nodeNr]._io = 1;
944   this.plusSignTimer = null;
945 }
946
947 var messageListGhost = function () {
948   var newDiv = document.createElement("div");
949   //   newDiv.style.width = "25px;";
950   //   newDiv.style.height = "25px;";
951   newDiv.style.backgroundColor = "#aae;";
952   newDiv.style.border = "2px solid #a3a;";
953   newDiv.style.padding = "5px;";
954   newDiv.ghostOffsetX = 10;
955   newDiv.ghostOffsetY = 5;
956
957   var newImg = document.createElement("img");
958   newImg.src = ResourcesURL + "/message-mail.png";
959
960   var list = $("messageList");
961   var count = list.getSelectedRows().length;
962   newDiv.appendChild(newImg);
963   newDiv.appendChild(document.createElement("br"));
964   newDiv.appendChild(document.createTextNode(count + " messages..."));
965
966   return newDiv;
967 }
968
969 var messageListData = function(type) {
970   var rows = this.parentNode.parentNode.getSelectedRowsId();
971   var msgIds = new Array();
972   for (var i = 0; i < rows.length; i++)
973     msgIds.push(rows[i].substr(4));
974
975   return msgIds;
976 }
977
978 /* a model for a futur refactoring of the sortable table headers mechanism */
979
980 function configureMessageListHeaders(cells) {
981   for (var i = 0; i < cells.length; i++) {
982     var currentCell = $(cells[i]);
983     Event.observe(currentCell, "click",
984                   onHeaderClick.bindAsEventListener(currentCell));
985     Event.observe(currentCell, "mousedown", listRowMouseDownHandler);
986   }
987 }
988
989 function configureMessageListEvents() {
990   var messageList = $("messageList");
991   if (messageList) {
992     Event.observe(messageList, "mousedown",
993                   onMessageSelectionChange.bindAsEventListener(messageList));
994
995     configureMessageListHeaders(messageList.tHead.rows[0].cells);
996     var cell = messageList.tHead.rows[1].cells[0];
997     if ($(cell).hasClassName("tbtv_navcell")) {
998       var anchors = $(cell).childNodesWithTag("a");
999       for (var i = 0; i < anchors.length; i++)
1000         Event.observe(anchors[i], "click", openMailboxAtIndex.bindAsEventListener(anchors[i]));
1001     }
1002
1003     rows = messageList.tBodies[0].rows;
1004     for (var i = 0; i < rows.length; i++) {
1005       Event.observe(rows[i], "mousedown", onRowClick);
1006       Event.observe(rows[i], "contextmenu", onMessageContextMenu.bindAsEventListener(rows[i]));
1007          
1008       rows[i].dndTypes = function() { return new Array("mailRow"); };
1009       rows[i].dndGhost = messageListGhost;
1010       rows[i].dndDataForType = messageListData;
1011       document.DNDManager.registerSource(rows[i]);
1012
1013       for (var j = 0; j < rows[i].cells.length; j++) {
1014         var cell = rows[i].cells[j];
1015         Event.observe(cell, "mousedown", listRowMouseDownHandler);
1016         if (j == 2 || j == 3 || j == 5)
1017           Event.observe(cell, "dblclick", onMessageDoubleClick.bindAsEventListener(cell));
1018         else if (j == 4) {
1019           var img = cell.childNodesWithTag("img")[0];
1020           Event.observe(img, "click", mailListMarkMessage);
1021         }
1022       }
1023     }
1024   }
1025 }
1026
1027 function configureDragHandles() {
1028   var handle = $("verticalDragHandle");
1029   if (handle) {
1030     handle.addInterface(SOGoDragHandlesInterface);
1031     handle.leftMargin = 1;
1032     handle.leftBlock=$("leftPanel");
1033     handle.rightBlock=$("rightPanel");
1034   }
1035
1036   handle = $("rightDragHandle");
1037   if (handle) {
1038     handle.addInterface(SOGoDragHandlesInterface);
1039     handle.upperBlock=$("mailboxContent");
1040     handle.lowerBlock=$("messageContent");
1041   }
1042 }
1043
1044 /* dnd */
1045 function initDnd() {
1046   //   log("MailerUI initDnd");
1047
1048   var tree = $("mailboxTree");
1049   if (tree) {
1050     var images = tree.getElementsByTagName("img");
1051     for (var i = 0; i < images.length; i++) {
1052       if (images[i].id[0] == 'j') {
1053         images[i].dndAcceptType = mailboxSpanAcceptType;
1054         images[i].dndEnter = plusSignEnter;
1055         images[i].dndExit = plusSignExit;
1056         document.DNDManager.registerDestination(images[i]);
1057       }
1058     }
1059     var nodes = document.getElementsByClassName("nodeName", tree);
1060     for (var i = 0; i < nodes.length; i++) {
1061       nodes[i].dndAcceptType = mailboxSpanAcceptType;
1062       nodes[i].dndEnter = mailboxSpanEnter;
1063       nodes[i].dndExit = mailboxSpanExit;
1064       nodes[i].dndDrop = mailboxSpanDrop;
1065       document.DNDManager.registerDestination(nodes[i]);
1066     }
1067   }
1068 }
1069
1070 /* stub */
1071
1072 function refreshContacts() {
1073 }
1074
1075 function openInbox(node) {
1076   var done = false;
1077   openMailbox(node.parentNode.getAttribute("dataname"));
1078   var tree = $("mailboxTree");
1079   tree.selectedEntry = node;
1080   node.select();
1081   mailboxTree.o(1);
1082 }
1083
1084 function initMailer(event) {
1085   if (!document.body.hasClassName("popup")) {
1086     configureMessageListEvents();
1087     initDnd();
1088     currentMailbox = "/" + accounts[0] + "/folderINBOX";
1089     initMailboxTree();
1090   }
1091 }
1092
1093 function initMailboxTree() {
1094   mailboxTree = new dTree("mailboxTree");
1095   mailboxTree.config.folderLinks = true;
1096   mailboxTree.config.hideRoot = true;
1097
1098   mailboxTree.icon.root = ResourcesURL + "/tbtv_account_17x17.gif";
1099   mailboxTree.icon.folder = ResourcesURL + "/tbtv_leaf_corner_17x17.gif";
1100   mailboxTree.icon.folderOpen   = ResourcesURL + "/tbtv_leaf_corner_17x17.gif";
1101   mailboxTree.icon.node = ResourcesURL + "/tbtv_leaf_corner_17x17.gif";
1102   mailboxTree.icon.line = ResourcesURL + "/tbtv_line_17x17.gif";
1103   mailboxTree.icon.join = ResourcesURL + "/tbtv_junction_17x17.gif";
1104   mailboxTree.icon.joinBottom   = ResourcesURL + "/tbtv_corner_17x17.gif";
1105   mailboxTree.icon.plus = ResourcesURL + "/tbtv_plus_17x17.gif";
1106   mailboxTree.icon.plusBottom   = ResourcesURL + "/tbtv_corner_plus_17x17.gif";
1107   mailboxTree.icon.minus = ResourcesURL + "/tbtv_minus_17x17.gif";
1108   mailboxTree.icon.minusBottom = ResourcesURL + "/tbtv_corner_minus_17x17.gif";
1109   mailboxTree.icon.nlPlus = ResourcesURL + "/tbtv_corner_plus_17x17.gif";
1110   mailboxTree.icon.nlMinus = ResourcesURL + "/tbtv_corner_minus_17x17.gif";
1111   mailboxTree.icon.empty = ResourcesURL + "/empty.gif";
1112
1113   mailboxTree.add(0, -1, '');
1114
1115   mailboxTree.pendingRequests = mailAccounts.length;
1116   for (var i = 0; i < mailAccounts.length; i++) {
1117     var url = ApplicationBaseURL + "/" + mailAccounts[i] + "/mailboxes";
1118     triggerAjaxRequest(url, onLoadMailboxesCallback, mailAccounts[i]);
1119   }
1120 }
1121
1122 function updateMailboxTreeInPage() {
1123   $("folderTreeContent").innerHTML = mailboxTree;
1124
1125   var inboxFound = false;
1126   var tree = $("mailboxTree");
1127   var nodes = document.getElementsByClassName("node", tree);
1128   for (i = 0; i < nodes.length; i++) {
1129     Event.observe(nodes[i], "click", onMailboxTreeItemClick.bindAsEventListener(nodes[i]));
1130     Event.observe(nodes[i], "contextmenu", onFolderMenuClick.bindAsEventListener(nodes[i]));
1131     if (!inboxFound
1132         && nodes[i].parentNode.getAttribute("datatype") == "inbox") {
1133       openInbox(nodes[i]);
1134       inboxFound = true;
1135     }
1136   }
1137 }
1138
1139 function mailboxMenuNode(type, name) {
1140   var newNode = document.createElement("li");
1141   var icon = MailerUIdTreeExtension.folderIcons[type];
1142   if (!icon)
1143     icon = "tbtv_leaf_corner_17x17.gif";
1144   var image = document.createElement("img");
1145   image.src = ResourcesURL + "/" + icon;
1146   newNode.appendChild(image);
1147   newNode.appendChild(document.createTextNode(" " + name));
1148
1149   return newNode;
1150 }
1151
1152 function generateMenuForMailbox(mailbox, prefix, callback) {
1153   var menuDIV = document.createElement("div");
1154   $(menuDIV).addClassName("menu");
1155   menuDIV.setAttribute("id", prefix + "Submenu");
1156   var menu = document.createElement("ul");
1157   menuDIV.appendChild(menu);
1158
1159   var callbacks = new Array();
1160   if (mailbox.type != "account") {
1161     var newNode = document.createElement("li");
1162     newNode.mailbox = mailbox;
1163     newNode.appendChild(document.createTextNode("coucou"));
1164     menu.appendChild(newNode);
1165     menu.appendChild(document.createElement("li"));
1166     callbacks.push(callback);
1167     callbacks.push("-");
1168   }
1169
1170   var submenuCount = 0;
1171   for (var i = 0; i < mailbox.children.length; i++) {
1172     var child = mailbox.children[i];
1173     var newNode = mailboxMenuNode(child.type, child.name);
1174     menu.appendChild(newNode);
1175     if (child.children.length > 0) {
1176       var newPrefix = prefix + submenuCount;
1177       var newSubmenu = generateMenuForMailbox(child,
1178                                               newPrefix,
1179                                               callback);
1180       document.body.appendChild(newSubmenu);
1181       callbacks.push(newPrefix + "Submenu");
1182       submenuCount++;
1183     }
1184     else {
1185       newNode.mailbox = child;
1186       callbacks.push(callback);
1187     }
1188   }
1189   initMenu(menuDIV, callbacks);
1190
1191   return menuDIV;
1192 }
1193
1194 function updateMailboxMenus() {
1195   var mailboxActions = { move: onMailboxMenuMove,
1196                          copy: onMailboxMenuCopy };
1197
1198   for (key in mailboxActions) {
1199     var menuId = key + "MailboxMenu";
1200     var menuDIV = $(menuId);
1201     if (menuDIV)
1202       menuDIV.parentNode.removeChild(menuDIV);
1203
1204     menuDIV = document.createElement("div");
1205     document.body.appendChild(menuDIV);
1206
1207     var menu = document.createElement("ul");
1208     menuDIV.appendChild(menu);
1209
1210     $(menuDIV).addClassName("menu");
1211     menuDIV.setAttribute("id", menuId);
1212       
1213     var submenuIds = new Array();
1214     for (var i = 0; i < mailAccounts.length; i++) {
1215       var menuEntry = mailboxMenuNode("account", mailAccounts[i]);
1216       menu.appendChild(menuEntry);
1217       var mailbox = accounts[mailAccounts[i]];
1218       var newSubmenu = generateMenuForMailbox(mailbox,
1219                                               key, mailboxActions[key]);
1220       document.body.appendChild(newSubmenu);
1221       submenuIds.push(newSubmenu.getAttribute("id"));
1222     }
1223     initMenu(menuDIV, submenuIds);
1224   }
1225 }
1226
1227 function onLoadMailboxesCallback(http) {
1228   if (http.readyState == 4
1229       && http.status == 200) {
1230     var newAccount = buildMailboxes(http.callbackData,
1231                                     http.responseText);
1232     accounts[http.callbackData] = newAccount;
1233     mailboxTree.addMailAccount(newAccount);
1234     mailboxTree.pendingRequests--;
1235     if (!mailboxTree.pendingRequests) {
1236       updateMailboxTreeInPage();
1237       updateMailboxMenus();
1238     }
1239   }
1240
1241   //       var tree = $("mailboxTree");
1242   //       var treeNodes = document.getElementsByClassName("dTreeNode", tree);
1243   //       var i = 0;
1244   //       while (i < treeNodes.length
1245   //         && treeNodes[i].getAttribute("dataname") != currentMailbox)
1246   //     i++;
1247   //       if (i < treeNodes.length) {
1248   //     //     log("found mailbox");
1249   //     var links = document.getElementsByClassName("node", treeNodes[i]);
1250   //     if (tree.selectedEntry)
1251   //        tree.selectedEntry.deselect();
1252   //     links[0].select();
1253   //     tree.selectedEntry = links[0];
1254   //     expandUpperTree(links[0]);
1255   //       }
1256 }
1257
1258 function buildMailboxes(accountName, encoded) {
1259   var account = new Mailbox("account", accountName);
1260   var data = encoded.evalJSON(true);
1261   for (var i = 0; i < data.length; i++) {
1262     var currentNode = account;
1263     var names = data[i].path.split("/");
1264     for (var j = 1; j < (names.length - 1); j++) {
1265       var node = currentNode.findMailboxByName(names[j]);
1266       if (!node) {
1267         node = new Mailbox("additional", names[j]);
1268         currentNode.addMailbox(node);
1269       }
1270       currentNode = node;
1271     }
1272     var basename = names[names.length-1];
1273     var leaf = currentNode.findMailboxByName(basename);
1274     if (leaf)
1275       leaf.type = data[i].type;
1276     else {
1277       leaf = new Mailbox(data[i].type, basename);
1278       currentNode.addMailbox(leaf);
1279     }
1280   }
1281
1282   return account;
1283 }
1284
1285 function onMenuCreateFolder(event) {
1286   var name = window.prompt(labels["Name :"].decodeEntities(), "");
1287   if (name && name.length > 0) {
1288     var folderID = document.menuTarget.getAttribute("dataname");
1289     var urlstr = URLForFolderID(folderID) + "/createFolder?name=" + name;
1290     triggerAjaxRequest(urlstr, folderOperationCallback);
1291   }
1292 }
1293
1294 function onMenuRenameFolder(event) {
1295   var name = window.prompt(labels["Enter the new name of your folder :"]
1296                            .decodeEntities(),
1297                            "");
1298   if (name && name.length > 0) {
1299     var folderID = document.menuTarget.getAttribute("dataname");
1300     var urlstr = URLForFolderID(folderID) + "/renameFolder?name=" + name;
1301     triggerAjaxRequest(urlstr, folderOperationCallback);
1302   }
1303 }
1304
1305 function onMenuDeleteFolder(event) {
1306   var answer = window.confirm(labels["Do you really want to move this folder into the trash ?"].decodeEntities());
1307   if (answer) {
1308     var folderID = document.menuTarget.getAttribute("dataname");
1309     var urlstr = URLForFolderID(folderID) + "/deleteFolder";
1310     triggerAjaxRequest(urlstr, folderOperationCallback);
1311   }
1312 }
1313
1314 function onMenuExpungeFolder(event) {
1315   var folderID = document.menuTarget.getAttribute("dataname");
1316   var urlstr = URLForFolderID(folderID) + "/expunge";
1317
1318   triggerAjaxRequest(urlstr, folderRefreshCallback, folderID);
1319 }
1320
1321 function onMenuEmptyTrash(event) {
1322   var folderID = document.menuTarget.getAttribute("dataname");
1323   var urlstr = URLForFolderID(folderID) + "/emptyTrash";
1324
1325   triggerAjaxRequest(urlstr, folderRefreshCallback, folderID);
1326 }
1327
1328 function folderOperationCallback(http) {
1329   if (http.readyState == 4
1330       && http.status == 204)
1331     initMailboxTree();
1332   else
1333     window.alert(labels["Operation failed"].decodeEntities());
1334 }
1335
1336 function folderRefreshCallback(http) {
1337   if (http.readyState == 4
1338       && http.status == 204) {
1339     var oldMailbox = http.callbackData;
1340     if (oldMailbox == currentMailbox)
1341       refreshCurrentFolder();
1342   }
1343   else
1344     window.alert(labels["Operation failed"].decodeEntities());
1345 }
1346
1347 function getMenus() {
1348   var menus = {}
1349   menus["accountIconMenu"] = new Array(null, null, onMenuCreateFolder, null,
1350                                        null, null);
1351   menus["inboxIconMenu"] = new Array(null, null, null, "-", null,
1352                                      onMenuCreateFolder, onMenuExpungeFolder,
1353                                      "-", null,
1354                                      onMenuSharing);
1355   menus["trashIconMenu"] = new Array(null, null, null, "-", null,
1356                                      onMenuCreateFolder, onMenuExpungeFolder,
1357                                      onMenuEmptyTrash, "-", null,
1358                                      onMenuSharing);
1359   menus["mailboxIconMenu"] = new Array(null, null, null, "-", null,
1360                                        onMenuCreateFolder,
1361                                        onMenuRenameFolder,
1362                                        onMenuExpungeFolder,
1363                                        onMenuDeleteFolder, "-", null,
1364                                        onMenuSharing);
1365   menus["addressMenu"] = new Array(newContactFromEmail, newEmailTo, null);
1366   menus["messageListMenu"] = new Array(onMenuOpenMessage, "-",
1367                                        onMenuReplyToSender,
1368                                        onMenuReplyToAll,
1369                                        onMenuForwardMessage, null,
1370                                        "-", "moveMailboxMenu",
1371                                        "copyMailboxMenu", "label-menu",
1372                                        "mark-menu", "-", null,
1373                                        onMenuViewMessageSource, null,
1374                                        null, onMenuDeleteMessage);
1375   menus["messageContentMenu"] = new Array(onMenuReplyToSender,
1376                                           onMenuReplyToAll,
1377                                           onMenuForwardMessage,
1378                                           null, "moveMailboxMenu",
1379                                           "copyMailboxMenu",
1380                                           "-", "label-menu", "mark-menu",
1381                                           "-",
1382                                           null, onMenuViewMessageSource,
1383                                           null, onPrintCurrentMessage,
1384                                           onMenuDeleteMessage);
1385   menus["label-menu"] = new Array(null, "-", null , null, null, null , null,
1386                                   null);
1387   menus["mark-menu"] = new Array(null, null, null, null, "-", null, "-",
1388                                  null, null, null);
1389   menus["searchMenu"] = new Array(setSearchCriteria, setSearchCriteria,
1390                                   setSearchCriteria, setSearchCriteria,
1391                                   setSearchCriteria);
1392
1393   return menus;
1394 }
1395
1396 addEvent(window, 'load', initMailer);
1397
1398 function Mailbox(type, name) {
1399   this.type = type;
1400   this.name = name;
1401   this.parentFolder = null;
1402   this.children = new Array();
1403   return this;
1404 }
1405
1406 Mailbox.prototype.dump = function(indent) {
1407   if (!indent)
1408     indent = 0;
1409   log(" ".repeat(indent) + this.name);
1410   for (var i = 0; i < this.children.length; i++) {
1411     this.children[i].dump(indent + 2);
1412   }
1413 }
1414
1415 Mailbox.prototype.findMailboxByName = function(name) {
1416   var mailbox = null;
1417
1418   var i = 0;
1419   while (!mailbox && i < this.children.length)
1420     if (this.children[i].name == name)
1421       mailbox = this.children[i];
1422     else
1423       i++;
1424
1425   return mailbox;
1426 }
1427
1428 Mailbox.prototype.addMailbox = function(mailbox) {
1429   mailbox.parentFolder = this;
1430   this.children.push(mailbox);
1431 }