Monotone-Parent: 8494d73eddd971425d160f71b9402b3e05217405
Monotone-Revision: e9991645e03e37c7b75619ac4070814a2b6e9ad8 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2008-03-27T21:05:47 Monotone-Branch: ca.inverse.sogomaint-2.0.2
parent
9fc6aa568e
commit
00565ecbaf
2
NEWS
2
NEWS
|
@ -5,8 +5,10 @@
|
|||
- pressing enter in the contact edition dialog will perform the creation/update operation
|
||||
- implemented more of the CalDAV specification for compatibility with Lightning 0.8
|
||||
- added Italian translation, thanks to Marco Lertora
|
||||
- added initial logic for splitting overlapping events
|
||||
- improved restoration of drag handles state
|
||||
- improved contextual menu handling of Address Book module
|
||||
- fixed time/date control widget of attendees editor
|
||||
- fixed various bugs occuring with Safari 3.1
|
||||
- monthly events would not be returned properly
|
||||
- bi-weekly events would appear every week instead
|
||||
|
|
|
@ -99,12 +99,14 @@
|
|||
<div><var:string label:value="Start:"
|
||||
/><var:component className="UIxTimeDateControl"
|
||||
const:controlID="startTime"
|
||||
date="aptStartDate"
|
||||
const:dayStartHour="0"
|
||||
const:dayEndHour="23"
|
||||
/></div>
|
||||
<div><var:string label:value="End:"
|
||||
/><var:component className="UIxTimeDateControl"
|
||||
const:controlID="endTime"
|
||||
date="aptEndDate"
|
||||
const:dayStartHour="0"
|
||||
const:dayEndHour="23"
|
||||
/></div>
|
||||
|
|
|
@ -703,9 +703,134 @@ function refreshCalendarEventsCallback(http) {
|
|||
// log("refresh calendar events: " + data.length);
|
||||
var dateTuples = new Array();
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
drawCalendarEvent(data[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] ){
|
||||
// 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 + "%" });
|
||||
}
|
||||
}
|
||||
scrollDayView(http.callbackData["scrollEvent"]);
|
||||
|
@ -715,6 +840,8 @@ function refreshCalendarEventsCallback(http) {
|
|||
}
|
||||
|
||||
function drawCalendarEvent(eventData, sd, ed) {
|
||||
var dateTuples = new Array();
|
||||
|
||||
var viewStartDate = sd.asDate();
|
||||
var viewEndDate = ed.asDate();
|
||||
|
||||
|
@ -775,6 +902,10 @@ function drawCalendarEvent(eventData, sd, ed) {
|
|||
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;
|
||||
|
@ -817,6 +948,8 @@ function drawCalendarEvent(eventData, sd, ed) {
|
|||
if (parentDiv)
|
||||
parentDiv.appendChild(eventDiv);
|
||||
}
|
||||
|
||||
return dateTuples;
|
||||
}
|
||||
|
||||
function eventClass(cname) {
|
||||
|
|
|
@ -68,7 +68,7 @@ function performSearch() {
|
|||
}
|
||||
if (currentField.value.trim().length > 0) {
|
||||
var urlstr = ( UserFolderURL + "Contacts/contactSearch?search="
|
||||
+ escape(currentField.value) ); log (urlstr);
|
||||
+ escape(currentField.value) );
|
||||
document.contactLookupAjaxRequest =
|
||||
triggerAjaxRequest(urlstr, performSearchCallback, currentField);
|
||||
}
|
||||
|
@ -465,14 +465,17 @@ function synchronizeWithParent(srcWidgetName, dstWidgetName) {
|
|||
var srcDate = parent$(srcWidgetName + "_date");
|
||||
var dstDate = $(dstWidgetName + "_date");
|
||||
dstDate.value = srcDate.value;
|
||||
dstDate.updateShadowValue(srcDate);
|
||||
|
||||
var srcHour = parent$(srcWidgetName + "_time_hour");
|
||||
var dstHour = $(dstWidgetName + "_time_hour");
|
||||
dstHour.value = srcHour.value;
|
||||
dstHour.updateShadowValue(srcHour);
|
||||
|
||||
var srcMinute = parent$(srcWidgetName + "_time_minute");
|
||||
var dstMinute = $(dstWidgetName + "_time_minute");
|
||||
dstMinute.value = srcMinute.value;
|
||||
dstMinute.updateShadowValue(dstMinute);
|
||||
}
|
||||
|
||||
function updateParentDateFields(srcWidgetName, dstWidgetName) {
|
||||
|
@ -489,36 +492,23 @@ function updateParentDateFields(srcWidgetName, dstWidgetName) {
|
|||
dstMinute.value = srcMinute.value;
|
||||
}
|
||||
|
||||
function initializeTimeWidgets() {
|
||||
synchronizeWithParent("startTime", "startTime");
|
||||
synchronizeWithParent("endTime", "endTime");
|
||||
|
||||
Event.observe($("startTime_date"), "change", onTimeDateWidgetChange, false);
|
||||
Event.observe($("startTime_time_hour"), "change", onTimeWidgetChange, false);
|
||||
Event.observe($("startTime_time_minute"), "change", onTimeWidgetChange, false);
|
||||
|
||||
Event.observe($("endTime_date"), "change", onTimeDateWidgetChange, false);
|
||||
Event.observe($("endTime_time_hour"), "change", onTimeWidgetChange, false);
|
||||
Event.observe($("endTime_time_minute"), "change", onTimeWidgetChange, false);
|
||||
}
|
||||
|
||||
function onTimeWidgetChange() {
|
||||
redisplayFreeBusyZone();
|
||||
}
|
||||
|
||||
function onTimeDateWidgetChange(event) {
|
||||
var table = $("freeBusy");
|
||||
|
||||
var rows = table.tHead.rows;
|
||||
function onTimeDateWidgetChange() {
|
||||
var table = $("freeBusyHeader");
|
||||
var rows = table.select("tr");
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
for (var j = rows[i].cells.length - 1; j > 0; j--) {
|
||||
for (var j = rows[i].cells.length - 1; j > -1; j--) {
|
||||
rows[i].deleteCell(j);
|
||||
}
|
||||
}
|
||||
|
||||
rows = table.tBodies[0].rows;
|
||||
table = $("freeBusyData");
|
||||
rows = table.select("tr");
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
for (var j = rows[i].cells.length - 1; j > 0; j--) {
|
||||
for (var j = rows[i].cells.length - 1; j > -1; j--) {
|
||||
rows[i].deleteCell(j);
|
||||
}
|
||||
}
|
||||
|
@ -662,8 +652,18 @@ function onScroll(event) {
|
|||
}
|
||||
|
||||
function onFreeBusyLoadHandler() {
|
||||
var widgets = {'start': {'date': $("startTime_date"),
|
||||
'hour': $("startTime_time_hour"),
|
||||
'minute': $("startTime_time_minute")},
|
||||
'end': {'date': $("endTime_date"),
|
||||
'hour': $("endTime_time_hour"),
|
||||
'minute': $("endTime_time_minute")}};
|
||||
|
||||
synchronizeWithParent("startTime", "startTime");
|
||||
synchronizeWithParent("endTime", "endTime");
|
||||
|
||||
initTimeWidgets(widgets);
|
||||
initializeWindowButtons();
|
||||
initializeTimeWidgets();
|
||||
prepareTableHeaders();
|
||||
prepareTableRows();
|
||||
redisplayFreeBusyZone();
|
||||
|
@ -674,3 +674,123 @@ function onFreeBusyLoadHandler() {
|
|||
}
|
||||
|
||||
FastInit.addOnLoad(onFreeBusyLoadHandler);
|
||||
|
||||
/* Functions related to UIxTimeDateControl widget */
|
||||
|
||||
function initTimeWidgets(widgets) {
|
||||
this.timeWidgets = widgets;
|
||||
|
||||
assignCalendar('startTime_date');
|
||||
assignCalendar('endTime_date');
|
||||
|
||||
Event.observe(widgets['start']['date'], "change",
|
||||
this.onAdjustTime, false);
|
||||
Event.observe(widgets['start']['hour'], "change",
|
||||
this.onAdjustTime, false);
|
||||
Event.observe(widgets['start']['minute'], "change",
|
||||
this.onAdjustTime, false);
|
||||
|
||||
Event.observe(widgets['end']['date'], "change",
|
||||
this.onAdjustTime, false);
|
||||
Event.observe(widgets['end']['hour'], "change",
|
||||
this.onAdjustTime, false);
|
||||
Event.observe(widgets['end']['minute'], "change",
|
||||
this.onAdjustTime, false);
|
||||
|
||||
var allDayLabel = $("allDay");
|
||||
if (allDayLabel) {
|
||||
var input = $(allDayLabel).childNodesWithTag("input")[0];
|
||||
Event.observe(input, "change", onAllDayChanged.bindAsEventListener(input));
|
||||
if (input.checked) {
|
||||
for (var type in widgets) {
|
||||
widgets[type]['hour'].disabled = true;
|
||||
widgets[type]['minute'].disabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onAdjustTime(event) {
|
||||
var endDate = window.getEndDate();
|
||||
var startDate = window.getStartDate();
|
||||
if ($(this).readAttribute("id").startsWith("start")) {
|
||||
// Start date was changed
|
||||
var delta = window.getShadowStartDate().valueOf() -
|
||||
startDate.valueOf();
|
||||
var newEndDate = new Date(endDate.valueOf() - delta);
|
||||
window.setEndDate(newEndDate);
|
||||
window.timeWidgets['end']['date'].updateShadowValue();
|
||||
window.timeWidgets['end']['hour'].updateShadowValue();
|
||||
window.timeWidgets['end']['minute'].updateShadowValue();
|
||||
window.timeWidgets['start']['date'].updateShadowValue();
|
||||
window.timeWidgets['start']['hour'].updateShadowValue();
|
||||
window.timeWidgets['start']['minute'].updateShadowValue();
|
||||
}
|
||||
else {
|
||||
// End date was changed
|
||||
var delta = endDate.valueOf() - startDate.valueOf();
|
||||
if (delta < 0) {
|
||||
alert(labels.validate_endbeforestart);
|
||||
var oldEndDate = window.getShadowEndDate();
|
||||
window.setEndDate(oldEndDate);
|
||||
|
||||
window.timeWidgets['end']['date'].updateShadowValue();
|
||||
window.timeWidgets['end']['hour'].updateShadowValue();
|
||||
window.timeWidgets['end']['minute'].updateShadowValue();
|
||||
}
|
||||
}
|
||||
|
||||
// Specific function for the attendees editor
|
||||
onTimeDateWidgetChange();
|
||||
}
|
||||
|
||||
function _getDate(which) {
|
||||
var date = window.timeWidgets[which]['date'].valueAsDate();
|
||||
date.setHours( window.timeWidgets[which]['hour'].value );
|
||||
date.setMinutes( window.timeWidgets[which]['minute'].value );
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
function getStartDate() {
|
||||
return this._getDate('start');
|
||||
}
|
||||
|
||||
function getEndDate() {
|
||||
return this._getDate('end');
|
||||
}
|
||||
|
||||
function _getShadowDate(which) {
|
||||
var date = window.timeWidgets[which]['date'].getAttribute("shadow-value").asDate();
|
||||
var intValue = parseInt(window.timeWidgets[which]['hour'].getAttribute("shadow-value"));
|
||||
date.setHours(intValue);
|
||||
intValue = parseInt(window.timeWidgets[which]['minute'].getAttribute("shadow-value"));
|
||||
date.setMinutes(intValue);
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
function getShadowStartDate() {
|
||||
return this._getShadowDate('start');
|
||||
}
|
||||
|
||||
function getShadowEndDate() {
|
||||
return this._getShadowDate('end');
|
||||
}
|
||||
|
||||
function _setDate(which, newDate) {
|
||||
window.timeWidgets[which]['date'].setValueAsDate(newDate);
|
||||
window.timeWidgets[which]['hour'].value = newDate.getHours();
|
||||
var minutes = newDate.getMinutes();
|
||||
if (minutes % 15)
|
||||
minutes += (15 - minutes % 15);
|
||||
window.timeWidgets[which]['minute'].value = minutes;
|
||||
}
|
||||
|
||||
function setStartDate(newStartDate) {
|
||||
this._setDate('start', newStartDate);
|
||||
}
|
||||
|
||||
function setEndDate(newEndDate) {
|
||||
this._setDate('end', newEndDate);
|
||||
}
|
||||
|
|
|
@ -185,7 +185,7 @@ this._getDate = function(which) {
|
|||
date.setMinutes( window.timeWidgets[which]['minute'].value );
|
||||
|
||||
return date;
|
||||
}
|
||||
};
|
||||
|
||||
this._getShadowDate = function(which) {
|
||||
var date = window.timeWidgets[which]['date'].getAttribute("shadow-value").asDate();
|
||||
|
@ -196,23 +196,23 @@ this._getDate = function(which) {
|
|||
// window.alert("shadow: " + date);
|
||||
|
||||
return date;
|
||||
}
|
||||
};
|
||||
|
||||
this.getStartDate = function() {
|
||||
return this._getDate('start');
|
||||
}
|
||||
};
|
||||
|
||||
this.getDueDate = function() {
|
||||
return this._getDate('due');
|
||||
}
|
||||
};
|
||||
|
||||
this.getShadowStartDate = function() {
|
||||
return this._getShadowDate('start');
|
||||
}
|
||||
};
|
||||
|
||||
this.getShadowDueDate = function() {
|
||||
return this._getShadowDate('due');
|
||||
}
|
||||
};
|
||||
|
||||
this._setDate = function(which, newDate) {
|
||||
window.timeWidgets[which]['date'].setValueAsDate(newDate);
|
||||
|
@ -221,16 +221,20 @@ this._getDate = function(which) {
|
|||
if (minutes % 15)
|
||||
minutes += (15 - minutes % 15);
|
||||
window.timeWidgets[which]['minute'].value = minutes;
|
||||
}
|
||||
};
|
||||
|
||||
this.setStartDate = function(newStartDate) {
|
||||
this._setDate('start', newStartDate);
|
||||
}
|
||||
};
|
||||
|
||||
this.setDueDate = function(newDueDate) {
|
||||
// window.alert(newDueDate);
|
||||
this._setDate('due', newDueDate);
|
||||
}
|
||||
};
|
||||
|
||||
this.onAdjustTime = function(event) {
|
||||
onAdjustDueTime(event);
|
||||
};
|
||||
|
||||
this.onAdjustDueTime = function(event) {
|
||||
if (!window.timeWidgets['due']['date'].disabled) {
|
||||
|
@ -242,7 +246,7 @@ this._getDate = function(which) {
|
|||
window.timeWidgets['start']['date'].updateShadowValue();
|
||||
window.timeWidgets['start']['hour'].updateShadowValue();
|
||||
window.timeWidgets['start']['minute'].updateShadowValue();
|
||||
}
|
||||
};
|
||||
|
||||
this.initTimeWidgets = function (widgets) {
|
||||
this.timeWidgets = widgets;
|
||||
|
@ -250,7 +254,7 @@ this._getDate = function(which) {
|
|||
Event.observe(widgets['start']['date'], "change", this.onAdjustDueTime, false);
|
||||
Event.observe(widgets['start']['hour'], "change", this.onAdjustDueTime, false);
|
||||
Event.observe(widgets['start']['minute'], "change", this.onAdjustDueTime, false);
|
||||
}
|
||||
};
|
||||
|
||||
function onStatusListChange(event) {
|
||||
var value = $("statusList").value;
|
||||
|
@ -294,6 +298,14 @@ function onTaskEditorLoad() {
|
|||
assignCalendar('dueTime_date');
|
||||
assignCalendar('statusTime_date');
|
||||
|
||||
var widgets = {'start': {'date': $("startTime_date"),
|
||||
'hour': $("startTime_time_hour"),
|
||||
'minute': $("startTime_time_minute")},
|
||||
'due': {'date': $("dueTime_date"),
|
||||
'hour': $("dueTime_time_hour"),
|
||||
'minute': $("dueTime_time_minute")}};
|
||||
initTimeWidgets(widgets);
|
||||
|
||||
initializeStatusLine();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue