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