1 /* JavaScript for SOGoCalendar */
3 var listFilter = 'view_today';
5 var listOfSelection = null;
6 var selectedCalendarCell;
7 var calendarColorIndex = null;
9 var showCompletedTasks = 0;
12 var currentView = "weekview";
14 var cachedDateSelectors = new Array();
16 var contactSelectorAction = 'calendars-contacts';
18 var eventsToDelete = new Array();
19 var calendarsOfEventsToDelete = new Array();
21 var usersRightsWindowHeight = 250;
22 var usersRightsWindowWidth = 502;
24 function newEvent(sender, type) {
25 var day = sender.readAttribute("day");
28 var hour = sender.readAttribute("hour");
29 var folder = getSelectedFolder();
30 var folderID = folder.readAttribute("id");
31 var roles = folder.readAttribute("roles");
33 roles = roles.split(",")
34 if ($(roles).indexOf("PublicModifier") < 0)
35 folderID = "/personal";
37 var urlstr = ApplicationBaseURL + folderID + "/new" + type;
38 var params = new Array();
40 params.push("day=" + day);
42 params.push("hm=" + hour);
43 if (params.length > 0)
44 urlstr += "?" + params.join("&");
45 window.open(urlstr, "", "width=490,height=470,resizable=0");
47 return false; /* stop following the link */
50 function getSelectedFolder() {
52 var list = $("calendarList");
53 var nodes = list.getSelectedRows();
57 folder = list.down("li");
62 function onMenuNewEventClick(event) {
63 newEvent(this, "event");
66 function onMenuNewTaskClick(event) {
67 newEvent(this, "task");
70 function _editEventId(id, calendar) {
71 var urlstr = ApplicationBaseURL + "/" + calendar + "/" + id + "/edit";
72 var targetname = "SOGo_edit_" + id;
73 var win = window.open(urlstr, "_blank",
74 "width=490,height=470,resizable=0");
79 function editEvent() {
80 if (listOfSelection) {
81 var nodes = listOfSelection.getSelectedRows();
83 if (nodes.length == 0) {
84 window.alert(labels["Please select an event or a task."]);
88 for (var i = 0; i < nodes.length; i++)
89 _editEventId(nodes[i].getAttribute("id"),
91 } else if (selectedCalendarCell) {
92 _editEventId(selectedCalendarCell[0].cname,
93 selectedCalendarCell[0].calendar);
95 window.alert(labels["Please select an event or a task."]);
98 return false; /* stop following the link */
101 function _batchDeleteEvents() {
102 var events = eventsToDelete.shift();
103 var calendar = calendarsOfEventsToDelete.shift();
104 var urlstr = (ApplicationBaseURL + "/" + calendar
105 + "/batchDelete?ids=" + events.join('/'));
106 document.deleteEventAjaxRequest = triggerAjaxRequest(urlstr,
111 function deleteEvent() {
112 if (listOfSelection) {
113 var nodes = listOfSelection.getSelectedRows();
115 if (nodes.length > 0) {
117 if (listOfSelection == $("tasksList"))
118 label = labels["taskDeleteConfirmation"];
120 label = labels["eventDeleteConfirmation"];
122 if (confirm(label)) {
123 if (document.deleteEventAjaxRequest) {
124 document.deleteEventAjaxRequest.aborted = true;
125 document.deleteEventAjaxRequest.abort();
127 var sortedNodes = new Array();
128 var calendars = new Array();
130 for (var i = 0; i < nodes.length; i++) {
131 var calendar = nodes[i].calendar;
132 if (!sortedNodes[calendar]) {
133 sortedNodes[calendar] = new Array();
134 calendars.push(calendar);
136 sortedNodes[calendar].push(nodes[i].cname);
138 for (var i = 0; i < calendars.length; i++) {
139 calendarsOfEventsToDelete.push(calendars[i]);
140 eventsToDelete.push(sortedNodes[calendars[i]]);
142 _batchDeleteEvents();
145 window.alert(labels["Please select an event or a task."]);
148 else if (selectedCalendarCell) {
149 var label = labels["eventDeleteConfirmation"];
150 if (confirm(label)) {
151 if (document.deleteEventAjaxRequest) {
152 document.deleteEventAjaxRequest.aborted = true;
153 document.deleteEventAjaxRequest.abort();
155 eventsToDelete.push([selectedCalendarCell[0].cname]);
156 calendarsOfEventsToDelete.push(selectedCalendarCell[0].calendar);
157 _batchDeleteEvents();
161 window.alert(labels["Please select an event or a task."]);
166 function modifyEvent(sender, modification) {
167 var currentLocation = '' + window.location;
168 var arr = currentLocation.split("/");
169 arr[arr.length-1] = modification;
171 document.modifyEventAjaxRequest = triggerAjaxRequest(arr.join("/"),
178 function closeInvitationWindow() {
179 var closeDiv = document.createElement("div");
180 document.body.appendChild(closeDiv);
181 closeDiv.addClassName("javascriptPopupBackground");
183 var closePseudoWin = document.createElement("div");
184 document.body.appendChild(closePseudoWin);
185 closePseudoWin.addClassName("javascriptMessagePseudoTopWindow");
186 closePseudoWin.style.top = "0px;";
187 closePseudoWin.style.left = "0px;";
188 closePseudoWin.style.right = "0px;";
189 closePseudoWin.appendChild(document.createTextNode(labels["closeThisWindowMessage"]));
191 var calLink = document.createElement("a");
192 closePseudoWin.appendChild(calLink);
193 calLink.href = ApplicationBaseURL;
194 calLink.appendChild(document.createTextNode(labels["Calendar"].toLowerCase()));
197 function modifyEventCallback(http) {
198 if (http.readyState == 4) {
199 if (http.status == 200) {
200 var mailInvitation = queryParameters["mail-invitation"];
201 if (mailInvitation && mailInvitation.toLowerCase() == "yes")
202 closeInvitationWindow();
204 window.opener.setTimeout("refreshEventsAndDisplay();", 100);
205 window.setTimeout("window.close();", 100);
209 // log("showing alert...");
210 window.alert(labels["eventPartStatModificationError"]);
212 document.modifyEventAjaxRequest = null;
216 function deleteEventCallback(http) {
217 if (http.readyState == 4) {
218 if (isHttpStatus204(http.status)) {
219 var nodes = http.callbackData;
220 for (var i = 0; i < nodes.length; i++) {
221 var node = $(nodes[i]);
223 node.parentNode.removeChild(node);
225 if (eventsToDelete.length)
226 _batchDeleteEvents();
228 document.deleteEventAjaxRequest = null;
231 changeCalendarDisplay();
235 log ("deleteEventCallback Ajax error");
239 function editDoubleClickedEvent(event) {
240 _editEventId(this.cname, this.calendar);
242 preventDefault(event);
243 event.cancelBubble = true;
246 function onSelectAll() {
247 var list = $("eventsList");
248 list.selectRowsMatchingClass("eventRow");
253 function onDaySelect(node) {
254 var day = node.getAttribute('day');
255 var needRefresh = (listFilter == 'view_selectedday'
256 && day != currentDay);
258 var td = $(node).getParentWithTagName("td");
259 var table = $(td).getParentWithTagName("table");
261 // log ("table.selected: " + table.selected);
263 if (document.selectedDate)
264 document.selectedDate.deselect();
267 document.selectedDate = td;
269 changeCalendarDisplay( { "day": day } );
276 function onDateSelectorGotoMonth(event) {
277 var day = this.getAttribute("date");
279 changeDateSelectorDisplay(day, true);
284 function onCalendarGotoDay(node) {
285 var day = node.getAttribute("date");
287 changeDateSelectorDisplay(day);
288 changeCalendarDisplay( { "day": day } );
293 function gotoToday() {
294 changeDateSelectorDisplay('');
295 changeCalendarDisplay();
300 function setDateSelectorContent(content) {
301 var div = $("dateSelectorView");
303 div.innerHTML = content;
304 if (currentDay.length > 0)
305 restoreCurrentDaySelection(div);
307 initDateSelectorEvents();
310 function dateSelectorCallback(http) {
311 if (http.readyState == 4
312 && http.status == 200) {
313 document.dateSelectorAjaxRequest = null;
314 var content = http.responseText;
315 setDateSelectorContent(content);
316 cachedDateSelectors[http.callbackData] = content;
319 log ("dateSelectorCallback Ajax error");
322 function eventsListCallback(http) {
323 if (http.readyState == 4
324 && http.status == 200) {
325 var div = $("eventsListView");
327 document.eventsListAjaxRequest = null;
328 var table = $("eventsList");
329 lastClickedRow = -1; // from generic.js
331 if (http.responseText.length > 0) {
332 var data = http.responseText.evalJSON(true);
333 for (var i = 0; i < data.length; i++) {
334 var row = document.createElement("tr");
335 table.tBodies[0].appendChild(row);
336 $(row).addClassName("eventRow");
337 row.setAttribute("id", escape(data[i][0]));
338 row.cname = escape(data[i][0]);
339 row.calendar = data[i][1];
341 var startDate = new Date();
342 startDate.setTime(data[i][4] * 1000);
343 row.day = startDate.getDayString();
344 row.hour = startDate.getHourString();
345 Event.observe(row, "mousedown", onRowClick);
346 Event.observe(row, "selectstart", listRowMouseDownHandler);
347 Event.observe(row, "dblclick",
348 editDoubleClickedEvent.bindAsEventListener(row));
349 Event.observe(row, "contextmenu",
350 onEventContextMenu.bindAsEventListener(row));
352 var td = document.createElement("td");
354 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
355 td.appendChild(document.createTextNode(data[i][3]));
357 td = document.createElement("td");
359 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
360 td.appendChild(document.createTextNode(data[i][10]));
362 td = document.createElement("td");
364 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
365 td.appendChild(document.createTextNode(data[i][11]));
367 td = document.createElement("td");
369 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
370 td.appendChild(document.createTextNode(data[i][6]));
373 if (sorting["attribute"] && sorting["attribute"].length > 0) {
374 var sortHeader = $(sorting["attribute"] + "Header");
377 var sortImages = $(table.tHead).getElementsByClassName("sortImage");
378 $(sortImages).each(function(item) {
382 var sortImage = createElement("img", "messageSortImage", "sortImage");
383 sortHeader.insertBefore(sortImage, sortHeader.firstChild);
384 if (sorting["ascending"])
385 sortImage.src = ResourcesURL + "/title_sortdown_12x12.png";
387 sortImage.src = ResourcesURL + "/title_sortup_12x12.png";
393 log ("eventsListCallback Ajax error");
396 function tasksListCallback(http) {
397 var div = $("tasksListView");
399 if (http.readyState == 4
400 && http.status == 200) {
401 document.tasksListAjaxRequest = null;
402 var list = $("tasksList");
404 if (http.responseText.length > 0) {
405 var data = http.responseText.evalJSON(true);
407 for (var i = 0; i < data.length; i++) {
408 var listItem = document.createElement("li");
409 list.appendChild(listItem);
410 Event.observe(listItem, "mousedown", listRowMouseDownHandler);
411 Event.observe(listItem, "click", onRowClick);
412 Event.observe(listItem, "dblclick",
413 editDoubleClickedEvent.bindAsEventListener(listItem));
414 listItem.setAttribute("id", data[i][0]);
415 $(listItem).addClassName(data[i][5]);
416 $(listItem).addClassName(data[i][6]);
417 listItem.calendar = data[i][1];
418 $(listItem).addClassName("calendarFolder" + data[i][1]);
419 listItem.cname = escape(data[i][0]);
420 var input = document.createElement("input");
421 input.setAttribute("type", "checkbox");
422 listItem.appendChild(input);
423 Event.observe(input, "click", updateTaskStatus.bindAsEventListener(input), true);
424 input.setAttribute("value", "1");
426 input.setAttribute("checked", "checked");
427 $(input).addClassName("checkBox");
428 listItem.appendChild(document.createTextNode(data[i][3]));
431 list.scrollTop = list.previousScroll;
433 if (http.callbackData) {
434 var selectedNodesId = http.callbackData;
435 for (var i = 0; i < selectedNodesId.length; i++) {
436 // log(selectedNodesId[i] + " (" + i + ") is selected");
437 $(selectedNodesId[i]).select();
441 log ("tasksListCallback: no data");
445 log ("tasksListCallback Ajax error");
448 function restoreCurrentDaySelection(div) {
449 var elements = $(div).getElementsByTagName("a");
452 while (!day && i < elements.length)
454 day = elements[i].day;
459 && day.substr(0, 6) == currentDay.substr(0, 6)) {
460 for (i = 0; i < elements.length; i++) {
461 day = elements[i].day;
462 if (day && day == currentDay) {
463 var td = $(elements[i]).getParentWithTagName("td");
464 if (document.selectedDate)
465 document.selectedDate.deselect();
467 document.selectedDate = td;
473 function changeDateSelectorDisplay(day, keepCurrentDay) {
474 var url = ApplicationBaseURL + "dateselector";
476 url += "?day=" + day;
478 if (day != currentDay) {
482 var month = day.substr(0, 6);
483 if (cachedDateSelectors[month]) {
484 // log ("restoring cached selector for month: " + month);
485 setDateSelectorContent(cachedDateSelectors[month]);
488 // log ("loading selector for month: " + month);
489 if (document.dateSelectorAjaxRequest) {
490 document.dateSelectorAjaxRequest.aborted = true;
491 document.dateSelectorAjaxRequest.abort();
493 document.dateSelectorAjaxRequest
494 = triggerAjaxRequest(url,
495 dateSelectorCallback,
501 function changeCalendarDisplay(data, newView) {
502 var url = ApplicationBaseURL + ((newView) ? newView : currentView);
504 var scrollEvent = null;
508 scrollEvent = data['scrollEvent'];
516 var divs = $$('div.day[day='+day+']');
518 // Don't reload the view if the event is present in current view
520 // Deselect previous day
521 var selectedDivs = $$('div.day.selectedDay');
522 selectedDivs.each(function(div) {
523 div.removeClassName('selectedDay');
527 divs.each(function(div) {
528 div.addClassName('selectedDay');
531 // Deselect day in date selector
532 if (document.selectedDate)
533 document.selectedDate.deselect();
535 // Select day in date selector
536 var selectedLink = $$('table#dateSelectorTable a[day='+day+']');
537 if (selectedLink.length > 0) {
538 selectedCell = selectedLink[0].up(1);
539 selectedCell.select();
540 document.selectedDate = selectedCell;
544 scrollDayView(scrollEvent);
549 url += "?day=" + day;
552 // log ("switching to view: " + newView);
553 // log ("changeCalendarDisplay: " + url);
555 selectedCalendarCell = null;
557 if (document.dayDisplayAjaxRequest) {
558 // log ("aborting day ajaxrq");
559 document.dayDisplayAjaxRequest.aborted = true;
560 document.dayDisplayAjaxRequest.abort();
562 document.dayDisplayAjaxRequest
563 = triggerAjaxRequest(url, calendarDisplayCallback,
566 "scrollEvent": scrollEvent });
571 function _ensureView(view) {
572 if (currentView != view)
573 changeCalendarDisplay(null, view);
578 function onDayOverview() {
579 return _ensureView("dayview");
582 function onMulticolumnDayOverview() {
583 return _ensureView("multicolumndayview");
586 function onWeekOverview() {
587 return _ensureView("weekview");
590 function onMonthOverview() {
591 return _ensureView("monthview");
594 function scrollDayView(scrollEvent) {
597 // Select event in calendar view
599 divs = $$("div#calendarContent div." + eventClass(scrollEvent));
600 selectCalendarEvent(divs[0]);
603 // Don't scroll if in month view
604 if (currentView == "monthview")
608 var daysView = $("daysView");
610 $(daysView.childNodesWithTag("div")[0]).childNodesWithTag("div");
613 divs = $$("div#calendarContent div." + eventClass(scrollEvent));
614 var classes = $w(divs[0].className);
615 for (var i = 0; i < classes.length; i++) {
616 if (classes[i].startsWith("starts")) {
617 var starts = Math.floor(parseInt(classes[i].substr(6)) / 4);
618 offset = hours[starts].offsetTop;
624 offset = hours[8].offsetTop;
626 daysView.scrollTop = offset - 5;
629 function onClickableCellsDblClick(event) {
630 newEvent(this, 'event');
632 event.cancelBubble = true;
633 event.returnValue = false;
636 function refreshCalendarEvents(scrollEvent) {
637 var todayDate = new Date();
640 if (currentView == "dayview") {
644 sd = todayDate.getDayString();
647 else if (currentView == "weekview") {
650 startDate = currentDay.asDate();
652 startDate = todayDate;
653 startDate = startDate.beginOfWeek();
654 sd = startDate.getDayString();
655 var endDate = new Date();
656 endDate.setTime(startDate.getTime());
658 ed = endDate.getDayString();
663 monthDate = currentDay.asDate();
665 monthDate = todayDate;
666 monthDate.setDate(1);
667 sd = monthDate.beginOfWeek().getDayString();
669 var lastMonthDate = new Date();
670 lastMonthDate.setTime(monthDate.getTime());
671 lastMonthDate.setMonth(monthDate.getMonth() + 1);
672 lastMonthDate.addDays(-1);
673 ed = lastMonthDate.endOfWeek().getDayString();
675 if (document.refreshCalendarEventsAjaxRequest) {
676 document.refreshCalendarEventsAjaxRequest.aborted = true;
677 document.refreshCalendarEventsAjaxRequest.abort();
679 var url = ApplicationBaseURL + "eventslist?sd=" + sd + "&ed=" + ed;
680 document.refreshCalendarEventsAjaxRequest
681 = triggerAjaxRequest(url, refreshCalendarEventsCallback,
682 {"startDate": sd, "endDate": ed,
683 "scrollEvent": scrollEvent});
686 function refreshCalendarEventsCallback(http) {
687 if (http.readyState == 4
688 && http.status == 200) {
690 if (http.responseText.length > 0) {
691 var data = http.responseText.evalJSON(true);
692 // log("refresh calendar events: " + data.length);
693 for (var i = 0; i < data.length; i++)
694 drawCalendarEvent(data[i],
695 http.callbackData["startDate"],
696 http.callbackData["endDate"]);
698 scrollDayView(http.callbackData["scrollEvent"]);
701 log("AJAX error when refreshing calendar events");
704 function drawCalendarEvent(eventData, sd, ed) {
705 var viewStartDate = sd.asDate();
706 var viewEndDate = ed.asDate();
708 var startDate = new Date();
709 startDate.setTime(eventData[4] * 1000);
710 var endDate = new Date();
711 endDate.setTime(eventData[5] * 1000);
713 // log ("s: " + startDate + "; e: " + endDate);
715 var days = startDate.daysUpTo(endDate);
718 if (currentView == "monthview"
719 && (eventData[7] == 0))
720 title = startDate.getDisplayHoursString() + " " + eventData[3];
722 title = eventData[3];
724 // log("title: " + title);
725 // log("viewS: " + viewStartDate);
726 var startHour = null;
729 var siblings = new Array();
730 for (var i = 0; i < days.length; i++)
731 if (days[i].earlierDate(viewStartDate) == viewStartDate
732 && days[i].laterDate(viewEndDate) == viewEndDate) {
735 // log("day: " + days[i]);
737 var quarters = (startDate.getUTCHours() * 4
738 + Math.floor(startDate.getUTCMinutes() / 15));
740 startHour = startDate.getDisplayHoursString();
741 endHour = endDate.getDisplayHoursString();
748 if (i == days.length - 1) {
749 var quarters = (endDate.getUTCHours() * 4
750 + Math.ceil(endDate.getUTCMinutes() / 15));
755 lasts = ends - starts;
759 var eventDiv = newEventDIV(eventData[0], eventData[1], starts, lasts,
761 siblings.push(eventDiv);
762 eventDiv.siblings = siblings;
763 if (eventData[9].length > 0)
764 eventDiv.addClassName(eventData[9]);
765 var dayString = days[i].getDayString();
766 // log("day: " + dayString);
767 var parentDiv = null;
768 if (currentView == "monthview") {
769 var dayDivs = $("monthDaysView").childNodesWithTag("div");
771 while (!parentDiv && j < dayDivs.length) {
772 if (dayDivs[j].getAttribute("day") == dayString)
773 parentDiv = dayDivs[j];
779 if (eventData[7] == 0) {
780 var daysView = $("daysView");
781 var eventsDiv = $(daysView).childNodesWithTag("div")[1];
782 var dayDivs = $(eventsDiv).childNodesWithTag("div");
784 while (!parentDiv && j < dayDivs.length) {
785 if (dayDivs[j].getAttribute("day") == dayString)
786 parentDiv = dayDivs[j].childNodesWithTag("div")[0];
792 var header = $("calendarHeader");
793 var daysDiv = $(header).childNodesWithTag("div")[1];
794 var dayDivs = $(daysDiv).childNodesWithTag("div");
796 while (!parentDiv && j < dayDivs.length) {
797 if (dayDivs[j].getAttribute("day") == dayString)
798 parentDiv = dayDivs[j];
805 parentDiv.appendChild(eventDiv);
809 function eventClass(cname) {
810 return escape(cname.replace(".", "-"));
814 function newEventDIV(cname, calendar, starts, lasts,
815 startHour, endHour, title) {
816 var eventDiv = document.createElement("div");
817 eventDiv.cname = escape(cname);
818 eventDiv.calendar = calendar;
819 $(eventDiv).addClassName("event");
820 $(eventDiv).addClassName(eventClass(cname));
821 $(eventDiv).addClassName("starts" + starts);
822 $(eventDiv).addClassName("lasts" + lasts);
823 for (var i = 1; i < 5; i++) {
824 var shadowDiv = document.createElement("div");
825 eventDiv.appendChild(shadowDiv);
826 $(shadowDiv).addClassName("shadow");
827 $(shadowDiv).addClassName("shadow" + i);
829 var innerDiv = document.createElement("div");
830 eventDiv.appendChild(innerDiv);
831 $(innerDiv).addClassName("eventInside");
832 $(innerDiv).addClassName("calendarFolder" + calendar);
834 var gradientDiv = document.createElement("div");
835 innerDiv.appendChild(gradientDiv);
836 $(gradientDiv).addClassName("gradient");
837 var gradientImg = document.createElement("img");
838 gradientDiv.appendChild(gradientImg);
839 gradientImg.src = ResourcesURL + "/event-gradient.png";
841 var textDiv = document.createElement("div");
842 innerDiv.appendChild(textDiv);
843 $(textDiv).addClassName("text");
845 var headerSpan = document.createElement("span");
846 textDiv.appendChild(headerSpan);
847 $(headerSpan).addClassName("eventHeader");
848 headerSpan.appendChild(document.createTextNode(startHour + " - "
850 textDiv.appendChild(document.createElement("br"));
852 textDiv.appendChild(document.createTextNode(title));
854 Event.observe(eventDiv, "mousedown", listRowMouseDownHandler);
855 Event.observe(eventDiv, "click",
856 onCalendarSelectEvent.bindAsEventListener(eventDiv));
857 Event.observe(eventDiv, "dblclick",
858 editDoubleClickedEvent.bindAsEventListener(eventDiv));
863 function calendarDisplayCallback(http) {
864 var div = $("calendarView");
866 if (http.readyState == 4
867 && http.status == 200) {
868 document.dayDisplayAjaxRequest = null;
869 div.update(http.responseText);
870 if (http.callbackData["view"])
871 currentView = http.callbackData["view"];
872 if (http.callbackData["day"])
873 currentDay = http.callbackData["day"];
876 if (currentView == "monthview")
877 contentView = $("calendarContent");
879 contentView = $("daysView");
881 refreshCalendarEvents(http.callbackData.scrollEvent);
883 var days = document.getElementsByClassName("day", contentView);
884 if (currentView == "monthview")
885 for (var i = 0; i < days.length; i++) {
886 Event.observe(days[i], "click",
887 onCalendarSelectDay.bindAsEventListener(days[i]));
888 Event.observe(days[i], "dblclick",
889 onClickableCellsDblClick.bindAsEventListener(days[i]));
892 var headerDivs = $("calendarHeader").childNodesWithTag("div");
893 var headerDaysLabels = document.getElementsByClassName("day", headerDivs[0]);
894 var headerDays = document.getElementsByClassName("day", headerDivs[1]);
895 for (var i = 0; i < days.length; i++) {
896 headerDays[i].hour = "allday";
897 Event.observe(headerDaysLabels[i], "mousedown", listRowMouseDownHandler);
898 Event.observe(headerDays[i], "click",
899 onCalendarSelectDay.bindAsEventListener(days[i]));
900 Event.observe(headerDays[i], "dblclick",
901 onClickableCellsDblClick.bindAsEventListener(headerDays[i]));
902 Event.observe(days[i], "click",
903 onCalendarSelectDay.bindAsEventListener(days[i]));
904 var clickableCells = document.getElementsByClassName("clickableHourCell",
906 for (var j = 0; j < clickableCells.length; j++)
907 Event.observe(clickableCells[j], "dblclick",
908 onClickableCellsDblClick.bindAsEventListener(clickableCells[j]));
913 log ("calendarDisplayCallback Ajax error (" + http.readyState + "/" + http.status + ")");
916 function assignCalendar(name) {
917 if (typeof(skycalendar) != "undefined") {
920 node.calendar = new skycalendar(node);
921 node.calendar.setCalendarPage(ResourcesURL + "/skycalendar.html");
922 var dateFormat = node.getAttribute("dateFormat");
924 node.calendar.setDateFormat(dateFormat);
928 function popupCalendar(node) {
929 var nodeId = $(node).readAttribute("inputId");
930 var input = $(nodeId);
931 input.calendar.popup();
936 function onEventContextMenu(event) {
937 var topNode = $("eventsList");
938 var menu = $("eventsListMenu");
940 Event.observe(menu, "hideMenu", onEventContextMenuHide);
941 popupMenu(event, "eventsListMenu", this);
944 function onEventContextMenuHide(event) {
945 var topNode = $("eventsList");
947 if (topNode.menuSelectedEntry) {
948 topNode.menuSelectedEntry.deselect();
949 topNode.menuSelectedEntry = null;
953 function onEventsSelectionChange() {
954 listOfSelection = this;
955 this.removeClassName("_unfocused");
956 $("tasksList").addClassName("_unfocused");
958 var rows = this.tBodies[0].getSelectedNodes();
959 if (rows.length == 1) {
961 changeCalendarDisplay( { "day": row.day,
962 "scrollEvent": row.getAttribute("id") } );
963 changeDateSelectorDisplay(row.day);
967 function onTasksSelectionChange() {
968 listOfSelection = this;
969 this.removeClassName("_unfocused");
970 $("eventsList").addClassName("_unfocused");
973 function _loadEventHref(href) {
974 if (document.eventsListAjaxRequest) {
975 document.eventsListAjaxRequest.aborted = true;
976 document.eventsListAjaxRequest.abort();
978 var url = ApplicationBaseURL + "/" + href;
979 document.eventsListAjaxRequest
980 = triggerAjaxRequest(url, eventsListCallback, href);
982 var table = $("eventsList").tBodies[0];
983 while (table.rows.length > 0)
984 table.removeChild(table.rows[0]);
989 function _loadTasksHref(href) {
990 if (document.tasksListAjaxRequest) {
991 document.tasksListAjaxRequest.aborted = true;
992 document.tasksListAjaxRequest.abort();
994 url = ApplicationBaseURL + href;
996 var tasksList = $("tasksList");
999 selectedIds = tasksList.getSelectedNodesId();
1002 document.tasksListAjaxRequest
1003 = triggerAjaxRequest(url, tasksListCallback, selectedIds);
1005 tasksList.previousScroll = tasksList.scrollTop;
1006 while (tasksList.childNodes.length)
1007 tasksList.removeChild(tasksList.childNodes[0]);
1012 function onHeaderClick(event) {
1013 var headerId = this.getAttribute("id");
1014 var newSortAttribute;
1015 if (headerId == "titleHeader")
1016 newSortAttribute = "title";
1017 else if (headerId == "startHeader")
1018 newSortAttribute = "start";
1019 else if (headerId == "endHeader")
1020 newSortAttribute = "end";
1021 else if (headerId == "locationHeader")
1022 newSortAttribute = "location";
1024 newSortAttribute = "start";
1026 if (sorting["attribute"] == newSortAttribute)
1027 sorting["ascending"] = !sorting["ascending"];
1029 sorting["attribute"] = newSortAttribute;
1030 sorting["ascending"] = true;
1037 function refreshCurrentFolder() {
1041 function refreshEvents() {
1043 var value = search["value"];
1044 if (value && value.length)
1045 titleSearch = "&search=" + value;
1049 return _loadEventHref("eventslist?asc=" + sorting["ascending"]
1050 + "&sort=" + sorting["attribute"]
1051 + "&day=" + currentDay
1053 + "&filterpopup=" + listFilter);
1056 function refreshTasks() {
1057 return _loadTasksHref("taskslist?show-completed=" + showCompletedTasks);
1060 function refreshEventsAndDisplay() {
1062 changeCalendarDisplay();
1065 function onListFilterChange() {
1066 var node = $("filterpopup");
1068 listFilter = node.value;
1069 // log ("listFilter = " + listFilter);
1071 return refreshEvents();
1074 function selectMonthInMenu(menu, month) {
1075 var entries = menu.childNodes[1].childNodesWithTag("LI");
1076 for (i = 0; i < entries.length; i++) {
1077 var entry = entries[i];
1078 var entryMonth = entry.getAttribute("month");
1079 if (entryMonth == month)
1080 entry.addClassName("currentMonth");
1082 entry.removeClassName("currentMonth");
1086 function selectYearInMenu(menu, month) {
1087 var entries = menu.childNodes[1].childNodes;
1088 for (i = 0; i < entries.length; i++) {
1089 var entry = entries[i];
1090 if (entry.tagName == "LI") {
1091 var entryMonth = entry.innerHTML;
1092 if (entryMonth == month)
1093 entry.addClassName("currentMonth");
1095 entry.removeClassName("currentMonth");
1100 function popupMonthMenu(event) {
1101 if (event.button == 0) {
1102 var id = this.getAttribute("id");
1103 if (id == "monthLabel")
1104 menuId = "monthListMenu";
1106 menuId = "yearListMenu";
1108 var popup = $(menuId);
1109 if (id == "monthLabel")
1110 selectMonthInMenu(popup, this.getAttribute("month"));
1112 selectYearInMenu(popup, this.innerHTML);
1114 popupToolbarMenu(this, menuId);
1119 function onMonthMenuItemClick(event) {
1120 var month = '' + this.getAttribute("month");
1121 var year = '' + $("yearLabel").innerHTML;
1123 changeDateSelectorDisplay(year + month + "01", true);
1126 function onYearMenuItemClick(event) {
1127 var month = '' + $("monthLabel").getAttribute("month");;
1128 var year = '' + this.innerHTML;
1130 changeDateSelectorDisplay(year + month + "01", true);
1133 function selectCalendarEvent(div) {
1134 // Select event in calendar view
1135 if (selectedCalendarCell)
1136 for (var i = 0; i < selectedCalendarCell.length; i++)
1137 selectedCalendarCell[i].deselect();
1139 for (var i = 0; i < div.siblings.length; i++)
1140 div.siblings[i].select();
1142 selectedCalendarCell = div.siblings;
1145 function onCalendarSelectEvent() {
1146 var list = $("eventsList");
1148 selectCalendarEvent(this);
1150 // Select event in events list
1151 $(list.tBodies[0]).deselectAll();
1152 var row = $(this.cname);
1154 var div = row.parentNode.parentNode.parentNode;
1155 div.scrollTop = row.offsetTop - (div.offsetHeight / 2);
1160 function onCalendarSelectDay(event) {
1162 if (currentView == "multicolumndayview")
1163 day = this.getAttribute("day");
1165 day = this.getAttribute("day");
1166 var needRefresh = (listFilter == 'view_selectedday'
1167 && day != currentDay);
1169 if (currentView == 'weekview')
1170 changeWeekCalendarDisplayOfSelectedDay(this);
1171 else if (currentView == 'monthview')
1172 changeMonthCalendarDisplayOfSelectedDay(this);
1173 changeDateSelectorDisplay(day);
1175 if (listOfSelection) {
1176 listOfSelection.addClassName("_unfocused");
1177 listOfSelection = null;
1184 function changeWeekCalendarDisplayOfSelectedDay(node) {
1185 var days = document.getElementsByClassName("day", node.parentNode);
1186 var headerDiv = $("calendarHeader").childNodesWithTag("div")[1];
1187 var headerDays = document.getElementsByClassName("day", headerDiv);
1189 // log ("days: " + days.length + "; headerDays: " + headerDays.length);
1190 for (var i = 0; i < days.length; i++)
1191 if (days[i] != node) {
1192 // log("unselect day : " + i);
1193 headerDays[i].removeClassName("selectedDay");
1194 days[i].removeClassName("selectedDay");
1197 // log("selected day : " + i);
1198 headerDays[i].addClassName("selectedDay");
1199 days[i].addClassName("selectedDay");
1203 function findMonthCalendarSelectedCell(daysContainer) {
1207 while (!found && i < daysContainer.childNodes.length) {
1208 var currentNode = daysContainer.childNodes[i];
1209 if (currentNode.tagName == 'DIV'
1210 && currentNode.hasClassName("selectedDay")) {
1211 daysContainer.selectedCell = currentNode;
1219 function changeMonthCalendarDisplayOfSelectedDay(node) {
1220 var daysContainer = node.parentNode;
1221 if (!daysContainer.selectedCell)
1222 findMonthCalendarSelectedCell(daysContainer);
1224 if (daysContainer.selectedCell)
1225 daysContainer.selectedCell.removeClassName("selectedDay");
1226 daysContainer.selectedCell = node;
1227 node.addClassName("selectedDay");
1230 function onShowCompletedTasks(event) {
1231 showCompletedTasks = (this.checked ? 1 : 0);
1233 return refreshTasks();
1236 function updateTaskStatus(event) {
1237 var taskId = this.parentNode.getAttribute("id");
1238 var newStatus = (this.checked ? 1 : 0);
1239 var http = createHTTPClient();
1241 if (isSafari() && !isSafari3()) {
1242 newStatus = (newStatus ? 0 : 1);
1245 url = (ApplicationBaseURL + this.parentNode.calendar
1246 + "/" + taskId + "/changeStatus?status=" + newStatus);
1249 // TODO: add parameter to signal that we are only interested in OK
1250 http.open("POST", url, false /* not async */);
1253 if (isHttpStatus204(http.status))
1256 log ("no http client?");
1261 function updateCalendarStatus(event) {
1262 var list = new Array();
1263 var newStatus = (this.checked ? 1 : 0);
1265 if (isSafari() && !isSafari3()) {
1266 newStatus = (newStatus ? 0 : 1);
1267 this.checked = newStatus;
1270 var nodes = $("calendarList").childNodesWithTag("li");
1271 for (var i = 0; i < nodes.length; i++) {
1272 var input = $(nodes[i]).childNodesWithTag("input")[0];
1273 if (input.checked) {
1274 var folderId = nodes[i].getAttribute("id");
1275 var elems = folderId.split(":");
1276 if (elems.length > 1)
1277 list.push(elems[0]);
1279 list.push(UserLogin);
1283 // if (!list.length) {
1284 // list.push(UserLogin);
1285 // nodes[0].childNodesWithTag("input")[0].checked = true;
1288 // ApplicationBaseURL = (UserFolderURL + "Groups/_custom_"
1289 // + list.join(",") + "/Calendar/");
1292 var folderID = this.parentNode.getAttribute("id");
1293 var urlstr = URLForFolderID(folderID);
1295 urlstr += "/activateFolder";
1297 urlstr += "/deactivateFolder";
1298 //log("updateCalendarStatus: ajax request = " + urlstr + ", folderID = " + folderID);
1299 triggerAjaxRequest(urlstr, calendarStatusCallback, folderID);
1302 updateCalendarsList();
1305 changeCalendarDisplay();
1311 function calendarStatusCallback(http) {
1312 if (http.readyState == 4) {
1313 if (isHttpStatus204(http.status)) {
1316 changeCalendarDisplay();
1319 var folder = $(http.callbackData);
1320 var input = folder.childNodesWithTag("input")[0];
1321 input.checked = (!input.checked);
1325 log("calendarStatusCallback Ajax error");
1328 function calendarEntryCallback(http) {
1329 if (http.readyState == 4) {
1330 var denied = !isHttpStatus204(http.status);
1331 var entry = $(http.callbackData);
1333 entry.addClassName("denied");
1335 entry.removeClassName("denied");
1339 function updateCalendarsList(method) {
1340 var list = $("calendarList").childNodesWithTag("li");
1341 for (var i = 0; i < list.length; i++) {
1342 var folderID = list[i].getAttribute("id");
1343 var url = URLForFolderID(folderID) + "/canAccessContent";
1344 triggerAjaxRequest(url, calendarEntryCallback, folderID);
1348 function addContact(tag, fullContactName, contactId, contactName, contactEmail) {
1349 var uids = $("uixselector-calendarsList-uidList");
1350 // log("addContact");
1353 var re = new RegExp("(^|,)" + contactId + "($|,)");
1355 if (!re.test(uids.value))
1357 if (uids.value.length > 0)
1358 uids.value += ',' + contactId;
1360 uids.value = contactId;
1361 var names = $("calendarList");
1362 var listElems = names.childNodesWithTag("li");
1363 var colorDef = indexColor(listElems.length);
1364 names.appendChild(userCalendarEntry(contactId, colorDef));
1372 function validateBrowseURL(input) {
1373 var button = $("browseURLBtn");
1375 if (input.value.length) {
1376 if (!button.enabled)
1377 enableAnchor(button);
1378 } else if (!button.disabled)
1379 disableAnchor(button);
1382 function browseURL(anchor, event) {
1383 if (event.button == 0) {
1384 var input = $("url");
1385 var url = input.value;
1387 window.open(url, '_blank');
1393 function onCalendarsMenuPrepareVisibility() {
1394 var folders = $("calendarList");
1395 var selected = folders.getSelectedNodes();
1397 if (selected.length > 0) {
1398 var folderOwner = selected[0].getAttribute("owner");
1399 var sharingOption = $(this).down("ul").childElements().last();
1400 // Disable the "Sharing" option when calendar is not owned by user
1401 if (folderOwner == UserLogin || IsSuperUser)
1402 sharingOption.removeClassName("disabled");
1404 sharingOption.addClassName("disabled");
1408 function getMenus() {
1411 var dateMenu = new Array();
1412 for (var i = 0; i < 12; i++)
1413 dateMenu.push(onMonthMenuItemClick);
1414 menus["monthListMenu"] = dateMenu;
1416 dateMenu = new Array();
1417 for (var i = 0; i < 11; i++)
1418 dateMenu.push(onYearMenuItemClick);
1419 menus["yearListMenu"] = dateMenu;
1421 menus["eventsListMenu"] = new Array(onMenuNewEventClick, "-",
1423 editEvent, deleteEvent, "-",
1426 menus["calendarsMenu"] = new Array(onMenuModify,
1428 onCalendarNew, onCalendarRemove,
1429 "-", null, null, "-",
1430 null, "-", onMenuSharing);
1431 menus["searchMenu"] = new Array(setSearchCriteria);
1433 var calendarsMenu = $("calendarsMenu");
1435 calendarsMenu.prepareVisibility = onCalendarsMenuPrepareVisibility;
1440 function onMenuSharing(event) {
1441 if ($(this).hasClassName("disabled"))
1444 var folders = $("calendarList");
1445 var selected = folders.getSelectedNodes()[0];
1446 /* FIXME: activation of the context menu should preferably select the entry
1447 above which the event has occured */
1449 var folderID = selected.getAttribute("id");
1450 var urlstr = URLForFolderID(folderID) + "/acls";
1452 openAclWindow(urlstr);
1456 function configureDragHandles() {
1457 var handle = $("verticalDragHandle");
1459 handle.addInterface(SOGoDragHandlesInterface);
1460 handle.leftBlock=$("leftPanel");
1461 handle.rightBlock=$("rightPanel");
1464 handle = $("rightDragHandle");
1466 handle.addInterface(SOGoDragHandlesInterface);
1467 handle.upperBlock=$("eventsListView");
1468 handle.lowerBlock=$("calendarView");
1472 function initCalendarSelector() {
1473 var selector = $("calendarSelector");
1474 updateCalendarStatus();
1475 selector.changeNotification = updateCalendarsList;
1477 var list = $("calendarList");
1478 list.multiselect = true;
1479 var items = list.childNodesWithTag("li");
1480 for (var i = 0; i < items.length; i++) {
1481 var input = items[i].childNodesWithTag("input")[0];
1482 Event.observe(input, "click", updateCalendarStatus.bindAsEventListener(input));
1483 Event.observe(items[i], "mousedown", listRowMouseDownHandler);
1484 Event.observe(items[i], "selectstart", listRowMouseDownHandler);
1485 Event.observe(items[i], "click", onRowClick);
1488 var links = $("calendarSelectorButtons").childNodesWithTag("a");
1489 Event.observe(links[0], "click", onCalendarNew);
1490 Event.observe(links[1], "click", onCalendarAdd);
1491 Event.observe(links[2], "click", onCalendarRemove);
1494 function onMenuModify(event) {
1495 var folders = $("calendarList");
1496 var selected = folders.getSelectedNodes()[0];
1498 if (UserLogin == selected.getAttribute("owner")) {
1499 var node = selected.childNodes[selected.childNodes.length - 1];
1500 var currentName = node.nodeValue.trim();
1501 var newName = window.prompt(labels["Name of the Calendar"],
1503 if (newName && newName.length > 0
1504 && newName != currentName) {
1505 var url = (URLForFolderID(selected.getAttribute("id"))
1506 + "/renameFolder?name=" + escape(newName.utf8encode()));
1507 triggerAjaxRequest(url, folderRenameCallback,
1508 {node: node, name: " " + newName});
1511 window.alert(clabels["Unable to rename that folder!"]);
1514 function folderRenameCallback(http) {
1515 if (http.readyState == 4) {
1516 if (isHttpStatus204(http.status)) {
1517 var dict = http.callbackData;
1518 dict["node"].nodeValue = dict["name"];
1523 function onCalendarNew(event) {
1524 createFolder(window.prompt(labels["Name of the Calendar"]),
1526 preventDefault(event);
1529 function onCalendarAdd(event) {
1530 openUserFolderSelector(onFolderSubscribeCB, "calendar");
1531 preventDefault(event);
1534 function appendCalendar(folderName, folderPath) {
1538 owner = getSubscribedFolderOwner(folderPath);
1539 folderPath = accessToSubscribedFolder(folderPath);
1542 folderPath = "/" + folderName;
1547 //log ("append name: " + folderName + "; path: " + folderPath + "; owner: " + owner);
1550 window.alert(clabels["You have already subscribed to that folder!"]);
1552 var calendarList = $("calendarList");
1553 var items = calendarList.childNodesWithTag("li");
1554 var li = document.createElement("li");
1556 // Add the calendar to the proper place
1557 var i = getListIndexForFolder(items, owner, folderName);
1558 if (i != items.length) // User is subscribed to other calendars of the same owner
1559 calendarList.insertBefore(li, items[i]);
1561 calendarList.appendChild(li);
1563 li.setAttribute("id", folderPath);
1564 li.setAttribute("owner", owner);
1566 // Generate new color
1567 if (calendarColorIndex == null)
1568 calendarColorIndex = items.length;
1569 calendarColorIndex++;
1570 var colorTable = [1, 1, 1];
1572 var currentValue = calendarColorIndex;
1574 while (currentValue) {
1575 if (currentValue & 1)
1576 colorTable[index]++;
1582 colorTable[0] = parseInt(255 / colorTable[0]) - 1;
1583 colorTable[1] = parseInt(255 / colorTable[1]) - 1;
1584 colorTable[2] = parseInt(255 / colorTable[2]) - 1;
1587 + colorTable[2].toString(16)
1588 + colorTable[1].toString(16)
1589 + colorTable[0].toString(16);
1590 //log ("color = " + color);
1592 var checkBox = document.createElement("input");
1593 checkBox.setAttribute("type", "checkbox");
1594 li.appendChild(checkBox);
1595 li.appendChild(document.createTextNode(" "));
1596 $(checkBox).addClassName("checkBox");
1598 var colorBox = document.createElement("div");
1599 li.appendChild(colorBox);
1600 li.appendChild(document.createTextNode(folderName));
1601 colorBox.appendChild(document.createTextNode("OO"));
1603 $(colorBox).addClassName("colorBox");
1604 $(colorBox).addClassName('calendarFolder' + folderPath.substr(1));
1606 // Register events (doesn't work with Safari)
1607 Event.observe(li, "mousedown", listRowMouseDownHandler);
1608 Event.observe(li, "selectstart", listRowMouseDownHandler);
1609 Event.observe(li, "click", onRowClick);
1610 Event.observe(checkBox, "click",
1611 updateCalendarStatus.bindAsEventListener(checkBox));
1613 var url = URLForFolderID(folderPath) + "/canAccessContent";
1614 triggerAjaxRequest(url, calendarEntryCallback, folderPath);
1616 // Update CSS for events color
1617 if (!document.styleSheets) return;
1619 var styleElement = document.createElement("style");
1620 styleElement.type = "text/css";
1622 '.calendarFolder' + folderPath.substr(1),
1623 'div.colorBox.calendarFolder' + folderPath.substr(1)
1626 ' { background-color: ' + color + ' !important; }',
1627 ' { color: ' + color + ' !important; }'
1629 for (var i = 0; i < rules.length; i++)
1630 if (styleElement.styleSheet && styleElement.styleSheet.addRule)
1631 styleElement.styleSheet.addRule(selectors[i], rules[i]); // IE
1633 styleElement.appendChild(document.createTextNode(selectors[i] + rules[i])); // Mozilla _+ Safari
1634 document.getElementsByTagName("head")[0].appendChild(styleElement);
1638 function onFolderSubscribeCB(folderData) {
1639 var folder = $(folderData["folder"]);
1641 appendCalendar(folderData["folderName"], folderData["folder"]);
1644 function onFolderUnsubscribeCB(folderId) {
1645 var node = $(folderId);
1646 node.parentNode.removeChild(node);
1647 if (removeFolderRequestCount == 0) {
1650 changeCalendarDisplay();
1654 function onCalendarRemove(event) {
1655 if (removeFolderRequestCount == 0) {
1656 var nodes = $("calendarList").getSelectedNodes();
1657 for (var i = 0; i < nodes.length; i++) {
1658 nodes[i].deselect();
1659 var folderId = nodes[i].getAttribute("id");
1660 var folderIdElements = folderId.split("_");
1661 if (folderIdElements.length > 1) {
1662 unsubscribeFromFolder(folderId, onFolderUnsubscribeCB, folderId);
1665 deletePersonalCalendar(folderIdElements[0]);
1669 preventDefault(event);
1672 function deletePersonalCalendar(folderElement) {
1673 var folderId = folderElement.substr(1);
1675 = labels["Are you sure you want to delete the calendar \"%{0}\"?"].formatted($(folderElement).lastChild.nodeValue.strip());
1676 if (window.confirm(label)) {
1677 removeFolderRequestCount++;
1678 var url = ApplicationBaseURL + "/" + folderId + "/deleteFolder";
1679 triggerAjaxRequest(url, deletePersonalCalendarCallback, folderId);
1683 function deletePersonalCalendarCallback(http) {
1684 if (http.readyState == 4) {
1685 if (isHttpStatus204(http.status)) {
1686 var ul = $("calendarList");
1687 var children = ul.childNodesWithTag("li");
1690 while (!done && i < children.length) {
1691 var currentFolderId = children[i].getAttribute("id").substr(1);
1692 if (currentFolderId == http.callbackData) {
1693 ul.removeChild(children[i]);
1699 removeFolderRequestCount--;
1700 if (removeFolderRequestCount == 0) {
1703 changeCalendarDisplay();
1708 log ("ajax problem 5: " + http.status);
1711 function configureLists() {
1712 var list = $("tasksList");
1713 list.multiselect = true;
1714 Event.observe(list, "mousedown",
1715 onTasksSelectionChange.bindAsEventListener(list));
1717 var input = $("showHideCompletedTasks");
1718 Event.observe(input, "click",
1719 onShowCompletedTasks.bindAsEventListener(input));
1721 list = $("eventsList");
1722 list.multiselect = true;
1723 configureSortableTableHeaders(list);
1724 TableKit.Resizable.init(list, {'trueResize' : true, 'keepWidth' : true});
1725 Event.observe(list, "mousedown",
1726 onEventsSelectionChange.bindAsEventListener(list));
1729 function initDateSelectorEvents() {
1730 var arrow = $("rightArrow");
1731 Event.observe(arrow, "click",
1732 onDateSelectorGotoMonth.bindAsEventListener(arrow));
1733 arrow = $("leftArrow");
1734 Event.observe(arrow, "click",
1735 onDateSelectorGotoMonth.bindAsEventListener(arrow));
1737 var menuButton = $("monthLabel");
1738 Event.observe(menuButton, "click",
1739 popupMonthMenu.bindAsEventListener(menuButton));
1740 menuButton = $("yearLabel");
1741 Event.observe(menuButton, "click",
1742 popupMonthMenu.bindAsEventListener(menuButton));
1745 function initCalendars() {
1746 sorting["attribute"] = "start";
1747 sorting["ascending"] = true;
1749 if (!document.body.hasClassName("popup")) {
1750 initDateSelectorEvents();
1751 initCalendarSelector();
1752 configureSearchField();
1754 var selector = $("calendarSelector");
1756 selector.attachMenu("calendarsMenu");
1760 FastInit.addOnLoad(initCalendars);