]> err.no Git - scalable-opengroupware.org/blob - UI/WebServerResources/SchedulerUI.js
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1032 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / UI / WebServerResources / SchedulerUI.js
1 var sortOrder = '';
2 var sortKey = '';
3 var listFilter = 'view_today';
4
5 var listOfSelection = null;
6 var selectedCalendarCell;
7
8 var hideCompletedTasks = 0;
9
10 var currentDay = '';
11 var currentView = "dayview";
12
13 var cachedDateSelectors = new Array();
14
15 var contactSelectorAction = 'calendars-contacts';
16
17 var eventsToDelete = new Array();
18 var ownersOfEventsToDelete = new Array();
19
20 function newEvent(sender, type) {
21   var day = sender.getAttribute("day");
22   if (!day)
23     day = currentDay;
24
25   var user = UserLogin;
26   if (sender.parentNode.getAttribute("id") != "toolbar"
27       && currentView == "multicolumndayview" && type == "event")
28      user = sender.parentNode.parentNode.getAttribute("user");
29
30   var hour = sender.getAttribute("hour");
31   var urlstr = UserFolderURL + "../" + user + "/Calendar/new" + type;
32   var params = new Array();
33   if (day)
34     params.push("day=" + day);
35   if (hour)
36     params.push("hm=" + hour);
37   if (params.length > 0)
38     urlstr += "?" + params.join("&");
39
40   window.open(urlstr, "", "width=620,height=600,resizable=0");
41
42   return false; /* stop following the link */
43 }
44
45 function _editEventId(id, owner) {
46   var urlBase;
47   if (owner)
48     urlBase = UserFolderURL + "../" + owner + "/";
49   urlBase += "Calendar/"
50
51   var urlstr = urlBase + id + "/edit";
52
53   var win = window.open(urlstr, "SOGo_edit_" + id,
54                         "width=620,height=600,resizable=0,scrollbars=0,toolbar=0," +
55                         "location=0,directories=0,status=0,menubar=0,copyhistory=0");
56   win.focus();
57 }
58
59 function editEvent() {
60   if (listOfSelection) {
61     var nodes = listOfSelection.getSelectedRows();
62
63     for (var i = 0; i < nodes.length; i++)
64       _editEventId(nodes[i].getAttribute("id"),
65                    nodes[i].getAttribute("owner"));
66   } else if (selectedCalendarCell) {
67       _editEventId(selectedCalendarCell.getAttribute("aptCName"),
68                    selectedCalendarCell.getAttribute("owner"));
69   }
70
71   return false; /* stop following the link */
72 }
73
74 function _batchDeleteEvents() {
75   var events = eventsToDelete.shift();
76   var owner = ownersOfEventsToDelete.shift();
77   var urlstr = (UserFolderURL + "../" + owner + "/Calendar/batchDelete?ids="
78                 + events.join('/'));
79   document.deleteEventAjaxRequest = triggerAjaxRequest(urlstr,
80                                                        deleteEventCallback,
81                                                        events);
82 }
83
84 function deleteEvent()
85 {
86   if (listOfSelection) {
87     var nodes = listOfSelection.getSelectedRows();
88
89     if (nodes.length > 0) {
90       var label = "";
91       if (listOfSelection == $("tasksList"))
92         label = labels["taskDeleteConfirmation"].decodeEntities();
93       else
94         label = labels["appointmentDeleteConfirmation"].decodeEntities();
95       
96       if (confirm(label)) {
97         if (document.deleteEventAjaxRequest) {
98           document.deleteEventAjaxRequest.aborted = true;
99           document.deleteEventAjaxRequest.abort();
100         }
101         var sortedNodes = new Array();
102         var owners = new Array();
103
104         for (var i = 0; i < nodes.length; i++) {
105           var owner = nodes[i].getAttribute("owner");
106           if (!sortedNodes[owner]) {
107               sortedNodes[owner] = new Array();
108               owners.push(owner);
109           }
110           sortedNodes[owner].push(nodes[i].getAttribute("id"));
111         }
112         for (var i = 0; i < owners.length; i++) {
113           ownersOfEventsToDelete.push(owners[i]);
114           eventsToDelete.push(sortedNodes[owners[i]]);
115         }
116         _batchDeleteEvents();
117       }
118     }
119   }
120   else if (selectedCalendarCell) {
121      var label = labels["appointmentDeleteConfirmation"].decodeEntities();
122      if (confirm(label)) {
123         if (document.deleteEventAjaxRequest) {
124            document.deleteEventAjaxRequest.aborted = true;
125            document.deleteEventAjaxRequest.abort();
126         }
127         eventsToDelete.push([selectedCalendarCell.getAttribute("aptCName")]);
128         ownersOfEventsToDelete.push(selectedCalendarCell.getAttribute("owner"));
129         _batchDeleteEvents();
130      }
131   }
132   else
133     window.alert("no selection");
134
135   return false;
136 }
137
138 function modifyEvent(sender, modification) {
139   var currentLocation = '' + window.location;
140   var arr = currentLocation.split("/");
141   arr[arr.length-1] = modification;
142
143   document.modifyEventAjaxRequest = triggerAjaxRequest(arr.join("/"),
144                                                        modifyEventCallback,
145                                                        modification);
146
147   return false;
148 }
149
150 function closeInvitationWindow() {
151   var closeDiv = document.createElement("div");
152   closeDiv.addClassName("javascriptPopupBackground");
153   var closePseudoWin = document.createElement("div");
154   closePseudoWin.addClassName("javascriptMessagePseudoWindow");
155   closePseudoWin.style.top = "0px;";
156   closePseudoWin.style.left = "0px;";
157   closePseudoWin.style.right = "0px;";
158   closePseudoWin.appendChild(document.createTextNode(labels["closeThisWindowMessage"].decodeEntities()));
159   document.body.appendChild(closeDiv);
160   document.body.appendChild(closePseudoWin);
161 }
162
163 function modifyEventCallback(http) {
164   if (http.readyState == 4) {
165     if (http.status == 200) {
166       log("closing window...?");
167       if (queryParameters["mail-invitation"] == "yes")
168         closeInvitationWindow();
169       else {
170         window.opener.setTimeout("refreshAppointmentsAndDisplay();", 100);
171         window.setTimeout("window.close();", 100);
172       }
173     }
174     else {
175       log("showing alert...");
176       window.alert(labels["eventPartStatModificationError"]);
177     }
178     document.modifyEventAjaxRequest = null;
179   }
180 }
181
182 function deleteEventCallback(http)
183 {
184   if (http.readyState == 4
185       && http.status == 200) {
186     var nodes = http.callbackData;
187     for (var i = 0; i < nodes.length; i++) {
188       var node = $(nodes[i]);
189       if (node)
190         node.parentNode.removeChild(node);
191     }
192     if (eventsToDelete.length)
193       _batchDeleteEvents();
194     else {
195       document.deleteEventAjaxRequest = null;
196       refreshAppointments();
197       refreshTasks();
198       changeCalendarDisplay();
199     }
200   }
201   else
202     log ("ajax fuckage");
203 }
204
205 function editDoubleClickedEvent(node)
206 {
207   _editEventId(node.getAttribute("id"),
208                node.getAttribute("owner"));
209   
210   return false;
211 }
212
213 function onSelectAll() {
214   var list = $("appointmentsList");
215   list.selectRowsMatchingClass("appointmentRow");
216
217   return false;
218 }
219
220 function displayAppointment(event) {
221   _editEventId(this.getAttribute("aptCName"),
222                this.getAttribute("owner"));
223
224   event.preventDefault();
225   event.stopPropagation();
226   event.cancelBubble = true;
227   event.returnValue = false;
228 }
229
230 function onDaySelect(node)
231 {
232   var day = node.getAttribute("day");
233   var needRefresh = (listFilter == 'view_selectedday'
234                      && day != currentDay);
235
236   var td = node.getParentWithTagName("td");
237   var table = td.getParentWithTagName("table");
238
239 //   log ("table.selected: " + table.selected);
240
241   if (document.selectedDate)
242     document.selectedDate.deselect();
243
244   td.select();
245   document.selectedDate = td;
246
247   changeCalendarDisplay( { "day": day } );
248   if (needRefresh)
249     refreshAppointments();
250
251   return false;
252 }
253
254 function onDateSelectorGotoMonth(node)
255 {
256   var day = node.getAttribute("date");
257
258   changeDateSelectorDisplay(day, true);
259
260   return false;
261 }
262
263 function onCalendarGotoDay(node)
264 {
265   var day = node.getAttribute("date");
266
267   changeDateSelectorDisplay(day);
268   changeCalendarDisplay( { "day": day } );
269
270   return false;
271 }
272
273 function gotoToday()
274 {
275   changeDateSelectorDisplay('');
276   changeCalendarDisplay();
277
278   return false;
279 }
280
281 function setDateSelectorContent(content)
282 {
283   var div = $("dateSelectorView");
284
285   div.innerHTML = content;
286   if (currentDay.length > 0)
287     restoreCurrentDaySelection(div);
288 }
289
290 function dateSelectorCallback(http)
291 {
292   if (http.readyState == 4
293       && http.status == 200) {
294     document.dateSelectorAjaxRequest = null;
295     var content = http.responseText;
296     setDateSelectorContent(content);
297     cachedDateSelectors[http.callbackData] = content;
298   }
299   else
300     log ("ajax fuckage");
301 }
302
303 function appointmentsListCallback(http)
304 {
305   var div = $("appointmentsListView");
306
307   if (http.readyState == 4
308       && http.status == 200) {
309     document.appointmentsListAjaxRequest = null;
310     div.innerHTML = http.responseText;
311     var params = parseQueryParameters(http.callbackData);
312     sortKey = params["sort"];
313     sortOrder = params["desc"];
314     var list = $("appointmentsList");
315     list.addEventListener("selectionchange",
316                           onAppointmentsSelectionChange, true);
317     configureSortableTableHeaders();
318   }
319   else
320     log ("ajax fuckage");
321 }
322
323 function tasksListCallback(http)
324 {
325   var div = $("tasksListView");
326
327   if (http.readyState == 4
328       && http.status == 200) {
329     document.tasksListAjaxRequest = null;
330     var list = $("tasksList");
331     var scroll = list.scrollTop;
332     div.innerHTML = http.responseText;
333     list = $("tasksList");
334     list.addEventListener("selectionchange",
335                           onTasksSelectionChange, true);
336     list.scrollTop = scroll;
337     if (http.callbackData) {
338       var selectedNodesId = http.callbackData;
339       for (var i = 0; i < selectedNodesId.length; i++)
340         $(selectedNodesId[i]).select();
341     }
342   }
343   else
344     log ("ajax fuckage");
345 }
346
347 function restoreCurrentDaySelection(div)
348 {
349   var elements = div.getElementsByTagName("a");
350   var day = null;
351   var i = 9;
352   while (!day && i < elements.length)
353     {
354       day = elements[i].getAttribute("day");
355       i++;
356     }
357
358   if (day
359       && day.substr(0, 6) == currentDay.substr(0, 6)) {
360       for (i = 0; i < elements.length; i++) {
361         day = elements[i].getAttribute("day");
362         if (day && day == currentDay) {
363           var td = elements[i].getParentWithTagName("td");
364           if (document.selectedDate)
365             document.selectedDate.deselect();
366           td.select();
367           document.selectedDate = td;
368         }
369       }
370     }
371 }
372
373 function changeDateSelectorDisplay(day, keepCurrentDay)
374 {
375   var url = ApplicationBaseURL + "dateselector";
376   if (day)
377     url += "?day=" + day;
378
379   if (day != currentDay) {
380     if (!keepCurrentDay)
381       currentDay = day;
382
383     log (backtrace());
384     var month = day.substr(0, 6);
385     if (cachedDateSelectors[month]) {
386 //       log ("restoring cached selector for month: " + month);
387       setDateSelectorContent(cachedDateSelectors[month]);
388     }
389     else {
390 //       log ("loading selector for month: " + month);
391       if (document.dateSelectorAjaxRequest) {
392         document.dateSelectorAjaxRequest.aborted = true;
393         document.dateSelectorAjaxRequest.abort();
394       }
395       document.dateSelectorAjaxRequest
396         = triggerAjaxRequest(url,
397                              dateSelectorCallback,
398                              month);
399     }
400   }
401 }
402
403 function changeCalendarDisplay(time, newView)
404 {
405   var url = ApplicationBaseURL + ((newView) ? newView : currentView);
406
407   selectedCalendarCell = null;
408
409   var day = null;
410   var hour = null;
411   if (time) {
412     day = time['day'];
413     hour = time['hour'];
414   }
415
416   if (!day)
417     day = currentDay;
418   if (day)
419     url += "?day=" + day;
420
421 //   if (newView)
422 //     log ("switching to view: " + newView);
423 //   log ("changeCalendarDisplay: " + url);
424
425   if (document.dayDisplayAjaxRequest) {
426 //     log ("aborting day ajaxrq");
427     document.dayDisplayAjaxRequest.aborted = true;
428     document.dayDisplayAjaxRequest.abort();
429   }
430   document.dayDisplayAjaxRequest = triggerAjaxRequest(url,
431                                                       calendarDisplayCallback,
432                                                       { "view": newView,
433                                                         "day": day,
434                                                         "hour": hour });
435
436   return false;
437 }
438
439 function _ensureView(view) {
440   if (currentView != view)
441     changeCalendarDisplay(null, view);
442
443   return false;
444 }
445
446 function onDayOverview()
447 {
448   return _ensureView("dayview");
449 }
450
451 function onMulticolumnDayOverview()
452 {
453   return _ensureView("multicolumndayview");
454 }
455
456 function onWeekOverview()
457 {
458   return _ensureView("weekview");
459 }
460
461 function onMonthOverview()
462 {
463   return _ensureView("monthview");
464 }
465
466 function scrollDayView(hour)
467 {
468   var rowNumber;
469   if (hour) {
470     if (hour.length == 3)
471       rowNumber = parseInt(hour.substr(0, 1));
472     else {
473       if (hour.substr(0, 1) == "0")
474         rowNumber = parseInt(hour.substr(1, 1));
475       else
476         rowNumber = parseInt(hour.substr(0, 2));
477     }
478   } else
479     rowNumber = 8;
480
481   var daysView = $("daysView");
482   var hours = daysView.childNodesWithTag("div")[0].childNodesWithTag("div");
483   if (hours.length > 0)
484     daysView.parentNode.scrollTop = hours[rowNumber + 1].offsetTop;
485 }
486
487 function onClickableCellsDblClick(event) {
488   newEvent(this, 'event');
489
490   event.cancelBubble = true;
491   event.returnValue = false;
492 }
493
494 function calendarDisplayCallback(http)
495 {
496   var div = $("calendarView");
497
498 //   log ("calendardisplaycallback: " + div);
499   if (http.readyState == 4
500       && http.status == 200) {
501     document.dayDisplayAjaxRequest = null;
502     div.innerHTML = http.responseText;
503     if (http.callbackData["view"])
504       currentView = http.callbackData["view"];
505     if (http.callbackData["day"])
506       currentDay = http.callbackData["day"];
507     var hour = null;
508     if (http.callbackData["hour"])
509       hour = http.callbackData["hour"];
510     var contentView;
511     if (currentView == "monthview")
512       contentView = $("calendarContent");
513     else {
514       scrollDayView(hour);
515 //       log("cbtest1");
516       contentView = $("daysView");
517     }
518     var appointments = document.getElementsByClassName("appointment", contentView);
519     for (var i = 0; i < appointments.length; i++) {
520       appointments[i].addEventListener("mousedown", listRowMouseDownHandler, true);
521       appointments[i].addEventListener("click", onCalendarSelectAppointment, false);
522       appointments[i].addEventListener("dblclick", displayAppointment, true);
523     }
524     var days = document.getElementsByClassName("day", contentView);
525     if (currentView == "monthview")
526       for (var i = 0; i < days.length; i++) {
527         days[i].addEventListener("click", onCalendarSelectDay, true);
528         days[i].addEventListener("dblclick", onClickableCellsDblClick, false);
529       }
530     else
531       for (var i = 0; i < days.length; i++) {
532         days[i].addEventListener("click", onCalendarSelectDay, false);
533         var clickableCells = document.getElementsByClassName("clickableHourCell",
534                                                              days[i]);
535         for (var j = 0; j < clickableCells.length; j++)
536           clickableCells[j].addEventListener("dblclick",
537                                              onClickableCellsDblClick, false);
538       }
539 //     log("cbtest1");
540   }
541   else
542     log ("ajax fuckage");
543 }
544
545 function assignCalendar(name)
546 {
547   var node = $(name);
548
549   node.calendar = new skycalendar(node);
550   node.calendar.setCalendarPage(ResourcesURL + "/skycalendar.html");
551   var dateFormat = node.getAttribute("dateFormat");
552   if (dateFormat)
553     node.calendar.setDateFormat(dateFormat);
554 }
555
556 function popupCalendar(node)
557 {
558   var nodeId = node.getAttribute("inputId");
559   var input = $(nodeId);
560   input.calendar.popup();
561
562   return false;
563 }
564
565 function onAppointmentContextMenu(event, element)
566 {
567   var topNode = $("appointmentsList");
568 //   log(topNode);
569
570   var menu = $("appointmentsListMenu");
571
572   menu.addEventListener("hideMenu", onAppointmentContextMenuHide, false);
573   onMenuClick(event, "appointmentsListMenu");
574
575   var topNode = $("appointmentsList");
576   var selectedNodes = topNode.getSelectedRows();
577   topNode.menuSelectedRows = selectedNodes;
578   for (var i = 0; i < selectedNodes.length; i++)
579     selectedNodes[i].deselect();
580
581   topNode.menuSelectedEntry = element;
582   element.select();
583 }
584
585 function onAppointmentContextMenuHide(event)
586 {
587   var topNode = $("appointmentsList");
588
589   if (topNode.menuSelectedEntry) {
590     topNode.menuSelectedEntry.deselect();
591     topNode.menuSelectedEntry = null;
592   }
593   if (topNode.menuSelectedRows) {
594     var nodeIds = topNode.menuSelectedRows;
595     for (var i = 0; i < nodeIds.length; i++) {
596       var node = $(nodeIds[i]);
597       node.select();
598     }
599     topNode.menuSelectedRows = null;
600   }
601 }
602
603 function onAppointmentsSelectionChange() {
604   listOfSelection = this;
605   this.removeClassName("_unfocused");
606   $("tasksList").addClassName("_unfocused");
607 }
608
609 function onTasksSelectionChange() {
610   listOfSelection = this;
611   this.removeClassName("_unfocused");
612   $("appointmentsList").addClassName("_unfocused");
613 }
614
615 function _loadAppointmentHref(href) {
616   if (document.appointmentsListAjaxRequest) {
617     document.appointmentsListAjaxRequest.aborted = true;
618     document.appointmentsListAjaxRequest.abort();
619   }
620   var url = ApplicationBaseURL + href;
621   document.appointmentsListAjaxRequest
622     = triggerAjaxRequest(url, appointmentsListCallback, href);
623
624   return false;
625 }
626
627 function _loadTasksHref(href) {
628   if (document.tasksListAjaxRequest) {
629     document.tasksListAjaxRequest.aborted = true;
630     document.tasksListAjaxRequest.abort();
631   }
632   url = ApplicationBaseURL + href;
633
634   var selectedIds = $("tasksList").getSelectedNodesId();
635   document.tasksListAjaxRequest
636     = triggerAjaxRequest(url, tasksListCallback, selectedIds);
637
638   return false;
639 }
640
641 function onHeaderClick(event) {
642 //   log("onHeaderClick: " + this.link);
643   _loadAppointmentHref(this.link);
644
645   event.preventDefault();
646 }
647
648 function refreshAppointments() {
649   return _loadAppointmentHref("aptlist?desc=" + sortOrder
650                               + "&sort=" + sortKey
651                               + "&day=" + currentDay
652                               + "&filterpopup=" + listFilter);
653 }
654
655 function refreshTasks() {
656   return _loadTasksHref("taskslist?hide-completed=" + hideCompletedTasks);
657 }
658
659 function refreshAppointmentsAndDisplay()
660 {
661   refreshAppointments();
662   changeCalendarDisplay();
663 }
664
665 function onListFilterChange() {
666   var node = $("filterpopup");
667
668   listFilter = node.value;
669 //   log ("listFilter = " + listFilter);
670
671   return refreshAppointments();
672 }
673
674 function onAppointmentClick(event)
675 {
676   var node = event.target.getParentWithTagName("tr");
677   var day = node.getAttribute("day");
678   var hour = node.getAttribute("hour");
679
680   changeCalendarDisplay( { "day": day, "hour": hour} );
681   changeDateSelectorDisplay(day);
682
683   return onRowClick(event);
684 }
685
686 function selectMonthInMenu(menu, month)
687 {
688   var entries = menu.childNodes[1].childNodesWithTag("LI");
689   for (i = 0; i < entries.length; i++) {
690     var entry = entries[i];
691     var entryMonth = entry.getAttribute("month");
692     if (entryMonth == month)
693       entry.addClassName("currentMonth");
694     else
695       entry.removeClassName("currentMonth");
696   }
697 }
698
699 function selectYearInMenu(menu, month)
700 {
701   var entries = menu.childNodes[1].childNodes;
702   for (i = 0; i < entries.length; i++) {
703     var entry = entries[i];
704     if (entry instanceof HTMLLIElement) {
705       var entryMonth = entry.innerHTML;
706       if (entryMonth == month)
707         entry.addClassName("currentMonth");
708       else
709         entry.removeClassName("currentMonth");
710     }
711   }
712 }
713
714 function popupMonthMenu(event, menuId)
715 {
716   var node = event.target;
717
718   if (event.button == 0) {
719     event.cancelBubble = true;
720     event.returnValue = false;
721
722     if (document.currentPopupMenu)
723       hideMenu(event, document.currentPopupMenu);
724
725     var popup = $(menuId);
726     var id = node.getAttribute("id");
727     if (id == "monthLabel")
728       selectMonthInMenu(popup, node.getAttribute("month"));
729     else
730       selectYearInMenu(popup, node.innerHTML);
731
732     var diff = (popup.offsetWidth - node.offsetWidth) /2;
733
734     popup.style.top = (node.offsetTop + 95) + "px";
735     popup.style.left = (node.offsetLeft - diff) + "px";
736     popup.style.visibility = "visible";
737
738     bodyOnClick = "" + document.body.getAttribute("onclick");
739     document.body.setAttribute("onclick", "onBodyClick('" + menuId + "');");
740     document.currentPopupMenu = popup;
741   }
742 }
743
744 function onMonthMenuItemClick(node)
745 {
746   var month = '' + node.getAttribute("month");
747   var year = '' + $("yearLabel").innerHTML;
748   
749   changeDateSelectorDisplay(year+month+"01", true);
750
751   return false;
752 }
753
754 function onYearMenuItemClick(node) {
755   var month = '' + $("monthLabel").getAttribute("month");;
756   var year = '' + node.innerHTML;
757
758   changeDateSelectorDisplay(year+month+"01", true);
759
760   return false;
761 }
762
763 function onSearchFormSubmit() {
764   log ("search not implemented");
765
766   return false;
767 }
768
769 function onCalendarSelectAppointment() {
770   var list = $("appointmentsList");
771   list.deselectAll();
772
773   var aptCName = this.getAttribute("aptCName");
774   if (selectedCalendarCell)
775     selectedCalendarCell.deselect();
776   this.select();
777   selectedCalendarCell = this;
778   var row = $(aptCName);
779   if (row) {
780     var div = row.parentNode.parentNode.parentNode;
781     div.scrollTop = row.offsetTop - (div.offsetHeight / 2);
782     row.select();
783   }
784 }
785
786 function onCalendarSelectDay(event) {
787   var day;
788   if (currentView == "multicolumndayview")
789      day = this.parentNode.getAttribute("day");
790   else
791      day = this.getAttribute("day");
792   var needRefresh = (listFilter == 'view_selectedday'
793                      && day != currentDay);
794
795   if (currentView == 'weekview')
796     changeWeekCalendarDisplayOfSelectedDay(this);
797   else if (currentView == 'monthview')
798     changeMonthCalendarDisplayOfSelectedDay(this);
799   changeDateSelectorDisplay(day);
800
801   if (listOfSelection) {
802     listOfSelection.addClassName("_unfocused");
803     listOfSelection = null;
804   }
805
806   if (needRefresh)
807     refreshAppointments();
808 }
809
810 function changeWeekCalendarDisplayOfSelectedDay(node) {
811   var days = document.getElementsByClassName("day", node.parentNode);
812
813   for (var i = 0; i < days.length; i++)
814     if (days[i] != node)
815       days[i].removeClassName("selectedDay");
816
817   node.addClassName("selectedDay");
818 }
819
820 function findMonthCalendarSelectedCell(daysContainer) {
821    var found = false;
822    var i = 0;
823
824    while (!found && i < daysContainer.childNodes.length) {
825       var currentNode = daysContainer.childNodes[i];
826       if (currentNode instanceof HTMLDivElement
827           && currentNode.hasClassName("selectedDay")) {
828          daysContainer.selectedCell = currentNode;
829          found = true;
830       }
831       else
832          i++;
833    }
834 }
835
836 function changeMonthCalendarDisplayOfSelectedDay(node)
837 {
838    var daysContainer = node.parentNode;
839    if (!daysContainer.selectedCell)
840       findMonthCalendarSelectedCell(daysContainer);
841    
842    if (daysContainer.selectedCell)
843       daysContainer.selectedCell.removeClassName("selectedDay");
844    daysContainer.selectedCell = node;
845    node.addClassName("selectedDay");
846 }
847
848 function onHideCompletedTasks(node)
849 {
850   hideCompletedTasks = (node.checked ? 1 : 0);
851
852   return refreshTasks();
853 }
854
855 function updateTaskStatus(node)
856 {
857   var taskId = node.parentNode.getAttribute("id");
858   var taskOwner = node.parentNode.getAttribute("owner");
859   var newStatus = (node.checked ? 1 : 0);
860 //   log ("update task status: " + taskId);
861
862   var http = createHTTPClient();
863
864   url = (UserFolderURL + "../" + taskOwner + "/Calendar/"
865          + taskId + "/changeStatus?status=" + newStatus);
866
867   if (http) {
868 //     log ("url: " + url);
869     // TODO: add parameter to signal that we are only interested in OK
870     http.url = url;
871     http.open("GET", url, false /* not async */);
872     http.send("");
873     if (http.status == 200)
874       refreshTasks();
875   } else
876     log ("no http client?");
877
878   return false;
879 }
880
881 function updateCalendarStatus()
882 {
883   var list = new Array();
884
885   var clist = $("calendarsList");
886   var nodes = clist.childNodesWithTag("ul")[0].childNodesWithTag("li");
887   for (var i = 0; i < nodes.length; i++) {
888     var input = nodes[i].childNodesWithTag("input")[0];
889     if (input.checked)
890       list.push(nodes[i].getAttribute("uid"));
891   }
892
893   if (!list.length) {
894     list.push(nodes[0].getAttribute("uid"));
895     nodes[0].childNodesWithTag("input")[0].checked = true;
896   }
897 //   ApplicationBaseURL = (UserFolderURL + "Groups/_custom_"
898 //                      + list.join(",") + "/Calendar/");
899
900   updateCalendarsList();
901   refreshAppointments();
902   refreshTasks();
903   changeCalendarDisplay();
904
905   return false;
906 }
907
908 function calendarUidsList()
909 {
910   var list = "";
911
912   var nodes = $("uixselector-calendarsList-display").childNodesWithTag("li");
913   for (var i = 0; i < nodes.length; i++) {
914     var currentNode = nodes[i];
915     var input = currentNode.childNodesWithTag("input")[0];
916     if (!input.checked)
917       list += "-";
918     list += currentNode.getAttribute("uid") + ",";
919   }
920
921   return list.substr(0, list.length - 1);
922 }
923
924 // function updateCalendarContacts(contacts)
925 // {
926 //   var list = contacts.split(",");
927
928 //   var clist = $("calendarsList");
929 //   var nodes = clist.childNodes[5].childNodes;
930 //   for (var i = 0; i < nodes.length; i++) {
931 //     var currentNode = nodes[i];
932 //     if (currentNode instanceof HTMLLIElement) {
933 //       var input = currentNode.childNodes[3];
934 //       if (!input.checked)
935 //         list += "-";
936 //       list += currentNode.getAttribute("uid") + ",";
937 //     }
938 //   }
939 // }
940
941 function inhibitMyCalendarEntry()
942 {
943   var clist = $("calendarsList");
944   var nodes = clist.childNodes[5].childNodes;
945   var done = false;
946
947   var i = 0;
948   while (!done && i < nodes.length) {
949     var currentNode = nodes[i];
950     if (currentNode instanceof HTMLLIElement) {
951       var input = currentNode.childNodes[3];
952       if (currentNode.getAttribute("uid") == UserLogin) {
953         done = true;
954 //         currentNode.style.color = "#999;";
955         currentNode.style.fontWeight = "bold;";
956 //         currentNode.setAttribute("onclick", "");
957       }
958     }
959     i++;
960   }
961 }
962
963 function userCalendarEntry(user, color) {
964   var li = document.createElement("li");
965   li.setAttribute("uid", user);
966   li.addEventListener("mousedown", listRowMouseDownHandler, false);
967   li.addEventListener("click", onRowClick, false);
968   var colorBox = document.createElement("span");
969   colorBox.addClassName("colorBox");
970   if (color) {
971     log("color:  " + color);
972     colorBox.style.backgroundColor = color + ";";
973   }
974   li.appendChild(colorBox);
975   var checkBox = document.createElement("input");
976   checkBox.addClassName("checkBox");
977   checkBox.type = "checkbox";
978   checkBox.addEventListener("change", updateCalendarStatus, false);
979   li.appendChild(checkBox);
980   var text = document.createTextNode(" " + user);
981   li.appendChild(text);
982
983   return li;
984 }
985
986 function ensureSelfIfPresent() {
987   var ul = $("uixselector-calendarsList-display");
988   var list = ul.childNodesWithTag("li");
989   var selfEntry = userCalendarEntry(UserLogin, indexColor(0));
990   selfEntry.style.fontWeight = "bold;";
991   if (list.length < 1) {
992     ul.appendChild(selfEntry);
993   } else if (list[0].getAttribute("uid") != UserLogin) {
994     ul.insertBefore(selfEntry, list[0]);
995   }
996 }
997
998 function updateCalendarsList(method)
999 {
1000   ensureSelfIfPresent();
1001   var url = (ApplicationBaseURL + "updateCalendars?ids="
1002              + calendarUidsList());
1003   if (document.calendarsListAjaxRequest) {
1004     document.calendarsListAjaxRequest.aborted = true;
1005     document.calendarsListAjaxRequest.abort();
1006   }
1007   var http = createHTTPClient();
1008   if (http) {
1009     http.url = url;
1010     http.open("GET", url, false);
1011     http.send("");
1012
1013     if (method == "removal")
1014       updateCalendarStatus();
1015
1016     http = createHTTPClient();
1017     http.url = ApplicationBaseURL + "checkRights";
1018     http.open("GET", http.url, false /* not async */);
1019     http.send("");
1020     if (http.status == 200
1021         && http.responseText.length > 0) {
1022       rights = http.responseText.split(",");
1023       var list = $("uixselector-calendarsList-display").childNodesWithTag("li");
1024       for (var i = 0; i < list.length; i++) {
1025         var input = list[i].childNodesWithTag("input")[0];
1026         if (rights[i] == "1") {
1027           list[i].removeClassName("denied");
1028           input.disabled = false;
1029         }
1030         else {
1031           input.checked = false;
1032           input.disabled = true;
1033           list[i].addClassName("denied");
1034         }
1035       }
1036     }
1037   }
1038 }
1039
1040 function addContact(tag, fullContactName, contactId, contactName, contactEmail)
1041 {
1042   var uids = $("uixselector-calendarsList-uidList");
1043 //   log("addContact");
1044   if (contactId)
1045     {
1046       var re = new RegExp("(^|,)" + contactId + "($|,)");
1047
1048       if (!re.test(uids.value))
1049         {
1050           if (uids.value.length > 0)
1051             uids.value += ',' + contactId;
1052           else
1053             uids.value = contactId;
1054           var names = $("uixselector-calendarsList-display");
1055           var listElems = names.childNodesWithTag("li");
1056           var colorDef = indexColor(listElems.length);
1057           names.appendChild(userCalendarEntry(contactId, colorDef));
1058
1059           var styles = document.getElementsByTagName("style");
1060           styles[0].innerHTML += ('.ownerIs' + contactId + ' {'
1061                                   + ' background-color: '
1062                                   + colorDef
1063                                   + ' !important; }');
1064         }
1065     }
1066
1067   return false;
1068 }
1069
1070 function onChangeCalendar(list) {
1071    var form = document.forms.editform;
1072    log ("before: " + form.getAttribute("action"));
1073    var urlElems = form.getAttribute("action").split("/");
1074    urlElems[urlElems.length-4]
1075       = list.childNodesWithTag("option")[list.value].innerHTML;
1076    form.setAttribute("action", urlElems.join("/"));
1077    log ("after: " + form.getAttribute("action"));
1078 }
1079
1080 function validateBrowseURL(input) {
1081   var button = $("browseURLBtn");
1082
1083   if (input.value.length) {
1084     if (!button.enabled)
1085       enableAnchor(button);
1086   } else if (!button.disabled)
1087     disableAnchor(button);
1088 }
1089
1090 function browseURL(anchor, event) {
1091   if (event.button == 0) {
1092     var input = $("url");
1093     var url = input.value;
1094     if (url.length)
1095       window.open(url, '_blank');
1096   }
1097
1098   return false;
1099 }
1100
1101 function initializeMenus() {
1102   var menus = new Array("monthListMenu", "yearListMenu",
1103                         "appointmentsListMenu", "calendarsMenu", "searchMenu");
1104   initMenusNamed(menus);
1105
1106   $("calendarsList").attachMenu("calendarsMenu");
1107
1108   var accessRightsMenuEntry = $("accessRightsMenuEntry");
1109   accessRightsMenuEntry.addEventListener("mouseup",
1110                                          onAccessRightsMenuEntryMouseUp,
1111                                          false);
1112 }
1113
1114 function onAccessRightsMenuEntryMouseUp(event) {
1115   var folders = $("uixselector-calendarsList-display");
1116   var selected = folders.getSelectedNodes()[0];
1117   var uid = selected.getAttribute("uid");
1118   log("application base url: " + ApplicationBaseURL);
1119   if (uid == UserLogin)
1120     url = ApplicationBaseURL + "acls";
1121   else
1122     url = UserFolderURL + "../" + uid + "/Calendar/acls";
1123
1124   openAclWindow(url, uid);
1125 }
1126
1127 function configureDragHandles() {
1128   var handle = $("verticalDragHandle");
1129   if (handle) {
1130     handle.addInterface(SOGoDragHandlesInterface);
1131     handle.leftBlock=$("leftPanel");
1132     handle.rightBlock=$("rightPanel");
1133   }
1134
1135   handle = $("rightDragHandle");
1136   if (handle) {
1137     handle.addInterface(SOGoDragHandlesInterface);
1138     handle.upperBlock=$("appointmentsListView");
1139     handle.lowerBlock=$("calendarView");
1140   }
1141 }
1142
1143 function initCalendarContactsSelector() {
1144   var selector = $("calendarsList");
1145   inhibitMyCalendarEntry();
1146   updateCalendarStatus();
1147   selector.changeNotification = updateCalendarsList;
1148
1149   var list = $("uixselector-calendarsList-display").childNodesWithTag("li");
1150   for (var i = 0; i < list.length; i++) {
1151     var input = list[i].childNodesWithTag("input")[0];
1152     input.addEventListener("change", updateCalendarStatus, false);
1153   }
1154 }
1155
1156 function initCalendars() {
1157   if (!document.body.hasClassName("popup"))
1158     initCalendarContactsSelector();
1159 }
1160
1161 function onSchedulerBodyKeyUp(event) {
1162    if (event.which == 46) {
1163       window.alert("coucou");
1164       deleteEvent();
1165       event.cancelBubble = true;
1166    }
1167 }
1168
1169 window.addEventListener("load", initCalendars, false);
1170 // document.body.addEventListener("keyup", onSchedulerBodyKeyUp, false);