]> err.no Git - scalable-opengroupware.org/blob - UI/WebServerResources/ContactsUI.js
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1233 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   for (var i = 0; i < rows.length; i++) {
337     var emailCell = $(rows[i]).down('td', 1);
338     if (emailCell.firstChild) { // .nodeValue is the contact email address
339       rowsWithEmail++;
340       openMailComposeWindow(ApplicationBaseURL + currentContactFolder
341                             + "/" + rows[i] + "/write");
342     }
343   }
344   
345   if (rowsWithEmail == 0) {
346     window.alert(labels["The selected contact has no email address."]);
347   }
348   else if (document.body.hasClassName("popup"))
349     window.close();
350
351   return false;
352 }
353
354 function uixDeleteSelectedContacts(sender) {
355   var failCount = 0;
356   var contactsList = $('contactsList');
357   var rows = contactsList.getSelectedRowsId();
358
359   var contactView = $('contactView');
360   contactView.innerHTML = '';
361
362   for (var i = 0; i < rows.length; i++) {
363     var url, http, rowElem;
364     
365     /* send AJAX request (synchronously) */
366     
367     url = (URLForFolderID(currentContactFolder) + "/"
368            + rows[i] + "/delete");
369     http = createHTTPClient();
370     http.open("POST", url, false /* not async */);
371     http.send("");
372     if (http.status != 200) { /* request failed */
373       failCount++;
374       http = null;
375       continue;
376     }
377     http = null;
378
379     /* remove from page */
380
381     /* line-through would be nicer, but hiding is OK too */
382     rowElem = $(rows[i]);
383     rowElem.parentNode.removeChild(rowElem);
384   }
385
386   if (failCount > 0)
387     alert("Could not delete the selected contacts!");
388   
389   return false;
390 }
391
392 function newEmailTo(sender) {
393   var mailto = sanitizeMailTo(sender.parentNode.parentNode.menuTarget.innerHTML);
394
395   if (mailto.length > 0)
396     openMailComposeWindow("compose?mailto=" + mailto);
397
398   return false; /* stop following the link */
399 }
400
401 function onHeaderClick(event) {
402    var headerId = this.getAttribute("id");
403    var newSortAttribute;
404    if (headerId == "nameHeader")
405       newSortAttribute = "displayName";
406    else if (headerId == "mailHeader")
407       newSortAttribute = "mail";
408    else if (headerId == "screenNameHeader")
409       newSortAttribute = "screenName";
410    else if (headerId == "orgHeader")
411       newSortAttribute = "org";
412    else if (headerId == "phoneHeader")
413       newSortAttribute = "phone";
414
415    if (sorting["attribute"] == newSortAttribute)
416       sorting["ascending"] = !sorting["ascending"];
417    else {
418       sorting["attribute"] = newSortAttribute;
419       sorting["ascending"] = true;
420    }
421
422    refreshCurrentFolder();
423
424    Event.stop(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.update();
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     handle.leftMargin = 100;
618   }
619
620   handle = $("rightDragHandle");
621   if (handle) {
622     handle.addInterface(SOGoDragHandlesInterface);
623     handle.upperBlock=$("contactsListContent");
624     handle.lowerBlock=$("contactView");
625   }
626 }
627
628 function lookupDeniedFolders() {
629   var list = $("contactFolders").childNodesWithTag("li");
630   for (var i = 0; i < list.length; i++) {
631      var folderID = list[i].getAttribute("id");
632      var url = URLForFolderID(folderID) + "/canAccessContent";
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 owner = selected.getAttribute("owner");
712    if (owner == "nobody")
713      window.alert(clabels["The user rights cannot be"
714                           + " edited for this object!"]);
715    else {
716      var title = this.innerHTML;
717      var url = URLForFolderID(selected.getAttribute("id"));
718
719      openAclWindow(url + "/acls", title);
720    }
721 }
722
723 function getMenus() {
724    var menus = {};
725    menus["contactFoldersMenu"] = new Array(onMenuModify, "-", null,
726                                            null, "-", null, "-",
727                                            onMenuSharing);
728    menus["contactMenu"] = new Array(onMenuEditContact, "-",
729                                     onMenuWriteToContact, null, "-",
730                                     onMenuDeleteContact);
731    menus["searchMenu"] = new Array(setSearchCriteria);
732
733    return menus;
734 }
735
736 function configureSelectionButtons() {
737    var container = $("contactSelectionButtons");
738    if (container) {
739       var buttons = container.childNodesWithTag("input");
740       for (var i = 0; i < buttons.length; i++)
741         Event.observe(buttons[i], "click",
742                       onConfirmContactSelection.bindAsEventListener(buttons[i]));
743    }
744 }
745
746 function initContacts(event) {
747    if (!document.body.hasClassName("popup")) {
748      configureAbToolbar();
749    }
750    else
751      configureSelectionButtons();
752    configureContactFolders();
753 //     initDnd();
754
755    var table = $("contactsList");
756    if (table) {
757      // Initialize contacts table
758      configureSortableTableHeaders(table);
759      TableKit.Resizable.init(table, {'trueResize' : true, 'keepWidth' : true});
760    }
761 }
762
763 addEvent(window, 'load', initContacts);