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