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