Monotone-Parent: 95b1c285d67a034685e2ef30e56e10e7c253438d

Monotone-Revision: 2609687767884b123c1ff765253fde7c75ef81b3

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2008-07-16T02:12:18
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2008-07-16 02:12:18 +00:00
parent 8078250b1a
commit 7512f5d512
11 changed files with 756 additions and 466 deletions

View File

@ -1,3 +1,21 @@
2008-07-15 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* UI/Scheduler/NSDictionary+Scheduler.m: new category module that
implement helper methods for the Scheduler module.
([NSDictionary -compareEventByStart:otherEvent]): new method that
compares event block dictionaries based on their value for
"start".
* UI/Scheduler/UIxCalListingActions.m ([UIxCalListingActions
-eventsBlocksAction]): new web method that returns the list of
events as well as the precomputed blocks of events, whether "all
day" or not.
* SoObjects/Appointments/SOGoAppointmentFolder.m
([SOGoAppointmentFolder
-fetchCoreInfosFrom:_startDateto:_endDatetitle:titlecomponent:_componentadditionalFilters:filters]):
requests "c_iscycle".
2008-07-14 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/SOGo/SOGoContentObject.m ([SOGoContentObject

View File

@ -1399,7 +1399,6 @@ static Class sogoAppointmentFolderKlass = Nil;
- (NSString *) davCalendarOrder
{
NSArray *siblings;
unsigned int order;
order = [[container subFolders] indexOfObject: self];
@ -1409,8 +1408,6 @@ static Class sogoAppointmentFolderKlass = Nil;
- (NSException *) setDavCalendarOrder: (NSString *) newColor
{
NSException *error;
return nil;
}
@ -2218,7 +2215,7 @@ static Class sogoAppointmentFolderKlass = Nil;
@"c_classification", @"c_isallday",
@"c_isopaque", @"c_participants", @"c_partmails",
@"c_partstates", @"c_sequence", @"c_priority",
@"c_cycleinfo", nil];
@"c_cycleinfo", @"c_iscycle", nil];
return [self fetchFields: infos from: _startDate to: _endDate title: title
component: _component

View File

@ -11,6 +11,7 @@ SchedulerUI_LANGUAGES = Dutch English French German Italian Spanish
SchedulerUI_OBJC_FILES = \
SchedulerUIProduct.m \
NSArray+Scheduler.m \
NSDictionary+Scheduler.m \
\
UIxCalMainView.m \
UIxCalendarProperties.m \

View File

@ -0,0 +1,29 @@
/* NSDictionary+Scheduler.h - this file is part of SOGo
*
* Copyright (C) 2008 Inverse groupe conseil
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSDictionary.h>
@interface NSDictionary (SOGoEventComparison)
- (NSComparisonResult) compareEventByStart: (NSDictionary *) otherEvent;
@end

View File

@ -0,0 +1,35 @@
/* NSDictionary+Scheduler.m - this file is part of SOGo
*
* Copyright (C) 2008 Inverse groupe conseil
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSString.h>
#import "NSDictionary+Scheduler.h"
@implementation NSDictionary (SOGoEventComparison)
- (NSComparisonResult) compareEventByStart: (NSDictionary *) otherEvent
{
return [[self objectForKey: @"start"]
compare: [otherEvent objectForKey: @"start"]];
}
@end

View File

@ -42,6 +42,7 @@
NSCalendarDate *endDate;
NSString *title;
NSString *userLogin;
BOOL dayBasedView;
WORequest *request;
SOGoDateFormatter *dateFormatter;
NSTimeZone *userTimeZone;

View File

@ -49,8 +49,34 @@
#import "UIxCalListingActions.h"
static NSArray *eventsFields = nil;
static NSArray *tasksFields = nil;
#define dayLength 86400
#define quarterLength 900
@implementation UIxCalListingActions
+ (void) initialize
{
if (!eventsFields)
{
eventsFields = [NSArray arrayWithObjects: @"c_name", @"c_folder",
@"c_status", @"c_title", @"c_startdate",
@"c_enddate", @"c_location", @"c_isallday",
@"c_classification", @"c_partmails",
@"c_partstates", @"c_owner", @"c_iscycle", nil];
[eventsFields retain];
}
if (!tasksFields)
{
tasksFields = [NSArray arrayWithObjects: @"c_name", @"c_folder",
@"c_status", @"c_title", @"c_enddate",
@"c_classification", nil];
[tasksFields retain];
}
}
- (id) initWithRequest: (WORequest *) newRequest
{
SOGoUser *user;
@ -64,6 +90,7 @@
user = [[self context] activeUser];
dateFormatter = [user dateFormatterInContext: context];
ASSIGN (userTimeZone, [user timeZone]);
dayBasedView = NO;
}
return self;
@ -161,7 +188,7 @@
userTZ = [user timeZone];
param = [request formValueForKey: @"filterpopup"];
if ([param length] > 0)
if ([param length])
{
[self _setupDatesWithPopup: param andUserTZ: userTZ];
title = [request formValueForKey: @"search"];
@ -175,7 +202,7 @@
inTimeZone: userTZ] beginOfDay];
else
startDate = nil;
param = [request formValueForKey: @"ed"];
if ([param length] > 0)
endDate = [[NSCalendarDate dateFromShortDateString: param
@ -183,6 +210,9 @@
inTimeZone: userTZ] endOfDay];
else
endDate = nil;
param = [request formValueForKey: @"view"];
dayBasedView = ![param isEqualToString: @"monthview"];
}
}
@ -291,27 +321,9 @@
return formattedDate;
}
- (NSString *) _adjustedDateForSeconds: (unsigned int) seconds
forAllDay: (BOOL) forAllDay
{
NSCalendarDate *date;
unsigned int newSeconds, offset;
date = [NSCalendarDate dateWithTimeIntervalSince1970: seconds];
[date setTimeZone: userTimeZone];
offset = [userTimeZone secondsFromGMTForDate: date];
if (forAllDay)
newSeconds = seconds + [userTimeZone secondsFromGMT] - offset;
else
newSeconds = seconds + offset;
return [NSString stringWithFormat: @"%u", newSeconds];
}
- (WOResponse *) eventsListAction
{
NSArray *fields, *oldEvent, *participants, *states;
NSArray *oldEvent, *participants, *states;
NSEnumerator *events;
NSMutableArray *newEvents, *newEvent;
unsigned int interval, i;
@ -322,27 +334,16 @@
[self _setupContext];
newEvents = [NSMutableArray array];
fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status",
@"c_title", @"c_startdate", @"c_enddate", @"c_location",
@"c_isallday", @"c_classification", @"c_partmails", @"c_partstates",
@"c_owner", nil];
events = [[self _fetchFields: fields
events = [[self _fetchFields: eventsFields
forComponentOfType: @"vevent"] objectEnumerator];
oldEvent = [events nextObject];
while (oldEvent)
while ((oldEvent = [events nextObject]))
{
newEvent = [NSMutableArray arrayWithArray: oldEvent];
isAllDay = [[oldEvent objectAtIndex: 7] boolValue];
interval = [[oldEvent objectAtIndex: 4] intValue];
[newEvent replaceObjectAtIndex: 4
withObject: [self _adjustedDateForSeconds: interval
forAllDay: isAllDay]];
[newEvent addObject: [self _formattedDateForSeconds: interval
forAllDay: isAllDay]];
interval = [[oldEvent objectAtIndex: 5] intValue];
[newEvent replaceObjectAtIndex: 5
withObject: [self _adjustedDateForSeconds: interval
forAllDay: isAllDay]];
[newEvent addObject: [self _formattedDateForSeconds: interval
forAllDay: isAllDay]];
@ -380,8 +381,6 @@
[newEvent removeObjectAtIndex: 10];
[newEvents addObject: newEvent];
oldEvent = [events nextObject];
}
sort = [[context request] formValueForKey: @"sort"];
@ -393,7 +392,7 @@
[newEvents sortUsingSelector: @selector (compareEventsLocationAscending:)];
else
[newEvents sortUsingSelector: @selector (compareEventsStartDateAscending:)];
ascending = [[context request] formValueForKey: @"asc"];
if (![ascending boolValue])
[newEvents reverseArray];
@ -401,6 +400,361 @@
return [self _responseWithData: newEvents];
}
static inline void
_feedBlockWithDayBasedData(NSMutableDictionary *block, unsigned int start,
unsigned int end, unsigned int dayStart)
{
unsigned int delta, quarterStart, length;
quarterStart = (start - dayStart) / quarterLength;
delta = end - dayStart;
if ((delta % quarterLength))
delta += quarterLength;
length = (delta / quarterLength) - quarterStart;
if (!length)
length = 1;
[block setObject: [NSNumber numberWithUnsignedInt: quarterStart]
forKey: @"start"];
[block setObject: [NSNumber numberWithUnsignedInt: length]
forKey: @"length"];
}
static inline void
_feedBlockWithMonthBasedData(NSMutableDictionary *block, unsigned int start,
NSTimeZone *userTimeZone,
SOGoDateFormatter *dateFormatter)
{
NSCalendarDate *eventStartDate;
NSString *startHour;
eventStartDate = [NSCalendarDate dateWithTimeIntervalSince1970: start];
[eventStartDate setTimeZone: userTimeZone];
startHour = [dateFormatter formattedTime: eventStartDate];
[block setObject: startHour forKey: @"starthour"];
[block setObject: [NSNumber numberWithUnsignedInt: start]
forKey: @"start"];
}
- (NSMutableDictionary *) _eventBlockWithStart: (unsigned int) start
end: (unsigned int) end
cname: (NSString *) cName
onDay: (unsigned int) dayStart
recurrence: (BOOL) recurrence
{
NSMutableDictionary *block;
block = [NSMutableDictionary dictionary];
if (dayBasedView)
_feedBlockWithDayBasedData (block, start, end, dayStart);
else
_feedBlockWithMonthBasedData (block, start, userTimeZone, dateFormatter);
[block setObject: cName forKey: @"cname"];
if (recurrence)
[block setObject: @"1" forKey: @"recurrence"];
return block;
}
- (void) _fillBlocks: (NSArray *) blocks
withEvent: (NSArray *) event
{
unsigned int currentDayStart, startSecs, endsSecs, currentStart, eventStart,
eventEnd, offset;
NSMutableArray *currentDay;
NSMutableDictionary *eventBlock;
NSString *eventCName;
BOOL recurrence;
startSecs = (unsigned int) [startDate timeIntervalSince1970];
endsSecs = (unsigned int) [endDate timeIntervalSince1970];
eventStart = [[event objectAtIndex: 4] unsignedIntValue];
eventEnd = [[event objectAtIndex: 5] unsignedIntValue];
recurrence = [[event objectAtIndex: 12] boolValue];
currentStart = eventStart;
if (currentStart < startSecs)
{
currentStart = startSecs;
offset = 0;
}
else
offset = ((currentStart - startSecs)
/ dayLength);
currentDay = [blocks objectAtIndex: offset];
currentDayStart = startSecs + dayLength * offset;
if (eventEnd > endsSecs)
eventEnd = endsSecs;
eventCName = [event objectAtIndex: 0];
while (currentStart + dayLength < eventEnd)
{
eventBlock = [self _eventBlockWithStart: currentStart
end: currentDayStart + 86399
cname: eventCName
onDay: currentDayStart
recurrence: recurrence];
[currentDay addObject: eventBlock];
currentDayStart += dayLength;
currentStart = currentDayStart;
offset++;
currentDay = [blocks objectAtIndex: offset];
}
eventBlock = [self _eventBlockWithStart: currentStart
end: eventEnd
cname: eventCName
onDay: currentDayStart
recurrence: recurrence];
[currentDay addObject: eventBlock];
}
- (void) _prepareEventBlocks: (NSMutableArray **) blocks
withAllDays: (NSMutableArray **) allDayBlocks
{
unsigned int count, nbrDays;
int seconds;
seconds = [endDate timeIntervalSinceDate: startDate];
if (seconds > 0)
{
nbrDays = 1 + (unsigned int) (seconds / dayLength);
*blocks = [NSMutableArray arrayWithCapacity: nbrDays];
*allDayBlocks = [NSMutableArray arrayWithCapacity: nbrDays];
for (count = 0; count < nbrDays; count++)
{
[*blocks addObject: [NSMutableArray array]];
[*allDayBlocks addObject: [NSMutableArray array]];
}
}
else
{
*blocks = nil;
*allDayBlocks = nil;
}
}
- (NSArray *) _horizontalBlocks: (NSMutableArray *) day
{
NSMutableArray *quarters[96];
NSMutableArray *currentBlock, *blocks;
NSDictionary *currentEvent;
unsigned int count, max, qCount, qMax, qOffset;
blocks = [NSMutableArray array];
bzero (quarters, 96 * sizeof (NSMutableArray *));
max = [day count];
for (count = 0; count < max; count++)
{
currentEvent = [day objectAtIndex: count];
qMax = [[currentEvent objectForKey: @"length"] unsignedIntValue];
qOffset = [[currentEvent objectForKey: @"start"] unsignedIntValue];
for (qCount = 0; qCount < qMax; qCount++)
{
currentBlock = quarters[qCount + qOffset];
if (!currentBlock)
{
currentBlock = [NSMutableArray array];
quarters[qCount + qOffset] = currentBlock;
[blocks addObject: currentBlock];
}
[currentBlock addObject: currentEvent];
}
}
return blocks;
}
static inline unsigned int
_computeMaxBlockSiblings (NSArray *block)
{
unsigned int count, max, maxSiblings, siblings;
NSNumber *nbrEvents;
max = [block count];
maxSiblings = max;
for (count = 0; count < max; count++)
{
nbrEvents = [[block objectAtIndex: count] objectForKey: @"siblings"];
if (nbrEvents)
{
siblings = [nbrEvents unsignedIntValue];
if (siblings > maxSiblings)
maxSiblings = siblings;
}
}
return maxSiblings;
}
static inline void
_propagateBlockSiblings (NSArray *block, NSNumber *maxSiblings)
{
unsigned int count, max;
NSMutableDictionary *event;
NSNumber *realSiblings;
max = [block count];
realSiblings = [NSNumber numberWithUnsignedInt: max];
for (count = 0; count < max; count++)
{
event = [block objectAtIndex: count];
[event setObject: maxSiblings forKey: @"siblings"];
[event setObject: realSiblings forKey: @"realSiblings"];
}
}
/* this requires two vertical passes */
static inline void
_computeBlocksSiblings (NSArray *blocks)
{
NSArray *currentBlock;
unsigned int count, max, maxSiblings;
max = [blocks count];
for (count = 0; count < max; count++)
{
currentBlock = [blocks objectAtIndex: count];
maxSiblings = _computeMaxBlockSiblings (currentBlock);
_propagateBlockSiblings (currentBlock,
[NSNumber numberWithUnsignedInt: maxSiblings]);
}
}
static inline void
_computeBlockPosition (NSArray *block)
{
unsigned int count, max, j, siblings;
NSNumber *position;
NSMutableDictionary *event;
NSMutableDictionary **positions;
max = [block count];
event = [block objectAtIndex: 0];
siblings = [[event objectForKey: @"siblings"] unsignedIntValue];
positions = calloc (siblings, sizeof (NSMutableDictionary *));
for (count = 0; count < max; count++)
{
event = [block objectAtIndex: count];
position = [event objectForKey: @"position"];
if (position)
*(positions + [position unsignedIntValue]) = event;
else
{
j = 0;
while (j < max && *(positions + j))
j++;
*(positions + j) = event;
[event setObject: [NSNumber numberWithUnsignedInt: j]
forKey: @"position"];
}
}
free (positions);
}
// static inline void
// _addBlockMultipliers (NSArray *block, NSMutableDictionary **positions)
// {
// unsigned int count, max, limit, multiplier;
// NSMutableDictionary *currentEvent, *event;
// max = [block count];
// event = [block objectAtIndex: 0];
// limit = [[event objectForKey: @"siblings"] unsignedIntValue];
// if (max < limit)
// {
// currentEvent = nil;
// for (count = 0; count < limit; count++)
// {
// multiplier = 1;
// event = positions[count];
// if ([[event objectForKey: @"realSiblings"] unsignedIntValue]
// < limit)
// {
// if (event)
// {
// if (currentEvent && multiplier > 1)
// [currentEvent setObject: [NSNumber numberWithUnsignedInt: multiplier]
// forKey: @"multiplier"];
// currentEvent = event;
// multiplier = 1;
// }
// else
// multiplier++;
// }
// }
// }
// }
static inline void
_computeBlocksPosition (NSArray *blocks)
{
NSArray *block;
unsigned int count, max;
// NSMutableDictionary **positions;
max = [blocks count];
for (count = 0; count < max; count++)
{
block = [blocks objectAtIndex: count];
_computeBlockPosition (block);
// _addBlockMultipliers (block, positions);
// free (positions);
}
}
- (void) _addBlocksWidth: (NSMutableArray *) day
{
NSArray *blocks;
blocks = [self _horizontalBlocks: day];
_computeBlocksSiblings (blocks);
_computeBlocksSiblings (blocks);
_computeBlocksPosition (blocks);
/* ... _computeBlocksMultiplier() ... */
}
- (WOResponse *) eventsBlocksAction
{
int count, max;
NSArray *events, *event, *eventsBlocks;
NSMutableArray *allDayBlocks, *blocks, *currentDay;
[self _setupContext];
[self _prepareEventBlocks: &blocks withAllDays: &allDayBlocks];
events = [self _fetchFields: eventsFields
forComponentOfType: @"vevent"];
eventsBlocks
= [NSArray arrayWithObjects: events, allDayBlocks, blocks, nil];
max = [events count];
for (count = 0; count < max; count++)
{
event = [events objectAtIndex: count];
if (dayBasedView && [[event objectAtIndex: 7] boolValue])
[self _fillBlocks: allDayBlocks withEvent: event];
else
[self _fillBlocks: blocks withEvent: event];
}
max = [blocks count];
for (count = 0; count < max; count++)
{
currentDay = [blocks objectAtIndex: count];
[currentDay sortUsingSelector: @selector (compareEventByStart:)];
[self _addBlocksWidth: currentDay];
}
return [self _responseWithData: eventsBlocks];
// timeIntervalSinceDate:
}
- (NSString *) _getStatusClassForStatusCode: (int) statusCode
andEndDateStamp: (unsigned int) endDateStamp
{
@ -438,7 +792,7 @@
NSEnumerator *tasks;
NSMutableArray *filteredTasks, *filteredTask;
BOOL showCompleted;
NSArray *fields, *task;
NSArray *task;
int statusCode;
unsigned int endDateStamp;
NSString *statusFlag;
@ -447,10 +801,7 @@
[self _setupContext];
fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status",
@"c_title", @"c_enddate", @"c_classification", nil];
tasks = [[self _fetchFields: fields
tasks = [[self _fetchFields: tasksFields
forComponentOfType: @"vtodo"] objectEnumerator];
showCompleted = [[request formValueForKey: @"show-completed"] intValue];

View File

@ -59,6 +59,11 @@
actionClass = "UIxCalListingActions";
actionName = "eventsList";
};
eventsblocks = {
protectedBy = "View";
actionClass = "UIxCalListingActions";
actionName = "eventsBlocks";
};
taskslist = {
protectedBy = "View";
actionClass = "UIxCalListingActions";

View File

@ -42,20 +42,6 @@
var:day="currentTableDay.shortDateString"
var:hour="currentAppointmentHour">
</div></var:foreach>
<!-- <var:foreach list="appointmentsForCurrentDay" item="currentAppointment"
><var:component className="UIxCalInlineAptView"
dayStartHour="dayStartHour"
dayEndHour="dayEndHour"
appointment="currentAppointment"
formatter="aptFormatter"
tooltipFormatter="aptTooltipFormatter"
url="appointmentViewURL"
const:style="dayoverview"
queryDictionary="currentDateQueryParameters"
referenceDate="selectedDate"
canAccess="canAccessApt"
/></var:foreach
> -->
</div>
</div>
</var:foreach>

View File

@ -47,89 +47,15 @@
><var:string value="labelForCurrentDayToDisplay"
/></div></var:foreach>
<div class="days" const:id="monthDaysView"
><var:foreach list="daysToDisplay" item="currentTableColumn">
<var:foreach list="currentTableColumn" item="currentTableDay">
<div var:class="dayCellClasses"
><var:foreach list="daysToDisplay" item="currentTableColumn"
><var:foreach list="currentTableColumn" item="currentTableDay"
><div var:class="dayCellClasses"
var:day="currentTableDay.shortDateString">
<div class="dayHeader"><var:string value="dayHeaderNumber"/></div>
<!-- var:foreach
list="aptsForCurrentDate"
item="appointment"
var:component className="UIxCalInlineMdsadsadsaonthAptView"
appointment="appointment"
formatter="monthAptFormatter"
tooltipFormatter="aptTooltipFormatter"
url="appointmentViewURL"
const:style="dayoverview"
queryDictionary="currentDayQueryParameters"
referenceDate="currentTableDay"
canAccess="canAccessApt"
var:foreach -->
</div>
<div class="dayHeader"><var:string value="dayHeaderNumber"/></div
></div>
</var:foreach>
</var:foreach>
</div>
</div>
</div>
</container>
<!-- <table class="monthOverview">
<tr>
</tr>
<var:if condition="hasHolidayInfo">
<tr>
<td class="hourOfDay" colspan="2">
<b><var:string value="holidayInfo.title" /></b>
</td>
</tr>
</var:if> -->
<!-- <var:foreach list="allDayApts" item="appointment">
<tr>
<td class="hourOfDay">
<var:entity name="nbsp" />
</td>
<td class="day" width="90%">
<var:foreach list="allDayApts" item="appointment">
<var:component className="UIxCaaaaalInlineAptView"
appointment="appointment"
formatter="aptFormatter"
tooltipFormatter="aptTooltipFormatter"
url="appointmentViewURL"
const:style="dayoverview"
queryDictionary="currentDateQueryParameters"
referenceDate="selectedDate"
canAccess="canAccessApt"
/>
</var:foreach>
</td>
</tr>
</var:foreach> -->
<!-- <var:foreach list="rangesOf7Days" item="currentRangeOf7Days">
<tr>
<var:foreach list="currentRangeOf7Days" item="currentTableDay"
><td var:class="dayCellClasses"
var:day="currentTableDay.shortDateString"
const:hour="0800"
><div class="dayContent"><span class="dayCellLabel"
><var:string value="labelForCurrentDayCell" /></span
><br /><var:foreach
list="aptsForCurrentDate"
item="appointment"
><var:component className="UIxCalInlineAptxxxxView"
appointment="appointment"
formatter="monthAptFormatter"
tooltipFormatter="aptTooltipFormatter"
url="appointmentViewURL"
const:style="dayoverview"
queryDictionary="currentDayQueryParameters"
referenceDate="currentTableDay"
canAccess="canAccessApt"
/>
</var:foreach></div></td>
</var:foreach>
</tr>
</var:foreach>
</table> -->

View File

@ -10,16 +10,19 @@ var showCompletedTasks = 0;
var currentDay = '';
var currentView = "weekview";
var cachedDateSelectors = new Array();
var cachedDateSelectors = [];
var contactSelectorAction = 'calendars-contacts';
var eventsToDelete = new Array();
var calendarsOfEventsToDelete = new Array();
var eventsToDelete = [];
var calendarsOfEventsToDelete = [];
var usersRightsWindowHeight = 250;
var usersRightsWindowWidth = 502;
var eventsBlocks;
var calendarEvents = null;
function newEvent(sender, type) {
var day = $(sender).readAttribute("day");
if (!day)
@ -34,7 +37,7 @@ function newEvent(sender, type) {
folderID = "/personal";
}
var urlstr = ApplicationBaseURL + folderID + "/new" + type;
var params = new Array();
var params = [];
if (day)
params.push("day=" + day);
if (hour)
@ -67,7 +70,7 @@ function onMenuNewTaskClick(event) {
}
function _editEventId(id, calendar) {
var urlstr = ApplicationBaseURL + "/" + calendar + "/" + id + "/edit";
var urlstr = ApplicationBaseURL + calendar + "/" + id + "/edit";
var targetname = "SOGo_edit_" + id;
var win = window.open(urlstr, "_blank",
"width=490,height=470,resizable=0");
@ -100,7 +103,7 @@ function editEvent() {
function _batchDeleteEvents() {
var events = eventsToDelete.shift();
var calendar = calendarsOfEventsToDelete.shift();
var urlstr = (ApplicationBaseURL + "/" + calendar
var urlstr = (ApplicationBaseURL + calendar
+ "/batchDelete?ids=" + events.join('/'));
document.deleteEventAjaxRequest = triggerAjaxRequest(urlstr,
deleteEventCallback,
@ -123,13 +126,13 @@ function deleteEvent() {
document.deleteEventAjaxRequest.aborted = true;
document.deleteEventAjaxRequest.abort();
}
var sortedNodes = new Array();
var calendars = new Array();
var sortedNodes = [];
var calendars = [];
for (var i = 0; i < nodes.length; i++) {
var calendar = nodes[i].calendar;
if (!sortedNodes[calendar]) {
sortedNodes[calendar] = new Array();
sortedNodes[calendar] = [];
calendars.push(calendar);
}
sortedNodes[calendar].push(nodes[i].cname);
@ -228,19 +231,41 @@ function deleteEventCallback(http) {
_batchDeleteEvents();
else {
document.deleteEventAjaxRequest = null;
if (isTask)
refreshTasks();
else {
refreshEvents();
changeCalendarDisplay();
}
}
if (isTask)
deleteTasksFromViews(nodes);
else
deleteEventsFromViews(nodes)
}
else
log ("deleteEventCallback Ajax error");
}
}
function deleteTasksFromViews(tasks) {
}
function deleteEventsFromViews(events) {
if (calendarEvents) {
for (var i = 0; i < events.length; i++) {
var cname = events[i];
var event = calendarEvents[cname];
if (event) {
if (event.siblings) {
for (var j = 0; j < event.siblings.length; j++) {
var eventDiv = event.siblings[j];
eventDiv.parentNode.removeChild(eventDiv);
}
}
delete calendarEvents[cname]
}
var row = $(cname);
if (row)
row.parentNode.removeChild(row);
}
}
}
function editDoubleClickedEvent(event) {
_editEventId(this.cname, this.calendar);
@ -364,12 +389,12 @@ function eventsListCallback(http) {
td = $(document.createElement("td"));
row.appendChild(td);
td.observe("mousedown", listRowMouseDownHandler, true);
td.appendChild(document.createTextNode(data[i][10]));
td.appendChild(document.createTextNode(data[i][11]));
td = $(document.createElement("td"));
row.appendChild(td);
td.observe("mousedown", listRowMouseDownHandler, true);
td.appendChild(document.createTextNode(data[i][11]));
td.appendChild(document.createTextNode(data[i][12]));
td = $(document.createElement("td"));
row.appendChild(td);
@ -603,10 +628,8 @@ function scrollDayView(scrollEvent) {
var divs;
// Select event in calendar view
if (scrollEvent) {
divs = $$("div#calendarContent div." + eventClass(scrollEvent));
selectCalendarEvent(divs[0]);
}
if (scrollEvent)
selectCalendarEvent(scrollEvent);
// Don't scroll if in month view
if (currentView == "monthview")
@ -614,22 +637,23 @@ function scrollDayView(scrollEvent) {
var offset = 0;
var daysView = $("daysView");
var hours =
$(daysView.childNodesWithTag("div")[0]).childNodesWithTag("div");
var hours = $(daysView.childNodesWithTag("div")[0])
.childNodesWithTag("div");
if (scrollEvent) {
divs = $$("div#calendarContent div." + eventClass(scrollEvent));
var classes = $w(divs[0].className);
for (var i = 0; i < classes.length; i++) {
if (classes[i].startsWith("starts")) {
var starts = Math.floor(parseInt(classes[i].substr(6)) / 4);
offset = hours[starts].offsetTop;
}
// Scroll to 8 AM by default
offset = hours[8].offsetTop;
if (scrollEvent && calendarEvents) {
var event = calendarEvents[scrollEvent];
if (event) {
var classes = $w(event.siblings[0].className);
for (var i = 0; i < classes.length; i++)
if (classes[i].startsWith("starts")) {
var starts = Math.floor(parseInt(classes[i].substr(6)) / 4);
offset = hours[starts].offsetTop;
}
}
}
else
// Scroll to 8 AM
offset = hours[8].offsetTop;
daysView.scrollTop = offset - 5;
}
@ -684,7 +708,8 @@ function refreshCalendarEvents(scrollEvent) {
document.refreshCalendarEventsAjaxRequest.aborted = true;
document.refreshCalendarEventsAjaxRequest.abort();
}
var url = ApplicationBaseURL + "eventslist?sd=" + sd + "&ed=" + ed;
var url = (ApplicationBaseURL + "eventsblocks?sd=" + sd + "&ed=" + ed
+ "&view=" + currentView);
document.refreshCalendarEventsAjaxRequest
= triggerAjaxRequest(url, refreshCalendarEventsCallback,
{"startDate": sd, "endDate": ed,
@ -695,142 +720,13 @@ function refreshCalendarEventsCallback(http) {
if (http.readyState == 4
&& http.status == 200) {
if (http.responseText.length > 0) {
var data = http.responseText.evalJSON(true);
// log("refresh calendar events: " + data.length);
var dateTuples = new Array();
for (var i = 0; i < data.length; i++) {
var dates = drawCalendarEvent(data[i],
http.callbackData["startDate"],
http.callbackData["endDate"]);
dates.each(function(tuple) {
if (tuple[3] == 0) tuple[3] = 96;
dateTuples.push(tuple);
});
}
var c = {
div: 0,
day: 1,
start: 2,
end: 3,
siblingsCount: 4,
siblingsPosition: 5,
siblingsMaxCount: 6
};
for (var i = 0; i < dateTuples.length; i++) {
if (dateTuples[i].length < 6) {
dateTuples[i][c.siblingsCount] = 1;
dateTuples[i][c.siblingsPosition] = 0;
}
for (var j = 0; j < dateTuples.length; j++) {
if (j == i) continue;
if (dateTuples[i][c.day] == dateTuples[j][c.day]) {
// Same day
if (dateTuples[j][c.start] > dateTuples[i][c.start] &&
dateTuples[j][c.start] < dateTuples[i][c.end] ||
dateTuples[j][c.start] == dateTuples[i][c.start] &&
dateTuples[j][c.end] < dateTuples[i][c.end] ||
dateTuples[j][c.start] == dateTuples[i][c.start] &&
dateTuples[j][c.end] == dateTuples[i][c.end] &&
i < j) {
// Same period
if (dateTuples[j].length < 6) {
dateTuples[j][c.siblingsCount] = 2;
dateTuples[j][c.siblingsPosition] = dateTuples[i][c.siblingsPosition] + 1;
}
else {
dateTuples[j][c.siblingsCount]++;
dateTuples[j][c.siblingsPosition]++;
}
dateTuples[i][c.siblingsCount]++;
}
}
}
}
// Second loop; adjust total number of siblings for each event
for (var i = 0; i < dateTuples.length; i++) {
//log (i + " " + dateTuples[i].inspect());
var maxCount = 0;
for (var j = 0; j < dateTuples.length; j++) {
if (j == i) continue;
if (dateTuples[i][c.day] == dateTuples[j][c.day]) {
// Same day
if (dateTuples[j][c.start] > dateTuples[i][c.start] &&
dateTuples[j][c.start] < dateTuples[i][c.end] ||
dateTuples[j][c.start] == dateTuples[i][c.start] &&
dateTuples[j][c.end] < dateTuples[i][c.end] ||
dateTuples[j][c.start] == dateTuples[i][c.start] &&
dateTuples[j][c.end] == dateTuples[i][c.end] &&
i < j) {
// Same period
if (dateTuples[j][c.siblingsCount] > maxCount)
maxCount = dateTuples[j][c.siblingsCount];
}
}
}
if (maxCount > 0) {
dateTuples[i][c.siblingsCount] = maxCount;
dateTuples[i][c.siblingsMaxCount] = maxCount;
}
}
// Third loop; adjust position and total number of siblings for each event
for (var i = 0; i < dateTuples.length; i++) {
//log (i + " " + dateTuples[i].inspect());
for (var j = 0; j < dateTuples.length; j++) {
if (j == i) continue;
if (dateTuples[i][c.day] == dateTuples[j][c.day]) {
// Same day
if (dateTuples[j][c.start] > dateTuples[i][c.start] &&
dateTuples[j][c.start] < dateTuples[i][c.end] ||
dateTuples[j][c.start] == dateTuples[i][c.start] &&
dateTuples[j][c.end] < dateTuples[i][c.end] ||
dateTuples[j][c.start] == dateTuples[i][c.start] &&
dateTuples[j][c.end] == dateTuples[i][c.end] &&
i < j) {
// Overlapping period
if (dateTuples[j][c.siblingsPosition] == dateTuples[i][c.siblingsPosition]) {
// Same position
dateTuples[j][c.siblingsPosition]--; // not very clever
}
if (dateTuples[j].length < 7 ||
dateTuples[j][c.siblingsMaxCount] < dateTuples[i][c.siblingsMaxCount])
dateTuples[j][c.siblingsMaxCount] = dateTuples[i][c.siblingsMaxCount];
}
}
}
if (dateTuples[i].length < 7)
dateTuples[i][c.siblingsMaxCount] = dateTuples[i][c.siblingsCount];
}
// Final loop; draw the events
//log ("[div, day, start index, end index, siblings count, siblings position, siblings max count]");
for (var i = 0; i < dateTuples.length; i++) {
//log (i + " " + dateTuples[i].inspect());
var base = dateTuples[i][c.siblingsCount] * dateTuples[i][c.siblingsMaxCount];
var length = 1;
var maxLength = 1 * dateTuples[i][c.siblingsMaxCount];
for (var j = dateTuples[i][c.siblingsCount];
j < maxLength;
j += dateTuples[i][c.siblingsCount]) { }
if (j > maxLength) {
j -= dateTuples[i][c.siblingsCount];
}
var width = 100 * j / base;
var left = width * dateTuples[i][c.siblingsPosition];
dateTuples[i][0].setStyle({ width: width + "%",
left: left + "%" });
var eventsBlocks = http.responseText.evalJSON(true);
calendarEvents = _prepareCalendarEventsCache(eventsBlocks[0]);
if (currentView == "monthview")
_drawMonthCalendarEvents(eventsBlocks[2]);
else {
_drawCalendarAllDaysEvents(eventsBlocks[1]);
_drawCalendarEvents(eventsBlocks[2]);
}
}
scrollDayView(http.callbackData["scrollEvent"]);
@ -839,133 +735,42 @@ function refreshCalendarEventsCallback(http) {
log("AJAX error when refreshing calendar events");
}
function drawCalendarEvent(eventData, sd, ed) {
var dateTuples = new Array();
function _prepareCalendarEventsCache(events) {
var cache = {};
// log ("drawCalendarEvent...");
var viewStartDate = sd.asDate();
var viewEndDate = ed.asDate();
for (var i = 0; i < events.length; i++) {
cache[events[i][0]] = events[i];
}
var startDate = new Date();
startDate.setTime(eventData[4] * 1000);
var endDate = new Date();
endDate.setTime(eventData[5] * 1000);
return cache;
}
// log ("s: " + startDate + "; e: " + endDate);
var days = startDate.daysUpTo(endDate);
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.getUTCHours() * 4
+ Math.floor(startDate.getUTCMinutes() / 15));
starts = quarters;
startHour = startDate.getDisplayHoursString();
endHour = endDate.getDisplayHoursString();
}
else
starts = 0;
var ends;
var lasts;
if (i == days.length - 1) {
var quarters = (endDate.getUTCHours() * 4
+ Math.ceil(endDate.getUTCMinutes() / 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;
if (eventData[9].length > 0)
eventDiv.addClassName(eventData[9]); // event owner status
//eventDiv.setStyle({ width: '50%' });
if (currentView != "monthview" &&
eventData[7] == 0) // not "all day"
dateTuples.push(new Array(eventDiv, days[i].getDayString(), starts, ends));
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 _drawCalendarAllDaysEvents(events) {
var daysView = $("calendarHeader");
var subdivs = daysView.childNodesWithTag("div");
var days = subdivs[1].childNodesWithTag("div");
for (var i = 0; i < events.length; i++) {
var parentDiv = days[i];
for (var j = 0; j < events[i].length; j++) {
var eventRep = events[i][j];
var eventDiv = newAllDayEventDIV(eventRep);
parentDiv.appendChild(eventDiv);
}
return dateTuples;
}
}
function eventClass(cname) {
return escape(cname.replace(".", "-"));
}
function newEventDIV(cname, calendar, starts, lasts,
startHour, endHour, title) {
function newAllDayEventDIV(eventRep) {
// cname, calendar, starts, lasts,
// startHour, endHour, title) {
var eventDiv = document.createElement("div");
eventDiv.cname = escape(cname);
eventDiv.calendar = calendar;
var event = calendarEvents[eventRep.cname];
if (!event.siblings)
event.siblings = [];
eventDiv.event = event;
eventDiv.cname = event[0];
eventDiv.calendar = event[1];
$(eventDiv).addClassName("event");
$(eventDiv).addClassName(eventClass(cname));
$(eventDiv).addClassName("starts" + starts);
$(eventDiv).addClassName("lasts" + lasts);
for (var i = 1; i < 5; i++) {
var shadowDiv = document.createElement("div");
eventDiv.appendChild(shadowDiv);
@ -975,7 +780,7 @@ function newEventDIV(cname, calendar, starts, lasts,
var innerDiv = document.createElement("div");
eventDiv.appendChild(innerDiv);
$(innerDiv).addClassName("eventInside");
$(innerDiv).addClassName("calendarFolder" + calendar);
$(innerDiv).addClassName("calendarFolder" + event[1]);
var gradientDiv = document.createElement("div");
innerDiv.appendChild(gradientDiv);
@ -987,20 +792,151 @@ function newEventDIV(cname, calendar, starts, lasts,
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));
textDiv.appendChild(document.createTextNode(event[3]));
eventDiv.observe("mousedown", listRowMouseDownHandler);
eventDiv.observe("click", onCalendarSelectEvent);
eventDiv.observe("dblclick", editDoubleClickedEvent);
event.siblings.push(eventDiv);
return eventDiv;
}
function _drawCalendarEvents(events) {
var daysView = $("daysView");
var subdivs = daysView.childNodesWithTag("div");
var days = subdivs[1].childNodesWithTag("div");
for (var i = 0; i < events.length; i++) {
var parentDiv = days[i].childNodesWithTag("div")[0];
for (var j = 0; j < events[i].length; j++) {
var eventRep = events[i][j];
var eventDiv = newEventDIV(eventRep);
parentDiv.appendChild(eventDiv);
}
}
}
function newEventDIV(eventRep) {
// cname, calendar, starts, lasts,
// startHour, endHour, title) {
var eventDiv = document.createElement("div");
var event = calendarEvents[eventRep.cname];
if (!event.siblings)
event.siblings = [];
eventDiv.event = event;
eventDiv.cname = event[0];
eventDiv.calendar = event[1];
$(eventDiv).addClassName("event");
// $(eventDiv).addClassName(eventClass(cname));
$(eventDiv).addClassName("starts" + eventRep.start);
$(eventDiv).addClassName("lasts" + eventRep.length);
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("calendarFolder" + event[1]);
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(event[3]));
var pc = 100 / eventRep.siblings;
eventDiv.style.width = pc + "%";
var left = eventRep.position * pc;
eventDiv.style.left = left + "%";
eventDiv.observe("mousedown", listRowMouseDownHandler);
eventDiv.observe("click", onCalendarSelectEvent);
eventDiv.observe("dblclick", editDoubleClickedEvent);
event.siblings.push(eventDiv);
return eventDiv;
}
function _drawMonthCalendarEvents(events) {
var daysView = $("monthDaysView");
var days = daysView.childNodesWithTag("div");
for (var i = 0; i < days.length; i++) {
var parentDiv = days[i];
for (var j = 0; j < events[i].length; j++) {
var eventRep = events[i][j];
var eventDiv = newMonthEventDIV(eventRep);
parentDiv.appendChild(eventDiv);
}
}
}
function newMonthEventDIV(eventRep) {
// cname, calendar, starts, lasts,
// startHour, endHour, title) {
var eventDiv = document.createElement("div");
var event = calendarEvents[eventRep.cname];
if (!event.siblings)
event.siblings = [];
eventDiv.event = event;
eventDiv.cname = event[0];
eventDiv.calendar = event[1];
$(eventDiv).addClassName("event");
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("calendarFolder" + event[1]);
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("textw");
var eventText;
if (event[7])
eventText = event[3];
else
eventText = eventRep.starthour + " - " + event[3];
textDiv.appendChild(document.createTextNode(eventText));
eventDiv.observe("mousedown", listRowMouseDownHandler);
eventDiv.observe("click", onCalendarSelectEvent);
eventDiv.observe("dblclick", editDoubleClickedEvent);
event.siblings.push(eventDiv);
return eventDiv;
}
@ -1021,7 +957,7 @@ function calendarDisplayCallback(http) {
contentView = $("calendarContent");
else
contentView = $("daysView");
refreshCalendarEvents(http.callbackData.scrollEvent);
var days = document.getElementsByClassName("day", contentView);
@ -1270,22 +1206,30 @@ function onYearMenuItemClick(event) {
changeDateSelectorDisplay(year + month + "01", true);
}
function selectCalendarEvent(div) {
function selectCalendarEvent(cname) {
// Select event in calendar view
if (selectedCalendarCell)
for (var i = 0; i < selectedCalendarCell.length; i++)
selectedCalendarCell[i].deselect();
for (var i = 0; i < div.siblings.length; i++)
div.siblings[i].selectElement();
selectedCalendarCell = div.siblings;
if (calendarEvents) {
var event = calendarEvents[cname];
// if (event) {
// if (event[12])
// log("recurrence; date=" + event[4]);
// }
if (event && event.siblings) {
for (var i = 0; i < event.siblings.length; i++)
event.siblings[i].selectElement();
selectedCalendarCell = event.siblings;
}
}
}
function onCalendarSelectEvent() {
var list = $("eventsList");
selectCalendarEvent(this);
selectCalendarEvent(this.cname);
// Select event in events list
$(list.tBodies[0]).deselectAll();
@ -1298,11 +1242,7 @@ function onCalendarSelectEvent() {
}
function onCalendarSelectDay(event) {
var day;
if (currentView == "multicolumndayview")
day = this.getAttribute("day");
else
day = this.getAttribute("day");
var day = this.getAttribute("day");
var needRefresh = (listFilter == 'view_selectedday'
&& day != currentDay);
@ -1322,22 +1262,23 @@ function onCalendarSelectDay(event) {
}
function changeWeekCalendarDisplayOfSelectedDay(node) {
var days = document.getElementsByClassName("day", node.parentNode);
var daysView = $("daysView");
var daysDiv = daysView.childNodesWithTag("div");
var days = daysDiv[1].childNodesWithTag("div");
var headerDiv = $("calendarHeader").childNodesWithTag("div")[1];
var headerDays = document.getElementsByClassName("day", headerDiv);
var headerDays = $(headerDiv).childNodesWithTag("div");
// log ("days: " + days.length + "; headerDays: " + headerDays.length);
for (var i = 0; i < days.length; i++)
if (days[i] != node) {
// log("unselect day : " + i);
headerDays[i].removeClassName("selectedDay");
days[i].removeClassName("selectedDay");
}
else {
// log("selected day : " + i);
for (var i = 0; i < days.length; i++) {
if (days[i] == node
|| headerDays[i] == node) {
headerDays[i].addClassName("selectedDay");
days[i].addClassName("selectedDay");
}
else {
headerDays[i].removeClassName("selectedDay");
days[i].removeClassName("selectedDay");
}
}
}
function findMonthCalendarSelectedCell(daysContainer) {
@ -1400,7 +1341,7 @@ function updateTaskStatus(event) {
}
function updateCalendarStatus(event) {
var list = new Array();
var list = [];
var newStatus = (this.checked ? 1 : 0);
if (isSafari() && !isSafari3()) {
@ -1525,12 +1466,12 @@ function onCalendarsMenuPrepareVisibility() {
function getMenus() {
var menus = {};
var dateMenu = new Array();
var dateMenu = [];
for (var i = 0; i < 12; i++)
dateMenu.push(onMonthMenuItemClick);
menus["monthListMenu"] = dateMenu;
dateMenu = new Array();
dateMenu = [];
for (var i = 0; i < 11; i++)
dateMenu.push(onYearMenuItemClick);
menus["yearListMenu"] = dateMenu;
@ -1830,7 +1771,7 @@ function initDateSelectorEvents() {
arrow.observe("click", onDateSelectorGotoMonth);
arrow = $("leftArrow");
arrow.observe("click", onDateSelectorGotoMonth);
var menuButton = $("monthLabel");
menuButton.observe("click", popupMonthMenu);
menuButton = $("yearLabel");