]> err.no Git - scalable-opengroupware.org/blobdiff - UI/WebServerResources/SchedulerUI.js
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1083 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / UI / WebServerResources / SchedulerUI.js
index 3070c492316b0137b30bc5560fca6ef9e4866548..d5993316f376ffa6d7dbc5b09ad0c0ff60eb1a49 100644 (file)
@@ -23,7 +23,7 @@ var usersRightsWindowHeight = 250;
 var usersRightsWindowWidth = 502;
 
 function newEvent(sender, type) {
-   var day = sender.getAttribute("day");
+   var day = sender.day;
    if (!day)
       day = currentDay;
 
@@ -32,7 +32,9 @@ function newEvent(sender, type) {
        && currentView == "multicolumndayview" && type == "event")
       user = sender.parentNode.parentNode.getAttribute("user");
 
-   var hour = sender.getAttribute("hour");
+   var hour = sender.hour;
+   if (!hour)
+      hour = sender.getAttribute("hour");
    var urlstr = UserFolderURL + "../" + user + "/Calendar/new" + type;
    var params = new Array();
    if (day)
@@ -62,8 +64,8 @@ function _editEventId(id, owner) {
   urlBase += "Calendar/"
 
   var urlstr = urlBase + id + "/edit";
-
-  var win = window.open(urlstr, "SOGo_edit_" + id,
+  var targetname = "SOGo_edit_" + id;
+  var win = window.open(urlstr, "_blank",
                         "width=490,height=470,resizable=0");
   win.focus();
 }
@@ -74,10 +76,10 @@ function editEvent() {
 
     for (var i = 0; i < nodes.length; i++)
       _editEventId(nodes[i].getAttribute("id"),
-                   nodes[i].getAttribute("owner"));
+                   nodes[i].owner);
   } else if (selectedCalendarCell) {
-      _editEventId(selectedCalendarCell.getAttribute("aptCName"),
-                   selectedCalendarCell.getAttribute("owner"));
+      _editEventId(selectedCalendarCell[0].cname,
+                   selectedCalendarCell[0].owner);
   }
 
   return false; /* stop following the link */
@@ -102,7 +104,7 @@ function deleteEvent() {
       if (listOfSelection == $("tasksList"))
         label = labels["taskDeleteConfirmation"].decodeEntities();
       else
-        label = labels["appointmentDeleteConfirmation"].decodeEntities();
+        label = labels["eventDeleteConfirmation"].decodeEntities();
       
       if (confirm(label)) {
         if (document.deleteEventAjaxRequest) {
@@ -113,12 +115,12 @@ function deleteEvent() {
         var owners = new Array();
 
         for (var i = 0; i < nodes.length; i++) {
-          var owner = nodes[i].getAttribute("owner");
+          var owner = nodes[i].owner;
           if (!sortedNodes[owner]) {
               sortedNodes[owner] = new Array();
               owners.push(owner);
           }
-          sortedNodes[owner].push(nodes[i].getAttribute("id"));
+          sortedNodes[owner].push(nodes[i].cname);
         }
         for (var i = 0; i < owners.length; i++) {
           ownersOfEventsToDelete.push(owners[i]);
@@ -129,14 +131,14 @@ function deleteEvent() {
     }
   }
   else if (selectedCalendarCell) {
-     var label = labels["appointmentDeleteConfirmation"].decodeEntities();
+     var label = labels["eventDeleteConfirmation"].decodeEntities();
      if (confirm(label)) {
         if (document.deleteEventAjaxRequest) {
            document.deleteEventAjaxRequest.aborted = true;
            document.deleteEventAjaxRequest.abort();
         }
-        eventsToDelete.push([selectedCalendarCell.getAttribute("aptCName")]);
-        ownersOfEventsToDelete.push(selectedCalendarCell.getAttribute("owner"));
+        eventsToDelete.push([selectedCalendarCell[0].cname]);
+        ownersOfEventsToDelete.push(selectedCalendarCell[0].owner);
         _batchDeleteEvents();
      }
   }
@@ -162,7 +164,7 @@ function closeInvitationWindow() {
   var closeDiv = document.createElement("div");
   closeDiv.addClassName("javascriptPopupBackground");
   var closePseudoWin = document.createElement("div");
-  closePseudoWin.addClassName("javascriptMessagePseudoWindow");
+  closePseudoWin.addClassName("javascriptMessagePseudoTopWindow");
   closePseudoWin.style.top = "0px;";
   closePseudoWin.style.left = "0px;";
   closePseudoWin.style.right = "0px;";
@@ -172,22 +174,21 @@ function closeInvitationWindow() {
 }
 
 function modifyEventCallback(http) {
-  if (http.readyState == 4) {
-    if (http.status == 200) {
-      log("closing window...?");
-      if (queryParameters["mail-invitation"] == "yes")
-        closeInvitationWindow();
+   if (http.readyState == 4) {
+      if (http.status == 200) {
+        if (queryParameters["mail-invitation"].toLowerCase() == "yes")
+           closeInvitationWindow();
+        else {
+           window.opener.setTimeout("refreshEventsAndDisplay();", 100);
+           window.setTimeout("window.close();", 100);
+        }
+      }
       else {
-        window.opener.setTimeout("refreshAppointmentsAndDisplay();", 100);
-        window.setTimeout("window.close();", 100);
+//      log("showing alert...");
+        window.alert(labels["eventPartStatModificationError"]);
       }
-    }
-    else {
-      log("showing alert...");
-      window.alert(labels["eventPartStatModificationError"]);
-    }
-    document.modifyEventAjaxRequest = null;
-  }
+      document.modifyEventAjaxRequest = null;
+   }
 }
 
 function deleteEventCallback(http) {
@@ -203,46 +204,36 @@ function deleteEventCallback(http) {
       _batchDeleteEvents();
     else {
       document.deleteEventAjaxRequest = null;
-      refreshAppointments();
+      refreshEvents();
       refreshTasks();
       changeCalendarDisplay();
     }
   }
   else
-    log ("ajax fuckage");
+    log ("deleteEventCallback Ajax error");
 }
 
-function editDoubleClickedEvent(node) {
-  _editEventId(node.getAttribute("id"),
-               node.getAttribute("owner"));
-  
-  return false;
+function editDoubleClickedEvent(event) {
+  _editEventId(this.cname, this.owner);
+
+  preventDefault(event);
+  event.cancelBubble = true;
 }
 
 function onSelectAll() {
-  var list = $("appointmentsList");
-  list.selectRowsMatchingClass("appointmentRow");
+  var list = $("eventsList");
+  list.selectRowsMatchingClass("eventRow");
 
   return false;
 }
 
-function displayAppointment(event) {
-  _editEventId(this.getAttribute("aptCName"),
-               this.getAttribute("owner"));
-
-  preventDefault(event);
-  event.stopPropagation();
-  event.cancelBubble = true;
-  event.returnValue = false;
-}
-
 function onDaySelect(node) {
-  var day = node.getAttribute("day");
+  var day = node.getAttribute('day');
   var needRefresh = (listFilter == 'view_selectedday'
                      && day != currentDay);
 
-  var td = node.getParentWithTagName("td");
-  var table = td.getParentWithTagName("table");
+  var td = $(node).getParentWithTagName("td");
+  var table = $(td).getParentWithTagName("table");
 
 //   log ("table.selected: " + table.selected);
 
@@ -254,7 +245,7 @@ function onDaySelect(node) {
 
   changeCalendarDisplay( { "day": day } );
   if (needRefresh)
-    refreshAppointments();
+    refreshEvents();
 
   return false;
 }
@@ -300,25 +291,62 @@ function dateSelectorCallback(http) {
     cachedDateSelectors[http.callbackData] = content;
   }
   else
-    log ("ajax fuckage");
+    log ("dateSelectorCallback Ajax error");
 }
 
-function appointmentsListCallback(http) {
-  var div = $("appointmentsListView");
-
+function eventsListCallback(http) {
   if (http.readyState == 4
       && http.status == 200) {
-    document.appointmentsListAjaxRequest = null;
-    div.innerHTML = http.responseText;
+     var div = $("eventsListView");
+
+    document.eventsListAjaxRequest = null;
+    var table = $("eventsList").tBodies[0];
     var params = parseQueryParameters(http.callbackData);
     sortKey = params["sort"];
     sortOrder = params["desc"];
-    var list = $("appointmentsList");
-    Event.observe(list, "selectionchange", onAppointmentsSelectionChange.bindAsEventListener(list), true);
     configureSortableTableHeaders();
+
+    var data = http.responseText.evalJSON(true);
+    for (var i = 0; i < data.length; i++) {
+      var row = document.createElement("tr");
+      table.appendChild(row);
+      $(row).addClassName("eventRow");
+      row.setAttribute("id", data[i][0]);
+      row.cname = data[i][0];
+      row.owner = data[i][1];
+
+      var startDate = new Date();
+      startDate.setTime(data[i][4] * 1000);
+      row.day = startDate.getDayString();
+      row.hour = startDate.getHourString();
+      Event.observe(row, "click", onEventClick.bindAsEventListener(row));
+      Event.observe(row, "dblclick", editDoubleClickedEvent.bindAsEventListener(row));
+      Event.observe(row, "contextmenu",
+                   onEventContextMenu.bindAsEventListener(row));
+
+      var td = document.createElement("td");
+      row.appendChild(td);
+      Event.observe(td, "mousedown", listRowMouseDownHandler, true);
+      td.appendChild(document.createTextNode(data[i][3]));
+
+      td = document.createElement("td");
+      row.appendChild(td);
+      Event.observe(td, "mousedown", listRowMouseDownHandler, true);
+      td.appendChild(document.createTextNode(data[i][8]));
+
+      td = document.createElement("td");
+      row.appendChild(td);
+      Event.observe(td, "mousedown", listRowMouseDownHandler, true);
+      td.appendChild(document.createTextNode(data[i][9]));
+      
+      td = document.createElement("td");
+      row.appendChild(td);
+      Event.observe(td, "mousedown", listRowMouseDownHandler, true);
+      td.appendChild(document.createTextNode(data[i][6]));
+    }
   }
   else
-    log ("ajax fuckage");
+    log ("eventsListCallback Ajax error");
 }
 
 function tasksListCallback(http) {
@@ -328,19 +356,46 @@ function tasksListCallback(http) {
       && http.status == 200) {
     document.tasksListAjaxRequest = null;
     var list = $("tasksList");
-    var scroll = list.scrollTop;
-    div.innerHTML = http.responseText;
-    list = $("tasksList");
-    Event.observe(list, "selectionchange", onTasksSelectionChange.bindAsEventListener(list), true);
-    list.scrollTop = scroll;
+    var data = http.responseText.evalJSON(true);
+
+    for (var i = 0; i < data.length; i++) {
+      //log(i + " = " + data[i][3]);
+      var listItem = document.createElement("li");
+      list.appendChild(listItem);
+      Event.observe(listItem, "mousedown", listRowMouseDownHandler); // causes problem with Safari
+      Event.observe(listItem, "click", onRowClick);
+      Event.observe(listItem, "dblclick", editDoubleClickedEvent.bindAsEventListener(listItem));
+      listItem.setAttribute("id", data[i][0]);
+      $(listItem).addClassName(data[i][5]);
+      var owner = data[i][1];
+      listItem.owner = owner;
+      $(listItem).addClassName("ownerIs" + owner);
+      listItem.cname = data[i][0];
+      var input = document.createElement("input");
+      input.setAttribute("type", "checkbox");
+      listItem.appendChild(input);
+      Event.observe(input, "click", updateTaskStatus.bindAsEventListener(input), true);
+      input.setAttribute("value", "1");
+      if (data[i][2] == 1)
+       input.setAttribute("checked", "checked");
+      $(input).addClassName("checkBox");
+      listItem.appendChild(document.createTextNode(data[i][3]));
+    }
+
+    list.scrollTop = list.previousScroll;
+
     if (http.callbackData) {
       var selectedNodesId = http.callbackData;
-      for (var i = 0; i < selectedNodesId.length; i++)
+      for (var i = 0; i < selectedNodesId.length; i++) {
+//     log(selectedNodesId[i] + " (" + i + ") is selected");
         $(selectedNodesId[i]).select();
+      }
     }
+    else
+      log ("tasksListCallback: no data");
   }
   else
-    log ("ajax fuckage");
+    log ("tasksListCallback Ajax error");
 }
 
 function restoreCurrentDaySelection(div) {
@@ -349,14 +404,14 @@ function restoreCurrentDaySelection(div) {
   var i = 9;
   while (!day && i < elements.length)
     {
-      day = elements[i].getAttribute("day");
+      day = elements[i].day;
       i++;
     }
 
   if (day
       && day.substr(0, 6) == currentDay.substr(0, 6)) {
       for (i = 0; i < elements.length; i++) {
-        day = elements[i].getAttribute("day");
+        day = elements[i].day;
         if (day && day == currentDay) {
           var td = elements[i].getParentWithTagName("td");
           if (document.selectedDate)
@@ -422,11 +477,9 @@ function changeCalendarDisplay(time, newView) {
     document.dayDisplayAjaxRequest.aborted = true;
     document.dayDisplayAjaxRequest.abort();
   }
-  document.dayDisplayAjaxRequest = triggerAjaxRequest(url,
-                                                      calendarDisplayCallback,
-                                                      { "view": newView,
-                                                        "day": day,
-                                                        "hour": hour });
+  document.dayDisplayAjaxRequest
+     = triggerAjaxRequest(url, calendarDisplayCallback,
+                         { "view": newView, "day": day, "hour": hour });
 
   return false;
 }
@@ -469,9 +522,10 @@ function scrollDayView(hour) {
     rowNumber = 8;
 
   var daysView = $("daysView");
-  var hours = $(daysView.childNodesWithTag("div")[0]).childNodesWithTag("div");
+  var hours =
+     $(daysView.childNodesWithTag("div")[0]).childNodesWithTag("div");
   if (hours.length > 0)
-    daysView.parentNode.scrollTop = hours[rowNumber + 1].offsetTop;
+    daysView.scrollTop = hours[rowNumber].offsetTop;
 }
 
 function onClickableCellsDblClick(event) {
@@ -481,10 +535,223 @@ function onClickableCellsDblClick(event) {
   event.returnValue = false;
 }
 
+function refreshCalendarEvents() {
+   var todayDate = new Date();
+   var sd;
+   var ed;
+   if (currentView == "dayview") {
+      if (currentDay)
+        sd = currentDay;
+      else
+        sd = todayDate.getDayString();
+      ed = sd;
+   }
+   else if (currentView == "weekview") {
+      var startDate;
+      if (currentDay)
+        startDate = currentDay.asDate();
+      else
+        startDate = todayDate;
+      startDate = startDate.beginOfWeek();
+      sd = startDate.getDayString();
+      var endDate = new Date();
+      endDate.setTime(startDate.getTime());
+      endDate.addDays(6);
+      ed = endDate.getDayString();
+   }
+   else {
+      var monthDate;
+      if (currentDay)
+        monthDate = currentDay.asDate();
+      else
+        monthDate = todayDate;
+      monthDate.setDate(1);
+      sd = monthDate.beginOfWeek().getDayString();
+
+      var lastMonthDate = new Date();
+      lastMonthDate.setTime(monthDate.getTime());
+      lastMonthDate.setMonth(monthDate.getMonth() + 1);
+      lastMonthDate.addDays(-1);
+      ed = lastMonthDate.endOfWeek().getDayString();
+   }
+   if (document.refreshCalendarEventsAjaxRequest) {
+      document.refreshCalendarEventsAjaxRequest.aborted = true;
+      document.refreshCalendarEventsAjaxRequest.abort();
+   }
+   var url = ApplicationBaseURL + "eventslist?sd=" + sd + "&ed=" + ed;
+   document.refreshCalendarEventsAjaxRequest
+      = triggerAjaxRequest(url, refreshCalendarEventsCallback,
+                          {"startDate": sd, "endDate": ed});
+}
+
+function refreshCalendarEventsCallback(http) {
+  if (http.readyState == 4
+      && http.status == 200) {
+     var data = http.responseText.evalJSON(true);
+//      log("refresh calendar events: " + data.length);
+     for (var i = 0; i < data.length; i++)
+       drawCalendarEvent(data[i],
+                         http.callbackData["startDate"],
+                         http.callbackData["endDate"]);
+  }
+  else
+     log("AJAX error when refreshing calendar events");
+}
+
+function drawCalendarEvent(eventData, sd, ed) {
+   var viewStartDate = sd.asDate();
+   var viewEndDate = ed.asDate();
+
+   var startDate = new Date();
+   startDate.setTime(eventData[4] * 1000);
+   var endDate = new Date();
+   endDate.setTime(eventData[5] * 1000);
+
+   var days = startDate.daysUpTo(endDate);
+
+   var divs = new Array();
+
+   var title;
+   if (currentView == "monthview"
+       && (eventData[7] == 0))
+      title = startDate.getDisplayHoursString() + " " + eventData[3];
+   else
+      title = eventData[3];
+
+//    log("title: " + title); 
+//    log("viewS: " + viewStartDate);
+   var startHour = null;
+   var endHour = null;
+
+   var siblings = new Array();
+   for (var i = 0; i < days.length; i++)
+      if (days[i].earlierDate(viewStartDate) == viewStartDate
+         && days[i].laterDate(viewEndDate) == viewEndDate) {
+        var starts;
+
+//      log("day: " + days[i]);
+        if (i == 0) {
+           var quarters = (startDate.getHours() * 4
+                           + Math.floor(startDate.getMinutes() / 15));
+           starts = quarters;
+           startHour = startDate.getDisplayHoursString();
+           endHour = endDate.getDisplayHoursString();
+        }
+        else
+           starts = 0;
+        
+        var ends;
+        var lasts;
+        if (i == days.length - 1) {
+           var quarters = (endDate.getHours() * 4
+                           + Math.ceil(endDate.getMinutes() / 15));
+           ends = quarters;
+        }
+        else
+           ends = 96;
+        lasts = ends - starts;
+        if (!lasts)
+           lasts = 1;
+
+        var eventDiv = newEventDIV(eventData[0], eventData[1], starts, lasts,
+                                   null, null, title);
+        siblings.push(eventDiv);
+        eventDiv.siblings = siblings;
+        var dayString = days[i].getDayString();
+//      log("day: " + dayString);
+        var parentDiv = null;
+        if (currentView == "monthview") {
+           var dayDivs = $("monthDaysView").childNodesWithTag("div");
+           var j = 0; 
+           while (!parentDiv && j < dayDivs.length) {
+              if (dayDivs[j].getAttribute("day") == dayString)
+                 parentDiv = dayDivs[j];
+              else
+                 j++;
+           }
+        }
+        else {
+           if (eventData[7] == 0) {
+              var daysView = $("daysView");
+              var eventsDiv = $(daysView).childNodesWithTag("div")[1];
+              var dayDivs = $(eventsDiv).childNodesWithTag("div");
+              var j = 0; 
+              while (!parentDiv && j < dayDivs.length) {
+                 if (dayDivs[j].getAttribute("day") == dayString)
+                    parentDiv = dayDivs[j].childNodesWithTag("div")[0];
+                 else
+                    j++;
+              }
+           }
+           else {
+              var header = $("calendarHeader");
+              var daysDiv = $(header).childNodesWithTag("div")[1];
+              var dayDivs = $(daysDiv).childNodesWithTag("div");
+              var j = 0; 
+              while (!parentDiv && j < dayDivs.length) {
+                 if (dayDivs[j].getAttribute("day") == dayString)
+                    parentDiv = dayDivs[j];
+                 else
+                    j++;
+              }
+           }
+        }
+        if (parentDiv)
+           parentDiv.appendChild(eventDiv);
+      }
+}
+
+function newEventDIV(cname, owner, starts, lasts,
+                    startHour, endHour, title) {
+   var eventDiv = document.createElement("div");
+   eventDiv.cname = cname;
+   eventDiv.owner = owner;
+   eventDiv.addClassName("event");
+   eventDiv.addClassName("starts" + starts);
+   eventDiv.addClassName("lasts" + lasts);
+   for (var i = 1; i < 5; i++) {
+      var shadowDiv = document.createElement("div");
+      eventDiv.appendChild(shadowDiv);
+      shadowDiv.addClassName("shadow");
+      shadowDiv.addClassName("shadow" + i);
+   }
+   var innerDiv = document.createElement("div");
+   eventDiv.appendChild(innerDiv);
+   innerDiv.addClassName("eventInside");
+   innerDiv.addClassName("ownerIs" + owner);
+
+   var gradientDiv = document.createElement("div");
+   innerDiv.appendChild(gradientDiv);
+   gradientDiv.addClassName("gradient");
+   var gradientImg = document.createElement("img");
+   gradientDiv.appendChild(gradientImg);
+   gradientImg.src = ResourcesURL + "/event-gradient.png";
+
+   var textDiv = document.createElement("div");
+   innerDiv.appendChild(textDiv);
+   textDiv.addClassName("text");
+   if (startHour) {
+      var headerSpan = document.createElement("span");
+      textDiv.appendChild(headerSpan);
+      headerSpan.addClassName("eventHeader");
+      headerSpan.appendChild(document.createTextNode(startHour + " - "
+                                                    + endHour));
+      textDiv.appendChild(document.createElement("br"));
+   }
+   textDiv.appendChild(document.createTextNode(title));
+
+   Event.observe(eventDiv, "mousedown", listRowMouseDownHandler);
+   Event.observe(eventDiv, "click",
+                onCalendarSelectEvent.bindAsEventListener(eventDiv));
+   Event.observe(eventDiv, "dblclick",
+                editDoubleClickedEvent.bindAsEventListener(eventDiv));
+
+   return eventDiv;
+}
+
 function calendarDisplayCallback(http) {
   var div = $("calendarView");
 
-  //log ("calendarDisplayCallback: " + div);
   if (http.readyState == 4
       && http.status == 200) {
     document.dayDisplayAjaxRequest = null;
@@ -503,30 +770,36 @@ function calendarDisplayCallback(http) {
       scrollDayView(hour);
       contentView = $("daysView");
     }
-    var appointments = document.getElementsByClassName("appointment", contentView);
-    for (var i = 0; i < appointments.length; i++) {
-      Event.observe(appointments[i], "mousedown",  listRowMouseDownHandler);
-      Event.observe(appointments[i], "click",  onCalendarSelectAppointment.bindAsEventListener(appointments[i]));
-      Event.observe(appointments[i], "dblclick", displayAppointment.bindAsEventListener(appointments[i]));
-    }
+    refreshCalendarEvents();
     var days = document.getElementsByClassName("day", contentView);
     if (currentView == "monthview")
       for (var i = 0; i < days.length; i++) {
         Event.observe(days[i], "click",  onCalendarSelectDay.bindAsEventListener(days[i]));
         Event.observe(days[i], "dblclick",  onClickableCellsDblClick.bindAsEventListener(days[i]));
       }
-    else
-      for (var i = 0; i < days.length; i++) {
-        Event.observe(days[i], "click",  onCalendarSelectDay.bindAsEventListener(days[i]));
-        var clickableCells = document.getElementsByClassName("clickableHourCell",
-                                                             days[i]);
-        for (var j = 0; j < clickableCells.length; j++)
-          Event.observe(clickableCells[j], "dblclick", onClickableCellsDblClick.bindAsEventListener(clickableCells[j]));
-      }
-//     log("cbtest1");
+    else {
+       var headerDivs = $("calendarHeader").childNodesWithTag("div"); 
+       var headerDaysLabels = document.getElementsByClassName("day", headerDivs[0]);
+       var headerDays = document.getElementsByClassName("day", headerDivs[1]);
+       for (var i = 0; i < days.length; i++) {
+         headerDays[i].hour = "allday";
+         Event.observe(headerDaysLabels[i], "mousedown", listRowMouseDownHandler);
+         Event.observe(headerDays[i], "click",
+                       onCalendarSelectDay.bindAsEventListener(days[i]));
+         Event.observe(headerDays[i], "dblclick",
+                       onClickableCellsDblClick.bindAsEventListener(headerDays[i]));
+         Event.observe(days[i], "click",
+                       onCalendarSelectDay.bindAsEventListener(days[i]));
+         var clickableCells = document.getElementsByClassName("clickableHourCell",
+                                                              days[i]);
+         for (var j = 0; j < clickableCells.length; j++)
+            Event.observe(clickableCells[j], "dblclick",
+                          onClickableCellsDblClick.bindAsEventListener(clickableCells[j]));
+       }
+    }
   }
   else
-    log ("ajax fuckage");
+    log ("calendarDisplayCallback Ajax error (" + http.readyState + "/" + http.status + ")");
 }
 
 function assignCalendar(name) {
@@ -549,27 +822,27 @@ function popupCalendar(node) {
    return false;
 }
 
-function onAppointmentContextMenu(event, element) {
-  var topNode = $("appointmentsList");
+function onEventContextMenu(event) {
+  var topNode = $("eventsList");
 //   log(topNode);
 
-  var menu = $("appointmentsListMenu");
+  var menu = $("eventsListMenu");
 
-  Event.observe(menu, "hideMenu",  onAppointmentContextMenuHide);
-  popupMenu(event, "appointmentsListMenu", element);
+  Event.observe(menu, "hideMenu",  onEventContextMenuHide);
+  popupMenu(event, "eventsListMenu", this);
 
-  var topNode = $("appointmentsList");
+  var topNode = $("eventsList");
   var selectedNodes = topNode.getSelectedRows();
   topNode.menuSelectedRows = selectedNodes;
   for (var i = 0; i < selectedNodes.length; i++)
     selectedNodes[i].deselect();
 
-  topNode.menuSelectedEntry = element;
-  element.select();
+  topNode.menuSelectedEntry = this;
+  this.select();
 }
 
-function onAppointmentContextMenuHide(event) {
-  var topNode = $("appointmentsList");
+function onEventContextMenuHide(event) {
+  var topNode = $("eventsList");
 
   if (topNode.menuSelectedEntry) {
     topNode.menuSelectedEntry.deselect();
@@ -585,7 +858,7 @@ function onAppointmentContextMenuHide(event) {
   }
 }
 
-function onAppointmentsSelectionChange() {
+function onEventsSelectionChange() {
   listOfSelection = this;
   this.removeClassName("_unfocused");
   $("tasksList").addClassName("_unfocused");
@@ -594,17 +867,21 @@ function onAppointmentsSelectionChange() {
 function onTasksSelectionChange() {
   listOfSelection = this;
   this.removeClassName("_unfocused");
-  $("appointmentsList").addClassName("_unfocused");
+  $("eventsList").addClassName("_unfocused");
 }
 
-function _loadAppointmentHref(href) {
-  if (document.appointmentsListAjaxRequest) {
-    document.appointmentsListAjaxRequest.aborted = true;
-    document.appointmentsListAjaxRequest.abort();
+function _loadEventHref(href) {
+  if (document.eventsListAjaxRequest) {
+    document.eventsListAjaxRequest.aborted = true;
+    document.eventsListAjaxRequest.abort();
   }
   var url = ApplicationBaseURL + href;
-  document.appointmentsListAjaxRequest
-    = triggerAjaxRequest(url, appointmentsListCallback, href);
+  document.eventsListAjaxRequest
+    = triggerAjaxRequest(url, eventsListCallback, href);
+
+  var table = $("eventsList").tBodies[0];
+  while (table.rows.length > 1)
+     table.removeChild(table.rows[1]);
 
   return false;
 }
@@ -616,33 +893,42 @@ function _loadTasksHref(href) {
   }
   url = ApplicationBaseURL + href;
 
-  var selectedIds = $("tasksList").getSelectedNodesId();
+  var tasksList = $("tasksList");
+  var selectedIds;
+  if (tasksList)
+     selectedIds = tasksList.getSelectedNodesId();
+  else
+     selectedIds = null;
   document.tasksListAjaxRequest
     = triggerAjaxRequest(url, tasksListCallback, selectedIds);
 
-  return false;
+  tasksList.previousScroll = tasksList.scrollTop;
+  while (tasksList.childNodes.length)
+     tasksList.removeChild(tasksList.childNodes[0]);
+
+  return true;
 }
 
 function onHeaderClick(event) {
 //   log("onHeaderClick: " + this.link);
-  _loadAppointmentHref(this.link);
+  _loadEventHref(this.link);
 
   preventDefault(event);
 }
 
-function refreshAppointments() {
-  return _loadAppointmentHref("aptlist?desc=" + sortOrder
-                              + "&sort=" + sortKey
-                              + "&day=" + currentDay
-                              + "&filterpopup=" + listFilter);
+function refreshEvents() {
+   return _loadEventHref("eventslist?desc=" + sortOrder
+                        + "&sort=" + sortKey
+                        + "&day=" + currentDay
+                        + "&filterpopup=" + listFilter);
 }
 
 function refreshTasks() {
   return _loadTasksHref("taskslist?show-completed=" + showCompletedTasks);
 }
 
-function refreshAppointmentsAndDisplay() {
-  refreshAppointments();
+function refreshEventsAndDisplay() {
+  refreshEvents();
   changeCalendarDisplay();
 }
 
@@ -652,14 +938,14 @@ function onListFilterChange() {
   listFilter = node.value;
 //   log ("listFilter = " + listFilter);
 
-  return refreshAppointments();
+  return refreshEvents();
 }
 
-function onAppointmentClick(event) {
+function onEventClick(event) {
   var target = getTarget(event);
   var node = target.getParentWithTagName("tr");
-  var day = node.getAttribute("day");
-  var hour = node.getAttribute("hour");
+  var day = node.day;
+  var hour = node.hour;
 
   changeCalendarDisplay( { "day": day, "hour": hour} );
   changeDateSelectorDisplay(day);
@@ -727,8 +1013,6 @@ function onMonthMenuItemClick(event) {
   var year = '' + $("yearLabel").innerHTML;
 
   changeDateSelectorDisplay(year + month + "01", true);
-
-//   event.cancelBubble();
 }
 
 function onYearMenuItemClick(event) {
@@ -744,16 +1028,18 @@ function onSearchFormSubmit() {
   return false;
 }
 
-function onCalendarSelectAppointment() {
-  var list = $("appointmentsList");
+function onCalendarSelectEvent() {
+  var list = $("eventsList");
   list.deselectAll();
 
-  var aptCName = this.getAttribute("aptCName");
   if (selectedCalendarCell)
-    selectedCalendarCell.deselect();
-  this.select();
-  selectedCalendarCell = this;
-  var row = $(aptCName);
+     for (var i = 0; i < selectedCalendarCell.length; i++)
+       selectedCalendarCell[i].deselect();
+
+  for (var i = 0; i < this.siblings.length; i++)
+     this.siblings[i].select();
+  selectedCalendarCell = this.siblings;
+  var row = $(this.cname);
   if (row) {
     var div = row.parentNode.parentNode.parentNode;
     div.scrollTop = row.offsetTop - (div.offsetHeight / 2);
@@ -764,7 +1050,7 @@ function onCalendarSelectAppointment() {
 function onCalendarSelectDay(event) {
   var day;
   if (currentView == "multicolumndayview")
-     day = this.parentNode.getAttribute("day");
+     day = this.getAttribute("day");
   else
      day = this.getAttribute("day");
   var needRefresh = (listFilter == 'view_selectedday'
@@ -782,17 +1068,26 @@ function onCalendarSelectDay(event) {
   }
 
   if (needRefresh)
-    refreshAppointments();
+    refreshEvents();
 }
 
 function changeWeekCalendarDisplayOfSelectedDay(node) {
   var days = document.getElementsByClassName("day", node.parentNode);
+  var headerDiv = $("calendarHeader").childNodesWithTag("div")[1];
+  var headerDays = document.getElementsByClassName("day", headerDiv);
 
+//   log ("days: " + days.length + "; headerDays: " + headerDays.length);
   for (var i = 0; i < days.length; i++)
-    if (days[i] != node)
-      days[i].removeClassName("selectedDay");
-
-  node.addClassName("selectedDay");
+     if (days[i] != node) {
+//     log("unselect day : " + i);
+       headerDays[i].removeClassName("selectedDay");
+       days[i].removeClassName("selectedDay");
+     }
+     else {
+//     log("selected day : " + i);
+       headerDays[i].addClassName("selectedDay");
+       days[i].addClassName("selectedDay");
+     }
 }
 
 function findMonthCalendarSelectedCell(daysContainer) {
@@ -822,28 +1117,30 @@ function changeMonthCalendarDisplayOfSelectedDay(node) {
    node.addClassName("selectedDay");
 }
 
-function onShowCompletedTasks(node) {
-  showCompletedTasks = (node.checked ? 1 : 0);
+function onShowCompletedTasks(event) {
+   showCompletedTasks = (this.checked ? 1 : 0);
 
-  return refreshTasks();
+   return refreshTasks();
 }
 
-function updateTaskStatus(node) {
-  var taskId = node.parentNode.getAttribute("id");
-  var taskOwner = node.parentNode.getAttribute("owner");
-  var newStatus = (node.checked ? 1 : 0);
-//   log ("update task status: " + taskId);
-
+function updateTaskStatus(event) {
+  var taskId = this.parentNode.getAttribute("id");
+  var taskOwner = this.parentNode.owner;
+  var newStatus = (this.checked ? 1 : 0);
   var http = createHTTPClient();
-
-  url = (UserFolderURL + "../" + taskOwner + "/Calendar/"
-         + taskId + "/changeStatus?status=" + newStatus);
+  
+//   log("update task status: " + taskId + " to " + this.checked);
+  event.cancelBubble = true;
+  
+  url = (UserFolderURL + "../" + taskOwner 
+        + "/Calendar/" + taskId
+        + "/changeStatus?status=" + newStatus);
 
   if (http) {
 //     log ("url: " + url);
     // TODO: add parameter to signal that we are only interested in OK
+    http.open("POST", url, false /* not async */);
     http.url = url;
-    http.open("GET", url, false /* not async */);
     http.send("");
     if (http.status == 200)
       refreshTasks();
@@ -880,14 +1177,15 @@ function updateCalendarStatus(event) {
      var folderID = this.parentNode.getAttribute("id");
      var urlstr = URLForFolderID(folderID);
      if (this.checked)
-       urlstr += "/activateFolder";
+       urlstr += "/activateFolder";
      else
-       urlstr += "/deactivateFolder";
+       urlstr += "/deactivateFolder";
+     //log("updateCalendarStatus: ajax request = " + urlstr + ", folderID = " + folderID);
      triggerAjaxRequest(urlstr, calendarStatusCallback, folderID);
   }
   else {
      updateCalendarsList();
-     refreshAppointments();
+     refreshEvents();
      refreshTasks();
      changeCalendarDisplay();
   }
@@ -896,35 +1194,30 @@ function updateCalendarStatus(event) {
 }
 
 function calendarStatusCallback(http) {
-   if (http.readyState == 4) {
-      if (http.status == 204) {
-         refreshAppointments();
+  if (http.readyState == 4) {
+    if (isHttpStatus204(http.status)) {
+         refreshEvents();
          refreshTasks();
          changeCalendarDisplay();
       }
       else {
-         var folder = $(http.callbackData);
+        var folder = $(http.callbackData);
          var input = folder.childNodesWithTag("input")[0];
-         input.checked = (!input.checked);
+        input.checked = (!input.checked);
       }
    }
+   else
+      log("calendarStatusCallback Ajax error");
 }
 
 function calendarEntryCallback(http) {
-   var disabled = true;
-
-   if (http.readyState == 4) {
-      if (http.status == 200)
-        disabled = (http.responseText == "0");
+   if (http.readyState == 4) { 
+      var denied = (http.status != 204)
       var entry = $(http.callbackData);
-      var input = entry.childNodesWithTag("input")[0];
-      input.disabled = disabled;
-      if (disabled) {
-        input.checked = false;
-        $(entry).addClassName("denied");
-      }
+      if (denied)
+        entry.addClassName("denied");
       else
-        $(entry).removeClassName("denied");
+        entry.removeClassName("denied");
    }
 }
 
@@ -995,7 +1288,7 @@ function getMenus() {
       dateMenu.push(onYearMenuItemClick);
    menus["yearListMenu"] = dateMenu;
 
-   menus["appointmentsListMenu"] = new Array(onMenuNewEventClick, "-",
+   menus["eventsListMenu"] = new Array(onMenuNewEventClick, "-",
                                             onMenuNewTaskClick,
                                             editEvent, deleteEvent, "-",
                                             onSelectAll, "-",
@@ -1031,7 +1324,7 @@ function configureDragHandles() {
   handle = $("rightDragHandle");
   if (handle) {
     handle.addInterface(SOGoDragHandlesInterface);
-    handle.upperBlock=$("appointmentsListView");
+    handle.upperBlock=$("eventsListView");
     handle.lowerBlock=$("calendarView");
   }
 }
@@ -1044,8 +1337,8 @@ function initCalendarSelector() {
   var list = $("calendarList").childNodesWithTag("li");
   for (var i = 0; i < list.length; i++) {
     var input = list[i].childNodesWithTag("input")[0];
-    Event.observe(input, "change", updateCalendarStatus.bindAsEventListener(input));
-    Event.observe(list[i], "mousedown", listRowMouseDownHandler);
+    Event.observe(input, "click", updateCalendarStatus.bindAsEventListener(input)); // not registered in IE?
+    //Event.observe(list[i], "mousedown", listRowMouseDownHandler, true); // problem with Safari
     Event.observe(list[i], "click", onRowClick);
   }
 
@@ -1065,27 +1358,32 @@ function appendCalendar(folderName, folder) {
    var lis = calendarList.childNodesWithTag("li");
    var color = indexColor(lis.length);
    log ("color: " + color);
+
    var li = document.createElement("li");
-   li.setAttribute("id", folder);
-   Event.observe(li, "mousedown",  listRowMouseDownHandler);
-   Event.observe(li, "click",  onRowClick);
+   calendarList.appendChild(li);
+
    var checkBox = document.createElement("input");
-   checkBox.addClassName("checkBox");
-   checkBox.type = "checkbox";
-   Event.observe(checkBox, "change",  updateCalendarStatus);
    li.appendChild(checkBox);
+   
    li.appendChild(document.createTextNode(" "));
+
    var colorBox = document.createElement("div");
+   li.appendChild(colorBox);
+   li.appendChild(document.createTextNode(" " + folderName));
    colorBox.appendChild(document.createTextNode("OO"));
+
+   li.setAttribute("id", folder);
+   Event.observe(li, "mousedown",  listRowMouseDownHandler);
+   Event.observe(li, "click",  onRowClick);
+   checkBox.addClassName("checkBox");
+   checkBox.type = "checkbox";
+   Event.observe(checkBox, "click",  updateCalendarStatus.bindAsEventListener(checkBox));
+   
    colorBox.addClassName("colorBox");
    if (color) {
      colorBox.setStyle({ color: color,
                         backgroundColor: color });
    }
-   li.appendChild(colorBox);
-   li.appendChild(document.createTextNode(" " + folderName));
-
-   calendarList.appendChild(li);
 
    var contactId = folder.split(":")[0];
    var styles = document.getElementsByTagName("style");
@@ -1127,17 +1425,42 @@ function onCalendarRemove(event) {
 function configureSearchField() {
    var searchValue = $("searchValue");
 
-   Event.observe(searchValue, "mousedown",  onSearchMouseDown.bindAsEventListener(searchValue));
-   Event.observe(searchValue, "click",  popupSearchMenu.bindAsEventListener(searchValue));
-   Event.observe(searchValue, "blur",  onSearchBlur.bindAsEventListener(searchValue));
-   Event.observe(searchValue, "focus",  onSearchFocus.bindAsEventListener(searchValue));
-   Event.observe(searchValue, "keydown",  onSearchKeyDown.bindAsEventListener(searchValue));
+   Event.observe(searchValue, "mousedown",
+                onSearchMouseDown.bindAsEventListener(searchValue));
+   Event.observe(searchValue, "click",
+                popupSearchMenu.bindAsEventListener(searchValue));
+   Event.observe(searchValue, "blur",
+                onSearchBlur.bindAsEventListener(searchValue));
+   Event.observe(searchValue, "focus",
+                onSearchFocus.bindAsEventListener(searchValue));
+   Event.observe(searchValue, "keydown",
+                onSearchKeyDown.bindAsEventListener(searchValue));
+}
+
+function configureLists() {
+   var list = $("tasksList");
+   list.multiselect = true;
+   Event.observe(list, "mousedown",
+                onTasksSelectionChange.bindAsEventListener(list));
+
+   var input = $("showHideCompletedTasks");
+   Event.observe(input, "click",
+                onShowCompletedTasks.bindAsEventListener(input));
+
+   list = $("eventsList");
+   list.multiselect = true;
+   Event.observe(list, "mousedown",
+                onEventsSelectionChange.bindAsEventListener(list));
+   var div = list.parentNode;
+   Event.observe(div, "contextmenu",
+                onEventContextMenu.bindAsEventListener(div));
 }
 
 function initCalendars() {
    if (!document.body.hasClassName("popup")) {
       initCalendarSelector();
       configureSearchField();
+      configureLists();
       var selector = $("calendarSelector");
       if (selector)
         selector.attachMenu("calendarsMenu");