1 /* JavaScript for SOGoCalendar */
5 var listFilter = 'view_today';
7 var listOfSelection = null;
8 var selectedCalendarCell;
9 var calendarColorIndex = null;
11 var showCompletedTasks = 0;
14 var currentView = "weekview";
16 var cachedDateSelectors = new Array();
18 var contactSelectorAction = 'calendars-contacts';
20 var eventsToDelete = new Array();
21 var calendarsOfEventsToDelete = new Array();
23 var usersRightsWindowHeight = 250;
24 var usersRightsWindowWidth = 502;
26 function newEvent(sender, type) {
31 var hour = sender.hour;
33 hour = sender.getAttribute("hour");
34 var folder = getSelectedFolder();
35 var roles = folder.getAttribute("roles").split(",");
36 var folderID = folder.getAttribute("id");
37 if ($(roles).indexOf("PublicModifier") < 0)
38 folderID = "/personal";
39 var urlstr = ApplicationBaseURL + folderID + "/new" + type;
40 var params = new Array();
42 params.push("day=" + day);
44 params.push("hm=" + hour);
45 if (params.length > 0)
46 urlstr += "?" + params.join("&");
48 window.open(urlstr, "", "width=490,height=470,resizable=0");
50 return false; /* stop following the link */
53 function getSelectedFolder() {
55 var list = $("calendarList");
56 var nodes = list.getSelectedRows();
60 folder = list.down("li");
65 function onMenuNewEventClick(event) {
66 newEvent(this, "event");
69 function onMenuNewTaskClick(event) {
70 newEvent(this, "task");
73 function _editEventId(id, calendar) {
74 var urlstr = ApplicationBaseURL + "/" + calendar + "/" + id + "/edit";
75 var targetname = "SOGo_edit_" + id;
76 var win = window.open(urlstr, "_blank",
77 "width=490,height=470,resizable=0");
81 function editEvent() {
82 if (listOfSelection) {
83 var nodes = listOfSelection.getSelectedRows();
85 for (var i = 0; i < nodes.length; i++)
86 _editEventId(nodes[i].getAttribute("id"),
88 } else if (selectedCalendarCell) {
89 _editEventId(selectedCalendarCell[0].cname,
90 selectedCalendarCell[0].calendar);
93 return false; /* stop following the link */
96 function _batchDeleteEvents() {
97 var events = eventsToDelete.shift();
98 var calendar = calendarsOfEventsToDelete.shift();
99 var urlstr = (ApplicationBaseURL + "/" + calendar
100 + "/batchDelete?ids=" + events.join('/'));
101 document.deleteEventAjaxRequest = triggerAjaxRequest(urlstr,
106 function deleteEvent() {
107 if (listOfSelection) {
108 var nodes = listOfSelection.getSelectedRows();
110 if (nodes.length > 0) {
112 if (listOfSelection == $("tasksList"))
113 label = labels["taskDeleteConfirmation"];
115 label = labels["eventDeleteConfirmation"];
117 if (confirm(label)) {
118 if (document.deleteEventAjaxRequest) {
119 document.deleteEventAjaxRequest.aborted = true;
120 document.deleteEventAjaxRequest.abort();
122 var sortedNodes = new Array();
123 var calendars = new Array();
125 for (var i = 0; i < nodes.length; i++) {
126 var calendar = nodes[i].calendar;
127 if (!sortedNodes[calendar]) {
128 sortedNodes[calendar] = new Array();
129 calendars.push(calendar);
131 sortedNodes[calendar].push(nodes[i].cname);
133 for (var i = 0; i < calendars.length; i++) {
134 calendarsOfEventsToDelete.push(calendars[i]);
135 eventsToDelete.push(sortedNodes[calendars[i]]);
137 _batchDeleteEvents();
141 else if (selectedCalendarCell) {
142 var label = labels["eventDeleteConfirmation"];
143 if (confirm(label)) {
144 if (document.deleteEventAjaxRequest) {
145 document.deleteEventAjaxRequest.aborted = true;
146 document.deleteEventAjaxRequest.abort();
148 eventsToDelete.push([selectedCalendarCell[0].cname]);
149 calendarsOfEventsToDelete.push(selectedCalendarCell[0].calendar);
150 _batchDeleteEvents();
154 window.alert("no selection");
159 function modifyEvent(sender, modification) {
160 var currentLocation = '' + window.location;
161 var arr = currentLocation.split("/");
162 arr[arr.length-1] = modification;
164 document.modifyEventAjaxRequest = triggerAjaxRequest(arr.join("/"),
171 function closeInvitationWindow() {
172 var closeDiv = document.createElement("div");
173 document.body.appendChild(closeDiv);
174 closeDiv.addClassName("javascriptPopupBackground");
176 var closePseudoWin = document.createElement("div");
177 document.body.appendChild(closePseudoWin);
178 closePseudoWin.addClassName("javascriptMessagePseudoTopWindow");
179 closePseudoWin.style.top = "0px;";
180 closePseudoWin.style.left = "0px;";
181 closePseudoWin.style.right = "0px;";
182 closePseudoWin.appendChild(document.createTextNode(labels["closeThisWindowMessage"]));
184 var calLink = document.createElement("a");
185 closePseudoWin.appendChild(calLink);
186 calLink.href = ApplicationBaseURL;
187 calLink.appendChild(document.createTextNode(labels["Calendar"].toLowerCase()));
190 function modifyEventCallback(http) {
191 if (http.readyState == 4) {
192 if (http.status == 200) {
193 var mailInvitation = queryParameters["mail-invitation"];
194 if (mailInvitation && mailInvitation.toLowerCase() == "yes")
195 closeInvitationWindow();
197 window.opener.setTimeout("refreshEventsAndDisplay();", 100);
198 window.setTimeout("window.close();", 100);
202 // log("showing alert...");
203 window.alert(labels["eventPartStatModificationError"]);
205 document.modifyEventAjaxRequest = null;
209 function deleteEventCallback(http) {
210 if (http.readyState == 4) {
211 if (isHttpStatus204(http.status)) {
212 var nodes = http.callbackData;
213 for (var i = 0; i < nodes.length; i++) {
214 var node = $(nodes[i]);
216 node.parentNode.removeChild(node);
218 if (eventsToDelete.length)
219 _batchDeleteEvents();
221 document.deleteEventAjaxRequest = null;
224 changeCalendarDisplay();
228 log ("deleteEventCallback Ajax error");
232 function editDoubleClickedEvent(event) {
233 _editEventId(this.cname, this.calendar);
235 preventDefault(event);
236 event.cancelBubble = true;
239 function onSelectAll() {
240 var list = $("eventsList");
241 list.selectRowsMatchingClass("eventRow");
246 function onDaySelect(node) {
247 var day = node.getAttribute('day');
248 var needRefresh = (listFilter == 'view_selectedday'
249 && day != currentDay);
251 var td = $(node).getParentWithTagName("td");
252 var table = $(td).getParentWithTagName("table");
254 // log ("table.selected: " + table.selected);
256 if (document.selectedDate)
257 document.selectedDate.deselect();
260 document.selectedDate = td;
262 changeCalendarDisplay( { "day": day } );
269 function onDateSelectorGotoMonth(event) {
270 var day = this.getAttribute("date");
272 changeDateSelectorDisplay(day, true);
277 function onCalendarGotoDay(node) {
278 var day = node.getAttribute("date");
280 changeDateSelectorDisplay(day);
281 changeCalendarDisplay( { "day": day } );
286 function gotoToday() {
287 changeDateSelectorDisplay('');
288 changeCalendarDisplay();
293 function setDateSelectorContent(content) {
294 var div = $("dateSelectorView");
296 div.innerHTML = content;
297 if (currentDay.length > 0)
298 restoreCurrentDaySelection(div);
300 initDateSelectorEvents();
303 function dateSelectorCallback(http) {
304 if (http.readyState == 4
305 && http.status == 200) {
306 document.dateSelectorAjaxRequest = null;
307 var content = http.responseText;
308 setDateSelectorContent(content);
309 cachedDateSelectors[http.callbackData] = content;
312 log ("dateSelectorCallback Ajax error");
315 function eventsListCallback(http) {
316 if (http.readyState == 4
317 && http.status == 200) {
318 var div = $("eventsListView");
320 document.eventsListAjaxRequest = null;
321 var table = $("eventsList");
322 var params = parseQueryParameters(http.callbackData);
323 sortKey = params["sort"];
324 sortOrder = params["desc"];
325 lastClickedRow = -1; // from generic.js
327 if (http.responseText.length > 0) {
328 var data = http.responseText.evalJSON(true);
329 for (var i = 0; i < data.length; i++) {
330 var row = document.createElement("tr");
331 table.tBodies[0].appendChild(row);
332 $(row).addClassName("eventRow");
333 row.setAttribute("id", escape(data[i][0]));
334 row.cname = escape(data[i][0]);
335 row.calendar = data[i][1];
337 var startDate = new Date();
338 startDate.setTime(data[i][4] * 1000);
339 row.day = startDate.getDayString();
340 row.hour = startDate.getHourString();
341 Event.observe(row, "click",
342 onEventClick.bindAsEventListener(row));
343 Event.observe(row, "dblclick",
344 editDoubleClickedEvent.bindAsEventListener(row));
345 Event.observe(row, "contextmenu",
346 onEventContextMenu.bindAsEventListener(row));
348 var td = document.createElement("td");
350 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
351 td.appendChild(document.createTextNode(data[i][3]));
353 td = document.createElement("td");
355 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
356 td.appendChild(document.createTextNode(data[i][8]));
358 td = document.createElement("td");
360 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
361 td.appendChild(document.createTextNode(data[i][9]));
363 td = document.createElement("td");
365 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
366 td.appendChild(document.createTextNode(data[i][6]));
371 log ("eventsListCallback Ajax error");
374 function tasksListCallback(http) {
375 var div = $("tasksListView");
377 if (http.readyState == 4
378 && http.status == 200) {
379 document.tasksListAjaxRequest = null;
380 var list = $("tasksList");
382 if (http.responseText.length > 0) {
383 var data = http.responseText.evalJSON(true);
385 for (var i = 0; i < data.length; i++) {
386 //log(i + " = " + data[i][3]);
387 var listItem = document.createElement("li");
388 list.appendChild(listItem);
389 Event.observe(listItem, "mousedown", listRowMouseDownHandler);
390 Event.observe(listItem, "click", onRowClick);
391 Event.observe(listItem, "dblclick",
392 editDoubleClickedEvent.bindAsEventListener(listItem));
393 listItem.setAttribute("id", data[i][0]);
394 $(listItem).addClassName(data[i][5]);
395 listItem.calendar = data[i][1];
396 $(listItem).addClassName("calendarFolder" + data[i][1]);
397 listItem.cname = escape(data[i][0]);
398 var input = document.createElement("input");
399 input.setAttribute("type", "checkbox");
400 listItem.appendChild(input);
401 Event.observe(input, "click", updateTaskStatus.bindAsEventListener(input), true);
402 input.setAttribute("value", "1");
404 input.setAttribute("checked", "checked");
405 $(input).addClassName("checkBox");
406 listItem.appendChild(document.createTextNode(data[i][3]));
409 list.scrollTop = list.previousScroll;
411 if (http.callbackData) {
412 var selectedNodesId = http.callbackData;
413 for (var i = 0; i < selectedNodesId.length; i++) {
414 // log(selectedNodesId[i] + " (" + i + ") is selected");
415 $(selectedNodesId[i]).select();
419 log ("tasksListCallback: no data");
423 log ("tasksListCallback Ajax error");
426 function restoreCurrentDaySelection(div) {
427 var elements = $(div).getElementsByTagName("a");
430 while (!day && i < elements.length)
432 day = elements[i].day;
437 && day.substr(0, 6) == currentDay.substr(0, 6)) {
438 for (i = 0; i < elements.length; i++) {
439 day = elements[i].day;
440 if (day && day == currentDay) {
441 var td = $(elements[i]).getParentWithTagName("td");
442 if (document.selectedDate)
443 document.selectedDate.deselect();
445 document.selectedDate = td;
451 function changeDateSelectorDisplay(day, keepCurrentDay) {
452 var url = ApplicationBaseURL + "/dateselector";
454 url += "?day=" + day;
456 if (day != currentDay) {
460 var month = day.substr(0, 6);
461 if (cachedDateSelectors[month]) {
462 // log ("restoring cached selector for month: " + month);
463 setDateSelectorContent(cachedDateSelectors[month]);
466 // log ("loading selector for month: " + month);
467 if (document.dateSelectorAjaxRequest) {
468 document.dateSelectorAjaxRequest.aborted = true;
469 document.dateSelectorAjaxRequest.abort();
471 document.dateSelectorAjaxRequest
472 = triggerAjaxRequest(url,
473 dateSelectorCallback,
479 function changeCalendarDisplay(data, newView) {
480 var url = ApplicationBaseURL + "/" + ((newView) ? newView : currentView);
482 selectedCalendarCell = null;
485 var scrollEvent = null;
488 scrollEvent = data['scrollEvent'];
494 url += "?day=" + day;
497 // log ("switching to view: " + newView);
498 // log ("changeCalendarDisplay: " + url);
500 if (document.dayDisplayAjaxRequest) {
501 // log ("aborting day ajaxrq");
502 document.dayDisplayAjaxRequest.aborted = true;
503 document.dayDisplayAjaxRequest.abort();
505 document.dayDisplayAjaxRequest
506 = triggerAjaxRequest(url, calendarDisplayCallback,
509 "scrollEvent": scrollEvent });
514 function _ensureView(view) {
515 if (currentView != view)
516 changeCalendarDisplay(null, view);
521 function onDayOverview() {
522 return _ensureView("dayview");
525 function onMulticolumnDayOverview() {
526 return _ensureView("multicolumndayview");
529 function onWeekOverview() {
530 return _ensureView("weekview");
533 function onMonthOverview() {
534 return _ensureView("monthview");
537 function scrollDayView(scrollEvent) {
539 var daysView = $("daysView");
541 $(daysView.childNodesWithTag("div")[0]).childNodesWithTag("div");
543 if (scrollEvent && scrollEvent.siblings) {
544 var classes = scrollEvent.siblings[0].getAttribute("class").split(" ");
545 for (var i = 0; i < classes.length; i++)
546 if (classes[i].startsWith("starts")) {
547 var starts = Math.floor(parseInt(classes[i].substr(6)) / 4);
548 offset = hours[starts].offsetTop;
552 offset = hours[8].offsetTop;
554 daysView.scrollTop = offset - 5;
557 function onClickableCellsDblClick(event) {
558 newEvent(this, 'event');
560 event.cancelBubble = true;
561 event.returnValue = false;
564 function refreshCalendarEvents() {
565 var todayDate = new Date();
568 if (currentView == "dayview") {
572 sd = todayDate.getDayString();
575 else if (currentView == "weekview") {
578 startDate = currentDay.asDate();
580 startDate = todayDate;
581 startDate = startDate.beginOfWeek();
582 sd = startDate.getDayString();
583 var endDate = new Date();
584 endDate.setTime(startDate.getTime());
586 ed = endDate.getDayString();
591 monthDate = currentDay.asDate();
593 monthDate = todayDate;
594 monthDate.setDate(1);
595 sd = monthDate.beginOfWeek().getDayString();
597 var lastMonthDate = new Date();
598 lastMonthDate.setTime(monthDate.getTime());
599 lastMonthDate.setMonth(monthDate.getMonth() + 1);
600 lastMonthDate.addDays(-1);
601 ed = lastMonthDate.endOfWeek().getDayString();
603 if (document.refreshCalendarEventsAjaxRequest) {
604 document.refreshCalendarEventsAjaxRequest.aborted = true;
605 document.refreshCalendarEventsAjaxRequest.abort();
607 var url = ApplicationBaseURL + "/eventslist?sd=" + sd + "&ed=" + ed;
608 document.refreshCalendarEventsAjaxRequest
609 = triggerAjaxRequest(url, refreshCalendarEventsCallback,
610 {"startDate": sd, "endDate": ed});
613 function refreshCalendarEventsCallback(http) {
614 if (http.readyState == 4
615 && http.status == 200) {
617 if (http.responseText.length > 0) {
618 var data = http.responseText.evalJSON(true);
619 // log("refresh calendar events: " + data.length);
620 for (var i = 0; i < data.length; i++)
621 drawCalendarEvent(data[i],
622 http.callbackData["startDate"],
623 http.callbackData["endDate"]);
627 log("AJAX error when refreshing calendar events");
630 function drawCalendarEvent(eventData, sd, ed) {
631 var viewStartDate = sd.asDate();
632 var viewEndDate = ed.asDate();
634 var startDate = new Date();
635 startDate.setTime(eventData[4] * 1000);
636 var endDate = new Date();
637 endDate.setTime(eventData[5] * 1000);
639 // log ("s: " + startDate + "; e: " + endDate);
641 var days = startDate.daysUpTo(endDate);
644 if (currentView == "monthview"
645 && (eventData[7] == 0))
646 title = startDate.getDisplayHoursString() + " " + eventData[3];
648 title = eventData[3];
650 // log("title: " + title);
651 // log("viewS: " + viewStartDate);
652 var startHour = null;
655 var siblings = new Array();
656 for (var i = 0; i < days.length; i++)
657 if (days[i].earlierDate(viewStartDate) == viewStartDate
658 && days[i].laterDate(viewEndDate) == viewEndDate) {
661 // log("day: " + days[i]);
663 var quarters = (startDate.getUTCHours() * 4
664 + Math.floor(startDate.getUTCMinutes() / 15));
666 startHour = startDate.getDisplayHoursString();
667 endHour = endDate.getDisplayHoursString();
674 if (i == days.length - 1) {
675 var quarters = (endDate.getUTCHours() * 4
676 + Math.ceil(endDate.getUTCMinutes() / 15));
681 lasts = ends - starts;
685 var eventDiv = newEventDIV(eventData[0], eventData[1], starts, lasts,
687 siblings.push(eventDiv);
688 eventDiv.siblings = siblings;
689 var dayString = days[i].getDayString();
690 // log("day: " + dayString);
691 var parentDiv = null;
692 if (currentView == "monthview") {
693 var dayDivs = $("monthDaysView").childNodesWithTag("div");
695 while (!parentDiv && j < dayDivs.length) {
696 if (dayDivs[j].getAttribute("day") == dayString)
697 parentDiv = dayDivs[j];
703 if (eventData[7] == 0) {
704 var daysView = $("daysView");
705 var eventsDiv = $(daysView).childNodesWithTag("div")[1];
706 var dayDivs = $(eventsDiv).childNodesWithTag("div");
708 while (!parentDiv && j < dayDivs.length) {
709 if (dayDivs[j].getAttribute("day") == dayString)
710 parentDiv = dayDivs[j].childNodesWithTag("div")[0];
716 var header = $("calendarHeader");
717 var daysDiv = $(header).childNodesWithTag("div")[1];
718 var dayDivs = $(daysDiv).childNodesWithTag("div");
720 while (!parentDiv && j < dayDivs.length) {
721 if (dayDivs[j].getAttribute("day") == dayString)
722 parentDiv = dayDivs[j];
729 parentDiv.appendChild(eventDiv);
732 var eventTR = $(eventData[0]);
734 eventTR.siblings = siblings;
737 function newEventDIV(cname, calendar, starts, lasts,
738 startHour, endHour, title) {
739 var eventDiv = document.createElement("div");
740 eventDiv.cname = escape(cname);
741 eventDiv.calendar = calendar;
742 $(eventDiv).addClassName("event");
743 $(eventDiv).addClassName("starts" + starts);
744 $(eventDiv).addClassName("lasts" + lasts);
745 for (var i = 1; i < 5; i++) {
746 var shadowDiv = document.createElement("div");
747 eventDiv.appendChild(shadowDiv);
748 $(shadowDiv).addClassName("shadow");
749 $(shadowDiv).addClassName("shadow" + i);
751 var innerDiv = document.createElement("div");
752 eventDiv.appendChild(innerDiv);
753 $(innerDiv).addClassName("eventInside");
754 $(innerDiv).addClassName("calendarFolder" + calendar);
756 var gradientDiv = document.createElement("div");
757 innerDiv.appendChild(gradientDiv);
758 $(gradientDiv).addClassName("gradient");
759 var gradientImg = document.createElement("img");
760 gradientDiv.appendChild(gradientImg);
761 gradientImg.src = ResourcesURL + "/event-gradient.png";
763 var textDiv = document.createElement("div");
764 innerDiv.appendChild(textDiv);
765 $(textDiv).addClassName("text");
767 var headerSpan = document.createElement("span");
768 textDiv.appendChild(headerSpan);
769 $(headerSpan).addClassName("eventHeader");
770 headerSpan.appendChild(document.createTextNode(startHour + " - "
772 textDiv.appendChild(document.createElement("br"));
774 textDiv.appendChild(document.createTextNode(title));
776 Event.observe(eventDiv, "mousedown", listRowMouseDownHandler);
777 Event.observe(eventDiv, "click",
778 onCalendarSelectEvent.bindAsEventListener(eventDiv));
779 Event.observe(eventDiv, "dblclick",
780 editDoubleClickedEvent.bindAsEventListener(eventDiv));
785 function calendarDisplayCallback(http) {
786 var div = $("calendarView");
788 if (http.readyState == 4
789 && http.status == 200) {
790 document.dayDisplayAjaxRequest = null;
791 div.update(http.responseText);
792 if (http.callbackData["view"])
793 currentView = http.callbackData["view"];
794 if (http.callbackData["day"])
795 currentDay = http.callbackData["day"];
798 if (currentView == "monthview")
799 contentView = $("calendarContent");
801 var scrollEvent = http.callbackData.scrollEvent;
802 scrollDayView($(scrollEvent));
803 contentView = $("daysView");
805 refreshCalendarEvents();
806 var days = document.getElementsByClassName("day", contentView);
807 if (currentView == "monthview")
808 for (var i = 0; i < days.length; i++) {
809 Event.observe(days[i], "click",
810 onCalendarSelectDay.bindAsEventListener(days[i]));
811 Event.observe(days[i], "dblclick",
812 onClickableCellsDblClick.bindAsEventListener(days[i]));
815 var headerDivs = $("calendarHeader").childNodesWithTag("div");
816 var headerDaysLabels = document.getElementsByClassName("day", headerDivs[0]);
817 var headerDays = document.getElementsByClassName("day", headerDivs[1]);
818 for (var i = 0; i < days.length; i++) {
819 headerDays[i].hour = "allday";
820 Event.observe(headerDaysLabels[i], "mousedown", listRowMouseDownHandler);
821 Event.observe(headerDays[i], "click",
822 onCalendarSelectDay.bindAsEventListener(days[i]));
823 Event.observe(headerDays[i], "dblclick",
824 onClickableCellsDblClick.bindAsEventListener(headerDays[i]));
825 Event.observe(days[i], "click",
826 onCalendarSelectDay.bindAsEventListener(days[i]));
827 var clickableCells = document.getElementsByClassName("clickableHourCell",
829 for (var j = 0; j < clickableCells.length; j++)
830 Event.observe(clickableCells[j], "dblclick",
831 onClickableCellsDblClick.bindAsEventListener(clickableCells[j]));
836 log ("calendarDisplayCallback Ajax error (" + http.readyState + "/" + http.status + ")");
839 function assignCalendar(name) {
840 if (typeof(skycalendar) != "undefined") {
843 node.calendar = new skycalendar(node);
844 node.calendar.setCalendarPage(ResourcesURL + "/skycalendar.html");
845 var dateFormat = node.getAttribute("dateFormat");
847 node.calendar.setDateFormat(dateFormat);
851 function popupCalendar(node) {
852 var nodeId = node.getAttribute("inputId");
853 var input = $(nodeId);
854 input.calendar.popup();
859 function onEventContextMenu(event) {
860 var topNode = $("eventsList");
863 var menu = $("eventsListMenu");
865 Event.observe(menu, "hideMenu", onEventContextMenuHide);
866 popupMenu(event, "eventsListMenu", this);
868 var topNode = $("eventsList");
869 var selectedNodes = topNode.getSelectedRows();
870 topNode.menuSelectedRows = selectedNodes;
871 for (var i = 0; i < selectedNodes.length; i++)
872 selectedNodes[i].deselect();
874 topNode.menuSelectedEntry = this;
878 function onEventContextMenuHide(event) {
879 var topNode = $("eventsList");
881 if (topNode.menuSelectedEntry) {
882 topNode.menuSelectedEntry.deselect();
883 topNode.menuSelectedEntry = null;
885 if (topNode.menuSelectedRows) {
886 var nodeIds = topNode.menuSelectedRows;
887 for (var i = 0; i < nodeIds.length; i++) {
888 var node = $(nodeIds[i]);
891 topNode.menuSelectedRows = null;
895 function onEventsSelectionChange() {
896 listOfSelection = this;
897 this.removeClassName("_unfocused");
898 $("tasksList").addClassName("_unfocused");
901 function onTasksSelectionChange() {
902 listOfSelection = this;
903 this.removeClassName("_unfocused");
904 $("eventsList").addClassName("_unfocused");
907 function _loadEventHref(href) {
908 if (document.eventsListAjaxRequest) {
909 document.eventsListAjaxRequest.aborted = true;
910 document.eventsListAjaxRequest.abort();
912 var url = ApplicationBaseURL + "/" + href;
913 document.eventsListAjaxRequest
914 = triggerAjaxRequest(url, eventsListCallback, href);
916 var table = $("eventsList").tBodies[0];
917 while (table.rows.length > 0)
918 table.removeChild(table.rows[0]);
923 function _loadTasksHref(href) {
924 if (document.tasksListAjaxRequest) {
925 document.tasksListAjaxRequest.aborted = true;
926 document.tasksListAjaxRequest.abort();
928 url = ApplicationBaseURL + "/" + href;
930 var tasksList = $("tasksList");
933 selectedIds = tasksList.getSelectedNodesId();
936 document.tasksListAjaxRequest
937 = triggerAjaxRequest(url, tasksListCallback, selectedIds);
939 tasksList.previousScroll = tasksList.scrollTop;
940 while (tasksList.childNodes.length)
941 tasksList.removeChild(tasksList.childNodes[0]);
946 function onHeaderClick(event) {
947 //log("onHeaderClick: " + this.link);
948 //_loadEventHref(this.link);
950 preventDefault(event);
953 function refreshEvents() {
954 return _loadEventHref("eventslist?desc=" + sortOrder
956 + "&day=" + currentDay
957 + "&filterpopup=" + listFilter);
960 function refreshTasks() {
961 return _loadTasksHref("taskslist?show-completed=" + showCompletedTasks);
964 function refreshEventsAndDisplay() {
966 changeCalendarDisplay();
969 function onListFilterChange() {
970 var node = $("filterpopup");
972 listFilter = node.value;
973 // log ("listFilter = " + listFilter);
975 return refreshEvents();
978 function onEventClick(event) {
979 changeCalendarDisplay( { "day": this.day,
980 "scrollEvent": this.getAttribute("id") } );
981 changeDateSelectorDisplay(this.day);
983 return onRowClick(event);
986 function selectMonthInMenu(menu, month) {
987 var entries = menu.childNodes[1].childNodesWithTag("LI");
988 for (i = 0; i < entries.length; i++) {
989 var entry = entries[i];
990 var entryMonth = entry.getAttribute("month");
991 if (entryMonth == month)
992 entry.addClassName("currentMonth");
994 entry.removeClassName("currentMonth");
998 function selectYearInMenu(menu, month) {
999 var entries = menu.childNodes[1].childNodes;
1000 for (i = 0; i < entries.length; i++) {
1001 var entry = entries[i];
1002 if (entry.tagName == "LI") {
1003 var entryMonth = entry.innerHTML;
1004 if (entryMonth == month)
1005 entry.addClassName("currentMonth");
1007 entry.removeClassName("currentMonth");
1012 function popupMonthMenu(event) {
1013 if (event.button == 0) {
1014 var id = this.getAttribute("id");
1015 if (id == "monthLabel")
1016 menuId = "monthListMenu";
1018 menuId = "yearListMenu";
1020 var popup = $(menuId);
1021 if (id == "monthLabel")
1022 selectMonthInMenu(popup, this.getAttribute("month"));
1024 selectYearInMenu(popup, this.innerHTML);
1026 popupToolbarMenu(this, menuId);
1031 function onMonthMenuItemClick(event) {
1032 var month = '' + this.getAttribute("month");
1033 var year = '' + $("yearLabel").innerHTML;
1035 changeDateSelectorDisplay(year + month + "01", true);
1038 function onYearMenuItemClick(event) {
1039 var month = '' + $("monthLabel").getAttribute("month");;
1040 var year = '' + this.innerHTML;
1042 changeDateSelectorDisplay(year + month + "01", true);
1045 function onSearchFormSubmit() {
1046 log ("search not implemented");
1051 function onCalendarSelectEvent() {
1052 var list = $("eventsList");
1053 $(list.tBodies[0]).deselectAll();
1055 if (selectedCalendarCell)
1056 for (var i = 0; i < selectedCalendarCell.length; i++)
1057 selectedCalendarCell[i].deselect();
1059 for (var i = 0; i < this.siblings.length; i++)
1060 this.siblings[i].select();
1061 selectedCalendarCell = this.siblings;
1062 var row = $(this.cname);
1064 var div = row.parentNode.parentNode.parentNode;
1065 div.scrollTop = row.offsetTop - (div.offsetHeight / 2);
1070 function onCalendarSelectDay(event) {
1072 if (currentView == "multicolumndayview")
1073 day = this.getAttribute("day");
1075 day = this.getAttribute("day");
1076 var needRefresh = (listFilter == 'view_selectedday'
1077 && day != currentDay);
1079 if (currentView == 'weekview')
1080 changeWeekCalendarDisplayOfSelectedDay(this);
1081 else if (currentView == 'monthview')
1082 changeMonthCalendarDisplayOfSelectedDay(this);
1083 changeDateSelectorDisplay(day);
1085 if (listOfSelection) {
1086 listOfSelection.addClassName("_unfocused");
1087 listOfSelection = null;
1094 function changeWeekCalendarDisplayOfSelectedDay(node) {
1095 var days = document.getElementsByClassName("day", node.parentNode);
1096 var headerDiv = $("calendarHeader").childNodesWithTag("div")[1];
1097 var headerDays = document.getElementsByClassName("day", headerDiv);
1099 // log ("days: " + days.length + "; headerDays: " + headerDays.length);
1100 for (var i = 0; i < days.length; i++)
1101 if (days[i] != node) {
1102 // log("unselect day : " + i);
1103 headerDays[i].removeClassName("selectedDay");
1104 days[i].removeClassName("selectedDay");
1107 // log("selected day : " + i);
1108 headerDays[i].addClassName("selectedDay");
1109 days[i].addClassName("selectedDay");
1113 function findMonthCalendarSelectedCell(daysContainer) {
1117 while (!found && i < daysContainer.childNodes.length) {
1118 var currentNode = daysContainer.childNodes[i];
1119 if (currentNode.tagName == 'DIV'
1120 && currentNode.hasClassName("selectedDay")) {
1121 daysContainer.selectedCell = currentNode;
1129 function changeMonthCalendarDisplayOfSelectedDay(node) {
1130 var daysContainer = node.parentNode;
1131 if (!daysContainer.selectedCell)
1132 findMonthCalendarSelectedCell(daysContainer);
1134 if (daysContainer.selectedCell)
1135 daysContainer.selectedCell.removeClassName("selectedDay");
1136 daysContainer.selectedCell = node;
1137 node.addClassName("selectedDay");
1140 function onShowCompletedTasks(event) {
1141 showCompletedTasks = (this.checked ? 1 : 0);
1143 return refreshTasks();
1146 function updateTaskStatus(event) {
1147 var taskId = this.parentNode.getAttribute("id");
1148 var newStatus = (this.checked ? 1 : 0);
1149 var http = createHTTPClient();
1151 if (isSafari() && !isSafari3()) {
1152 newStatus = (newStatus ? 0 : 1);
1155 url = (ApplicationBaseURL + "/" + this.parentNode.calendar
1156 + "/" + taskId + "/changeStatus?status=" + newStatus);
1159 // TODO: add parameter to signal that we are only interested in OK
1160 http.open("POST", url, false /* not async */);
1163 if (http.status == 200)
1166 log ("no http client?");
1171 function updateCalendarStatus(event) {
1172 var list = new Array();
1173 var newStatus = (this.checked ? 1 : 0);
1175 if (isSafari() && !isSafari3()) {
1176 newStatus = (newStatus ? 0 : 1);
1177 this.checked = newStatus;
1180 var nodes = $("calendarList").childNodesWithTag("li");
1181 for (var i = 0; i < nodes.length; i++) {
1182 var input = $(nodes[i]).childNodesWithTag("input")[0];
1183 if (input.checked) {
1184 var folderId = nodes[i].getAttribute("id");
1185 var elems = folderId.split(":");
1186 if (elems.length > 1)
1187 list.push(elems[0]);
1189 list.push(UserLogin);
1193 // if (!list.length) {
1194 // list.push(UserLogin);
1195 // nodes[0].childNodesWithTag("input")[0].checked = true;
1198 // ApplicationBaseURL = (UserFolderURL + "Groups/_custom_"
1199 // + list.join(",") + "/Calendar/");
1202 var folderID = this.parentNode.getAttribute("id");
1203 var urlstr = URLForFolderID(folderID);
1205 urlstr += "/activateFolder";
1207 urlstr += "/deactivateFolder";
1208 //log("updateCalendarStatus: ajax request = " + urlstr + ", folderID = " + folderID);
1209 triggerAjaxRequest(urlstr, calendarStatusCallback, folderID);
1212 updateCalendarsList();
1215 changeCalendarDisplay();
1221 function calendarStatusCallback(http) {
1222 if (http.readyState == 4) {
1223 if (isHttpStatus204(http.status)) {
1226 changeCalendarDisplay();
1229 var folder = $(http.callbackData);
1230 var input = folder.childNodesWithTag("input")[0];
1231 input.checked = (!input.checked);
1235 log("calendarStatusCallback Ajax error");
1238 function calendarEntryCallback(http) {
1239 if (http.readyState == 4) {
1240 var denied = !isHttpStatus204(http.status);
1241 var entry = $(http.callbackData);
1243 entry.addClassName("denied");
1245 entry.removeClassName("denied");
1249 function updateCalendarsList(method) {
1250 var list = $("calendarList").childNodesWithTag("li");
1251 for (var i = 0; i < list.length; i++) {
1252 var folderID = list[i].getAttribute("id");
1253 var url = URLForFolderID(folderID) + "/canAccessContent";
1254 triggerAjaxRequest(url, calendarEntryCallback, folderID);
1258 function addContact(tag, fullContactName, contactId, contactName, contactEmail) {
1259 var uids = $("uixselector-calendarsList-uidList");
1260 // log("addContact");
1263 var re = new RegExp("(^|,)" + contactId + "($|,)");
1265 if (!re.test(uids.value))
1267 if (uids.value.length > 0)
1268 uids.value += ',' + contactId;
1270 uids.value = contactId;
1271 var names = $("calendarList");
1272 var listElems = names.childNodesWithTag("li");
1273 var colorDef = indexColor(listElems.length);
1274 names.appendChild(userCalendarEntry(contactId, colorDef));
1282 function validateBrowseURL(input) {
1283 var button = $("browseURLBtn");
1285 if (input.value.length) {
1286 if (!button.enabled)
1287 enableAnchor(button);
1288 } else if (!button.disabled)
1289 disableAnchor(button);
1292 function browseURL(anchor, event) {
1293 if (event.button == 0) {
1294 var input = $("url");
1295 var url = input.value;
1297 window.open(url, '_blank');
1303 function getMenus() {
1306 var dateMenu = new Array();
1307 for (var i = 0; i < 12; i++)
1308 dateMenu.push(onMonthMenuItemClick);
1309 menus["monthListMenu"] = dateMenu;
1311 dateMenu = new Array();
1312 for (var i = 0; i < 11; i++)
1313 dateMenu.push(onYearMenuItemClick);
1314 menus["yearListMenu"] = dateMenu;
1316 menus["eventsListMenu"] = new Array(onMenuNewEventClick, "-",
1318 editEvent, deleteEvent, "-",
1321 menus["calendarsMenu"] = new Array(onMenuModify,
1323 onCalendarNew, onCalendarRemove,
1324 "-", null, null, "-",
1325 null, "-", onMenuSharing);
1326 menus["searchMenu"] = new Array(setSearchCriteria);
1331 function onMenuSharing(event) {
1332 var folders = $("calendarList");
1333 var selected = folders.getSelectedNodes()[0];
1334 /* FIXME: activation of the context menu should preferable select the entry
1335 above which the event has occured */
1337 var folderID = selected.getAttribute("id");
1338 var urlstr = URLForFolderID(folderID) + "/acls";
1340 openAclWindow(urlstr);
1344 function configureDragHandles() {
1345 var handle = $("verticalDragHandle");
1347 handle.addInterface(SOGoDragHandlesInterface);
1348 handle.leftBlock=$("leftPanel");
1349 handle.rightBlock=$("rightPanel");
1352 handle = $("rightDragHandle");
1354 handle.addInterface(SOGoDragHandlesInterface);
1355 handle.upperBlock=$("eventsListView");
1356 handle.lowerBlock=$("calendarView");
1360 function initCalendarSelector() {
1361 var selector = $("calendarSelector");
1362 updateCalendarStatus();
1363 selector.changeNotification = updateCalendarsList;
1365 var list = $("calendarList");
1366 list.multiselect = true;
1367 var items = list.childNodesWithTag("li");
1368 for (var i = 0; i < items.length; i++) {
1369 var input = items[i].childNodesWithTag("input")[0];
1370 Event.observe(input, "click", updateCalendarStatus.bindAsEventListener(input));
1371 Event.observe(items[i], "mousedown", listRowMouseDownHandler);
1372 Event.observe(items[i], "selectstart", listRowMouseDownHandler);
1373 Event.observe(items[i], "click", onRowClick);
1376 var links = $("calendarSelectorButtons").childNodesWithTag("a");
1377 Event.observe(links[0], "click", onCalendarNew);
1378 Event.observe(links[1], "click", onCalendarAdd);
1379 Event.observe(links[2], "click", onCalendarRemove);
1382 function onMenuModify(event) {
1383 var folders = $("calendarList");
1384 var selected = folders.getSelectedNodes()[0];
1386 if (UserLogin == selected.getAttribute("owner")) {
1387 var node = selected.childNodes[4];
1388 var currentName = node.nodeValue.trim();
1389 var newName = window.prompt(labels["Name of the Calendar"],
1391 if (newName && newName.length > 0
1392 && newName != currentName) {
1393 var url = (URLForFolderID(selected.getAttribute("id"))
1394 + "/renameFolder?name=" + escape(newName.utf8encode()));
1395 triggerAjaxRequest(url, folderRenameCallback,
1396 {node: node, name: " " + newName});
1399 window.alert(clabels["Unable to rename that folder!"]);
1402 function folderRenameCallback(http) {
1403 if (http.readyState == 4) {
1404 if (isHttpStatus204(http.status)) {
1405 var dict = http.callbackData;
1406 dict["node"].nodeValue = dict["name"];
1411 function onCalendarNew(event) {
1412 createFolder(window.prompt(labels["Name of the Calendar"]),
1414 preventDefault(event);
1417 function onCalendarAdd(event) {
1418 openUserFolderSelector(onFolderSubscribeCB, "calendar");
1419 preventDefault(event);
1422 function appendCalendar(folderName, folderPath) {
1426 owner = getSubscribedFolderOwner(folderPath);
1427 folderPath = accessToSubscribedFolder(folderPath);
1430 folderPath = "/" + folderName;
1435 //log ("append name: " + folderName + "; path: " + folderPath + "; owner: " + owner);
1438 window.alert(clabels["You have already subscribed to that folder!"]);
1440 var calendarList = $("calendarList");
1441 var lis = calendarList.childNodesWithTag("li");
1442 var li = document.createElement("li");
1444 // Add the calendar to the proper place
1445 var previousOwner = null;
1446 for (var i = 0; i < lis.length; i++) {
1447 var currentFolderName = lis[i].lastChild.nodeValue.strip();
1448 var currentOwner = lis[i].readAttribute('owner');
1449 if (currentOwner == owner) {
1450 previousOwner = currentOwner;
1451 if (currentFolderName > folderName)
1454 else if (previousOwner ||
1455 (currentOwner != UserLogin && currentOwner > owner))
1458 if (i != lis.length) // User is subscribed to other calendars of the same owner
1459 calendarList.insertBefore(li, lis[i]);
1461 calendarList.appendChild(li);
1463 li.setAttribute("id", folderPath);
1464 li.setAttribute("owner", owner);
1466 // Generate new color
1467 if (calendarColorIndex == null)
1468 calendarColorIndex = lis.length;
1469 calendarColorIndex++;
1470 var colorTable = [1, 1, 1];
1472 var currentValue = calendarColorIndex;
1474 while (currentValue) {
1475 if (currentValue & 1)
1476 colorTable[index]++;
1482 colorTable[0] = parseInt(255 / colorTable[0]) - 1;
1483 colorTable[1] = parseInt(255 / colorTable[1]) - 1;
1484 colorTable[2] = parseInt(255 / colorTable[2]) - 1;
1487 + colorTable[2].toString(16)
1488 + colorTable[1].toString(16)
1489 + colorTable[0].toString(16);
1490 //log ("color = " + color);
1492 var checkBox = document.createElement("input");
1493 checkBox.setAttribute("type", "checkbox");
1494 li.appendChild(checkBox);
1495 li.appendChild(document.createTextNode(" "));
1496 $(checkBox).addClassName("checkBox");
1498 var colorBox = document.createElement("div");
1499 li.appendChild(colorBox);
1500 li.appendChild(document.createTextNode(folderName));
1501 colorBox.appendChild(document.createTextNode("OO"));
1503 $(colorBox).addClassName("colorBox");
1504 $(colorBox).addClassName('calendarFolder' + folderPath.substr(1));
1506 // Register events (doesn't work with Safari)
1507 Event.observe(li, "mousedown", listRowMouseDownHandler);
1508 Event.observe(li, "selectstart", listRowMouseDownHandler);
1509 Event.observe(li, "click", onRowClick);
1510 Event.observe(checkBox, "click",
1511 updateCalendarStatus.bindAsEventListener(checkBox));
1513 var url = URLForFolderID(folderPath) + "/canAccessContent";
1514 triggerAjaxRequest(url, calendarEntryCallback, folderPath);
1516 // Update CSS for events color
1517 if (!document.styleSheets) return;
1519 var styleElement = document.createElement("style");
1520 styleElement.type = "text/css";
1522 '.calendarFolder' + folderPath.substr(1),
1523 'div.colorBox.calendarFolder' + folderPath.substr(1)
1526 ' { background-color: ' + color + ' !important; }',
1527 ' { color: ' + color + ' !important; }'
1529 for (var i = 0; i < rules.length; i++)
1530 if (styleElement.styleSheet && styleElement.styleSheet.addRule)
1531 styleElement.styleSheet.addRule(selectors[i], rules[i]); // IE
1533 styleElement.appendChild(document.createTextNode(selectors[i] + rules[i])); // Mozilla _+ Safari
1534 document.getElementsByTagName("head")[0].appendChild(styleElement);
1538 function onFolderSubscribeCB(folderData) {
1539 var folder = $(folderData["folder"]);
1541 appendCalendar(folderData["folderName"], folderData["folder"]);
1544 function onFolderUnsubscribeCB(folderId) {
1545 var node = $(folderId);
1546 node.parentNode.removeChild(node);
1547 if (removeFolderRequestCount == 0) {
1550 changeCalendarDisplay();
1554 function onCalendarRemove(event) {
1555 if (removeFolderRequestCount == 0) {
1556 var nodes = $("calendarList").getSelectedNodes();
1557 for (var i = 0; i < nodes.length; i++) {
1558 nodes[i].deselect();
1559 var folderId = nodes[i].getAttribute("id");
1560 var folderIdElements = folderId.split("_");
1561 if (folderIdElements.length > 1) {
1562 unsubscribeFromFolder(folderId, onFolderUnsubscribeCB, folderId);
1565 deletePersonalCalendar(folderIdElements[0]);
1569 preventDefault(event);
1572 function deletePersonalCalendar(folderElement) {
1573 var folderId = folderElement.substr(1);
1575 = labels["Are you sure you want to delete the calendar \"%{0}\"?"].formatted($(folderElement).lastChild.nodeValue.strip());
1576 if (window.confirm(label)) {
1577 removeFolderRequestCount++;
1578 var url = ApplicationBaseURL + "/" + folderId + "/deleteFolder";
1579 triggerAjaxRequest(url, deletePersonalCalendarCallback, folderId);
1583 function deletePersonalCalendarCallback(http) {
1584 if (http.readyState == 4) {
1585 if (isHttpStatus204(http.status)) {
1586 var ul = $("calendarList");
1587 var children = ul.childNodesWithTag("li");
1590 while (!done && i < children.length) {
1591 var currentFolderId = children[i].getAttribute("id").substr(1);
1592 if (currentFolderId == http.callbackData) {
1593 ul.removeChild(children[i]);
1599 removeFolderRequestCount--;
1600 if (removeFolderRequestCount == 0) {
1603 changeCalendarDisplay();
1608 log ("ajax problem 5: " + http.status);
1611 function configureLists() {
1612 var list = $("tasksList");
1613 list.multiselect = true;
1614 Event.observe(list, "mousedown",
1615 onTasksSelectionChange.bindAsEventListener(list));
1617 var input = $("showHideCompletedTasks");
1618 Event.observe(input, "click",
1619 onShowCompletedTasks.bindAsEventListener(input));
1621 list = $("eventsList");
1622 list.multiselect = true;
1623 //configureSortableTableHeaders(list);
1624 TableKit.Resizable.init(list, {'trueResize' : true, 'keepWidth' : true});
1625 Event.observe(list, "mousedown",
1626 onEventsSelectionChange.bindAsEventListener(list));
1627 var div = list.parentNode;
1628 Event.observe(div, "contextmenu",
1629 onEventContextMenu.bindAsEventListener(div));
1632 function initDateSelectorEvents() {
1633 var arrow = $("rightArrow");
1634 Event.observe(arrow, "click",
1635 onDateSelectorGotoMonth.bindAsEventListener(arrow));
1636 arrow = $("leftArrow");
1637 Event.observe(arrow, "click",
1638 onDateSelectorGotoMonth.bindAsEventListener(arrow));
1640 var menuButton = $("monthLabel");
1641 Event.observe(menuButton, "click",
1642 popupMonthMenu.bindAsEventListener(menuButton));
1643 menuButton = $("yearLabel");
1644 Event.observe(menuButton, "click",
1645 popupMonthMenu.bindAsEventListener(menuButton));
1648 function initCalendars() {
1649 if (!document.body.hasClassName("popup")) {
1650 initDateSelectorEvents();
1651 initCalendarSelector();
1652 configureSearchField();
1654 var selector = $("calendarSelector");
1656 selector.attachMenu("calendarsMenu");
1660 addEvent(window, 'load', initCalendars);