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