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)) {
220 var nodes = http.callbackData;
221 for (var i = 0; i < nodes.length; i++) {
222 var node = $(nodes[i]);
224 isTask = isTask || (node.parentNode.id == 'tasksList');
225 node.parentNode.removeChild(node);
228 if (eventsToDelete.length)
229 _batchDeleteEvents();
231 document.deleteEventAjaxRequest = null;
236 changeCalendarDisplay();
241 log ("deleteEventCallback Ajax error");
245 function editDoubleClickedEvent(event) {
246 _editEventId(this.cname, this.calendar);
248 preventDefault(event);
249 event.cancelBubble = true;
252 function onSelectAll() {
253 var list = $("eventsList");
254 list.selectRowsMatchingClass("eventRow");
259 function onDaySelect(node) {
260 var day = node.getAttribute('day');
261 var needRefresh = (listFilter == 'view_selectedday'
262 && day != currentDay);
264 var td = $(node).getParentWithTagName("td");
265 var table = $(td).getParentWithTagName("table");
267 // log ("table.selected: " + table.selected);
269 if (document.selectedDate)
270 document.selectedDate.deselect();
273 document.selectedDate = td;
275 changeCalendarDisplay( { "day": day } );
283 function onDateSelectorGotoMonth(event) {
284 var day = this.getAttribute("date");
286 changeDateSelectorDisplay(day, true);
291 function onCalendarGotoDay(node) {
292 var day = node.getAttribute("date");
293 var needRefresh = (listFilter == 'view_selectedday'
294 && day != currentDay);
296 changeDateSelectorDisplay(day);
297 changeCalendarDisplay( { "day": day } );
304 function gotoToday() {
305 changeDateSelectorDisplay('');
306 changeCalendarDisplay();
311 function setDateSelectorContent(content) {
312 var div = $("dateSelectorView");
314 div.innerHTML = content;
315 if (currentDay.length > 0)
316 restoreCurrentDaySelection(div);
318 initDateSelectorEvents();
321 function dateSelectorCallback(http) {
322 if (http.readyState == 4
323 && http.status == 200) {
324 document.dateSelectorAjaxRequest = null;
325 var content = http.responseText;
326 setDateSelectorContent(content);
327 cachedDateSelectors[http.callbackData] = content;
330 log ("dateSelectorCallback Ajax error");
333 function eventsListCallback(http) {
334 if (http.readyState == 4
335 && http.status == 200) {
336 var div = $("eventsListView");
338 document.eventsListAjaxRequest = null;
339 var table = $("eventsList");
340 lastClickedRow = -1; // from generic.js
342 if (http.responseText.length > 0) {
343 var data = http.responseText.evalJSON(true);
344 for (var i = 0; i < data.length; i++) {
345 var row = document.createElement("tr");
346 table.tBodies[0].appendChild(row);
347 $(row).addClassName("eventRow");
348 row.setAttribute("id", escape(data[i][0]));
349 row.cname = escape(data[i][0]);
350 row.calendar = data[i][1];
352 var startDate = new Date();
353 startDate.setTime(data[i][4] * 1000);
354 row.day = startDate.getDayString();
355 row.hour = startDate.getHourString();
356 Event.observe(row, "mousedown", onRowClick);
357 Event.observe(row, "selectstart", listRowMouseDownHandler);
358 Event.observe(row, "dblclick",
359 editDoubleClickedEvent.bindAsEventListener(row));
360 Event.observe(row, "contextmenu",
361 onEventContextMenu.bindAsEventListener(row));
363 var td = document.createElement("td");
365 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
366 td.appendChild(document.createTextNode(data[i][3]));
368 td = document.createElement("td");
370 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
371 td.appendChild(document.createTextNode(data[i][10]));
373 td = document.createElement("td");
375 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
376 td.appendChild(document.createTextNode(data[i][11]));
378 td = document.createElement("td");
380 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
381 td.appendChild(document.createTextNode(data[i][6]));
384 if (sorting["attribute"] && sorting["attribute"].length > 0) {
385 var sortHeader = $(sorting["attribute"] + "Header");
388 var sortImages = $(table.tHead).getElementsByClassName("sortImage");
389 $(sortImages).each(function(item) {
393 var sortImage = createElement("img", "messageSortImage", "sortImage");
394 sortHeader.insertBefore(sortImage, sortHeader.firstChild);
395 if (sorting["ascending"])
396 sortImage.src = ResourcesURL + "/title_sortdown_12x12.png";
398 sortImage.src = ResourcesURL + "/title_sortup_12x12.png";
404 log ("eventsListCallback Ajax error");
407 function tasksListCallback(http) {
408 var div = $("tasksListView");
410 if (http.readyState == 4
411 && http.status == 200) {
412 document.tasksListAjaxRequest = null;
413 var list = $("tasksList");
415 if (http.responseText.length > 0) {
416 var data = http.responseText.evalJSON(true);
418 for (var i = 0; i < data.length; i++) {
419 var listItem = document.createElement("li");
420 list.appendChild(listItem);
421 Event.observe(listItem, "mousedown", listRowMouseDownHandler);
422 Event.observe(listItem, "click", onRowClick);
423 Event.observe(listItem, "dblclick",
424 editDoubleClickedEvent.bindAsEventListener(listItem));
425 listItem.setAttribute("id", data[i][0]);
426 $(listItem).addClassName(data[i][5]);
427 $(listItem).addClassName(data[i][6]);
428 listItem.calendar = data[i][1];
429 $(listItem).addClassName("calendarFolder" + data[i][1]);
430 listItem.cname = escape(data[i][0]);
431 var input = document.createElement("input");
432 input.setAttribute("type", "checkbox");
433 listItem.appendChild(input);
434 Event.observe(input, "click", updateTaskStatus.bindAsEventListener(input), true);
435 input.setAttribute("value", "1");
437 input.setAttribute("checked", "checked");
438 $(input).addClassName("checkBox");
439 listItem.appendChild(document.createTextNode(data[i][3]));
442 list.scrollTop = list.previousScroll;
444 if (http.callbackData) {
445 var selectedNodesId = http.callbackData;
446 for (var i = 0; i < selectedNodesId.length; i++) {
447 // log(selectedNodesId[i] + " (" + i + ") is selected");
448 $(selectedNodesId[i]).select();
452 log ("tasksListCallback: no data");
456 log ("tasksListCallback Ajax error");
459 function restoreCurrentDaySelection(div) {
460 var elements = $(div).getElementsByTagName("a");
463 while (!day && i < elements.length)
465 day = elements[i].day;
470 && day.substr(0, 6) == currentDay.substr(0, 6)) {
471 for (i = 0; i < elements.length; i++) {
472 day = elements[i].day;
473 if (day && day == currentDay) {
474 var td = $(elements[i]).getParentWithTagName("td");
475 if (document.selectedDate)
476 document.selectedDate.deselect();
478 document.selectedDate = td;
484 function changeDateSelectorDisplay(day, keepCurrentDay) {
485 var url = ApplicationBaseURL + "dateselector";
487 url += "?day=" + day;
489 if (day != currentDay) {
493 var month = day.substr(0, 6);
494 if (cachedDateSelectors[month]) {
495 // log ("restoring cached selector for month: " + month);
496 setDateSelectorContent(cachedDateSelectors[month]);
499 // log ("loading selector for month: " + month);
500 if (document.dateSelectorAjaxRequest) {
501 document.dateSelectorAjaxRequest.aborted = true;
502 document.dateSelectorAjaxRequest.abort();
504 document.dateSelectorAjaxRequest
505 = triggerAjaxRequest(url,
506 dateSelectorCallback,
512 function changeCalendarDisplay(data, newView) {
513 var url = ApplicationBaseURL + ((newView) ? newView : currentView);
515 var scrollEvent = null;
519 scrollEvent = data['scrollEvent'];
527 var divs = $$('div.day[day='+day+']');
529 // Don't reload the view if the event is present in current view
531 // Deselect previous day
532 var selectedDivs = $$('div.day.selectedDay');
533 selectedDivs.each(function(div) {
534 div.removeClassName('selectedDay');
538 divs.each(function(div) {
539 div.addClassName('selectedDay');
542 // Deselect day in date selector
543 if (document.selectedDate)
544 document.selectedDate.deselect();
546 // Select day in date selector
547 var selectedLink = $$('table#dateSelectorTable a[day='+day+']');
548 if (selectedLink.length > 0) {
549 selectedCell = selectedLink[0].up(1);
550 selectedCell.select();
551 document.selectedDate = selectedCell;
555 scrollDayView(scrollEvent);
560 url += "?day=" + day;
563 // log ("switching to view: " + newView);
564 // log ("changeCalendarDisplay: " + url);
566 selectedCalendarCell = null;
568 if (document.dayDisplayAjaxRequest) {
569 // log ("aborting day ajaxrq");
570 document.dayDisplayAjaxRequest.aborted = true;
571 document.dayDisplayAjaxRequest.abort();
573 document.dayDisplayAjaxRequest
574 = triggerAjaxRequest(url, calendarDisplayCallback,
577 "scrollEvent": scrollEvent });
582 function _ensureView(view) {
583 if (currentView != view)
584 changeCalendarDisplay(null, view);
589 function onDayOverview() {
590 return _ensureView("dayview");
593 function onMulticolumnDayOverview() {
594 return _ensureView("multicolumndayview");
597 function onWeekOverview() {
598 return _ensureView("weekview");
601 function onMonthOverview() {
602 return _ensureView("monthview");
605 function scrollDayView(scrollEvent) {
608 // Select event in calendar view
610 divs = $$("div#calendarContent div." + eventClass(scrollEvent));
611 selectCalendarEvent(divs[0]);
614 // Don't scroll if in month view
615 if (currentView == "monthview")
619 var daysView = $("daysView");
621 $(daysView.childNodesWithTag("div")[0]).childNodesWithTag("div");
624 divs = $$("div#calendarContent div." + eventClass(scrollEvent));
625 var classes = $w(divs[0].className);
626 for (var i = 0; i < classes.length; i++) {
627 if (classes[i].startsWith("starts")) {
628 var starts = Math.floor(parseInt(classes[i].substr(6)) / 4);
629 offset = hours[starts].offsetTop;
635 offset = hours[8].offsetTop;
637 daysView.scrollTop = offset - 5;
640 function onClickableCellsDblClick(event) {
641 newEvent(this, 'event');
643 event.cancelBubble = true;
644 event.returnValue = false;
647 function refreshCalendarEvents(scrollEvent) {
648 var todayDate = new Date();
651 if (currentView == "dayview") {
655 sd = todayDate.getDayString();
658 else if (currentView == "weekview") {
661 startDate = currentDay.asDate();
663 startDate = todayDate;
664 startDate = startDate.beginOfWeek();
665 sd = startDate.getDayString();
666 var endDate = new Date();
667 endDate.setTime(startDate.getTime());
669 ed = endDate.getDayString();
674 monthDate = currentDay.asDate();
676 monthDate = todayDate;
677 monthDate.setDate(1);
678 sd = monthDate.beginOfWeek().getDayString();
680 var lastMonthDate = new Date();
681 lastMonthDate.setTime(monthDate.getTime());
682 lastMonthDate.setMonth(monthDate.getMonth() + 1);
683 lastMonthDate.addDays(-1);
684 ed = lastMonthDate.endOfWeek().getDayString();
686 if (document.refreshCalendarEventsAjaxRequest) {
687 document.refreshCalendarEventsAjaxRequest.aborted = true;
688 document.refreshCalendarEventsAjaxRequest.abort();
690 var url = ApplicationBaseURL + "eventslist?sd=" + sd + "&ed=" + ed;
691 document.refreshCalendarEventsAjaxRequest
692 = triggerAjaxRequest(url, refreshCalendarEventsCallback,
693 {"startDate": sd, "endDate": ed,
694 "scrollEvent": scrollEvent});
697 function refreshCalendarEventsCallback(http) {
698 if (http.readyState == 4
699 && http.status == 200) {
701 if (http.responseText.length > 0) {
702 var data = http.responseText.evalJSON(true);
703 // log("refresh calendar events: " + data.length);
704 for (var i = 0; i < data.length; i++)
705 drawCalendarEvent(data[i],
706 http.callbackData["startDate"],
707 http.callbackData["endDate"]);
709 scrollDayView(http.callbackData["scrollEvent"]);
712 log("AJAX error when refreshing calendar events");
715 function drawCalendarEvent(eventData, sd, ed) {
716 var viewStartDate = sd.asDate();
717 var viewEndDate = ed.asDate();
719 var startDate = new Date();
720 startDate.setTime(eventData[4] * 1000);
721 var endDate = new Date();
722 endDate.setTime(eventData[5] * 1000);
724 // log ("s: " + startDate + "; e: " + endDate);
726 var days = startDate.daysUpTo(endDate);
729 if (currentView == "monthview"
730 && (eventData[7] == 0))
731 title = startDate.getDisplayHoursString() + " " + eventData[3];
733 title = eventData[3];
735 // log("title: " + title);
736 // log("viewS: " + viewStartDate);
737 var startHour = null;
740 var siblings = new Array();
741 for (var i = 0; i < days.length; i++)
742 if (days[i].earlierDate(viewStartDate) == viewStartDate
743 && days[i].laterDate(viewEndDate) == viewEndDate) {
746 // log("day: " + days[i]);
748 var quarters = (startDate.getUTCHours() * 4
749 + Math.floor(startDate.getUTCMinutes() / 15));
751 startHour = startDate.getDisplayHoursString();
752 endHour = endDate.getDisplayHoursString();
759 if (i == days.length - 1) {
760 var quarters = (endDate.getUTCHours() * 4
761 + Math.ceil(endDate.getUTCMinutes() / 15));
766 lasts = ends - starts;
770 var eventDiv = newEventDIV(eventData[0], eventData[1], starts, lasts,
772 siblings.push(eventDiv);
773 eventDiv.siblings = siblings;
774 if (eventData[9].length > 0)
775 eventDiv.addClassName(eventData[9]);
776 var dayString = days[i].getDayString();
777 // log("day: " + dayString);
778 var parentDiv = null;
779 if (currentView == "monthview") {
780 var dayDivs = $("monthDaysView").childNodesWithTag("div");
782 while (!parentDiv && j < dayDivs.length) {
783 if (dayDivs[j].getAttribute("day") == dayString)
784 parentDiv = dayDivs[j];
790 if (eventData[7] == 0) {
791 var daysView = $("daysView");
792 var eventsDiv = $(daysView).childNodesWithTag("div")[1];
793 var dayDivs = $(eventsDiv).childNodesWithTag("div");
795 while (!parentDiv && j < dayDivs.length) {
796 if (dayDivs[j].getAttribute("day") == dayString)
797 parentDiv = dayDivs[j].childNodesWithTag("div")[0];
803 var header = $("calendarHeader");
804 var daysDiv = $(header).childNodesWithTag("div")[1];
805 var dayDivs = $(daysDiv).childNodesWithTag("div");
807 while (!parentDiv && j < dayDivs.length) {
808 if (dayDivs[j].getAttribute("day") == dayString)
809 parentDiv = dayDivs[j];
816 parentDiv.appendChild(eventDiv);
820 function eventClass(cname) {
821 return escape(cname.replace(".", "-"));
825 function newEventDIV(cname, calendar, starts, lasts,
826 startHour, endHour, title) {
827 var eventDiv = document.createElement("div");
828 eventDiv.cname = escape(cname);
829 eventDiv.calendar = calendar;
830 $(eventDiv).addClassName("event");
831 $(eventDiv).addClassName(eventClass(cname));
832 $(eventDiv).addClassName("starts" + starts);
833 $(eventDiv).addClassName("lasts" + lasts);
834 for (var i = 1; i < 5; i++) {
835 var shadowDiv = document.createElement("div");
836 eventDiv.appendChild(shadowDiv);
837 $(shadowDiv).addClassName("shadow");
838 $(shadowDiv).addClassName("shadow" + i);
840 var innerDiv = document.createElement("div");
841 eventDiv.appendChild(innerDiv);
842 $(innerDiv).addClassName("eventInside");
843 $(innerDiv).addClassName("calendarFolder" + calendar);
845 var gradientDiv = document.createElement("div");
846 innerDiv.appendChild(gradientDiv);
847 $(gradientDiv).addClassName("gradient");
848 var gradientImg = document.createElement("img");
849 gradientDiv.appendChild(gradientImg);
850 gradientImg.src = ResourcesURL + "/event-gradient.png";
852 var textDiv = document.createElement("div");
853 innerDiv.appendChild(textDiv);
854 $(textDiv).addClassName("text");
856 var headerSpan = document.createElement("span");
857 textDiv.appendChild(headerSpan);
858 $(headerSpan).addClassName("eventHeader");
859 headerSpan.appendChild(document.createTextNode(startHour + " - "
861 textDiv.appendChild(document.createElement("br"));
863 textDiv.appendChild(document.createTextNode(title));
865 Event.observe(eventDiv, "mousedown", listRowMouseDownHandler);
866 Event.observe(eventDiv, "click",
867 onCalendarSelectEvent.bindAsEventListener(eventDiv));
868 Event.observe(eventDiv, "dblclick",
869 editDoubleClickedEvent.bindAsEventListener(eventDiv));
874 function calendarDisplayCallback(http) {
875 var div = $("calendarView");
877 if (http.readyState == 4
878 && http.status == 200) {
879 document.dayDisplayAjaxRequest = null;
880 div.update(http.responseText);
881 if (http.callbackData["view"])
882 currentView = http.callbackData["view"];
883 if (http.callbackData["day"])
884 currentDay = http.callbackData["day"];
887 if (currentView == "monthview")
888 contentView = $("calendarContent");
890 contentView = $("daysView");
892 refreshCalendarEvents(http.callbackData.scrollEvent);
894 var days = document.getElementsByClassName("day", contentView);
895 if (currentView == "monthview")
896 for (var i = 0; i < days.length; i++) {
897 Event.observe(days[i], "click",
898 onCalendarSelectDay.bindAsEventListener(days[i]));
899 Event.observe(days[i], "dblclick",
900 onClickableCellsDblClick.bindAsEventListener(days[i]));
903 var headerDivs = $("calendarHeader").childNodesWithTag("div");
904 var headerDaysLabels = document.getElementsByClassName("day", headerDivs[0]);
905 var headerDays = document.getElementsByClassName("day", headerDivs[1]);
906 for (var i = 0; i < days.length; i++) {
907 headerDays[i].hour = "allday";
908 Event.observe(headerDaysLabels[i], "mousedown", listRowMouseDownHandler);
909 Event.observe(headerDays[i], "click",
910 onCalendarSelectDay.bindAsEventListener(days[i]));
911 Event.observe(headerDays[i], "dblclick",
912 onClickableCellsDblClick.bindAsEventListener(headerDays[i]));
913 Event.observe(days[i], "click",
914 onCalendarSelectDay.bindAsEventListener(days[i]));
915 var clickableCells = document.getElementsByClassName("clickableHourCell",
917 for (var j = 0; j < clickableCells.length; j++)
918 Event.observe(clickableCells[j], "dblclick",
919 onClickableCellsDblClick.bindAsEventListener(clickableCells[j]));
924 log ("calendarDisplayCallback Ajax error (" + http.readyState + "/" + http.status + ")");
927 function assignCalendar(name) {
928 if (typeof(skycalendar) != "undefined") {
931 node.calendar = new skycalendar(node);
932 node.calendar.setCalendarPage(ResourcesURL + "/skycalendar.html");
933 var dateFormat = node.getAttribute("dateFormat");
935 node.calendar.setDateFormat(dateFormat);
939 function popupCalendar(node) {
940 var nodeId = $(node).readAttribute("inputId");
941 var input = $(nodeId);
942 input.calendar.popup();
947 function onEventContextMenu(event) {
948 var topNode = $("eventsList");
949 var menu = $("eventsListMenu");
951 Event.observe(menu, "hideMenu", onEventContextMenuHide);
952 popupMenu(event, "eventsListMenu", this);
955 function onEventContextMenuHide(event) {
956 var topNode = $("eventsList");
958 if (topNode.menuSelectedEntry) {
959 topNode.menuSelectedEntry.deselect();
960 topNode.menuSelectedEntry = null;
964 function onEventsSelectionChange() {
965 listOfSelection = this;
966 this.removeClassName("_unfocused");
967 $("tasksList").addClassName("_unfocused");
969 var rows = this.tBodies[0].getSelectedNodes();
970 if (rows.length == 1) {
972 changeCalendarDisplay( { "day": row.day,
973 "scrollEvent": row.getAttribute("id") } );
974 changeDateSelectorDisplay(row.day);
978 function onTasksSelectionChange() {
979 listOfSelection = this;
980 this.removeClassName("_unfocused");
981 $("eventsList").addClassName("_unfocused");
984 function _loadEventHref(href) {
985 if (document.eventsListAjaxRequest) {
986 document.eventsListAjaxRequest.aborted = true;
987 document.eventsListAjaxRequest.abort();
989 var url = ApplicationBaseURL + "/" + href;
990 document.eventsListAjaxRequest
991 = triggerAjaxRequest(url, eventsListCallback, href);
993 var table = $("eventsList").tBodies[0];
994 while (table.rows.length > 0)
995 table.removeChild(table.rows[0]);
1000 function _loadTasksHref(href) {
1001 if (document.tasksListAjaxRequest) {
1002 document.tasksListAjaxRequest.aborted = true;
1003 document.tasksListAjaxRequest.abort();
1005 url = ApplicationBaseURL + href;
1007 var tasksList = $("tasksList");
1010 selectedIds = tasksList.getSelectedNodesId();
1013 document.tasksListAjaxRequest
1014 = triggerAjaxRequest(url, tasksListCallback, selectedIds);
1016 tasksList.previousScroll = tasksList.scrollTop;
1017 while (tasksList.childNodes.length)
1018 tasksList.removeChild(tasksList.childNodes[0]);
1023 function onHeaderClick(event) {
1024 var headerId = this.getAttribute("id");
1025 var newSortAttribute;
1026 if (headerId == "titleHeader")
1027 newSortAttribute = "title";
1028 else if (headerId == "startHeader")
1029 newSortAttribute = "start";
1030 else if (headerId == "endHeader")
1031 newSortAttribute = "end";
1032 else if (headerId == "locationHeader")
1033 newSortAttribute = "location";
1035 newSortAttribute = "start";
1037 if (sorting["attribute"] == newSortAttribute)
1038 sorting["ascending"] = !sorting["ascending"];
1040 sorting["attribute"] = newSortAttribute;
1041 sorting["ascending"] = true;
1048 function refreshCurrentFolder() {
1052 function refreshEvents() {
1054 var value = search["value"];
1055 if (value && value.length)
1056 titleSearch = "&search=" + value;
1060 return _loadEventHref("eventslist?asc=" + sorting["ascending"]
1061 + "&sort=" + sorting["attribute"]
1062 + "&day=" + currentDay
1064 + "&filterpopup=" + listFilter);
1067 function refreshTasks() {
1068 return _loadTasksHref("taskslist?show-completed=" + showCompletedTasks);
1071 function refreshEventsAndDisplay() {
1073 changeCalendarDisplay();
1076 function onListFilterChange() {
1077 var node = $("filterpopup");
1079 listFilter = node.value;
1080 // log ("listFilter = " + listFilter);
1082 return refreshEvents();
1085 function selectMonthInMenu(menu, month) {
1086 var entries = menu.childNodes[1].childNodesWithTag("LI");
1087 for (i = 0; i < entries.length; i++) {
1088 var entry = entries[i];
1089 var entryMonth = entry.getAttribute("month");
1090 if (entryMonth == month)
1091 entry.addClassName("currentMonth");
1093 entry.removeClassName("currentMonth");
1097 function selectYearInMenu(menu, month) {
1098 var entries = menu.childNodes[1].childNodes;
1099 for (i = 0; i < entries.length; i++) {
1100 var entry = entries[i];
1101 if (entry.tagName == "LI") {
1102 var entryMonth = entry.innerHTML;
1103 if (entryMonth == month)
1104 entry.addClassName("currentMonth");
1106 entry.removeClassName("currentMonth");
1111 function popupMonthMenu(event) {
1112 if (event.button == 0) {
1113 var id = this.getAttribute("id");
1114 if (id == "monthLabel")
1115 menuId = "monthListMenu";
1117 menuId = "yearListMenu";
1119 var popup = $(menuId);
1120 if (id == "monthLabel")
1121 selectMonthInMenu(popup, this.getAttribute("month"));
1123 selectYearInMenu(popup, this.innerHTML);
1125 popupToolbarMenu(this, menuId);
1130 function onMonthMenuItemClick(event) {
1131 var month = '' + this.getAttribute("month");
1132 var year = '' + $("yearLabel").innerHTML;
1134 changeDateSelectorDisplay(year + month + "01", true);
1137 function onYearMenuItemClick(event) {
1138 var month = '' + $("monthLabel").getAttribute("month");;
1139 var year = '' + this.innerHTML;
1141 changeDateSelectorDisplay(year + month + "01", true);
1144 function selectCalendarEvent(div) {
1145 // Select event in calendar view
1146 if (selectedCalendarCell)
1147 for (var i = 0; i < selectedCalendarCell.length; i++)
1148 selectedCalendarCell[i].deselect();
1150 for (var i = 0; i < div.siblings.length; i++)
1151 div.siblings[i].select();
1153 selectedCalendarCell = div.siblings;
1156 function onCalendarSelectEvent() {
1157 var list = $("eventsList");
1159 selectCalendarEvent(this);
1161 // Select event in events list
1162 $(list.tBodies[0]).deselectAll();
1163 var row = $(this.cname);
1165 var div = row.parentNode.parentNode.parentNode;
1166 div.scrollTop = row.offsetTop - (div.offsetHeight / 2);
1171 function onCalendarSelectDay(event) {
1173 if (currentView == "multicolumndayview")
1174 day = this.getAttribute("day");
1176 day = this.getAttribute("day");
1177 var needRefresh = (listFilter == 'view_selectedday'
1178 && day != currentDay);
1180 if (currentView == 'weekview')
1181 changeWeekCalendarDisplayOfSelectedDay(this);
1182 else if (currentView == 'monthview')
1183 changeMonthCalendarDisplayOfSelectedDay(this);
1184 changeDateSelectorDisplay(day);
1186 if (listOfSelection) {
1187 listOfSelection.addClassName("_unfocused");
1188 listOfSelection = null;
1195 function changeWeekCalendarDisplayOfSelectedDay(node) {
1196 var days = document.getElementsByClassName("day", node.parentNode);
1197 var headerDiv = $("calendarHeader").childNodesWithTag("div")[1];
1198 var headerDays = document.getElementsByClassName("day", headerDiv);
1200 // log ("days: " + days.length + "; headerDays: " + headerDays.length);
1201 for (var i = 0; i < days.length; i++)
1202 if (days[i] != node) {
1203 // log("unselect day : " + i);
1204 headerDays[i].removeClassName("selectedDay");
1205 days[i].removeClassName("selectedDay");
1208 // log("selected day : " + i);
1209 headerDays[i].addClassName("selectedDay");
1210 days[i].addClassName("selectedDay");
1214 function findMonthCalendarSelectedCell(daysContainer) {
1218 while (!found && i < daysContainer.childNodes.length) {
1219 var currentNode = daysContainer.childNodes[i];
1220 if (currentNode.tagName == 'DIV'
1221 && currentNode.hasClassName("selectedDay")) {
1222 daysContainer.selectedCell = currentNode;
1230 function changeMonthCalendarDisplayOfSelectedDay(node) {
1231 var daysContainer = node.parentNode;
1232 if (!daysContainer.selectedCell)
1233 findMonthCalendarSelectedCell(daysContainer);
1235 if (daysContainer.selectedCell)
1236 daysContainer.selectedCell.removeClassName("selectedDay");
1237 daysContainer.selectedCell = node;
1238 node.addClassName("selectedDay");
1241 function onShowCompletedTasks(event) {
1242 showCompletedTasks = (this.checked ? 1 : 0);
1244 return refreshTasks();
1247 function updateTaskStatus(event) {
1248 var taskId = this.parentNode.getAttribute("id");
1249 var newStatus = (this.checked ? 1 : 0);
1250 var http = createHTTPClient();
1252 if (isSafari() && !isSafari3()) {
1253 newStatus = (newStatus ? 0 : 1);
1256 url = (ApplicationBaseURL + this.parentNode.calendar
1257 + "/" + taskId + "/changeStatus?status=" + newStatus);
1260 // TODO: add parameter to signal that we are only interested in OK
1261 http.open("POST", url, false /* not async */);
1264 if (isHttpStatus204(http.status))
1267 log ("no http client?");
1272 function updateCalendarStatus(event) {
1273 var list = new Array();
1274 var newStatus = (this.checked ? 1 : 0);
1276 if (isSafari() && !isSafari3()) {
1277 newStatus = (newStatus ? 0 : 1);
1278 this.checked = newStatus;
1281 var nodes = $("calendarList").childNodesWithTag("li");
1282 for (var i = 0; i < nodes.length; i++) {
1283 var input = $(nodes[i]).childNodesWithTag("input")[0];
1284 if (input.checked) {
1285 var folderId = nodes[i].getAttribute("id");
1286 var elems = folderId.split(":");
1287 if (elems.length > 1)
1288 list.push(elems[0]);
1290 list.push(UserLogin);
1294 // if (!list.length) {
1295 // list.push(UserLogin);
1296 // nodes[0].childNodesWithTag("input")[0].checked = true;
1299 // ApplicationBaseURL = (UserFolderURL + "Groups/_custom_"
1300 // + list.join(",") + "/Calendar/");
1303 var folderID = this.parentNode.getAttribute("id");
1304 var urlstr = URLForFolderID(folderID);
1306 urlstr += "/activateFolder";
1308 urlstr += "/deactivateFolder";
1309 //log("updateCalendarStatus: ajax request = " + urlstr + ", folderID = " + folderID);
1310 triggerAjaxRequest(urlstr, calendarStatusCallback, folderID);
1313 updateCalendarsList();
1316 changeCalendarDisplay();
1322 function calendarStatusCallback(http) {
1323 if (http.readyState == 4) {
1324 if (isHttpStatus204(http.status)) {
1327 changeCalendarDisplay();
1330 var folder = $(http.callbackData);
1331 var input = folder.childNodesWithTag("input")[0];
1332 input.checked = (!input.checked);
1336 log("calendarStatusCallback Ajax error");
1339 function calendarEntryCallback(http) {
1340 if (http.readyState == 4) {
1341 var denied = !isHttpStatus204(http.status);
1342 var entry = $(http.callbackData);
1344 entry.addClassName("denied");
1346 entry.removeClassName("denied");
1350 function updateCalendarsList(method) {
1351 var list = $("calendarList").childNodesWithTag("li");
1352 for (var i = 0; i < list.length; i++) {
1353 var folderID = list[i].getAttribute("id");
1354 var url = URLForFolderID(folderID) + "/canAccessContent";
1355 triggerAjaxRequest(url, calendarEntryCallback, folderID);
1359 function addContact(tag, fullContactName, contactId, contactName, contactEmail) {
1360 var uids = $("uixselector-calendarsList-uidList");
1361 // log("addContact");
1364 var re = new RegExp("(^|,)" + contactId + "($|,)");
1366 if (!re.test(uids.value))
1368 if (uids.value.length > 0)
1369 uids.value += ',' + contactId;
1371 uids.value = contactId;
1372 var names = $("calendarList");
1373 var listElems = names.childNodesWithTag("li");
1374 var colorDef = indexColor(listElems.length);
1375 names.appendChild(userCalendarEntry(contactId, colorDef));
1383 function validateBrowseURL(input) {
1384 var button = $("browseURLBtn");
1386 if (input.value.length) {
1387 if (!button.enabled)
1388 enableAnchor(button);
1389 } else if (!button.disabled)
1390 disableAnchor(button);
1393 function browseURL(anchor, event) {
1394 if (event.button == 0) {
1395 var input = $("url");
1396 var url = input.value;
1398 window.open(url, '_blank');
1404 function onCalendarsMenuPrepareVisibility() {
1405 var folders = $("calendarList");
1406 var selected = folders.getSelectedNodes();
1408 if (selected.length > 0) {
1409 var folderOwner = selected[0].getAttribute("owner");
1410 var sharingOption = $(this).down("ul").childElements().last();
1411 // Disable the "Sharing" option when calendar is not owned by user
1412 if (folderOwner == UserLogin || IsSuperUser)
1413 sharingOption.removeClassName("disabled");
1415 sharingOption.addClassName("disabled");
1419 function getMenus() {
1422 var dateMenu = new Array();
1423 for (var i = 0; i < 12; i++)
1424 dateMenu.push(onMonthMenuItemClick);
1425 menus["monthListMenu"] = dateMenu;
1427 dateMenu = new Array();
1428 for (var i = 0; i < 11; i++)
1429 dateMenu.push(onYearMenuItemClick);
1430 menus["yearListMenu"] = dateMenu;
1432 menus["eventsListMenu"] = new Array(onMenuNewEventClick, "-",
1434 editEvent, deleteEvent, "-",
1437 menus["calendarsMenu"] = new Array(onMenuModify,
1439 onCalendarNew, onCalendarRemove,
1440 "-", null, null, "-",
1441 null, "-", onMenuSharing);
1442 menus["searchMenu"] = new Array(setSearchCriteria);
1444 var calendarsMenu = $("calendarsMenu");
1446 calendarsMenu.prepareVisibility = onCalendarsMenuPrepareVisibility;
1451 function onMenuSharing(event) {
1452 if ($(this).hasClassName("disabled"))
1455 var folders = $("calendarList");
1456 var selected = folders.getSelectedNodes()[0];
1457 /* FIXME: activation of the context menu should preferably select the entry
1458 above which the event has occured */
1460 var folderID = selected.getAttribute("id");
1461 var urlstr = URLForFolderID(folderID) + "/acls";
1463 openAclWindow(urlstr);
1467 function configureDragHandles() {
1468 var handle = $("verticalDragHandle");
1470 handle.addInterface(SOGoDragHandlesInterface);
1471 handle.leftBlock=$("leftPanel");
1472 handle.rightBlock=$("rightPanel");
1475 handle = $("rightDragHandle");
1477 handle.addInterface(SOGoDragHandlesInterface);
1478 handle.upperBlock=$("eventsListView");
1479 handle.lowerBlock=$("calendarView");
1483 function initCalendarSelector() {
1484 var selector = $("calendarSelector");
1485 updateCalendarStatus();
1486 selector.changeNotification = updateCalendarsList;
1488 var list = $("calendarList");
1489 list.multiselect = true;
1490 var items = list.childNodesWithTag("li");
1491 for (var i = 0; i < items.length; i++) {
1492 var input = items[i].childNodesWithTag("input")[0];
1493 Event.observe(input, "click", updateCalendarStatus.bindAsEventListener(input));
1494 Event.observe(items[i], "mousedown", listRowMouseDownHandler);
1495 Event.observe(items[i], "selectstart", listRowMouseDownHandler);
1496 Event.observe(items[i], "click", onRowClick);
1499 var links = $("calendarSelectorButtons").childNodesWithTag("a");
1500 Event.observe(links[0], "click", onCalendarNew);
1501 Event.observe(links[1], "click", onCalendarAdd);
1502 Event.observe(links[2], "click", onCalendarRemove);
1505 function onMenuModify(event) {
1506 var folders = $("calendarList");
1507 var selected = folders.getSelectedNodes()[0];
1509 if (UserLogin == selected.getAttribute("owner")) {
1510 var node = selected.childNodes[selected.childNodes.length - 1];
1511 var currentName = node.nodeValue.trim();
1512 var newName = window.prompt(labels["Name of the Calendar"],
1514 if (newName && newName.length > 0
1515 && newName != currentName) {
1516 var url = (URLForFolderID(selected.getAttribute("id"))
1517 + "/renameFolder?name=" + escape(newName.utf8encode()));
1518 triggerAjaxRequest(url, folderRenameCallback,
1519 {node: node, name: " " + newName});
1522 window.alert(clabels["Unable to rename that folder!"]);
1525 function folderRenameCallback(http) {
1526 if (http.readyState == 4) {
1527 if (isHttpStatus204(http.status)) {
1528 var dict = http.callbackData;
1529 dict["node"].nodeValue = dict["name"];
1534 function onCalendarNew(event) {
1535 createFolder(window.prompt(labels["Name of the Calendar"]),
1537 preventDefault(event);
1540 function onCalendarAdd(event) {
1541 openUserFolderSelector(onFolderSubscribeCB, "calendar");
1542 preventDefault(event);
1545 function appendCalendar(folderName, folderPath) {
1549 owner = getSubscribedFolderOwner(folderPath);
1550 folderPath = accessToSubscribedFolder(folderPath);
1553 folderPath = "/" + folderName;
1558 //log ("append name: " + folderName + "; path: " + folderPath + "; owner: " + owner);
1561 window.alert(clabels["You have already subscribed to that folder!"]);
1563 var calendarList = $("calendarList");
1564 var items = calendarList.childNodesWithTag("li");
1565 var li = document.createElement("li");
1567 // Add the calendar to the proper place
1568 var i = getListIndexForFolder(items, owner, folderName);
1569 if (i != items.length) // User is subscribed to other calendars of the same owner
1570 calendarList.insertBefore(li, items[i]);
1572 calendarList.appendChild(li);
1574 li.setAttribute("id", folderPath);
1575 li.setAttribute("owner", owner);
1577 // Generate new color
1578 if (calendarColorIndex == null)
1579 calendarColorIndex = items.length;
1580 calendarColorIndex++;
1581 var colorTable = [1, 1, 1];
1583 var currentValue = calendarColorIndex;
1585 while (currentValue) {
1586 if (currentValue & 1)
1587 colorTable[index]++;
1593 colorTable[0] = parseInt(255 / colorTable[0]) - 1;
1594 colorTable[1] = parseInt(255 / colorTable[1]) - 1;
1595 colorTable[2] = parseInt(255 / colorTable[2]) - 1;
1598 + colorTable[2].toString(16)
1599 + colorTable[1].toString(16)
1600 + colorTable[0].toString(16);
1601 //log ("color = " + color);
1603 var checkBox = document.createElement("input");
1604 checkBox.setAttribute("type", "checkbox");
1605 li.appendChild(checkBox);
1606 li.appendChild(document.createTextNode(" "));
1607 $(checkBox).addClassName("checkBox");
1608 if (owner == UserLogin)
1609 checkBox.checked = 1;
1611 var colorBox = document.createElement("div");
1612 li.appendChild(colorBox);
1613 li.appendChild(document.createTextNode(folderName));
1614 colorBox.appendChild(document.createTextNode("OO"));
1616 $(colorBox).addClassName("colorBox");
1617 $(colorBox).addClassName('calendarFolder' + folderPath.substr(1));
1619 // Register events (doesn't work with Safari)
1620 Event.observe(li, "mousedown", listRowMouseDownHandler);
1621 Event.observe(li, "selectstart", listRowMouseDownHandler);
1622 Event.observe(li, "click", onRowClick);
1623 Event.observe(checkBox, "click",
1624 updateCalendarStatus.bindAsEventListener(checkBox));
1626 var url = URLForFolderID(folderPath) + "/canAccessContent";
1627 triggerAjaxRequest(url, calendarEntryCallback, folderPath);
1629 // Update CSS for events color
1630 if (!document.styleSheets) return;
1632 var styleElement = document.createElement("style");
1633 styleElement.type = "text/css";
1635 '.calendarFolder' + folderPath.substr(1),
1636 'div.colorBox.calendarFolder' + folderPath.substr(1)
1639 ' { background-color: ' + color + ' !important; }',
1640 ' { color: ' + color + ' !important; }'
1642 for (var i = 0; i < rules.length; i++)
1643 if (styleElement.styleSheet && styleElement.styleSheet.addRule)
1644 styleElement.styleSheet.addRule(selectors[i], rules[i]); // IE
1646 styleElement.appendChild(document.createTextNode(selectors[i] + rules[i])); // Mozilla _+ Safari
1647 document.getElementsByTagName("head")[0].appendChild(styleElement);
1651 function onFolderSubscribeCB(folderData) {
1652 var folder = $(folderData["folder"]);
1654 appendCalendar(folderData["folderName"], folderData["folder"]);
1657 function onFolderUnsubscribeCB(folderId) {
1658 var node = $(folderId);
1659 node.parentNode.removeChild(node);
1660 if (removeFolderRequestCount == 0) {
1663 changeCalendarDisplay();
1667 function onCalendarRemove(event) {
1668 if (removeFolderRequestCount == 0) {
1669 var nodes = $("calendarList").getSelectedNodes();
1670 for (var i = 0; i < nodes.length; i++) {
1671 nodes[i].deselect();
1672 var folderId = nodes[i].getAttribute("id");
1673 var folderIdElements = folderId.split("_");
1674 if (folderIdElements.length > 1) {
1675 unsubscribeFromFolder(folderId, onFolderUnsubscribeCB, folderId);
1678 deletePersonalCalendar(folderIdElements[0]);
1682 preventDefault(event);
1685 function deletePersonalCalendar(folderElement) {
1686 var folderId = folderElement.substr(1);
1688 = labels["Are you sure you want to delete the calendar \"%{0}\"?"].formatted($(folderElement).lastChild.nodeValue.strip());
1689 if (window.confirm(label)) {
1690 removeFolderRequestCount++;
1691 var url = ApplicationBaseURL + "/" + folderId + "/deleteFolder";
1692 triggerAjaxRequest(url, deletePersonalCalendarCallback, folderId);
1696 function deletePersonalCalendarCallback(http) {
1697 if (http.readyState == 4) {
1698 if (isHttpStatus204(http.status)) {
1699 var ul = $("calendarList");
1700 var children = ul.childNodesWithTag("li");
1703 while (!done && i < children.length) {
1704 var currentFolderId = children[i].getAttribute("id").substr(1);
1705 if (currentFolderId == http.callbackData) {
1706 ul.removeChild(children[i]);
1712 removeFolderRequestCount--;
1713 if (removeFolderRequestCount == 0) {
1716 changeCalendarDisplay();
1721 log ("ajax problem 5: " + http.status);
1724 function configureLists() {
1725 var list = $("tasksList");
1726 list.multiselect = true;
1727 Event.observe(list, "mousedown",
1728 onTasksSelectionChange.bindAsEventListener(list));
1730 var input = $("showHideCompletedTasks");
1731 Event.observe(input, "click",
1732 onShowCompletedTasks.bindAsEventListener(input));
1734 list = $("eventsList");
1735 list.multiselect = true;
1736 configureSortableTableHeaders(list);
1737 TableKit.Resizable.init(list, {'trueResize' : true, 'keepWidth' : true});
1738 Event.observe(list, "mousedown",
1739 onEventsSelectionChange.bindAsEventListener(list));
1742 function initDateSelectorEvents() {
1743 var arrow = $("rightArrow");
1744 Event.observe(arrow, "click",
1745 onDateSelectorGotoMonth.bindAsEventListener(arrow));
1746 arrow = $("leftArrow");
1747 Event.observe(arrow, "click",
1748 onDateSelectorGotoMonth.bindAsEventListener(arrow));
1750 var menuButton = $("monthLabel");
1751 Event.observe(menuButton, "click",
1752 popupMonthMenu.bindAsEventListener(menuButton));
1753 menuButton = $("yearLabel");
1754 Event.observe(menuButton, "click",
1755 popupMonthMenu.bindAsEventListener(menuButton));
1758 function initCalendars() {
1759 sorting["attribute"] = "start";
1760 sorting["ascending"] = true;
1762 if (!document.body.hasClassName("popup")) {
1763 initDateSelectorEvents();
1764 initCalendarSelector();
1765 configureSearchField();
1767 var selector = $("calendarSelector");
1769 selector.attachMenu("calendarsMenu");
1773 FastInit.addOnLoad(initCalendars);