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 = -1; // from generic.js
322 if (http.responseText.length > 0) {
323 var data = http.responseText.evalJSON(true);
324 for (var i = 0; i < data.length; i++) {
325 var row = document.createElement("tr");
326 table.tBodies[0].appendChild(row);
327 $(row).addClassName("eventRow");
328 row.setAttribute("id", escape(data[i][0]));
329 row.cname = escape(data[i][0]);
330 row.calendar = data[i][1];
332 var startDate = new Date();
333 startDate.setTime(data[i][4] * 1000);
334 row.day = startDate.getDayString();
335 row.hour = startDate.getHourString();
336 Event.observe(row, "click",
337 onEventClick.bindAsEventListener(row));
338 Event.observe(row, "dblclick",
339 editDoubleClickedEvent.bindAsEventListener(row));
340 Event.observe(row, "contextmenu",
341 onEventContextMenu.bindAsEventListener(row));
343 var td = document.createElement("td");
345 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
346 td.appendChild(document.createTextNode(data[i][3]));
348 td = document.createElement("td");
350 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
351 td.appendChild(document.createTextNode(data[i][8]));
353 td = document.createElement("td");
355 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
356 td.appendChild(document.createTextNode(data[i][9]));
358 td = document.createElement("td");
360 Event.observe(td, "mousedown", listRowMouseDownHandler, true);
361 td.appendChild(document.createTextNode(data[i][6]));
366 log ("eventsListCallback Ajax error");
369 function tasksListCallback(http) {
370 var div = $("tasksListView");
372 if (http.readyState == 4
373 && http.status == 200) {
374 document.tasksListAjaxRequest = null;
375 var list = $("tasksList");
377 if (http.responseText.length > 0) {
378 var data = http.responseText.evalJSON(true);
380 for (var i = 0; i < data.length; i++) {
381 //log(i + " = " + data[i][3]);
382 var listItem = document.createElement("li");
383 list.appendChild(listItem);
384 Event.observe(listItem, "mousedown", listRowMouseDownHandler);
385 Event.observe(listItem, "click", onRowClick);
386 Event.observe(listItem, "dblclick",
387 editDoubleClickedEvent.bindAsEventListener(listItem));
388 listItem.setAttribute("id", data[i][0]);
389 $(listItem).addClassName(data[i][5]);
390 listItem.calendar = data[i][1];
391 $(listItem).addClassName("calendarFolder" + data[i][1]);
392 listItem.cname = escape(data[i][0]);
393 var input = document.createElement("input");
394 input.setAttribute("type", "checkbox");
395 listItem.appendChild(input);
396 Event.observe(input, "click", updateTaskStatus.bindAsEventListener(input), true);
397 input.setAttribute("value", "1");
399 input.setAttribute("checked", "checked");
400 $(input).addClassName("checkBox");
401 listItem.appendChild(document.createTextNode(data[i][3]));
404 list.scrollTop = list.previousScroll;
406 if (http.callbackData) {
407 var selectedNodesId = http.callbackData;
408 for (var i = 0; i < selectedNodesId.length; i++) {
409 // log(selectedNodesId[i] + " (" + i + ") is selected");
410 $(selectedNodesId[i]).select();
414 log ("tasksListCallback: no data");
418 log ("tasksListCallback Ajax error");
421 function restoreCurrentDaySelection(div) {
422 var elements = $(div).getElementsByTagName("a");
425 while (!day && i < elements.length)
427 day = elements[i].day;
432 && day.substr(0, 6) == currentDay.substr(0, 6)) {
433 for (i = 0; i < elements.length; i++) {
434 day = elements[i].day;
435 if (day && day == currentDay) {
436 var td = $(elements[i]).getParentWithTagName("td");
437 if (document.selectedDate)
438 document.selectedDate.deselect();
440 document.selectedDate = td;
446 function changeDateSelectorDisplay(day, keepCurrentDay) {
447 var url = ApplicationBaseURL + "/dateselector";
449 url += "?day=" + day;
451 if (day != currentDay) {
455 var month = day.substr(0, 6);
456 if (cachedDateSelectors[month]) {
457 // log ("restoring cached selector for month: " + month);
458 setDateSelectorContent(cachedDateSelectors[month]);
461 // log ("loading selector for month: " + month);
462 if (document.dateSelectorAjaxRequest) {
463 document.dateSelectorAjaxRequest.aborted = true;
464 document.dateSelectorAjaxRequest.abort();
466 document.dateSelectorAjaxRequest
467 = triggerAjaxRequest(url,
468 dateSelectorCallback,
474 function changeCalendarDisplay(data, newView) {
475 var url = ApplicationBaseURL + "/" + ((newView) ? newView : currentView);
477 selectedCalendarCell = null;
480 var scrollEvent = null;
483 scrollEvent = data['scrollEvent'];
489 url += "?day=" + day;
492 // log ("switching to view: " + newView);
493 // log ("changeCalendarDisplay: " + url);
495 if (document.dayDisplayAjaxRequest) {
496 // log ("aborting day ajaxrq");
497 document.dayDisplayAjaxRequest.aborted = true;
498 document.dayDisplayAjaxRequest.abort();
500 document.dayDisplayAjaxRequest
501 = triggerAjaxRequest(url, calendarDisplayCallback,
504 "scrollEvent": scrollEvent });
509 function _ensureView(view) {
510 if (currentView != view)
511 changeCalendarDisplay(null, view);
516 function onDayOverview() {
517 return _ensureView("dayview");
520 function onMulticolumnDayOverview() {
521 return _ensureView("multicolumndayview");
524 function onWeekOverview() {
525 return _ensureView("weekview");
528 function onMonthOverview() {
529 return _ensureView("monthview");
532 function scrollDayView(scrollEvent) {
534 var daysView = $("daysView");
536 $(daysView.childNodesWithTag("div")[0]).childNodesWithTag("div");
538 if (scrollEvent && scrollEvent.siblings) {
539 var classes = scrollEvent.siblings[0].getAttribute("class").split(" ");
540 for (var i = 0; i < classes.length; i++) {
541 if (classes[i].startsWith("starts")) {
542 var starts = Math.floor(parseInt(classes[i].substr(6)) / 4);
543 offset = hours[starts].offsetTop;
548 offset = hours[8].offsetTop;
551 daysView.scrollTop = offset - 5;
554 function onClickableCellsDblClick(event) {
555 newEvent(this, 'event');
557 event.cancelBubble = true;
558 event.returnValue = false;
561 function refreshCalendarEvents() {
562 var todayDate = new Date();
565 if (currentView == "dayview") {
569 sd = todayDate.getDayString();
572 else if (currentView == "weekview") {
575 startDate = currentDay.asDate();
577 startDate = todayDate;
578 startDate = startDate.beginOfWeek();
579 sd = startDate.getDayString();
580 var endDate = new Date();
581 endDate.setTime(startDate.getTime());
583 ed = endDate.getDayString();
588 monthDate = currentDay.asDate();
590 monthDate = todayDate;
591 monthDate.setDate(1);
592 sd = monthDate.beginOfWeek().getDayString();
594 var lastMonthDate = new Date();
595 lastMonthDate.setTime(monthDate.getTime());
596 lastMonthDate.setMonth(monthDate.getMonth() + 1);
597 lastMonthDate.addDays(-1);
598 ed = lastMonthDate.endOfWeek().getDayString();
600 if (document.refreshCalendarEventsAjaxRequest) {
601 document.refreshCalendarEventsAjaxRequest.aborted = true;
602 document.refreshCalendarEventsAjaxRequest.abort();
604 var url = ApplicationBaseURL + "/eventslist?sd=" + sd + "&ed=" + ed;
605 document.refreshCalendarEventsAjaxRequest
606 = triggerAjaxRequest(url, refreshCalendarEventsCallback,
607 {"startDate": sd, "endDate": ed});
610 function refreshCalendarEventsCallback(http) {
611 if (http.readyState == 4
612 && http.status == 200) {
614 if (http.responseText.length > 0) {
615 var data = http.responseText.evalJSON(true);
616 // log("refresh calendar events: " + data.length);
617 for (var i = 0; i < data.length; i++)
618 drawCalendarEvent(data[i],
619 http.callbackData["startDate"],
620 http.callbackData["endDate"]);
624 log("AJAX error when refreshing calendar events");
627 function drawCalendarEvent(eventData, sd, ed) {
628 var viewStartDate = sd.asDate();
629 var viewEndDate = ed.asDate();
631 var startDate = new Date();
632 startDate.setTime(eventData[4] * 1000);
633 var endDate = new Date();
634 endDate.setTime(eventData[5] * 1000);
636 // log ("s: " + startDate + "; e: " + endDate);
638 var days = startDate.daysUpTo(endDate);
641 if (currentView == "monthview"
642 && (eventData[7] == 0))
643 title = startDate.getDisplayHoursString() + " " + eventData[3];
645 title = eventData[3];
647 // log("title: " + title);
648 // log("viewS: " + viewStartDate);
649 var startHour = null;
652 var siblings = new Array();
653 for (var i = 0; i < days.length; i++)
654 if (days[i].earlierDate(viewStartDate) == viewStartDate
655 && days[i].laterDate(viewEndDate) == viewEndDate) {
658 // log("day: " + days[i]);
660 var quarters = (startDate.getUTCHours() * 4
661 + Math.floor(startDate.getUTCMinutes() / 15));
663 startHour = startDate.getDisplayHoursString();
664 endHour = endDate.getDisplayHoursString();
671 if (i == days.length - 1) {
672 var quarters = (endDate.getUTCHours() * 4
673 + Math.ceil(endDate.getUTCMinutes() / 15));
678 lasts = ends - starts;
682 var eventDiv = newEventDIV(eventData[0], eventData[1], starts, lasts,
684 siblings.push(eventDiv);
685 eventDiv.siblings = siblings;
686 var dayString = days[i].getDayString();
687 // log("day: " + dayString);
688 var parentDiv = null;
689 if (currentView == "monthview") {
690 var dayDivs = $("monthDaysView").childNodesWithTag("div");
692 while (!parentDiv && j < dayDivs.length) {
693 if (dayDivs[j].getAttribute("day") == dayString)
694 parentDiv = dayDivs[j];
700 if (eventData[7] == 0) {
701 var daysView = $("daysView");
702 var eventsDiv = $(daysView).childNodesWithTag("div")[1];
703 var dayDivs = $(eventsDiv).childNodesWithTag("div");
705 while (!parentDiv && j < dayDivs.length) {
706 if (dayDivs[j].getAttribute("day") == dayString)
707 parentDiv = dayDivs[j].childNodesWithTag("div")[0];
713 var header = $("calendarHeader");
714 var daysDiv = $(header).childNodesWithTag("div")[1];
715 var dayDivs = $(daysDiv).childNodesWithTag("div");
717 while (!parentDiv && j < dayDivs.length) {
718 if (dayDivs[j].getAttribute("day") == dayString)
719 parentDiv = dayDivs[j];
726 parentDiv.appendChild(eventDiv);
729 var eventTR = $(eventData[0]);
731 eventTR.siblings = siblings;
734 function newEventDIV(cname, calendar, starts, lasts,
735 startHour, endHour, title) {
736 var eventDiv = document.createElement("div");
737 eventDiv.cname = escape(cname);
738 eventDiv.calendar = calendar;
739 $(eventDiv).addClassName("event");
740 $(eventDiv).addClassName("starts" + starts);
741 $(eventDiv).addClassName("lasts" + lasts);
742 for (var i = 1; i < 5; i++) {
743 var shadowDiv = document.createElement("div");
744 eventDiv.appendChild(shadowDiv);
745 $(shadowDiv).addClassName("shadow");
746 $(shadowDiv).addClassName("shadow" + i);
748 var innerDiv = document.createElement("div");
749 eventDiv.appendChild(innerDiv);
750 $(innerDiv).addClassName("eventInside");
751 $(innerDiv).addClassName("calendarFolder" + calendar);
753 var gradientDiv = document.createElement("div");
754 innerDiv.appendChild(gradientDiv);
755 $(gradientDiv).addClassName("gradient");
756 var gradientImg = document.createElement("img");
757 gradientDiv.appendChild(gradientImg);
758 gradientImg.src = ResourcesURL + "/event-gradient.png";
760 var textDiv = document.createElement("div");
761 innerDiv.appendChild(textDiv);
762 $(textDiv).addClassName("text");
764 var headerSpan = document.createElement("span");
765 textDiv.appendChild(headerSpan);
766 $(headerSpan).addClassName("eventHeader");
767 headerSpan.appendChild(document.createTextNode(startHour + " - "
769 textDiv.appendChild(document.createElement("br"));
771 textDiv.appendChild(document.createTextNode(title));
773 Event.observe(eventDiv, "mousedown", listRowMouseDownHandler);
774 Event.observe(eventDiv, "click",
775 onCalendarSelectEvent.bindAsEventListener(eventDiv));
776 Event.observe(eventDiv, "dblclick",
777 editDoubleClickedEvent.bindAsEventListener(eventDiv));
782 function calendarDisplayCallback(http) {
783 var div = $("calendarView");
785 if (http.readyState == 4
786 && http.status == 200) {
787 document.dayDisplayAjaxRequest = null;
788 div.update(http.responseText);
789 if (http.callbackData["view"])
790 currentView = http.callbackData["view"];
791 if (http.callbackData["day"])
792 currentDay = http.callbackData["day"];
795 if (currentView == "monthview")
796 contentView = $("calendarContent");
798 var scrollEvent = http.callbackData.scrollEvent;
799 scrollDayView($(scrollEvent));
800 contentView = $("daysView");
802 refreshCalendarEvents();
803 var days = document.getElementsByClassName("day", contentView);
804 if (currentView == "monthview")
805 for (var i = 0; i < days.length; i++) {
806 Event.observe(days[i], "click",
807 onCalendarSelectDay.bindAsEventListener(days[i]));
808 Event.observe(days[i], "dblclick",
809 onClickableCellsDblClick.bindAsEventListener(days[i]));
812 var headerDivs = $("calendarHeader").childNodesWithTag("div");
813 var headerDaysLabels = document.getElementsByClassName("day", headerDivs[0]);
814 var headerDays = document.getElementsByClassName("day", headerDivs[1]);
815 for (var i = 0; i < days.length; i++) {
816 headerDays[i].hour = "allday";
817 Event.observe(headerDaysLabels[i], "mousedown", listRowMouseDownHandler);
818 Event.observe(headerDays[i], "click",
819 onCalendarSelectDay.bindAsEventListener(days[i]));
820 Event.observe(headerDays[i], "dblclick",
821 onClickableCellsDblClick.bindAsEventListener(headerDays[i]));
822 Event.observe(days[i], "click",
823 onCalendarSelectDay.bindAsEventListener(days[i]));
824 var clickableCells = document.getElementsByClassName("clickableHourCell",
826 for (var j = 0; j < clickableCells.length; j++)
827 Event.observe(clickableCells[j], "dblclick",
828 onClickableCellsDblClick.bindAsEventListener(clickableCells[j]));
833 log ("calendarDisplayCallback Ajax error (" + http.readyState + "/" + http.status + ")");
836 function assignCalendar(name) {
837 if (typeof(skycalendar) != "undefined") {
840 node.calendar = new skycalendar(node);
841 node.calendar.setCalendarPage(ResourcesURL + "/skycalendar.html");
842 var dateFormat = node.getAttribute("dateFormat");
844 node.calendar.setDateFormat(dateFormat);
848 function popupCalendar(node) {
849 var nodeId = node.getAttribute("inputId");
850 var input = $(nodeId);
851 input.calendar.popup();
856 function onEventContextMenu(event) {
857 var topNode = $("eventsList");
860 var menu = $("eventsListMenu");
862 Event.observe(menu, "hideMenu", onEventContextMenuHide);
863 popupMenu(event, "eventsListMenu", this);
865 var topNode = $("eventsList");
866 var selectedNodes = topNode.getSelectedRows();
867 topNode.menuSelectedRows = selectedNodes;
868 for (var i = 0; i < selectedNodes.length; i++)
869 selectedNodes[i].deselect();
871 topNode.menuSelectedEntry = this;
875 function onEventContextMenuHide(event) {
876 var topNode = $("eventsList");
878 if (topNode.menuSelectedEntry) {
879 topNode.menuSelectedEntry.deselect();
880 topNode.menuSelectedEntry = null;
882 if (topNode.menuSelectedRows) {
883 var nodeIds = topNode.menuSelectedRows;
884 for (var i = 0; i < nodeIds.length; i++) {
885 var node = $(nodeIds[i]);
888 topNode.menuSelectedRows = null;
892 function onEventsSelectionChange() {
893 listOfSelection = this;
894 this.removeClassName("_unfocused");
895 $("tasksList").addClassName("_unfocused");
898 function onTasksSelectionChange() {
899 listOfSelection = this;
900 this.removeClassName("_unfocused");
901 $("eventsList").addClassName("_unfocused");
904 function _loadEventHref(href) {
905 if (document.eventsListAjaxRequest) {
906 document.eventsListAjaxRequest.aborted = true;
907 document.eventsListAjaxRequest.abort();
909 var url = ApplicationBaseURL + "/" + href;
910 document.eventsListAjaxRequest
911 = triggerAjaxRequest(url, eventsListCallback, href);
913 var table = $("eventsList").tBodies[0];
914 while (table.rows.length > 0)
915 table.removeChild(table.rows[0]);
920 function _loadTasksHref(href) {
921 if (document.tasksListAjaxRequest) {
922 document.tasksListAjaxRequest.aborted = true;
923 document.tasksListAjaxRequest.abort();
925 url = ApplicationBaseURL + "/" + href;
927 var tasksList = $("tasksList");
930 selectedIds = tasksList.getSelectedNodesId();
933 document.tasksListAjaxRequest
934 = triggerAjaxRequest(url, tasksListCallback, selectedIds);
936 tasksList.previousScroll = tasksList.scrollTop;
937 while (tasksList.childNodes.length)
938 tasksList.removeChild(tasksList.childNodes[0]);
943 function onHeaderClick(event) {
944 //log("onHeaderClick: " + this.link);
945 //_loadEventHref(this.link);
947 preventDefault(event);
950 function refreshEvents() {
951 return _loadEventHref("eventslist?desc=" + sortOrder
953 + "&day=" + currentDay
954 + "&filterpopup=" + listFilter);
957 function refreshTasks() {
958 return _loadTasksHref("taskslist?show-completed=" + showCompletedTasks);
961 function refreshEventsAndDisplay() {
963 changeCalendarDisplay();
966 function onListFilterChange() {
967 var node = $("filterpopup");
969 listFilter = node.value;
970 // log ("listFilter = " + listFilter);
972 return refreshEvents();
975 function onEventClick(event) {
976 changeCalendarDisplay( { "day": this.day,
977 "scrollEvent": this.getAttribute("id") } );
978 changeDateSelectorDisplay(this.day);
980 return onRowClick(event);
983 function selectMonthInMenu(menu, month) {
984 var entries = menu.childNodes[1].childNodesWithTag("LI");
985 for (i = 0; i < entries.length; i++) {
986 var entry = entries[i];
987 var entryMonth = entry.getAttribute("month");
988 if (entryMonth == month)
989 entry.addClassName("currentMonth");
991 entry.removeClassName("currentMonth");
995 function selectYearInMenu(menu, month) {
996 var entries = menu.childNodes[1].childNodes;
997 for (i = 0; i < entries.length; i++) {
998 var entry = entries[i];
999 if (entry.tagName == "LI") {
1000 var entryMonth = entry.innerHTML;
1001 if (entryMonth == month)
1002 entry.addClassName("currentMonth");
1004 entry.removeClassName("currentMonth");
1009 function popupMonthMenu(event) {
1010 if (event.button == 0) {
1011 var id = this.getAttribute("id");
1012 if (id == "monthLabel")
1013 menuId = "monthListMenu";
1015 menuId = "yearListMenu";
1017 var popup = $(menuId);
1018 if (id == "monthLabel")
1019 selectMonthInMenu(popup, this.getAttribute("month"));
1021 selectYearInMenu(popup, this.innerHTML);
1023 popupToolbarMenu(this, menuId);
1028 function onMonthMenuItemClick(event) {
1029 var month = '' + this.getAttribute("month");
1030 var year = '' + $("yearLabel").innerHTML;
1032 changeDateSelectorDisplay(year + month + "01", true);
1035 function onYearMenuItemClick(event) {
1036 var month = '' + $("monthLabel").getAttribute("month");;
1037 var year = '' + this.innerHTML;
1039 changeDateSelectorDisplay(year + month + "01", true);
1042 function onSearchFormSubmit() {
1043 log ("search not implemented");
1048 function onCalendarSelectEvent() {
1049 var list = $("eventsList");
1050 $(list.tBodies[0]).deselectAll();
1052 if (selectedCalendarCell)
1053 for (var i = 0; i < selectedCalendarCell.length; i++)
1054 selectedCalendarCell[i].deselect();
1056 for (var i = 0; i < this.siblings.length; i++)
1057 this.siblings[i].select();
1058 selectedCalendarCell = this.siblings;
1059 var row = $(this.cname);
1061 var div = row.parentNode.parentNode.parentNode;
1062 div.scrollTop = row.offsetTop - (div.offsetHeight / 2);
1067 function onCalendarSelectDay(event) {
1069 if (currentView == "multicolumndayview")
1070 day = this.getAttribute("day");
1072 day = this.getAttribute("day");
1073 var needRefresh = (listFilter == 'view_selectedday'
1074 && day != currentDay);
1076 if (currentView == 'weekview')
1077 changeWeekCalendarDisplayOfSelectedDay(this);
1078 else if (currentView == 'monthview')
1079 changeMonthCalendarDisplayOfSelectedDay(this);
1080 changeDateSelectorDisplay(day);
1082 if (listOfSelection) {
1083 listOfSelection.addClassName("_unfocused");
1084 listOfSelection = null;
1091 function changeWeekCalendarDisplayOfSelectedDay(node) {
1092 var days = document.getElementsByClassName("day", node.parentNode);
1093 var headerDiv = $("calendarHeader").childNodesWithTag("div")[1];
1094 var headerDays = document.getElementsByClassName("day", headerDiv);
1096 // log ("days: " + days.length + "; headerDays: " + headerDays.length);
1097 for (var i = 0; i < days.length; i++)
1098 if (days[i] != node) {
1099 // log("unselect day : " + i);
1100 headerDays[i].removeClassName("selectedDay");
1101 days[i].removeClassName("selectedDay");
1104 // log("selected day : " + i);
1105 headerDays[i].addClassName("selectedDay");
1106 days[i].addClassName("selectedDay");
1110 function findMonthCalendarSelectedCell(daysContainer) {
1114 while (!found && i < daysContainer.childNodes.length) {
1115 var currentNode = daysContainer.childNodes[i];
1116 if (currentNode.tagName == 'DIV'
1117 && currentNode.hasClassName("selectedDay")) {
1118 daysContainer.selectedCell = currentNode;
1126 function changeMonthCalendarDisplayOfSelectedDay(node) {
1127 var daysContainer = node.parentNode;
1128 if (!daysContainer.selectedCell)
1129 findMonthCalendarSelectedCell(daysContainer);
1131 if (daysContainer.selectedCell)
1132 daysContainer.selectedCell.removeClassName("selectedDay");
1133 daysContainer.selectedCell = node;
1134 node.addClassName("selectedDay");
1137 function onShowCompletedTasks(event) {
1138 showCompletedTasks = (this.checked ? 1 : 0);
1140 return refreshTasks();
1143 function updateTaskStatus(event) {
1144 var taskId = this.parentNode.getAttribute("id");
1145 var newStatus = (this.checked ? 1 : 0);
1146 var http = createHTTPClient();
1148 if (isSafari() && !isSafari3()) {
1149 newStatus = (newStatus ? 0 : 1);
1152 url = (ApplicationBaseURL + "/" + this.parentNode.calendar
1153 + "/" + taskId + "/changeStatus?status=" + newStatus);
1156 // TODO: add parameter to signal that we are only interested in OK
1157 http.open("POST", url, false /* not async */);
1160 if (http.status == 200)
1163 log ("no http client?");
1168 function updateCalendarStatus(event) {
1169 var list = new Array();
1170 var newStatus = (this.checked ? 1 : 0);
1172 if (isSafari() && !isSafari3()) {
1173 newStatus = (newStatus ? 0 : 1);
1174 this.checked = newStatus;
1177 var nodes = $("calendarList").childNodesWithTag("li");
1178 for (var i = 0; i < nodes.length; i++) {
1179 var input = $(nodes[i]).childNodesWithTag("input")[0];
1180 if (input.checked) {
1181 var folderId = nodes[i].getAttribute("id");
1182 var elems = folderId.split(":");
1183 if (elems.length > 1)
1184 list.push(elems[0]);
1186 list.push(UserLogin);
1190 // if (!list.length) {
1191 // list.push(UserLogin);
1192 // nodes[0].childNodesWithTag("input")[0].checked = true;
1195 // ApplicationBaseURL = (UserFolderURL + "Groups/_custom_"
1196 // + list.join(",") + "/Calendar/");
1199 var folderID = this.parentNode.getAttribute("id");
1200 var urlstr = URLForFolderID(folderID);
1202 urlstr += "/activateFolder";
1204 urlstr += "/deactivateFolder";
1205 //log("updateCalendarStatus: ajax request = " + urlstr + ", folderID = " + folderID);
1206 triggerAjaxRequest(urlstr, calendarStatusCallback, folderID);
1209 updateCalendarsList();
1212 changeCalendarDisplay();
1218 function calendarStatusCallback(http) {
1219 if (http.readyState == 4) {
1220 if (isHttpStatus204(http.status)) {
1223 changeCalendarDisplay();
1226 var folder = $(http.callbackData);
1227 var input = folder.childNodesWithTag("input")[0];
1228 input.checked = (!input.checked);
1232 log("calendarStatusCallback Ajax error");
1235 function calendarEntryCallback(http) {
1236 if (http.readyState == 4) {
1237 var denied = !isHttpStatus204(http.status);
1238 var entry = $(http.callbackData);
1240 entry.addClassName("denied");
1242 entry.removeClassName("denied");
1246 function updateCalendarsList(method) {
1247 var list = $("calendarList").childNodesWithTag("li");
1248 for (var i = 0; i < list.length; i++) {
1249 var folderID = list[i].getAttribute("id");
1250 var url = URLForFolderID(folderID) + "/canAccessContent";
1251 triggerAjaxRequest(url, calendarEntryCallback, folderID);
1255 function addContact(tag, fullContactName, contactId, contactName, contactEmail) {
1256 var uids = $("uixselector-calendarsList-uidList");
1257 // log("addContact");
1260 var re = new RegExp("(^|,)" + contactId + "($|,)");
1262 if (!re.test(uids.value))
1264 if (uids.value.length > 0)
1265 uids.value += ',' + contactId;
1267 uids.value = contactId;
1268 var names = $("calendarList");
1269 var listElems = names.childNodesWithTag("li");
1270 var colorDef = indexColor(listElems.length);
1271 names.appendChild(userCalendarEntry(contactId, colorDef));
1279 function validateBrowseURL(input) {
1280 var button = $("browseURLBtn");
1282 if (input.value.length) {
1283 if (!button.enabled)
1284 enableAnchor(button);
1285 } else if (!button.disabled)
1286 disableAnchor(button);
1289 function browseURL(anchor, event) {
1290 if (event.button == 0) {
1291 var input = $("url");
1292 var url = input.value;
1294 window.open(url, '_blank');
1300 function getMenus() {
1303 var dateMenu = new Array();
1304 for (var i = 0; i < 12; i++)
1305 dateMenu.push(onMonthMenuItemClick);
1306 menus["monthListMenu"] = dateMenu;
1308 dateMenu = new Array();
1309 for (var i = 0; i < 11; i++)
1310 dateMenu.push(onYearMenuItemClick);
1311 menus["yearListMenu"] = dateMenu;
1313 menus["eventsListMenu"] = new Array(onMenuNewEventClick, "-",
1315 editEvent, deleteEvent, "-",
1318 menus["calendarsMenu"] = new Array(onMenuModify,
1320 onCalendarNew, onCalendarRemove,
1321 "-", null, null, "-",
1322 null, "-", onMenuSharing);
1323 menus["searchMenu"] = new Array(setSearchCriteria);
1328 function onMenuSharing(event) {
1329 var folders = $("calendarList");
1330 var selected = folders.getSelectedNodes()[0];
1331 /* FIXME: activation of the context menu should preferable select the entry
1332 above which the event has occured */
1334 var folderID = selected.getAttribute("id");
1335 var urlstr = URLForFolderID(folderID) + "/acls";
1337 openAclWindow(urlstr);
1341 function configureDragHandles() {
1342 var handle = $("verticalDragHandle");
1344 handle.addInterface(SOGoDragHandlesInterface);
1345 handle.leftBlock=$("leftPanel");
1346 handle.rightBlock=$("rightPanel");
1349 handle = $("rightDragHandle");
1351 handle.addInterface(SOGoDragHandlesInterface);
1352 handle.upperBlock=$("eventsListView");
1353 handle.lowerBlock=$("calendarView");
1357 function initCalendarSelector() {
1358 var selector = $("calendarSelector");
1359 updateCalendarStatus();
1360 selector.changeNotification = updateCalendarsList;
1362 var list = $("calendarList");
1363 list.multiselect = true;
1364 var items = list.childNodesWithTag("li");
1365 for (var i = 0; i < items.length; i++) {
1366 var input = items[i].childNodesWithTag("input")[0];
1367 Event.observe(input, "click", updateCalendarStatus.bindAsEventListener(input));
1368 Event.observe(items[i], "mousedown", listRowMouseDownHandler);
1369 Event.observe(items[i], "selectstart", listRowMouseDownHandler);
1370 Event.observe(items[i], "click", onRowClick);
1373 var links = $("calendarSelectorButtons").childNodesWithTag("a");
1374 Event.observe(links[0], "click", onCalendarNew);
1375 Event.observe(links[1], "click", onCalendarAdd);
1376 Event.observe(links[2], "click", onCalendarRemove);
1379 function onMenuModify(event) {
1380 var folders = $("calendarList");
1381 var selected = folders.getSelectedNodes()[0];
1383 if (UserLogin == selected.getAttribute("owner")) {
1384 var node = selected.childNodes[4];
1385 var currentName = node.nodeValue.trim();
1386 var newName = window.prompt(labels["Name of the Calendar"],
1388 if (newName && newName.length > 0
1389 && newName != currentName) {
1390 var url = (URLForFolderID(selected.getAttribute("id"))
1391 + "/renameFolder?name=" + escape(newName.utf8encode()));
1392 triggerAjaxRequest(url, folderRenameCallback,
1393 {node: node, name: " " + newName});
1396 window.alert(clabels["Unable to rename that folder!"]);
1399 function folderRenameCallback(http) {
1400 if (http.readyState == 4) {
1401 if (isHttpStatus204(http.status)) {
1402 var dict = http.callbackData;
1403 dict["node"].nodeValue = dict["name"];
1408 function onCalendarNew(event) {
1409 createFolder(window.prompt(labels["Name of the Calendar"]),
1411 preventDefault(event);
1414 function onCalendarAdd(event) {
1415 openUserFolderSelector(onFolderSubscribeCB, "calendar");
1416 preventDefault(event);
1419 function appendCalendar(folderName, folderPath) {
1423 owner = getSubscribedFolderOwner(folderPath);
1424 folderPath = accessToSubscribedFolder(folderPath);
1427 folderPath = "/" + folderName;
1432 //log ("append name: " + folderName + "; path: " + folderPath + "; owner: " + owner);
1435 window.alert(clabels["You have already subscribed to that folder!"]);
1437 var calendarList = $("calendarList");
1438 var lis = calendarList.childNodesWithTag("li");
1439 var color = indexColor(lis.length + 100);
1440 //log ("color: " + color);
1442 var li = document.createElement("li");
1444 // Add the calendar to the proper place
1445 var previousOwner = null;
1446 for (var i = 1; 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 var checkBox = document.createElement("input");
1467 checkBox.setAttribute("type", "checkbox");
1468 li.appendChild(checkBox);
1469 li.appendChild(document.createTextNode(" "));
1470 $(checkBox).addClassName("checkBox");
1472 var colorBox = document.createElement("div");
1473 li.appendChild(colorBox);
1474 li.appendChild(document.createTextNode(folderName));
1475 colorBox.appendChild(document.createTextNode("OO"));
1477 $(colorBox).addClassName("colorBox");
1478 $(colorBox).addClassName('calendarFolder' + folderPath.substr(1));
1480 // Register events (doesn't work with Safari)
1481 Event.observe(li, "mousedown", listRowMouseDownHandler);
1482 Event.observe(li, "selectstart", listRowMouseDownHandler);
1483 Event.observe(li, "click", onRowClick);
1484 Event.observe(checkBox, "click",
1485 updateCalendarStatus.bindAsEventListener(checkBox));
1487 var url = URLForFolderID(folderPath) + "/canAccessContent";
1488 triggerAjaxRequest(url, calendarEntryCallback, folderPath);
1490 // Update CSS for events color
1491 if (!document.styleSheets) return;
1493 var styleElement = document.createElement("style");
1494 styleElement.type = "text/css";
1496 '.calendarFolder' + folderPath.substr(1),
1497 'div.colorBox.calendarFolder' + folderPath.substr(1)
1500 ' { background-color: ' + color + ' !important; }',
1501 ' { color: ' + color + ' !important; }'
1503 for (var i = 0; i < rules.length; i++)
1504 if (styleElement.styleSheet && styleElement.styleSheet.addRule)
1505 styleElement.styleSheet.addRule(selectors[i], rules[i]); // IE
1507 styleElement.appendChild(document.createTextNode(selectors[i] + rules[i])); // Mozilla _+ Safari
1508 document.getElementsByTagName("head")[0].appendChild(styleElement);
1512 function onFolderSubscribeCB(folderData) {
1513 var folder = $(folderData["folder"]);
1515 appendCalendar(folderData["folderName"], folderData["folder"]);
1518 function onFolderUnsubscribeCB(folderId) {
1519 var node = $(folderId);
1520 node.parentNode.removeChild(node);
1521 if (removeFolderRequestCount == 0) {
1524 changeCalendarDisplay();
1528 function onCalendarRemove(event) {
1529 if (removeFolderRequestCount == 0) {
1530 var nodes = $("calendarList").getSelectedNodes();
1531 for (var i = 0; i < nodes.length; i++) {
1532 nodes[i].deselect();
1533 var folderId = nodes[i].getAttribute("id");
1534 var folderIdElements = folderId.split("_");
1535 if (folderIdElements.length > 1) {
1536 unsubscribeFromFolder(folderId, onFolderUnsubscribeCB, folderId);
1539 deletePersonalCalendar(folderIdElements[0]);
1543 preventDefault(event);
1546 function deletePersonalCalendar(folderElement) {
1547 var folderId = folderElement.substr(1);
1549 = labels["Are you sure you want to delete the calendar \"%{0}\"?"].formatted($(folderElement).lastChild.nodeValue.strip());
1550 if (window.confirm(label)) {
1551 removeFolderRequestCount++;
1552 var url = ApplicationBaseURL + "/" + folderId + "/deleteFolder";
1553 triggerAjaxRequest(url, deletePersonalCalendarCallback, folderId);
1557 function deletePersonalCalendarCallback(http) {
1558 if (http.readyState == 4) {
1559 if (isHttpStatus204(http.status)) {
1560 var ul = $("calendarList");
1561 var children = ul.childNodesWithTag("li");
1564 while (!done && i < children.length) {
1565 var currentFolderId = children[i].getAttribute("id").substr(1);
1566 if (currentFolderId == http.callbackData) {
1567 ul.removeChild(children[i]);
1573 removeFolderRequestCount--;
1574 if (removeFolderRequestCount == 0) {
1577 changeCalendarDisplay();
1582 log ("ajax problem 5: " + http.status);
1585 function configureLists() {
1586 var list = $("tasksList");
1587 list.multiselect = true;
1588 Event.observe(list, "mousedown",
1589 onTasksSelectionChange.bindAsEventListener(list));
1591 var input = $("showHideCompletedTasks");
1592 Event.observe(input, "click",
1593 onShowCompletedTasks.bindAsEventListener(input));
1595 list = $("eventsList");
1596 list.multiselect = true;
1597 //configureSortableTableHeaders(list);
1598 TableKit.Resizable.init(list, {'trueResize' : true, 'keepWidth' : true});
1599 Event.observe(list, "mousedown",
1600 onEventsSelectionChange.bindAsEventListener(list));
1601 var div = list.parentNode;
1602 Event.observe(div, "contextmenu",
1603 onEventContextMenu.bindAsEventListener(div));
1606 function initDateSelectorEvents() {
1607 var arrow = $("rightArrow");
1608 Event.observe(arrow, "click",
1609 onDateSelectorGotoMonth.bindAsEventListener(arrow));
1610 arrow = $("leftArrow");
1611 Event.observe(arrow, "click",
1612 onDateSelectorGotoMonth.bindAsEventListener(arrow));
1614 var menuButton = $("monthLabel");
1615 Event.observe(menuButton, "click",
1616 popupMonthMenu.bindAsEventListener(menuButton));
1617 menuButton = $("yearLabel");
1618 Event.observe(menuButton, "click",
1619 popupMonthMenu.bindAsEventListener(menuButton));
1622 function initCalendars() {
1623 if (!document.body.hasClassName("popup")) {
1624 initDateSelectorEvents();
1625 initCalendarSelector();
1626 configureSearchField();
1628 var selector = $("calendarSelector");
1630 selector.attachMenu("calendarsMenu");
1634 addEvent(window, 'load', initCalendars);