1 /* JavaScript for SOGoCalendar */
5 var listFilter = 'view_today';
7 var listOfSelection = null;
8 var selectedCalendarCell;
10 var showCompletedTasks = 0;
13 var currentView = "weekview";
15 var cachedDateSelectors = new Array();
17 var contactSelectorAction = 'calendars-contacts';
19 var eventsToDelete = new Array();
20 var calendarsOfEventsToDelete = new Array();
22 var usersRightsWindowHeight = 250;
23 var usersRightsWindowWidth = 502;
25 function newEvent(sender, type) {
30 var hour = sender.hour;
32 hour = sender.getAttribute("hour");
33 var folderID = getSelectedFolder();
34 var urlstr = ApplicationBaseURL + folderID + "/new" + type;
35 var params = new Array();
37 params.push("day=" + day);
39 params.push("hm=" + hour);
40 if (params.length > 0)
41 urlstr += "?" + params.join("&");
43 window.open(urlstr, "", "width=490,height=470,resizable=0");
45 return false; /* stop following the link */
48 function getSelectedFolder() {
51 var nodes = $("calendarList").getSelectedRows();
53 folder = nodes[0].getAttribute("id");
60 function onMenuNewEventClick(event) {
61 newEvent(this, "event");
64 function onMenuNewTaskClick(event) {
65 newEvent(this, "task");
68 function _editEventId(id, calendar) {
69 var urlstr = ApplicationBaseURL + "/" + calendar + "/" + id + "/edit";
70 var targetname = "SOGo_edit_" + id;
71 var win = window.open(urlstr, "_blank",
72 "width=490,height=470,resizable=0");
76 function editEvent() {
77 if (listOfSelection) {
78 var nodes = listOfSelection.getSelectedRows();
80 for (var i = 0; i < nodes.length; i++)
81 _editEventId(nodes[i].getAttribute("id"),
83 } else if (selectedCalendarCell) {
84 _editEventId(selectedCalendarCell[0].cname,
85 selectedCalendarCell[0].calendar);
88 return false; /* stop following the link */
91 function _batchDeleteEvents() {
92 var events = eventsToDelete.shift();
93 var calendar = calendarsOfEventsToDelete.shift();
94 var urlstr = (ApplicationBaseURL + "/" + calendar
95 + "/batchDelete?ids=" + events.join('/'));
96 document.deleteEventAjaxRequest = triggerAjaxRequest(urlstr,
101 function deleteEvent() {
102 if (listOfSelection) {
103 var nodes = listOfSelection.getSelectedRows();
105 if (nodes.length > 0) {
107 if (listOfSelection == $("tasksList"))
108 label = labels["taskDeleteConfirmation"];
110 label = labels["eventDeleteConfirmation"];
112 if (confirm(label)) {
113 if (document.deleteEventAjaxRequest) {
114 document.deleteEventAjaxRequest.aborted = true;
115 document.deleteEventAjaxRequest.abort();
117 var sortedNodes = new Array();
118 var calendars = new Array();
120 for (var i = 0; i < nodes.length; i++) {
121 var calendar = nodes[i].calendar;
122 if (!sortedNodes[calendar]) {
123 sortedNodes[calendar] = new Array();
124 calendars.push(calendar);
126 sortedNodes[calendar].push(nodes[i].cname);
128 for (var i = 0; i < calendars.length; i++) {
129 calendarsOfEventsToDelete.push(calendars[i]);
130 eventsToDelete.push(sortedNodes[calendars[i]]);
132 _batchDeleteEvents();
136 else if (selectedCalendarCell) {
137 var label = labels["eventDeleteConfirmation"];
138 if (confirm(label)) {
139 if (document.deleteEventAjaxRequest) {
140 document.deleteEventAjaxRequest.aborted = true;
141 document.deleteEventAjaxRequest.abort();
143 eventsToDelete.push([selectedCalendarCell[0].cname]);
144 calendarsOfEventsToDelete.push(selectedCalendarCell[0].calendar);
145 _batchDeleteEvents();
149 window.alert("no selection");
154 function modifyEvent(sender, modification) {
155 var currentLocation = '' + window.location;
156 var arr = currentLocation.split("/");
157 arr[arr.length-1] = modification;
159 document.modifyEventAjaxRequest = triggerAjaxRequest(arr.join("/"),
166 function closeInvitationWindow() {
167 var closeDiv = document.createElement("div");
168 document.body.appendChild(closeDiv);
169 closeDiv.addClassName("javascriptPopupBackground");
171 var closePseudoWin = document.createElement("div");
172 document.body.appendChild(closePseudoWin);
173 closePseudoWin.addClassName("javascriptMessagePseudoTopWindow");
174 closePseudoWin.style.top = "0px;";
175 closePseudoWin.style.left = "0px;";
176 closePseudoWin.style.right = "0px;";
177 closePseudoWin.appendChild(document.createTextNode(labels["closeThisWindowMessage"]));
179 var calLink = document.createElement("a");
180 closePseudoWin.appendChild(calLink);
181 calLink.href = ApplicationBaseURL;
182 calLink.appendChild(document.createTextNode(labels["Calendar"].toLowerCase()));
185 function modifyEventCallback(http) {
186 if (http.readyState == 4) {
187 if (http.status == 200) {
188 var mailInvitation = queryParameters["mail-invitation"];
189 if (mailInvitation && mailInvitation.toLowerCase() == "yes")
190 closeInvitationWindow();
192 window.opener.setTimeout("refreshEventsAndDisplay();", 100);
193 window.setTimeout("window.close();", 100);
197 // log("showing alert...");
198 window.alert(labels["eventPartStatModificationError"]);
200 document.modifyEventAjaxRequest = null;
204 function deleteEventCallback(http) {
205 if (http.readyState == 4) {
206 if (isHttpStatus204(http.status)) {
207 var nodes = http.callbackData;
208 for (var i = 0; i < nodes.length; i++) {
209 var node = $(nodes[i]);
211 node.parentNode.removeChild(node);
213 if (eventsToDelete.length)
214 _batchDeleteEvents();
216 document.deleteEventAjaxRequest = null;
219 changeCalendarDisplay();
223 log ("deleteEventCallback Ajax error");
227 function editDoubleClickedEvent(event) {
228 _editEventId(this.cname, this.calendar);
230 preventDefault(event);
231 event.cancelBubble = true;
234 function onSelectAll() {
235 var list = $("eventsList");
236 list.selectRowsMatchingClass("eventRow");
241 function onDaySelect(node) {
242 var day = node.getAttribute('day');
243 var needRefresh = (listFilter == 'view_selectedday'
244 && day != currentDay);
246 var td = $(node).getParentWithTagName("td");
247 var table = $(td).getParentWithTagName("table");
249 // log ("table.selected: " + table.selected);
251 if (document.selectedDate)
252 document.selectedDate.deselect();
255 document.selectedDate = td;
257 changeCalendarDisplay( { "day": day } );
264 function onDateSelectorGotoMonth(event) {
265 var day = this.getAttribute("date");
267 changeDateSelectorDisplay(day, true);
272 function onCalendarGotoDay(node) {
273 var day = node.getAttribute("date");
275 changeDateSelectorDisplay(day);
276 changeCalendarDisplay( { "day": day } );
281 function gotoToday() {
282 changeDateSelectorDisplay('');
283 changeCalendarDisplay();
288 function setDateSelectorContent(content) {
289 var div = $("dateSelectorView");
291 div.innerHTML = content;
292 if (currentDay.length > 0)
293 restoreCurrentDaySelection(div);
295 initDateSelectorEvents();
298 function dateSelectorCallback(http) {
299 if (http.readyState == 4
300 && http.status == 200) {
301 document.dateSelectorAjaxRequest = null;
302 var content = http.responseText;
303 setDateSelectorContent(content);
304 cachedDateSelectors[http.callbackData] = content;
307 log ("dateSelectorCallback Ajax error");
310 function eventsListCallback(http) {
311 if (http.readyState == 4
312 && http.status == 200) {
313 var div = $("eventsListView");
315 document.eventsListAjaxRequest = null;
316 var table = $("eventsList");
317 var params = parseQueryParameters(http.callbackData);
318 sortKey = params["sort"];
319 sortOrder = params["desc"];
320 lastClickedRow = null; // from generic.js
322 var data = http.responseText.evalJSON(true);
323 for (var i = 0; i < data.length; i++) {
324 var row = document.createElement("tr");
325 table.tBodies[0].appendChild(row);
326 $(row).addClassName("eventRow");
327 row.setAttribute("id", escape(data[i][0]));
328 row.cname = escape(data[i][0]);
329 row.calendar = data[i][1];
331 var startDate = new Date();
332 startDate.setTime(data[i][4] * 1000);
333 row.day = startDate.getDayString();
334 row.hour = startDate.getHourString();
335 Event.observe(row, "click",
336 onEventClick.bindAsEventListener(row));
337 Event.observe(row, "dblclick",
338 editDoubleClickedEvent.bindAsEventListener(row));
339 Event.observe(row, "contextmenu",
340 onEventContextMenu.bindAsEventListener(row));
342 var td = document.createElement("td");
344 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
345 td.appendChild(document.createTextNode(data[i][3]));
347 td = document.createElement("td");
349 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
350 td.appendChild(document.createTextNode(data[i][8]));
352 td = document.createElement("td");
354 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
355 td.appendChild(document.createTextNode(data[i][9]));
357 td = document.createElement("td");
359 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
360 td.appendChild(document.createTextNode(data[i][6]));
364 log ("eventsListCallback Ajax error");
367 function tasksListCallback(http) {
368 var div = $("tasksListView");
370 if (http.readyState == 4
371 && http.status == 200) {
372 document.tasksListAjaxRequest = null;
373 var list = $("tasksList");
374 var data = http.responseText.evalJSON(true);
376 for (var i = 0; i < data.length; i++) {
377 //log(i + " = " + data[i][3]);
378 var listItem = document.createElement("li");
379 list.appendChild(listItem);
380 Event.observe(listItem, "mousedown", listRowMouseDownHandler);
381 Event.observe(listItem, "click", onRowClick);
382 Event.observe(listItem, "dblclick", editDoubleClickedEvent.bindAsEventListener(listItem));
383 listItem.setAttribute("id", data[i][0]);
384 $(listItem).addClassName(data[i][5]);
385 listItem.calendar = data[i][1];
386 $(listItem).addClassName("calendarFolder" + data[i][1]);
387 listItem.cname = escape(data[i][0]);
388 var input = document.createElement("input");
389 input.setAttribute("type", "checkbox");
390 listItem.appendChild(input);
391 Event.observe(input, "click", updateTaskStatus.bindAsEventListener(input), true);
392 input.setAttribute("value", "1");
394 input.setAttribute("checked", "checked");
395 $(input).addClassName("checkBox");
396 listItem.appendChild(document.createTextNode(data[i][3]));
399 list.scrollTop = list.previousScroll;
401 if (http.callbackData) {
402 var selectedNodesId = http.callbackData;
403 for (var i = 0; i < selectedNodesId.length; i++) {
404 // log(selectedNodesId[i] + " (" + i + ") is selected");
405 $(selectedNodesId[i]).select();
409 log ("tasksListCallback: no data");
412 log ("tasksListCallback Ajax error");
415 function restoreCurrentDaySelection(div) {
416 var elements = $(div).getElementsByTagName("a");
419 while (!day && i < elements.length)
421 day = elements[i].day;
426 && day.substr(0, 6) == currentDay.substr(0, 6)) {
427 for (i = 0; i < elements.length; i++) {
428 day = elements[i].day;
429 if (day && day == currentDay) {
430 var td = $(elements[i]).getParentWithTagName("td");
431 if (document.selectedDate)
432 document.selectedDate.deselect();
434 document.selectedDate = td;
440 function changeDateSelectorDisplay(day, keepCurrentDay) {
441 var url = ApplicationBaseURL + "/dateselector";
443 url += "?day=" + day;
445 if (day != currentDay) {
449 var month = day.substr(0, 6);
450 if (cachedDateSelectors[month]) {
451 // log ("restoring cached selector for month: " + month);
452 setDateSelectorContent(cachedDateSelectors[month]);
455 // log ("loading selector for month: " + month);
456 if (document.dateSelectorAjaxRequest) {
457 document.dateSelectorAjaxRequest.aborted = true;
458 document.dateSelectorAjaxRequest.abort();
460 document.dateSelectorAjaxRequest
461 = triggerAjaxRequest(url,
462 dateSelectorCallback,
468 function changeCalendarDisplay(time, newView) {
469 var url = ApplicationBaseURL + "/" + ((newView) ? newView : currentView);
471 selectedCalendarCell = null;
483 url += "?day=" + day;
486 // log ("switching to view: " + newView);
487 // log ("changeCalendarDisplay: " + url);
489 if (document.dayDisplayAjaxRequest) {
490 // log ("aborting day ajaxrq");
491 document.dayDisplayAjaxRequest.aborted = true;
492 document.dayDisplayAjaxRequest.abort();
494 document.dayDisplayAjaxRequest
495 = triggerAjaxRequest(url, calendarDisplayCallback,
496 { "view": newView, "day": day, "hour": hour });
501 function _ensureView(view) {
502 if (currentView != view)
503 changeCalendarDisplay(null, view);
508 function onDayOverview() {
509 return _ensureView("dayview");
512 function onMulticolumnDayOverview() {
513 return _ensureView("multicolumndayview");
516 function onWeekOverview() {
517 return _ensureView("weekview");
520 function onMonthOverview() {
521 return _ensureView("monthview");
524 function scrollDayView(hour) {
527 if (hour.length == 3)
528 rowNumber = parseInt(hour.substr(0, 1));
530 if (hour.substr(0, 1) == "0")
531 rowNumber = parseInt(hour.substr(1, 1));
533 rowNumber = parseInt(hour.substr(0, 2));
538 var daysView = $("daysView");
540 $(daysView.childNodesWithTag("div")[0]).childNodesWithTag("div");
541 if (hours.length > 0)
542 daysView.scrollTop = hours[rowNumber].offsetTop;
545 function onClickableCellsDblClick(event) {
546 newEvent(this, 'event');
548 event.cancelBubble = true;
549 event.returnValue = false;
552 function refreshCalendarEvents() {
553 var todayDate = new Date();
556 if (currentView == "dayview") {
560 sd = todayDate.getDayString();
563 else if (currentView == "weekview") {
566 startDate = currentDay.asDate();
568 startDate = todayDate;
569 startDate = startDate.beginOfWeek();
570 sd = startDate.getDayString();
571 var endDate = new Date();
572 endDate.setTime(startDate.getTime());
574 ed = endDate.getDayString();
579 monthDate = currentDay.asDate();
581 monthDate = todayDate;
582 monthDate.setDate(1);
583 sd = monthDate.beginOfWeek().getDayString();
585 var lastMonthDate = new Date();
586 lastMonthDate.setTime(monthDate.getTime());
587 lastMonthDate.setMonth(monthDate.getMonth() + 1);
588 lastMonthDate.addDays(-1);
589 ed = lastMonthDate.endOfWeek().getDayString();
591 if (document.refreshCalendarEventsAjaxRequest) {
592 document.refreshCalendarEventsAjaxRequest.aborted = true;
593 document.refreshCalendarEventsAjaxRequest.abort();
595 var url = ApplicationBaseURL + "/eventslist?sd=" + sd + "&ed=" + ed;
596 document.refreshCalendarEventsAjaxRequest
597 = triggerAjaxRequest(url, refreshCalendarEventsCallback,
598 {"startDate": sd, "endDate": ed});
601 function refreshCalendarEventsCallback(http) {
602 if (http.readyState == 4
603 && http.status == 200) {
604 var data = http.responseText.evalJSON(true);
605 // log("refresh calendar events: " + data.length);
606 for (var i = 0; i < data.length; i++)
607 drawCalendarEvent(data[i],
608 http.callbackData["startDate"],
609 http.callbackData["endDate"]);
612 log("AJAX error when refreshing calendar events");
615 function drawCalendarEvent(eventData, sd, ed) {
616 var viewStartDate = sd.asDate();
617 var viewEndDate = ed.asDate();
619 var startDate = new Date();
620 var endDate = new Date();
621 if (eventData[7] == 0) {
622 startDate.setTime(eventData[4] * 1000 + (1000 * UTCOffset));
623 endDate.setTime(eventData[5] * 1000 + (1000 * UTCOffset));
626 startDate.setTime(eventData[4] * 1000);
627 endDate.setTime(eventData[5] * 1000);
630 // log ("s: " + startDate+ "; e: " + endDate);
632 var days = startDate.daysUpTo(endDate);
634 var divs = new Array();
637 if (currentView == "monthview"
638 && (eventData[7] == 0))
639 title = startDate.getDisplayHoursString() + " " + eventData[3];
641 title = eventData[3];
643 // log("title: " + title);
644 // log("viewS: " + viewStartDate);
645 var startHour = null;
648 var siblings = new Array();
649 for (var i = 0; i < days.length; i++)
650 if (days[i].earlierDate(viewStartDate) == viewStartDate
651 && days[i].laterDate(viewEndDate) == viewEndDate) {
654 // log("day: " + days[i]);
656 var quarters = (startDate.getUTCHours() * 4
657 + Math.floor(startDate.getUTCMinutes() / 15));
659 startHour = startDate.getDisplayHoursString();
660 endHour = endDate.getDisplayHoursString();
667 if (i == days.length - 1) {
668 var quarters = (endDate.getUTCHours() * 4
669 + Math.ceil(endDate.getUTCMinutes() / 15));
674 lasts = ends - starts;
678 var eventDiv = newEventDIV(eventData[0], eventData[1], starts, lasts,
680 siblings.push(eventDiv);
681 eventDiv.siblings = siblings;
682 var dayString = days[i].getDayString();
683 // log("day: " + dayString);
684 var parentDiv = null;
685 if (currentView == "monthview") {
686 var dayDivs = $("monthDaysView").childNodesWithTag("div");
688 while (!parentDiv && j < dayDivs.length) {
689 if (dayDivs[j].getAttribute("day") == dayString)
690 parentDiv = dayDivs[j];
696 if (eventData[7] == 0) {
697 var daysView = $("daysView");
698 var eventsDiv = $(daysView).childNodesWithTag("div")[1];
699 var dayDivs = $(eventsDiv).childNodesWithTag("div");
701 while (!parentDiv && j < dayDivs.length) {
702 if (dayDivs[j].getAttribute("day") == dayString)
703 parentDiv = dayDivs[j].childNodesWithTag("div")[0];
709 var header = $("calendarHeader");
710 var daysDiv = $(header).childNodesWithTag("div")[1];
711 var dayDivs = $(daysDiv).childNodesWithTag("div");
713 while (!parentDiv && j < dayDivs.length) {
714 if (dayDivs[j].getAttribute("day") == dayString)
715 parentDiv = dayDivs[j];
722 parentDiv.appendChild(eventDiv);
726 function newEventDIV(cname, calendar, starts, lasts,
727 startHour, endHour, title) {
728 var eventDiv = document.createElement("div");
729 eventDiv.cname = escape(cname);
730 eventDiv.calendar = calendar;
731 $(eventDiv).addClassName("event");
732 $(eventDiv).addClassName("starts" + starts);
733 $(eventDiv).addClassName("lasts" + lasts);
734 for (var i = 1; i < 5; i++) {
735 var shadowDiv = document.createElement("div");
736 eventDiv.appendChild(shadowDiv);
737 $(shadowDiv).addClassName("shadow");
738 $(shadowDiv).addClassName("shadow" + i);
740 var innerDiv = document.createElement("div");
741 eventDiv.appendChild(innerDiv);
742 $(innerDiv).addClassName("eventInside");
743 $(innerDiv).addClassName("calendarFolder" + calendar);
745 var gradientDiv = document.createElement("div");
746 innerDiv.appendChild(gradientDiv);
747 $(gradientDiv).addClassName("gradient");
748 var gradientImg = document.createElement("img");
749 gradientDiv.appendChild(gradientImg);
750 gradientImg.src = ResourcesURL + "/event-gradient.png";
752 var textDiv = document.createElement("div");
753 innerDiv.appendChild(textDiv);
754 $(textDiv).addClassName("text");
756 var headerSpan = document.createElement("span");
757 textDiv.appendChild(headerSpan);
758 $(headerSpan).addClassName("eventHeader");
759 headerSpan.appendChild(document.createTextNode(startHour + " - "
761 textDiv.appendChild(document.createElement("br"));
763 textDiv.appendChild(document.createTextNode(title));
765 Event.observe(eventDiv, "mousedown", listRowMouseDownHandler);
766 Event.observe(eventDiv, "click",
767 onCalendarSelectEvent.bindAsEventListener(eventDiv));
768 Event.observe(eventDiv, "dblclick",
769 editDoubleClickedEvent.bindAsEventListener(eventDiv));
774 function calendarDisplayCallback(http) {
775 var div = $("calendarView");
777 if (http.readyState == 4
778 && http.status == 200) {
779 document.dayDisplayAjaxRequest = null;
780 div.update(http.responseText);
781 if (http.callbackData["view"])
782 currentView = http.callbackData["view"];
783 if (http.callbackData["day"])
784 currentDay = http.callbackData["day"];
787 if (http.callbackData["hour"])
788 hour = http.callbackData["hour"];
790 if (currentView == "monthview")
791 contentView = $("calendarContent");
794 contentView = $("daysView");
796 refreshCalendarEvents();
797 var days = document.getElementsByClassName("day", contentView);
798 if (currentView == "monthview")
799 for (var i = 0; i < days.length; i++) {
800 Event.observe(days[i], "click", onCalendarSelectDay.bindAsEventListener(days[i]));
801 Event.observe(days[i], "dblclick", onClickableCellsDblClick.bindAsEventListener(days[i]));
804 var headerDivs = $("calendarHeader").childNodesWithTag("div");
805 var headerDaysLabels = document.getElementsByClassName("day", headerDivs[0]);
806 var headerDays = document.getElementsByClassName("day", headerDivs[1]);
807 for (var i = 0; i < days.length; i++) {
808 headerDays[i].hour = "allday";
809 Event.observe(headerDaysLabels[i], "mousedown", listRowMouseDownHandler);
810 Event.observe(headerDays[i], "click",
811 onCalendarSelectDay.bindAsEventListener(days[i]));
812 Event.observe(headerDays[i], "dblclick",
813 onClickableCellsDblClick.bindAsEventListener(headerDays[i]));
814 Event.observe(days[i], "click",
815 onCalendarSelectDay.bindAsEventListener(days[i]));
816 var clickableCells = document.getElementsByClassName("clickableHourCell",
818 for (var j = 0; j < clickableCells.length; j++)
819 Event.observe(clickableCells[j], "dblclick",
820 onClickableCellsDblClick.bindAsEventListener(clickableCells[j]));
825 log ("calendarDisplayCallback Ajax error (" + http.readyState + "/" + http.status + ")");
828 function assignCalendar(name) {
829 if (typeof(skycalendar) != "undefined") {
832 node.calendar = new skycalendar(node);
833 node.calendar.setCalendarPage(ResourcesURL + "/skycalendar.html");
834 var dateFormat = node.getAttribute("dateFormat");
836 node.calendar.setDateFormat(dateFormat);
840 function popupCalendar(node) {
841 var nodeId = node.getAttribute("inputId");
842 var input = $(nodeId);
843 input.calendar.popup();
848 function onEventContextMenu(event) {
849 var topNode = $("eventsList");
852 var menu = $("eventsListMenu");
854 Event.observe(menu, "hideMenu", onEventContextMenuHide);
855 popupMenu(event, "eventsListMenu", this);
857 var topNode = $("eventsList");
858 var selectedNodes = topNode.getSelectedRows();
859 topNode.menuSelectedRows = selectedNodes;
860 for (var i = 0; i < selectedNodes.length; i++)
861 selectedNodes[i].deselect();
863 topNode.menuSelectedEntry = this;
867 function onEventContextMenuHide(event) {
868 var topNode = $("eventsList");
870 if (topNode.menuSelectedEntry) {
871 topNode.menuSelectedEntry.deselect();
872 topNode.menuSelectedEntry = null;
874 if (topNode.menuSelectedRows) {
875 var nodeIds = topNode.menuSelectedRows;
876 for (var i = 0; i < nodeIds.length; i++) {
877 var node = $(nodeIds[i]);
880 topNode.menuSelectedRows = null;
884 function onEventsSelectionChange() {
885 listOfSelection = this;
886 this.removeClassName("_unfocused");
887 $("tasksList").addClassName("_unfocused");
890 function onTasksSelectionChange() {
891 listOfSelection = this;
892 this.removeClassName("_unfocused");
893 $("eventsList").addClassName("_unfocused");
896 function _loadEventHref(href) {
897 if (document.eventsListAjaxRequest) {
898 document.eventsListAjaxRequest.aborted = true;
899 document.eventsListAjaxRequest.abort();
901 var url = ApplicationBaseURL + "/" + href;
902 document.eventsListAjaxRequest
903 = triggerAjaxRequest(url, eventsListCallback, href);
905 var table = $("eventsList").tBodies[0];
906 while (table.rows.length > 0)
907 table.removeChild(table.rows[0]);
912 function _loadTasksHref(href) {
913 if (document.tasksListAjaxRequest) {
914 document.tasksListAjaxRequest.aborted = true;
915 document.tasksListAjaxRequest.abort();
917 url = ApplicationBaseURL + "/" + href;
919 var tasksList = $("tasksList");
922 selectedIds = tasksList.getSelectedNodesId();
925 document.tasksListAjaxRequest
926 = triggerAjaxRequest(url, tasksListCallback, selectedIds);
928 tasksList.previousScroll = tasksList.scrollTop;
929 while (tasksList.childNodes.length)
930 tasksList.removeChild(tasksList.childNodes[0]);
935 function onHeaderClick(event) {
936 //log("onHeaderClick: " + this.link);
937 //_loadEventHref(this.link);
939 preventDefault(event);
942 function refreshEvents() {
943 return _loadEventHref("eventslist?desc=" + sortOrder
945 + "&day=" + currentDay
946 + "&filterpopup=" + listFilter);
949 function refreshTasks() {
950 return _loadTasksHref("taskslist?show-completed=" + showCompletedTasks);
953 function refreshEventsAndDisplay() {
955 changeCalendarDisplay();
958 function onListFilterChange() {
959 var node = $("filterpopup");
961 listFilter = node.value;
962 // log ("listFilter = " + listFilter);
964 return refreshEvents();
967 function onEventClick(event) { log ("onEventClick");
969 var hour = this.hour;
971 changeCalendarDisplay( { "day": day, "hour": hour} );
972 changeDateSelectorDisplay(day);
974 return onRowClick(event);
977 function selectMonthInMenu(menu, month) {
978 var entries = menu.childNodes[1].childNodesWithTag("LI");
979 for (i = 0; i < entries.length; i++) {
980 var entry = entries[i];
981 var entryMonth = entry.getAttribute("month");
982 if (entryMonth == month)
983 entry.addClassName("currentMonth");
985 entry.removeClassName("currentMonth");
989 function selectYearInMenu(menu, month) {
990 var entries = menu.childNodes[1].childNodes;
991 for (i = 0; i < entries.length; i++) {
992 var entry = entries[i];
993 if (entry.tagName == "LI") {
994 var entryMonth = entry.innerHTML;
995 if (entryMonth == month)
996 entry.addClassName("currentMonth");
998 entry.removeClassName("currentMonth");
1003 function popupMonthMenu(event) {
1004 if (event.button == 0) {
1005 var id = this.getAttribute("id");
1006 if (id == "monthLabel")
1007 menuId = "monthListMenu";
1009 menuId = "yearListMenu";
1011 var popup = $(menuId);
1012 if (id == "monthLabel")
1013 selectMonthInMenu(popup, this.getAttribute("month"));
1015 selectYearInMenu(popup, this.innerHTML);
1017 popupToolbarMenu(this, menuId);
1022 function onMonthMenuItemClick(event) {
1023 var month = '' + this.getAttribute("month");
1024 var year = '' + $("yearLabel").innerHTML;
1026 changeDateSelectorDisplay(year + month + "01", true);
1029 function onYearMenuItemClick(event) {
1030 var month = '' + $("monthLabel").getAttribute("month");;
1031 var year = '' + this.innerHTML;
1033 changeDateSelectorDisplay(year + month + "01", true);
1036 function onSearchFormSubmit() {
1037 log ("search not implemented");
1042 function onCalendarSelectEvent() {
1043 var list = $("eventsList");
1044 $(list.tBodies[0]).deselectAll();
1046 if (selectedCalendarCell)
1047 for (var i = 0; i < selectedCalendarCell.length; i++)
1048 selectedCalendarCell[i].deselect();
1050 for (var i = 0; i < this.siblings.length; i++)
1051 this.siblings[i].select();
1052 selectedCalendarCell = this.siblings;
1053 var row = $(this.cname);
1055 var div = row.parentNode.parentNode.parentNode;
1056 div.scrollTop = row.offsetTop - (div.offsetHeight / 2);
1061 function onCalendarSelectDay(event) {
1063 if (currentView == "multicolumndayview")
1064 day = this.getAttribute("day");
1066 day = this.getAttribute("day");
1067 var needRefresh = (listFilter == 'view_selectedday'
1068 && day != currentDay);
1070 if (currentView == 'weekview')
1071 changeWeekCalendarDisplayOfSelectedDay(this);
1072 else if (currentView == 'monthview')
1073 changeMonthCalendarDisplayOfSelectedDay(this);
1074 changeDateSelectorDisplay(day);
1076 if (listOfSelection) {
1077 listOfSelection.addClassName("_unfocused");
1078 listOfSelection = null;
1085 function changeWeekCalendarDisplayOfSelectedDay(node) {
1086 var days = document.getElementsByClassName("day", node.parentNode);
1087 var headerDiv = $("calendarHeader").childNodesWithTag("div")[1];
1088 var headerDays = document.getElementsByClassName("day", headerDiv);
1090 // log ("days: " + days.length + "; headerDays: " + headerDays.length);
1091 for (var i = 0; i < days.length; i++)
1092 if (days[i] != node) {
1093 // log("unselect day : " + i);
1094 headerDays[i].removeClassName("selectedDay");
1095 days[i].removeClassName("selectedDay");
1098 // log("selected day : " + i);
1099 headerDays[i].addClassName("selectedDay");
1100 days[i].addClassName("selectedDay");
1104 function findMonthCalendarSelectedCell(daysContainer) {
1108 while (!found && i < daysContainer.childNodes.length) {
1109 var currentNode = daysContainer.childNodes[i];
1110 if (currentNode.tagName == 'DIV'
1111 && currentNode.hasClassName("selectedDay")) {
1112 daysContainer.selectedCell = currentNode;
1120 function changeMonthCalendarDisplayOfSelectedDay(node) {
1121 var daysContainer = node.parentNode;
1122 if (!daysContainer.selectedCell)
1123 findMonthCalendarSelectedCell(daysContainer);
1125 if (daysContainer.selectedCell)
1126 daysContainer.selectedCell.removeClassName("selectedDay");
1127 daysContainer.selectedCell = node;
1128 node.addClassName("selectedDay");
1131 function onShowCompletedTasks(event) {
1132 showCompletedTasks = (this.checked ? 1 : 0);
1134 return refreshTasks();
1137 function updateTaskStatus(event) {
1138 var taskId = this.parentNode.getAttribute("id");
1139 var newStatus = (this.checked ? 1 : 0);
1140 var http = createHTTPClient();
1142 if (isSafari() && !isSafari3()) {
1143 newStatus = (newStatus ? 0 : 1);
1146 url = (ApplicationBaseURL + "/" + this.parentNode.calendar
1147 + "/" + taskId + "/changeStatus?status=" + newStatus);
1150 // TODO: add parameter to signal that we are only interested in OK
1151 http.open("POST", url, false /* not async */);
1154 if (http.status == 200)
1157 log ("no http client?");
1162 function updateCalendarStatus(event) {
1163 var list = new Array();
1164 var newStatus = (this.checked ? 1 : 0);
1166 if (isSafari() && !isSafari3()) {
1167 newStatus = (newStatus ? 0 : 1);
1168 this.checked = newStatus;
1171 var nodes = $("calendarList").childNodesWithTag("li");
1172 for (var i = 0; i < nodes.length; i++) {
1173 var input = $(nodes[i]).childNodesWithTag("input")[0];
1174 if (input.checked) {
1175 var folderId = nodes[i].getAttribute("id");
1176 var elems = folderId.split(":");
1177 if (elems.length > 1)
1178 list.push(elems[0]);
1180 list.push(UserLogin);
1184 // if (!list.length) {
1185 // list.push(UserLogin);
1186 // nodes[0].childNodesWithTag("input")[0].checked = true;
1189 // ApplicationBaseURL = (UserFolderURL + "Groups/_custom_"
1190 // + list.join(",") + "/Calendar/");
1193 var folderID = this.parentNode.getAttribute("id");
1194 var urlstr = URLForFolderID(folderID);
1196 urlstr += "/activateFolder";
1198 urlstr += "/deactivateFolder";
1199 //log("updateCalendarStatus: ajax request = " + urlstr + ", folderID = " + folderID);
1200 triggerAjaxRequest(urlstr, calendarStatusCallback, folderID);
1203 updateCalendarsList();
1206 changeCalendarDisplay();
1212 function calendarStatusCallback(http) {
1213 if (http.readyState == 4) {
1214 if (isHttpStatus204(http.status)) {
1217 changeCalendarDisplay();
1220 var folder = $(http.callbackData);
1221 var input = folder.childNodesWithTag("input")[0];
1222 input.checked = (!input.checked);
1226 log("calendarStatusCallback Ajax error");
1229 function calendarEntryCallback(http) {
1230 if (http.readyState == 4) {
1231 var denied = !isHttpStatus204(http.status);
1232 var entry = $(http.callbackData);
1234 entry.addClassName("denied");
1236 entry.removeClassName("denied");
1240 function updateCalendarsList(method) {
1241 var list = $("calendarList").childNodesWithTag("li");
1242 for (var i = 0; i < list.length; i++) {
1243 var folderID = list[i].getAttribute("id");
1244 var url = URLForFolderID(folderID) + "/canAccessContent";
1245 triggerAjaxRequest(url, calendarEntryCallback, folderID);
1249 function addContact(tag, fullContactName, contactId, contactName, contactEmail) {
1250 var uids = $("uixselector-calendarsList-uidList");
1251 // log("addContact");
1254 var re = new RegExp("(^|,)" + contactId + "($|,)");
1256 if (!re.test(uids.value))
1258 if (uids.value.length > 0)
1259 uids.value += ',' + contactId;
1261 uids.value = contactId;
1262 var names = $("calendarList");
1263 var listElems = names.childNodesWithTag("li");
1264 var colorDef = indexColor(listElems.length);
1265 names.appendChild(userCalendarEntry(contactId, colorDef));
1273 function validateBrowseURL(input) {
1274 var button = $("browseURLBtn");
1276 if (input.value.length) {
1277 if (!button.enabled)
1278 enableAnchor(button);
1279 } else if (!button.disabled)
1280 disableAnchor(button);
1283 function browseURL(anchor, event) {
1284 if (event.button == 0) {
1285 var input = $("url");
1286 var url = input.value;
1288 window.open(url, '_blank');
1294 function getMenus() {
1297 var dateMenu = new Array();
1298 for (var i = 0; i < 12; i++)
1299 dateMenu.push(onMonthMenuItemClick);
1300 menus["monthListMenu"] = dateMenu;
1302 dateMenu = new Array();
1303 for (var i = 0; i < 11; i++)
1304 dateMenu.push(onYearMenuItemClick);
1305 menus["yearListMenu"] = dateMenu;
1307 menus["eventsListMenu"] = new Array(onMenuNewEventClick, "-",
1309 editEvent, deleteEvent, "-",
1312 menus["calendarsMenu"] = new Array(onMenuModify,
1314 onCalendarNew, onCalendarRemove,
1315 "-", null, null, "-",
1316 null, "-", onMenuSharing);
1317 menus["searchMenu"] = new Array(setSearchCriteria);
1322 function onMenuSharing(event) {
1323 var folders = $("calendarList");
1324 var selected = folders.getSelectedNodes()[0];
1325 /* FIXME: activation of the context menu should preferable select the entry
1326 above which the event has occured */
1328 var folderID = selected.getAttribute("id");
1329 var urlstr = URLForFolderID(folderID) + "/acls";
1331 openAclWindow(urlstr);
1335 function configureDragHandles() {
1336 var handle = $("verticalDragHandle");
1338 handle.addInterface(SOGoDragHandlesInterface);
1339 handle.leftBlock=$("leftPanel");
1340 handle.rightBlock=$("rightPanel");
1343 handle = $("rightDragHandle");
1345 handle.addInterface(SOGoDragHandlesInterface);
1346 handle.upperBlock=$("eventsListView");
1347 handle.lowerBlock=$("calendarView");
1351 function initCalendarSelector() {
1352 var selector = $("calendarSelector");
1353 updateCalendarStatus();
1354 selector.changeNotification = updateCalendarsList;
1356 var list = $("calendarList");
1357 list.multiselect = true;
1358 var items = list.childNodesWithTag("li");
1359 for (var i = 0; i < items.length; i++) {
1360 var input = items[i].childNodesWithTag("input")[0];
1361 Event.observe(input, "click", updateCalendarStatus.bindAsEventListener(input));
1362 Event.observe(items[i], "mousedown", listRowMouseDownHandler);
1363 Event.observe(items[i], "selectstart", listRowMouseDownHandler);
1364 Event.observe(items[i], "click", onRowClick);
1367 var links = $("calendarSelectorButtons").childNodesWithTag("a");
1368 Event.observe(links[0], "click", onCalendarNew);
1369 Event.observe(links[1], "click", onCalendarAdd);
1370 Event.observe(links[2], "click", onCalendarRemove);
1373 function onMenuModify(event) {
1374 var folders = $("calendarList");
1375 var selected = folders.getSelectedNodes()[0];
1377 if (UserLogin == selected.getAttribute("owner")) {
1378 var node = selected.childNodes[4];
1379 var currentName = node.nodeValue.trim();
1380 var newName = window.prompt(labels["Name of the Calendar"],
1382 if (newName && newName.length > 0
1383 && newName != currentName) {
1384 var url = (URLForFolderID(selected.getAttribute("id"))
1385 + "/renameFolder?name=" + escape(newName.utf8encode()));
1386 triggerAjaxRequest(url, folderRenameCallback,
1387 {node: node, name: " " + newName});
1390 window.alert(clabels["Unable to rename that folder!"]);
1393 function folderRenameCallback(http) {
1394 if (http.readyState == 4) {
1395 if (isHttpStatus204(http.status)) {
1396 var dict = http.callbackData;
1397 dict["node"].nodeValue = dict["name"];
1402 function onCalendarNew(event) {
1403 createFolder(window.prompt(labels["Name of the Calendar"]),
1405 preventDefault(event);
1408 function onCalendarAdd(event) {
1409 openUserFolderSelector(onFolderSubscribeCB, "calendar");
1410 preventDefault(event);
1413 function appendCalendar(folderName, folderPath) {
1417 owner = getSubscribedFolderOwner(folderPath);
1418 folderPath = accessToSubscribedFolder(folderPath);
1421 folderPath = "/" + folderName;
1426 //log ("append name: " + folderName + "; path: " + folderPath + "; owner: " + owner);
1429 window.alert(clabels["You have already subscribed to that folder!"]);
1431 var calendarList = $("calendarList");
1432 var lis = calendarList.childNodesWithTag("li");
1433 var color = indexColor(lis.length + 100);
1434 //log ("color: " + color);
1436 var li = document.createElement("li");
1438 // Add the calendar to the proper place
1439 var previousOwner = null;
1440 for (var i = 1; i < lis.length; i++) {
1441 var currentFolderName = lis[i].lastChild.nodeValue.strip();
1442 var currentOwner = lis[i].readAttribute('owner');
1443 if (currentOwner == owner) {
1444 previousOwner = currentOwner;
1445 if (currentFolderName > folderName)
1448 else if (previousOwner ||
1449 (currentOwner != UserLogin && currentOwner > owner))
1452 if (i != lis.length) // User is subscribed to other calendars of the same owner
1453 calendarList.insertBefore(li, lis[i]);
1455 calendarList.appendChild(li);
1457 li.setAttribute("id", folderPath);
1458 li.setAttribute("owner", owner);
1460 var checkBox = document.createElement("input");
1461 checkBox.setAttribute("type", "checkbox");
1462 li.appendChild(checkBox);
1463 li.appendChild(document.createTextNode(" "));
1464 $(checkBox).addClassName("checkBox");
1466 var colorBox = document.createElement("div");
1467 li.appendChild(colorBox);
1468 li.appendChild(document.createTextNode(folderName));
1469 colorBox.appendChild(document.createTextNode("OO"));
1471 $(colorBox).addClassName("colorBox");
1472 $(colorBox).addClassName('calendarFolder' + folderPath.substr(1));
1474 // Register events (doesn't work with Safari)
1475 Event.observe(li, "mousedown", listRowMouseDownHandler);
1476 Event.observe(li, "selectstart", listRowMouseDownHandler);
1477 Event.observe(li, "click", onRowClick);
1478 Event.observe(checkBox, "click",
1479 updateCalendarStatus.bindAsEventListener(checkBox));
1481 var url = URLForFolderID(folderPath) + "/canAccessContent";
1482 triggerAjaxRequest(url, calendarEntryCallback, folderPath);
1484 // Update CSS for events color
1485 if (!document.styleSheets) return;
1486 var theRules = new Array();
1487 var lastSheet = document.styleSheets[document.styleSheets.length - 1];
1488 if (lastSheet.insertRule) { // Mozilla
1489 lastSheet.insertRule('.calendarFolder' + folderPath.substr(1) + ' {'
1490 + ' background-color: '
1492 + ' !important; }', 0);
1493 lastSheet.insertRule('div.colorBox.calendarFolder' + folderPath.substr(1) + ' {'
1496 + ' !important; }', 0);
1499 lastSheet.addRule('.calendarFolder' + folderPath.substr(1),
1500 ' background-color: '
1502 + ' !important; }');
1503 lastSheet.addRule('div.colorBox.calendarFolder' + folderPath.substr(1),
1506 + ' !important; }');
1511 function onFolderSubscribeCB(folderData) {
1512 var folder = $(folderData["folder"]);
1514 appendCalendar(folderData["folderName"], folderData["folder"]);
1517 function onFolderUnsubscribeCB(folderId) {
1518 var node = $(folderId);
1519 node.parentNode.removeChild(node);
1520 if (removeFolderRequestCount == 0) {
1523 changeCalendarDisplay();
1527 function onCalendarRemove(event) {
1528 if (removeFolderRequestCount == 0) {
1529 var nodes = $("calendarList").getSelectedNodes();
1530 for (var i = 0; i < nodes.length; i++) {
1531 nodes[i].deselect();
1532 var folderId = nodes[i].getAttribute("id");
1533 var folderIdElements = folderId.split("_");
1534 if (folderIdElements.length > 1) {
1535 unsubscribeFromFolder(folderId, onFolderUnsubscribeCB, folderId);
1538 deletePersonalCalendar(folderIdElements[0]);
1542 preventDefault(event);
1545 function deletePersonalCalendar(folderElement) {
1546 var folderId = folderElement.substr(1);
1548 = labels["Are you sure you want to delete the calendar \"%{0}\"?"].formatted($(folderElement).lastChild.nodeValue.strip());
1549 if (window.confirm(label)) {
1550 removeFolderRequestCount++;
1551 var url = ApplicationBaseURL + "/" + folderId + "/deleteFolder";
1552 triggerAjaxRequest(url, deletePersonalCalendarCallback, folderId);
1556 function deletePersonalCalendarCallback(http) {
1557 if (http.readyState == 4) {
1558 if (isHttpStatus204(http.status)) {
1559 var ul = $("calendarList");
1560 var children = ul.childNodesWithTag("li");
1563 while (!done && i < children.length) {
1564 var currentFolderId = children[i].getAttribute("id").substr(1);
1565 if (currentFolderId == http.callbackData) {
1566 ul.removeChild(children[i]);
1572 removeFolderRequestCount--;
1573 if (removeFolderRequestCount == 0) {
1576 changeCalendarDisplay();
1581 log ("ajax problem 5: " + http.status);
1584 function configureLists() {
1585 var list = $("tasksList");
1586 list.multiselect = true;
1587 Event.observe(list, "mousedown",
1588 onTasksSelectionChange.bindAsEventListener(list));
1590 var input = $("showHideCompletedTasks");
1591 Event.observe(input, "click",
1592 onShowCompletedTasks.bindAsEventListener(input));
1594 list = $("eventsList");
1595 list.multiselect = true;
1596 //configureSortableTableHeaders(list);
1597 TableKit.Resizable.init(list, {'trueResize' : true, 'keepWidth' : true});
1598 Event.observe(list, "mousedown",
1599 onEventsSelectionChange.bindAsEventListener(list));
1600 var div = list.parentNode;
1601 Event.observe(div, "contextmenu",
1602 onEventContextMenu.bindAsEventListener(div));
1605 function initDateSelectorEvents() {
1606 var arrow = $("rightArrow");
1607 Event.observe(arrow, "click",
1608 onDateSelectorGotoMonth.bindAsEventListener(arrow));
1609 arrow = $("leftArrow");
1610 Event.observe(arrow, "click",
1611 onDateSelectorGotoMonth.bindAsEventListener(arrow));
1613 var menuButton = $("monthLabel");
1614 Event.observe(menuButton, "click",
1615 popupMonthMenu.bindAsEventListener(menuButton));
1616 menuButton = $("yearLabel");
1617 Event.observe(menuButton, "click",
1618 popupMonthMenu.bindAsEventListener(menuButton));
1621 function initCalendars() {
1622 if (!document.body.hasClassName("popup")) {
1623 initDateSelectorEvents();
1624 initCalendarSelector();
1625 configureSearchField();
1627 var selector = $("calendarSelector");
1629 selector.attachMenu("calendarsMenu");
1633 addEvent(window, 'load', initCalendars);