]> err.no Git - scalable-opengroupware.org/blob - UI/WebServerResources/ContactsUI.js
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1174 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / UI / WebServerResources / ContactsUI.js
1 /* JavaScript for SOGoContacts */
2
3 var cachedContacts = new Array();
4 var currentContactFolder = null;
5 var savedColumnsWidth = null;
6
7 var usersRightsWindowHeight = 200;
8 var usersRightsWindowWidth = 450;
9
10 function validateEditorInput(sender) {
11   var errortext = "";
12   var field;
13   
14   field = document.pageform.subject;
15   if (field.value == "")
16     errortext = errortext + labels.error_missingsubject + "\n";
17
18   if (!UIxRecipientSelectorHasRecipients())
19     errortext = errortext + labels.error_missingrecipients + "\n";
20   
21   if (errortext.length > 0) {
22     alert(labels.error_validationfailed + ":\n"
23           + errortext);
24     return false;
25   }
26   return true;
27 }
28
29 function openContactsFolder(contactsFolder, reload, idx) {
30   if ((contactsFolder && contactsFolder != currentContactFolder)
31       || reload) {
32      currentContactFolder = contactsFolder;
33      var url = URLForFolderID(currentContactFolder) +
34         "/view?noframe=1";
35
36      var searchValue = search["value"];
37      if (searchValue && searchValue.length > 0)
38         url += ("&search=" + search["criteria"]
39                 + "&value=" + escape(searchValue.utf8encode()));
40      var sortAttribute = sorting["attribute"];
41      if (sortAttribute && sortAttribute.length > 0)
42         url += ("&sort=" + sorting["attribute"]
43                 + "&asc=" + sorting["ascending"]);
44
45      var selection;
46      if (contactsFolder == currentContactFolder) {
47         var contactsList = $("contactsList");
48         if (contactsList)
49            selection = contactsList.getSelectedRowsId();
50         else
51            window.alert("no contactsList");
52      }
53      else
54         selection = null;
55
56      if (document.contactsListAjaxRequest) {
57         document.contactsListAjaxRequest.aborted = true;
58         document.contactsListAjaxRequest.abort();
59      }
60      document.contactsListAjaxRequest
61         = triggerAjaxRequest(url, contactsListCallback, selection);
62   }
63 }
64
65 function openContactsFolderAtIndex(element) {
66   var idx = element.getAttribute("idx");
67   var url = URLForFolderID(currentContactFolder) + "/view?noframe=1&idx=" + idx;
68
69   if (document.contactsListAjaxRequest) {
70     document.contactsListAjaxRequest.aborted = true;
71     document.contactsListAjaxRequest.abort();
72   }
73   document.contactsListAjaxRequest
74     = triggerAjaxRequest(url, contactsListCallback);
75 }
76
77 function configureContactsListHeaders(cells) {
78    for (var i = 0; i < cells.length; i++) {
79       var currentCell = $(cells[i]);
80       Event.observe(currentCell, "click",
81                     onHeaderClick.bindAsEventListener(currentCell));
82       //Event.observe(currentCell, "mousedown", listRowMouseDownHandler);
83    }
84 }
85
86 function contactsListCallback(http) {
87   var div = $("contactsListContent");
88
89   if (http.readyState == 4
90       && http.status == 200) {
91     document.contactsListAjaxRequest = null;
92     div.update(http.responseText);
93
94     var table = $("contactsList");
95     if (table) {
96        TableKit.Resizable.init(table);
97        if (savedColumnsWidth != null) {
98          // Restore columns width
99          table.setColumnsWidth(savedColumnsWidth);
100        }
101        configureContactsListHeaders(table.tBodies[0].rows[0].cells);
102     }
103
104     if (sorting["attribute"] && sorting["attribute"].length > 0) {
105        var sortHeader;
106        if (sorting["attribute"] == "displayName")
107           sortHeader = $("nameHeader");
108        else if (sorting["attribute"] == "mail")
109           sortHeader = $("mailHeader");
110        else if (sorting["attribute"] == "screenName")
111           sortHeader = $("screenNameHeader");
112        else if (sorting["attribute"] == "org")
113           sortHeader = $("orgHeader");
114        else if (sorting["attribute"] == "phone")
115           sortHeader = $("phoneHeader");
116        else
117           sortHeader = null;
118        
119        if (sortHeader) {
120           var sortImage = createElement("img", "messageSortImage", "sortImage");
121           sortHeader.insertBefore(sortImage, sortHeader.firstChild);
122           if (sorting["ascending"])
123              sortImage.src = ResourcesURL + "/title_sortdown_12x12.png";
124           else
125              sortImage.src = ResourcesURL + "/title_sortup_12x12.png";
126        }
127     }
128
129     var selected = http.callbackData;
130     if (selected) {
131        for (var i = 0; i < selected.length; i++) {
132           var row = $(selected[i]);
133           if (row)
134              row.select();
135        }
136     }
137   }
138   else
139     log ("ajax problem 1: status = " + http.status);
140 }
141
142 function onContactFoldersContextMenu(event) {
143   var menu = $("contactFoldersMenu");
144   //Event.observe(menu, "hideMenu", onContactFoldersContextMenuHide, false);
145   Event.observe(menu, "mousedown", onContactFoldersContextMenuHide, false);
146   popupMenu(event, "contactFoldersMenu", this);
147
148   var topNode = $("contactFolders");
149   var selectedNodes = topNode.getSelectedRows();
150   topNode.menuSelectedRows = selectedNodes;
151   for (var i = 0; i < selectedNodes.length; i++)
152     $(selectedNodes[i]).deselect();
153   topNode.menuSelectedEntry = this;
154   $(this).select();
155 }
156
157 function onContactContextMenu(event, element) { log ("onContactContextMenu");
158   var menu = $("contactMenu");
159
160   Event.observe(menu, "mousedown", onContactContextMenuHide, false);
161   popupMenu(event, "contactMenu", element);
162
163   var topNode = $("contactsList");
164   var selectedNodes = topNode.getSelectedRows();
165   topNode.menuSelectedRows = selectedNodes;
166   for (var i = 0; i < selectedNodes.length; i++)
167     $(selectedNodes[i]).deselect();
168   topNode.menuSelectedEntry = element;
169   $(element).select();
170 }
171
172 function onContactContextMenuHide(event) {
173   var topNode = $("contactsList");
174
175   if (topNode.menuSelectedEntry) {
176     $(topNode.menuSelectedEntry).deselect();
177     topNode.menuSelectedEntry = null;
178   }
179   if (topNode.menuSelectedRows) {
180     var nodes = topNode.menuSelectedRows;
181     for (var i = 0; i < nodes.length; i++)
182       $(nodes[i]).select();
183     topNode.menuSelectedRows = null;
184   }
185 }
186
187 function onContactFoldersContextMenuHide(event) {
188   var topNode = $("contactFolders");
189
190   if (topNode.menuSelectedEntry) {
191     topNode.menuSelectedEntry.deselect();
192     topNode.menuSelectedEntry = null;
193   }
194   if (topNode.menuSelectedRows) {
195     var nodes = topNode.menuSelectedRows;
196     for (var i = 0; i < nodes.length; i++)
197       nodes[i].select();
198     topNode.menuSelectedRows = null;
199   }
200 }
201
202 function onFolderMenuHide(event) {
203   var topNode = $('d');
204
205   if (topNode.menuSelectedEntry) {
206     topNode.menuSelectedEntry.deselect();
207     topNode.menuSelectedEntry = null;
208   }
209   if (topNode.selectedEntry)
210     topNode.selectedEntry.select();
211 }
212
213 function loadContact(idx) {
214   if (document.contactAjaxRequest) {
215     document.contactAjaxRequest.aborted = true;
216     document.contactAjaxRequest.abort();
217   }
218
219   if (cachedContacts[currentContactFolder + "/" + idx]) {
220     var div = $('contactView');
221     div.innerHTML = cachedContacts[currentContactFolder + "/" + idx];
222   }
223   else {
224     var url = (URLForFolderID(currentContactFolder)
225                + "/" + idx + "/view?noframe=1");
226     document.contactAjaxRequest
227       = triggerAjaxRequest(url, contactLoadCallback, idx);
228   }
229 }
230
231 function contactLoadCallback(http) {
232   var div = $('contactView');
233
234   if (http.readyState == 4
235       && http.status == 200) {
236     document.contactAjaxRequest = null;
237     var content = http.responseText;
238     cachedContacts[currentContactFolder + "/" + http.callbackData] = content;
239     div.innerHTML = content;
240   }
241   else
242     log ("ajax problem 2: " + http.status);
243 }
244
245 var rowSelectionCount = 0;
246
247 validateControls();
248
249 function showElement(e, shouldShow) {
250   e.style.display = shouldShow ? "" : "none";
251 }
252
253 function enableElement(e, shouldEnable) {
254   if(!e)
255     return;
256   if(shouldEnable) {
257     if(e.hasAttribute("disabled"))
258       e.removeAttribute("disabled");
259   }
260   else {
261     e.setAttribute("disabled", "1");
262   }
263 }
264
265 function validateControls() {
266   var e = $("moveto");
267   this.enableElement(e, rowSelectionCount > 0);
268 }
269
270 function moveTo(uri) {
271   alert("MoveTo: " + uri);
272 }
273
274 /* contact menu entries */
275 function onContactRowClick(event, node) {
276   loadContact(node.getAttribute('id'));
277
278   return onRowClick(event);
279 }
280
281 function onContactRowDblClick(event, node) {
282   var contactId = node.getAttribute('id');
283
284   openContactWindow(URLForFolderID(currentContactFolder)
285                     + "/" + contactId + "/edit", contactId);
286
287   return false;
288 }
289
290 function onMenuEditContact(event) {
291   var contactId = document.menuTarget.getAttribute('id');
292
293   openContactWindow(URLForFolderID(currentContactFolder)
294                     + "/" + contactId + "/edit", contactId);
295 }
296
297 function onMenuWriteToContact(event) {
298    var contactId = document.menuTarget.getAttribute('id');
299    var contactRow = $(contactId);
300    var emailCell = contactRow.down('td', 1);
301
302    if (!emailCell.firstChild) { // .nodeValue is the contact email address
303      window.alert(labels["The selected contact has no email address."].decodeEntities());
304      return false;
305    }
306
307    openMailComposeWindow(ApplicationBaseURL + currentContactFolder
308                          + "/" + contactId + "/write");
309
310    if (document.body.hasClassName("popup"))
311      window.close();
312 }
313
314 function onMenuDeleteContact(event) {
315   uixDeleteSelectedContacts(this);
316 }
317
318 function onToolbarEditSelectedContacts(event) {
319   var contactsList = $('contactsList');
320   var rows = contactsList.getSelectedRowsId();
321
322   for (var i = 0; i < rows.length; i++) {
323     openContactWindow(URLForFolderID(currentContactFolder)
324                       + "/" + rows[i] + "/edit", rows[i]);
325   }
326
327   return false;
328 }
329
330 function onToolbarWriteToSelectedContacts(event) {
331   var contactsList = $('contactsList');
332   var rows = contactsList.getSelectedRowsId();
333   var rowsWithEmail = 0;
334
335   for (var i = 0; i < rows.length; i++) {
336     var emailCell = $(rows[i]).down('td', 1);
337     if (emailCell.firstChild) { // .nodeValue is the contact email address
338       rowsWithEmail++;
339       openMailComposeWindow(ApplicationBaseURL + currentContactFolder
340                             + "/" + rows[i] + "/write");
341     }
342   }
343   
344   if (rowsWithEmail == 0) {
345     window.alert(labels["The selected contact has no email address."].decodeEntities());
346   }
347   else if (document.body.hasClassName("popup"))
348     window.close();
349
350   return false;
351 }
352
353 function uixDeleteSelectedContacts(sender) {
354   var failCount = 0;
355   var contactsList = $('contactsList');
356   var rows = contactsList.getSelectedRowsId();
357
358   var contactView = $('contactView');
359   contactView.innerHTML = '';
360
361   for (var i = 0; i < rows.length; i++) {
362     var url, http, rowElem;
363     
364     /* send AJAX request (synchronously) */
365     
366     url = (URLForFolderID(currentContactFolder) + "/"
367            + rows[i] + "/delete");
368     http = createHTTPClient();
369     http.open("POST", url, false /* not async */);
370     http.send("");
371     if (http.status != 200) { /* request failed */
372       failCount++;
373       http = null;
374       continue;
375     }
376     http = null;
377
378     /* remove from page */
379
380     /* line-through would be nicer, but hiding is OK too */
381     rowElem = $(rows[i]);
382     rowElem.parentNode.removeChild(rowElem);
383   }
384
385   if (failCount > 0)
386     alert("Could not delete the selected contacts!");
387   
388   return false;
389 }
390
391 function newEmailTo(sender) {
392   var mailto = sanitizeMailTo(sender.parentNode.parentNode.menuTarget.innerHTML);
393
394   if (mailto.length > 0)
395     openMailComposeWindow("compose?mailto=" + mailto);
396
397   return false; /* stop following the link */
398 }
399
400 function onHeaderClick(event) {
401    var headerId = this.getAttribute("id");
402    var newSortAttribute;
403    if (headerId == "nameHeader")
404       newSortAttribute = "displayName";
405    else if (headerId == "mailHeader")
406       newSortAttribute = "mail";
407    else if (headerId == "screenNameHeader")
408       newSortAttribute = "screenName";
409    else if (headerId == "orgHeader")
410       newSortAttribute = "org";
411    else if (headerId == "phoneHeader")
412       newSortAttribute = "phone";
413
414    if (sorting["attribute"] == newSortAttribute)
415       sorting["ascending"] = !sorting["ascending"];
416    else {
417       sorting["attribute"] = newSortAttribute;
418       sorting["ascending"] = true;
419    }
420
421    savedColumnsWidth = this.up('table').getColumnsWidth();
422    refreshCurrentFolder();
423
424    preventDefault(event);
425 }
426
427 function newContact(sender) {
428   openContactWindow(URLForFolderID(currentContactFolder) + "/new");
429
430   return false; /* stop following the link */
431 }
432
433 function onFolderSelectionChange() {
434    var folderList = $("contactFolders");
435    var nodes = folderList.getSelectedNodes();
436    $("contactView").innerHTML = '';
437   
438    if (nodes[0].hasClassName("denied")) {
439       var div = $("contactsListContent");
440       div.innerHTML = "";
441    }
442    else {
443       search = {};
444       sorting = {};
445       $("searchValue").value = "";
446       initCriteria();
447       openContactsFolder(nodes[0].getAttribute("id"));
448    }
449 }
450
451 function refreshCurrentFolder() {
452    openContactsFolder(currentContactFolder, true);
453 }
454
455 function onConfirmContactSelection(event) {
456    var tag = this.getAttribute("name");
457    var folderLi = $(currentContactFolder);
458    var currentContactFolderName = folderLi.innerHTML;
459    var selectorList = null;
460    var initialValues = null;
461
462    if (selector) {
463       var selectorId = selector.getAttribute("id");
464       selectorList = opener.window.document.getElementById('uixselector-'
465                                                            + selectorId
466                                                            + '-uidList');
467       initialValues = selectorList.value;
468    }
469
470    var contactsList = $("contactsList");
471    var rows = contactsList.getSelectedRows();
472    for (i = 0; i < rows.length; i++) {
473       var cid = rows[i].getAttribute("contactid");
474       var cname = '' + rows[i].getAttribute("contactname");
475       var email = '' + rows[i].cells[1].innerHTML;
476       opener.window.addContact(tag, currentContactFolderName + '/' + cname,
477                                cid, cname, email);
478    }
479
480    if (selector && selector.changeNotification
481        && selectorList.value != initialValues)
482       selector.changeNotification("addition");
483
484    preventDefault(event);
485 }
486
487 function onContactMailTo(node) {
488   return openMailTo(node.innerHTML);
489 }
490
491 function refreshContacts(contactId) {
492    refreshCurrentFolder();
493    cachedContacts[currentContactFolder + "/" + contactId] = null;
494    loadContact(contactId);
495
496    return false;
497 }
498
499 function onAddressBookNew(event) {
500   createFolder(window.prompt(labels["Name of the Address Book"]),
501                appendAddressBook);
502   preventDefault(event);
503 }
504
505 function appendAddressBook(name, folder) {
506   if (folder)
507     folder = accessToSubscribedFolder(folder);
508   else
509     folder = "/" + name;
510   if ($(folder))
511     window.alert(clabels["You have already subscribed to that folder!"]);
512   else {
513     var li = document.createElement("li");
514     $("contactFolders").appendChild(li);
515     li.setAttribute("id", folder);
516     li.appendChild(document.createTextNode(name));
517     setEventsOnContactFolder(li);
518   }
519 }
520
521 function newFolderCallback(http) {
522   if (http.readyState == 4
523       && http.status == 201) {
524      var name = http.callbackData;
525      appendAddressBook(name, "/" + name);
526   }
527   else
528     log ("ajax problem 4:" + http.status);
529 }
530
531 function newUserFolderCallback(folderData) {
532    var folder = $(folderData["folder"]);
533    if (!folder)
534       appendAddressBook(folderData["folderName"], folderData["folder"]);
535 }
536
537 function onAddressBookAdd(event) {
538    openUserFolderSelector(newUserFolderCallback, "contact");
539
540    preventDefault(event);
541 }
542
543 function onFolderUnsubscribeCB(folderId) {
544    var node = $(folderId);
545    node.parentNode.removeChild(node);
546    var personal = $("/personal");
547    personal.select();
548    onFolderSelectionChange();
549 }
550
551 function onAddressBookRemove(event) {
552   var selector = $("contactFolders");
553   var nodes = selector.getSelectedNodes();
554   if (nodes.length > 0) { 
555     nodes[0].deselect();
556     var folderId = nodes[0].getAttribute("id");
557     var folderIdElements = folderId.split("_");
558     if (folderIdElements.length > 1)
559       unsubscribeFromFolder(folderId, onFolderUnsubscribeCB, folderId);
560     else {
561       var abId = folderIdElements[0].substr(1);
562       deletePersonalAddressBook(abId);
563       var personal = $("/personal");
564       personal.select();
565       onFolderSelectionChange();
566     }
567   }
568
569   preventDefault(event);
570 }
571
572 function deletePersonalAddressBook(folderId) {
573   var label
574     = labels["Are you sure you want to delete the selected address book?"];
575   if (window.confirm(label)) {
576     if (document.deletePersonalABAjaxRequest) {
577       document.deletePersonalABAjaxRequest.aborted = true;
578       document.deletePersonalABAjaxRequest.abort();
579     }
580     var url = ApplicationBaseURL + "/" + folderId + "/deleteFolder";
581     document.deletePersonalABAjaxRequest
582       = triggerAjaxRequest(url, deletePersonalAddressBookCallback,
583                            folderId);
584   }
585 }
586
587 function deletePersonalAddressBookCallback(http) {
588   if (http.readyState == 4) {
589     if (isHttpStatus204(http.status)) {
590       var ul = $("contactFolders");
591         
592       var children = ul.childNodesWithTag("li");
593       var i = 0;
594       var done = false;
595       while (!done && i < children.length) {
596         var currentFolderId = children[i].getAttribute("id").substr(1);
597         if (currentFolderId == http.callbackData) {
598           ul.removeChild(children[i]);
599           done = true;
600         }
601         else
602           i++;
603       }
604     }
605     document.deletePersonalABAjaxRequest = null;
606   }
607   else
608     log ("ajax problem 5: " + http.status);
609 }
610
611 function configureDragHandles() {
612   var handle = $("dragHandle");
613   if (handle) {
614     handle.addInterface(SOGoDragHandlesInterface);
615     handle.leftBlock=$("contactFoldersList");
616     handle.rightBlock=$("rightPanel");
617   }
618
619   handle = $("rightDragHandle");
620   if (handle) {
621     handle.addInterface(SOGoDragHandlesInterface);
622     handle.upperBlock=$("contactsListContent");
623     handle.lowerBlock=$("contactView");
624   }
625 }
626
627 function lookupDeniedFolders() {
628   var list = $("contactFolders").childNodesWithTag("li");
629   for (var i = 0; i < list.length; i++) {
630      var folderID = list[i].getAttribute("id");
631      var url = URLForFolderID(folderID) + "/canAccessContent";
632      
633      triggerAjaxRequest(url, deniedFoldersLookupCallback, folderID);
634   }
635 }
636
637 function deniedFoldersLookupCallback(http) {
638    if (http.readyState == 4) {
639       var denied = ! isHttpStatus204(http.status);
640       var entry = $(http.callbackData);
641       if (denied)
642          entry.addClassName("denied");
643       else
644          entry.removeClassName("denied");
645    }
646 }
647
648 function configureAbToolbar() {
649   var toolbar = $("abToolbar");
650   var links = toolbar.childNodesWithTag("a");
651   Event.observe(links[0], "click", onAddressBookNew, false);
652   Event.observe(links[1], "click", onAddressBookAdd, false);
653   Event.observe(links[2], "click", onAddressBookRemove, false);
654 }
655
656 function configureContactFolders() {
657   var contactFolders = $("contactFolders");
658   if (contactFolders) {
659     Event.observe(contactFolders, "mousedown", listRowMouseDownHandler);
660     Event.observe(contactFolders, "click", onFolderSelectionChange);
661     var lis = contactFolders.childNodesWithTag("li");
662     for (var i = 0; i < lis.length; i++)
663       setEventsOnContactFolder(lis[i]);
664
665     lookupDeniedFolders();
666
667     var personalFolder = $("/personal");
668     personalFolder.select();
669     openContactsFolder("/personal");
670   }
671 }
672
673 function setEventsOnContactFolder(node) {
674    Event.observe(node, "mousedown", listRowMouseDownHandler, false);
675    Event.observe(node, "click", onRowClick, false);
676    Event.observe(node, "contextmenu",
677                  onContactFoldersContextMenu.bindAsEventListener(node), false);
678 }
679
680 function onMenuModify(event) {
681   var folders = $("contactFolders");
682   var selected = folders.getSelectedNodes()[0];
683
684   if (UserLogin == selected.getAttribute("owner")) {
685     var currentName = selected.innerHTML;
686     var newName = window.prompt(labels["Address Book Name"],
687                                 currentName);
688     if (newName && newName.length > 0
689         && newName != currentName) {
690       var url = (URLForFolderID(selected.getAttribute("id"))
691                  + "/renameFolder?name=" + escape(newName.utf8encode()));
692       triggerAjaxRequest(url, folderRenameCallback,
693                          {node: selected, name: newName});
694     }
695   } else
696     window.alert(clabels["Unable to rename that folder!"]);
697 }
698
699 function folderRenameCallback(http) {
700   if (http.readyState == 4) {
701     if (isHttpStatus204(http.status)) {
702       var dict = http.callbackData;
703       dict["node"].innerHTML = dict["name"];
704     }
705   }
706 }
707
708 function onMenuSharing(event) {
709    var folders = $("contactFolders");
710    var selected = folders.getSelectedNodes()[0];
711    var title = this.innerHTML;
712    var url = URLForFolderID(selected.getAttribute("id"));
713
714    openAclWindow(url + "/acls", title);
715 }
716
717 function getMenus() {
718    var menus = {};
719    menus["contactFoldersMenu"] = new Array(onMenuModify, "-", null,
720                                            null, "-", null, "-",
721                                            onMenuSharing);
722    menus["contactMenu"] = new Array(onMenuEditContact, "-",
723                                     onMenuWriteToContact, null, "-",
724                                     onMenuDeleteContact);
725    menus["searchMenu"] = new Array(setSearchCriteria);
726
727    return menus;
728 }
729
730 function configureSelectionButtons() {
731    var container = $("contactSelectionButtons");
732    if (container) {
733       var buttons = container.childNodesWithTag("input");
734       for (var i = 0; i < buttons.length; i++)
735         Event.observe(buttons[i], "click",
736                       onConfirmContactSelection.bindAsEventListener(buttons[i]));
737    }
738 }
739
740 function initContacts(event) {
741    if (!document.body.hasClassName("popup")) {
742      configureAbToolbar();
743    }
744    else
745      configureSelectionButtons();
746    configureContactFolders();
747 //     initDnd();
748 }
749
750 addEvent(window, 'load', initContacts);