sogo/UI/WebServerResources/SchedulerUIDnD.js
Wolfgang Sourdeau 9e193f560d Monotone-Parent: 4015c6e667a4a4ca4d9a5b2a8cb346ea6d784fe4
Monotone-Revision: a33e5080dbd3082529a4559b78a962ccc535f5c9

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2010-08-02T20:42:53
Monotone-Branch: ca.inverse.sogo
2010-08-02 20:42:53 +00:00

1366 lines
49 KiB
JavaScript

/* bind method: attachToEventCells(cells), attachToDayNode(dayNode)
* callback method: updateDropCallback(this, eventCells, delta),
createDropCallback(this, dayDate, currentCoordinates);
*/
var SOGoEventDragDayLength = 24 * 4; /* quarters */
var SOGoEventDragHandleSize = 8; /* handles for dragging mode */
var SOGoEventDragHorizontalOffset = 3;
var SOGoEventDragVerticalOffset = 3;
/* singleton */
var _sogoEventDragUtilities = null;
function SOGoEventDragUtilities() {
if (!_sogoEventDragUtilities)
_sogoEventDragUtilities = new _SOGoEventDragUtilities();
return _sogoEventDragUtilities;
}
function _SOGoEventDragUtilities() {
}
_SOGoEventDragUtilities.prototype = {
eventType: null,
eventContainerNodes: null,
_prepareEventContainerNodes: null,
quarterHeight: -1,
dayWidth: -1,
dayHeight: -1,
daysOffset: -1,
eventsViewNode: null,
eventsViewNodeCumulativeCoordinates: null,
reset: function() {
this.eventContainerNodes = null;
this._prepareEventContainerNodes = null;
this.quarterHeight = -1;
this.dayWidth = -1;
this.dayHeight = -1;
this.daysOffset = -1;
this.eventsViewNode = null;
this.eventsViewNodeCumulativeCoordinates = null;
},
setEventType: function(eventType) {
var prepareMethods
= { "multiday": this._prepareEventMultiDayContainerNodes,
"multiday-allday": this._prepareEventMultiDayAllDayContainerNodes,
"monthly": this._prepareEventMonthlyContainerNodes,
"unknown": null };
this._prepareEventContainerNodes = prepareMethods[eventType];
this.eventType = eventType;
},
getEventType: function(eventType) {
return this.eventType;
},
getEventContainerNodes: function() {
if (!this.eventContainerNodes) {
this._prepareEventContainerNodes();
}
return this.eventContainerNodes;
},
_prepareEventMultiDayContainerNodes: function() {
this.eventContainerNodes = [];
var daysView = $("daysView");
var daysViewSubnodes = daysView.childNodesWithTag("div");
for (var i = 0; i < daysViewSubnodes.length; i++) {
var daysViewSubnode = daysViewSubnodes[i];
if (daysViewSubnode.hasClassName("days")) {
this.daysOffset = daysViewSubnode.offsetLeft + 2;
var daysSubnodes = daysViewSubnode.childNodesWithTag("div");
for (var j = 0; j < daysSubnodes.length; j++) {
var daysSubnode = daysSubnodes[j];
if (daysSubnode.hasClassName("day")) {
this._appendDayEventsNode(daysSubnode);
}
}
}
}
},
_prepareEventMultiDayAllDayContainerNodes: function() {
this.eventContainerNodes = [];
var headerNode = $("calendarHeader");
var headerSubnodes = headerNode.childNodesWithTag("div");
for (var i = 0; i < headerSubnodes.length; i++) {
var headerSubnode = headerSubnodes[i];
if (headerSubnode.hasClassName("days")) {
this.daysOffset = headerSubnode.offsetLeft + 2;
var daysSubnodes = headerSubnode.childNodesWithTag("div");
for (var j = 0; j < daysSubnodes.length; j++) {
var daysSubnode = daysSubnodes[j];
if (daysSubnode.hasClassName("day"))
this.eventContainerNodes.push(daysSubnode);
}
}
}
},
_prepareEventMonthlyContainerNodes: function() {
var monthView = $("monthDaysView");
this.eventContainerNodes = monthView.childNodesWithTag("div");
this.daysOffset = this.eventContainerNodes[0].offsetLeft + 2;
},
_appendDayEventsNode: function(dayNode) {
var daySubnodes = dayNode.childNodesWithTag("div");
for (var i = 0; i < daySubnodes.length; i++) {
var daySubnode = daySubnodes[i];
if (daySubnode.hasClassName("events")) {
this.eventContainerNodes.push(daySubnode);
}
}
},
getQuarterHeight: function() {
if (this.quarterHeight == -1) {
var hour0 = $("hour0");
var hour23 = $("hour23");
this.quarterHeight = ((hour23.offsetTop - hour0.offsetTop)
/ (23 * 4));
}
return this.quarterHeight;
},
getDaysOffset: function() {
if (this.daysOffset == -1)
this._prepareEventContainerNodes();
return this.daysOffset;
},
getDayWidth: function() {
if (this.dayWidth == -1) {
var nodes = this.getEventContainerNodes();
if (nodes.length > 1) {
if (this.eventType == "monthly") {
var total = (nodes[6].cumulativeOffset()[0]
- nodes[0].cumulativeOffset()[0]);
this.dayWidth = total / 6;
} else {
var total = (nodes[nodes.length-1].cumulativeOffset()[0]
- nodes[0].cumulativeOffset()[0]);
this.dayWidth = total / (nodes.length - 1);
}
}
else
this.dayWidth = nodes[0].offsetWidth;
}
return this.dayWidth;
},
getDayHeight: function() {
/* currently only used for monthly view */
if (this.dayHeight == -1) {
var nodes = this.getEventContainerNodes();
if (nodes.length > 1) {
var total = (nodes[3*7].cumulativeOffset()[1]
- nodes[0].cumulativeOffset()[1]);
this.dayHeight = total / 3;
}
}
return this.dayHeight;
},
getEventsViewNode: function() {
if (!this.eventsViewNode) {
if (this.eventType.startsWith("multiday"))
this.eventsViewNode = $("daysView");
else if (this.eventType.startsWith("multiday-allday")) {
this.eventsViewNode = $("calendarHeader");
}
else
this.eventsViewNode = $("monthDaysView");
}
return this.eventsViewNode;
},
getEventsViewNodeCumulativeCoordinates: function() {
if (!this.eventsViewNodeCumulativeCoordinates) {
this.eventsViewNodeCumulativeCoordinates = new SOGoCoordinates();
var node = this.getEventsViewNode();
var cumulativeOffset = node.cumulativeOffset();
this.eventsViewNodeCumulativeCoordinates.x = cumulativeOffset[0];
this.eventsViewNodeCumulativeCoordinates.y = cumulativeOffset[1];
}
return this.eventsViewNodeCumulativeCoordinates;
}
};
function SOGoEventDragEventCoordinates() {
}
SOGoEventDragEventCoordinates.prototype = {
dayNumber: -1,
start: -1,
duration: -1,
eventType: null,
setEventType: function(eventType) {
this.eventType = eventType;
this._prepareEventType();
},
_prepareEventType: function() {
var methods
= { "multiday": this.initFromEventCellMultiDay,
"multiday-allday": this.initFromEventCellMultiDayAllDay,
"monthly": this.initFromEventCellMonthly,
"unknown": null };
this.initFromEventCell = methods[this.eventType];
},
initFromEventCellMultiDay: function(eventCell) {
var classNames = eventCell.className.split(" ");
for (var i = 0;
(this.start == -1 || this.duration == -1)
&& i < classNames.length;
i++) {
var className = classNames[i];
if (className.startsWith("starts")) {
this.start = parseInt(className.substr(6));
}
else if (className.startsWith("lasts")) {
this.duration = parseInt(className.substr(5));
}
}
var dayNumber = -1;
var dayNode = eventCell.parentNode.parentNode;
var classNames = dayNode.className.split(" ");
for (var i = 0; dayNumber == -1 && i < classNames.length; i++) {
var className = classNames[i];
if (className.startsWith("day") && className.length > 3) {
dayNumber = parseInt(className.substr(3));
}
}
this.dayNumber = dayNumber;
},
initFromEventCellMultiDayAllDay: function(eventCell) {
this.start = 0;
this.duration = SOGoEventDragDayLength;
var dayNode = eventCell.parentNode;
var classNames = dayNode.className.split(" ");
var dayNumber = -1;
for (var i = 0; dayNumber == -1 && i < classNames.length; i++) {
var className = classNames[i];
if (className.startsWith("day") && className.length > 3) {
dayNumber = parseInt(className.substr(3));
}
}
this.dayNumber = dayNumber;
},
initFromEventCellMonthly: function(eventCell) {
this.start = 0;
this.duration = SOGoEventDragDayLength;
var dayNumber = -1;
var week = -1;
var day = -1;
var dayNode = eventCell.parentNode;
var classNames = dayNode.className.split(" ");
for (var i = 0;
(day == -1 || week == -1)
&& i < classNames.length;
i++) {
var className = classNames[i];
if (className.startsWith("day") && className.length > 3) {
day = parseInt(className.substr(3));
} else if (className.startsWith("week")
&& !className.startsWith("weekOf")
&& className != "weekEndDay") {
var ofIndex = className.indexOf("of");
if (ofIndex > -1) {
var len = ofIndex - 4;
week = parseInt(className.substr(4, len));
}
}
}
this.dayNumber = week * 7 + day;
},
initFromEventCells: function(eventCells) {
this.duration = 0;
for (var i = 0; i < eventCells.length; i++) {
var current = new SOGoEventDragEventCoordinates();
current.setEventType(this.eventType);
current.initFromEventCell(eventCells[i]);
if (this.dayNumber == -1 || current.dayNumber < this.dayNumber) {
this.dayNumber = current.dayNumber;
this.start = current.start;
}
this.duration += current.duration;
}
},
getDelta: function(otherCoordinates) {
var delta = new SOGoEventDragEventCoordinates();
delta.dayNumber = (this.dayNumber - otherCoordinates.dayNumber);
delta.start = (this.start - otherCoordinates.start);
delta.duration = (this.duration - otherCoordinates.duration);
return delta;
},
_quartersToHM: function(quarters) {
var minutes = quarters * 15;
var hours = Math.floor(minutes / 60);
if (hours < 10)
hours = "0" + hours;
var mins = minutes % 60;
if (mins < 10)
mins = "0" + mins;
return "" + hours + ":" + mins;
},
getStartTime: function() {
return this._quartersToHM(this.start);
},
getEndTime: function() {
var end = (this.start + this.duration) % SOGoEventDragDayLength;
return this._quartersToHM(end);
},
clone: function() {
var coordinates = new SOGoEventDragEventCoordinates();
coordinates.dayNumber = this.dayNumber;
coordinates.start = this.start;
coordinates.duration = this.duration;
return coordinates;
}
};
var SOGoDragGhostInterface = {
visible: true,
title: null,
folderClass: null,
inside: null,
currentStart: -1,
currentDuration: -1,
isStartGhost: false,
isEndGhost: false,
show: function SDGI_show() {
if (!this.visible) {
this.removeClassName("hidden");
if (this.inside)
this.inside.removeClassName("hidden");
this.visible = true;
}
},
hide: function SDGI_hide() {
if (this.visible) {
this.addClassName("hidden");
if (this.inside)
this.inside.addClassName("hidden");
this.visible = false;
}
},
setTitle: function SDGI_setTitle(title) {
if (this.title != title) {
while (this.inside.childNodes.length) {
this.inside.removeChild(this.inside.firstChild);
}
if (title) {
this.inside.appendChild(document.createTextNode(title));
}
this.title = title;
}
},
setLocation: function SDGI_setLocation(location) {
if (this.location != location) {
var spans = this.inside.select("SPAN.location");
if (spans && spans.length > 0) {
this.inside.removeChild(spans[0]);
}
if (location) {
this.inside.appendChild(createElement("br"));
var span = createElement("span", null, "location");
span.appendChild(document.createTextNode(location));
this.inside.appendChild(span);
}
this.location = location;
}
},
setFolderClass: function SDGI_setFolderClass(folderClass) {
if (this.folderClass != folderClass) {
this.removeClassName(this.folderClass);
this.folderClass = folderClass;
this.addClassName(this.folderClass);
}
},
setStart: function SDGI_setStart(start) {
if (this.currentStart != start) {
if (this.cssHandlesPosition)
this.removeClassName("starts" + this.currentStart);
this.currentStart = start;
if (this.cssHandlesPosition)
this.addClassName("starts" + this.currentStart);
}
},
setDuration: function SDGI_setDuration(duration) {
if (this.currentDuration != duration) {
if (this.cssHandlesPosition)
this.removeClassName("lasts" + this.currentDuration);
this.currentDuration = duration;
if (this.cssHandlesPosition)
this.addClassName("lasts" + this.currentDuration);
}
},
setStartGhost: function SDGI_setStartGhost() {
if (!this.isStartGhost) {
this.addClassName("startGhost");
this.isStartGhost = true;
}
},
unsetStartGhost: function SDGI_unsetStartGhost() {
if (this.isStartGhost) {
this.removeClassName("startGhost");
this.isStartGhost = false;
}
},
setEndGhost: function SDGI_setEndGhost() {
if (!this.isEndGhost) {
this.addClassName("endGhost");
this.isEndGhost = true;
}
},
unsetEndGhost: function SDGI_unsetEndGhost() {
if (this.isEndGhost) {
this.removeClassName("endGhost");
this.isEndGhost = false;
}
}
};
function SOGoEventDragGhostController() {
}
SOGoEventDragGhostController.prototype = {
originalCoordinates: null,
currentCoordinates: null,
originalPointerCoordinates: null,
currentPointerCoordinates: null,
dragMode: null,
startHourPara: null,
endHourPara: null,
ghosts: null,
initWithCoordinates: function SEDGC_initWithCoordinates(coordinates) {
this.originalCoordinates = coordinates;
this.currentCoordinates = coordinates.clone();
},
setTitle: function SEDGC_setTitle(title) {
this.eventTitle = title;
},
setLocation: function SEDGC_setLocation(location) {
this.eventLocation = location;
},
setFolderClass: function SEDGC_setFolderClass(folderClass) {
this.folderClass = folderClass;
},
setDragMode: function SEDGC_setDragMode(dragMode) {
this.dragMode = dragMode;
},
setPointerHandler: function SEDGC_setPointerHandler(pointerHandler) {
this.pointerHandler = pointerHandler;
this.originalPointerCoordinates = null;
this.currentPointerCoordinates = null;
this.updateFromPointerHandler();
this.originalPointerCoordinates = this.currentPointerCoordinates.clone();
},
updateFromPointerHandler: function SEDGC_updateFromPointerHandler() {
var newCoordinates = this.pointerHandler.getEventViewCoordinates();
if (!this.currentPointerCoordinates
|| !newCoordinates
|| newCoordinates.x != this.currentPointerCoordinates.x
|| newCoordinates.y != this.currentPointerCoordinates.y) {
this.currentPointerCoordinates = newCoordinates;
if (this.originalPointerCoordinates) {
if (!newCoordinates)
this.currentPointerCoordinates
= this.originalPointerCoordinates.clone();
this._updateCoordinates();
if (this.ghosts) {
this._updateGhosts();
if (this.startHourPara)
this._updateGhostsParas();
}
}
}
},
_updateCoordinates: function SEDGC__updateCoordinates() {
var delta = this.currentPointerCoordinates
.getDelta(this.originalPointerCoordinates);
var deltaQuarters = delta.x * SOGoEventDragDayLength + delta.y;
this.currentCoordinates.dayNumber = this.originalCoordinates.dayNumber;
// log("dragMode: " + this.dragMode);
if (this.dragMode == "move-event") {
this.currentCoordinates.start
= this.originalCoordinates.start + deltaQuarters;
this.currentCoordinates.duration
= this.originalCoordinates.duration;
// log("start: " + this.currentCoordinates.start);
// log(" duration: " + this.currentCoordinates.duration);
} else {
if (this.dragMode == "change-start") {
var newDuration = this.originalCoordinates.duration - deltaQuarters;
if (newDuration > 0) {
this.currentCoordinates.start
= this.originalCoordinates.start + deltaQuarters;
this.currentCoordinates.duration = newDuration;
} else if (newDuration < 0) {
this.currentCoordinates.start
= (this.originalCoordinates.start
+ this.originalCoordinates.duration);
this.currentCoordinates.duration = -newDuration;
}
} else if (this.dragMode == "change-end") {
var newDuration = this.originalCoordinates.duration + deltaQuarters;
if (newDuration > 0) {
this.currentCoordinates.start = this.originalCoordinates.start;
this.currentCoordinates.duration = newDuration;
} else if (newDuration < 0) {
this.currentCoordinates.start
= this.originalCoordinates.start + newDuration;
this.currentCoordinates.duration = -newDuration;
}
}
}
if (this.currentCoordinates.start < 0) {
var deltaDays = Math.ceil(-this.currentCoordinates.start
/ SOGoEventDragDayLength);
this.currentCoordinates.start += deltaDays * SOGoEventDragDayLength;
this.currentCoordinates.dayNumber -= deltaDays;
} else if (this.currentCoordinates.start >= SOGoEventDragDayLength) {
var deltaDays = Math.floor(this.currentCoordinates.start
/ SOGoEventDragDayLength);
this.currentCoordinates.start -= deltaDays * SOGoEventDragDayLength;
this.currentCoordinates.dayNumber += deltaDays;
}
},
showGhosts: function SEDGC_showGhosts() {
if (!this.ghosts) {
this.ghosts = [];
var utilities = SOGoEventDragUtilities();
var nodes = utilities.getEventContainerNodes();
var isMultiday = (utilities.getEventType() == "multiday");
for (var i = 0; i < nodes.length; i++) {
var newGhost = $(document.createElement("div"));
Object.extend(newGhost, SOGoDragGhostInterface);
newGhost.className = "event eventDragGhost";
newGhost.cssHandlesPosition = isMultiday;
newGhost.hide();
var ghostInside = $(document.createElement("div"));
ghostInside.className = "eventInside";
newGhost.inside = ghostInside;
newGhost.appendChild(ghostInside);
nodes[i].appendChild(newGhost);
this.ghosts.push(newGhost);
}
if (isMultiday) {
var ghostHourPara = $(document.createElement("div"));
ghostHourPara.setAttribute("id", "ghostStartHour");
this.startHourPara = ghostHourPara;
ghostHourPara = $(document.createElement("div"));
ghostHourPara.setAttribute("id", "ghostEndHour");
this.endHourPara = ghostHourPara;
}
this._updateGhosts();
if (this.startHourPara)
this._updateGhostsParas();
}
},
hideGhosts: function SEDGC_hideGhosts() {
if (this.ghosts) {
if (this.startHourPara && this.startHourPara.parentNode)
this.startHourPara.parentNode.removeChild(this.startHourPara);
this.startHourPara = null;
if (this.endHourPara && this.endHourPara.parentNode)
this.endHourPara.parentNode.removeChild(this.endHourPara);
this.endHourPara = null;
for (var i = 0; i < this.ghosts.length; i++) {
var ghost = this.ghosts[i];
ghost.parentNode.removeChild(ghost);
}
this.ghosts = null;
}
},
_updateGhosts: function SEDGC__updateGhosts() {
var maxGhosts = this.ghosts.length;
var max = this.currentCoordinates.dayNumber;
if (max > maxGhosts)
max = maxGhosts;
for (var i = 0; i < max; i++) {
var ghost = this.ghosts[i];
ghost.hide();
ghost.unsetStartGhost();
ghost.unsetEndGhost();
}
if (this.currentCoordinates.dayNumber < maxGhosts) {
var currentDay = this.currentCoordinates.dayNumber;
var durationLeft = this.currentCoordinates.duration;
var start = this.currentCoordinates.start;
var maxDuration = SOGoEventDragDayLength - start;
var duration = durationLeft;
if (duration > maxDuration)
duration = maxDuration;
var ghost = null;
if (currentDay > -1) {
ghost = this.ghosts[currentDay];
ghost.setStartGhost();
ghost.unsetEndGhost();
ghost.setTitle(this.eventTitle);
ghost.setLocation(this.eventLocation);
ghost.setFolderClass(this.folderClass);
ghost.setStart(this.currentCoordinates.start);
ghost.setDuration(duration);
ghost.show();
if (this.startHourPara) {
var parentNode = this.startHourPara.parentNode;
if (parentNode && parentNode != ghost)
parentNode.removeChild(this.startHourPara);
ghost.appendChild(this.startHourPara);
}
}
durationLeft -= duration;
currentDay++;
while (durationLeft && currentDay < maxGhosts) {
duration = durationLeft;
if (duration > SOGoEventDragDayLength)
duration = SOGoEventDragDayLength;
if (currentDay > -1) {
ghost = this.ghosts[currentDay];
ghost.unsetStartGhost();
ghost.unsetEndGhost();
ghost.setTitle();
ghost.setFolderClass(this.folderClass);
ghost.setStart(0);
ghost.setDuration(duration);
ghost.show();
}
durationLeft -= duration;
currentDay++;
}
if (!durationLeft) {
ghost.setEndGhost();
}
if (this.endHourPara) {
var parentNode = this.endHourPara.parentNode;
if (parentNode && parentNode != ghost)
parentNode.removeChild(this.endHourPara);
ghost.appendChild(this.endHourPara);
}
while (currentDay < maxGhosts) {
var ghost = this.ghosts[currentDay];
ghost.hide();
ghost.unsetStartGhost();
ghost.unsetEndGhost();
currentDay++;
}
}
},
_updateGhostsParas: function SEDGC__updateGhostsParas() {
var para = this.startHourPara;
while (para.childNodes.length)
para.removeChild(para.childNodes[0]);
var time = this.currentCoordinates.getStartTime();
para.appendChild(document.createTextNode(time));
para = this.endHourPara;
while (para.childNodes.length)
para.removeChild(para.childNodes[0]);
time = this.currentCoordinates.getEndTime();
para.appendChild(document.createTextNode(time));
}
};
function SOGoCoordinates() {
}
SOGoCoordinates.prototype = {
x: -1,
y: -1,
getDelta: function SC_getDelta(otherCoordinates) {
var delta = new SOGoCoordinates();
delta.x = this.x - otherCoordinates.x;
delta.y = this.y - otherCoordinates.y;
return delta;
},
getDistance: function SC_getDistance(otherCoordinates) {
var delta = this.getDelta(otherCoordinates);
return Math.sqrt(delta.x * delta.x + delta.y * delta.y);
},
clone: function SC_clone() {
var coordinates = new SOGoCoordinates();
coordinates.x = this.x;
coordinates.y = this.y;
return coordinates;
}
};
function SOGoEventDragPointerHandler() {
}
SOGoEventDragPointerHandler.prototype = {
originalCoordinates: null,
currentCoordinates: null,
containerCoordinates: null,
/* return the day and quarter coordinates of the pointer cursor within the
day view */
getEventViewCoordinates: null,
initFromEvent: function SEDPH_initFromEvent(event) {
this.currentCoordinates = new SOGoCoordinates();
this.updateFromEvent(event);
this.originalCoordinates = this.currentCoordinates.clone();
var utilities = SOGoEventDragUtilities();
this.containerCoordinates = utilities.getEventsViewNodeCumulativeCoordinates();
if (utilities.getEventType() == "multiday-allday") {
/* a hack */
this.containerCoordinates.x -= SOGoEventDragVerticalOffset;
this.containerCoordinates.y -= 40;
}
},
updateFromEvent: function SEDPH_updateFromEvent(event) {
this.currentCoordinates.x = Event.pointerX(event);
this.currentCoordinates.y = Event.pointerY(event);
},
getContainerBasedCoordinates: function SEDPH_getCBC() {
var coordinates = this.currentCoordinates.getDelta(this.containerCoordinates);
var container = SOGoEventDragUtilities().getEventsViewNode();
if (coordinates.x < 0 || coordinates.x > container.clientWidth
|| coordinates.y < 0 || coordinates.y > container.clientHeight)
coordinates = null;
return coordinates;
},
prepareWithEventType: function SEDPH_prepareWithEventType(eventType) {
var methods = { "multiday": this.getEventMultiDayViewCoordinates,
"multiday-allday": this.getEventMultiDayAllDayViewCoordinates,
"monthly": this.getEventMonthlyViewCoordinates,
"unknown": null };
var method = methods[eventType];
this.getEventViewCoordinates = method;
},
getEventMultiDayViewCoordinates: function SEDPH_gEMultiDayViewC() {
var coordinates = this.getEventMultiDayAllDayViewCoordinates();
if (coordinates) {
var utilities = SOGoEventDragUtilities();
var quarterHeight = utilities.getQuarterHeight();
var container = utilities.getEventsViewNode();
var pxCoordinates = this.getContainerBasedCoordinates();
pxCoordinates.y += container.scrollTop;
coordinates.y = Math.floor((pxCoordinates.y
- SOGoEventDragHorizontalOffset)
/ quarterHeight);
var maxY = SOGoEventDragDayLength - 1;
if (coordinates.y < 0)
coordinates.y = 0;
else if (coordinates.y > maxY)
coordinates.y = maxY;
}
return coordinates;
},
getEventMultiDayAllDayViewCoordinates: function SEDPH_gEMultiDayADVC() {
/* x = day; y = quarter */
var coordinates;
var pxCoordinates = this.getContainerBasedCoordinates();
if (pxCoordinates) {
coordinates = new SOGoCoordinates();
var utilities = SOGoEventDragUtilities();
var dayWidth = utilities.getDayWidth();
var daysOffset = utilities.getDaysOffset();
coordinates.x = Math.floor((pxCoordinates.x - daysOffset) / dayWidth);
var maxX = utilities.getEventContainerNodes().length - 1;
if (coordinates.x < 0)
coordinates.x = 0;
else if (coordinates.x > maxX)
coordinates.x = maxX;
coordinates.y = 0;
} else {
coordinates = null;
}
// logOnly("coordinates.x: " + coordinates.x);
return coordinates;
},
getEventMonthlyViewCoordinates: function SEDPH_gEMonthlyViewC() {
/* x = day; y = quarter */
var coordinates;
var pxCoordinates = this.getContainerBasedCoordinates();
if (pxCoordinates) {
coordinates = new SOGoCoordinates();
var utilities = SOGoEventDragUtilities();
var daysOffset = utilities.getDaysOffset();
var daysTopOffset = daysOffset; /* change later */
var dayHeight = utilities.getDayHeight();
var daysY = Math.floor((pxCoordinates.y - daysTopOffset) / dayHeight);
if (daysY < 0)
daysY = 0;
var dayWidth = utilities.getDayWidth();
coordinates.x = Math.floor((pxCoordinates.x - daysOffset) / dayWidth);
if (coordinates.x < 0)
coordinates.x = 0;
else if (coordinates.x > 6)
coordinates.x = 6;
coordinates.x += 7 * daysY;
coordinates.y = 0;
} else {
coordinates = null;
}
return coordinates;
},
getDistance: function SEDPH_getDistance() {
return this.currentCoordinates.getDistance(this.originalCoordinates);
}
};
function SOGoScrollController() {
this.init();
}
SOGoScrollController.prototype = {
pointerHandler: null,
scrollView: null,
lastScroll: 0,
scrollStep: 0,
init: function SSC_init() {
var utilities = SOGoEventDragUtilities();
this.scrollView = utilities.getEventsViewNode();
this.scrollStep = 6 * utilities.getQuarterHeight();
},
setPointerHandler: function SSC_setPointerHandler(pointerHandler) {
this.pointerHandler = pointerHandler;
},
updateFromPointerHandler: function SSC_updateFromPointerHandler() {
var pointerCoordinates
= this.pointerHandler.getContainerBasedCoordinates();
if (pointerCoordinates) {
var now = new Date().getTime();
if (!this.lastScroll || now > this.lastScroll + 100) {
this.lastScroll = now;
var scrollY = pointerCoordinates.y - this.scrollStep;
if (scrollY < 0) {
var minY = -this.scrollView.scrollTop;
if (scrollY < minY)
scrollY = minY;
this.scrollView.scrollTop += scrollY;
} else {
scrollY = pointerCoordinates.y + this.scrollStep;
var delta = scrollY - this.scrollView.clientHeight;
if (delta > 0) {
this.scrollView.scrollTop += delta;
}
}
}
}
}
};
function SOGoEventDragController() {
}
SOGoEventDragController.prototype = {
eventCells: null,
eventType: null,
eventIsInvitation: false,
title: null,
folderClass: null,
draggingModeAreas: null,
ghostController: null,
hasSelected: false,
dragHasStarted: false,
dragMode: null,
originalDayNumber: -1,
pointerHandler: null,
dropCallback: null,
onDragStartBound: null,
onDragStopBound: null,
onDragModeBound: null,
_determineDragMode: null,
attachToEventCells: function SEDC_attachToEventCells(eventCells) {
this.eventCells = eventCells;
this.ghostController = new SOGoEventDragGhostController();
this._determineEventInvitation(eventCells[0]);
this._determineEventType(eventCells[0]);
this._prepareEventType();
this._determineTitleAndFolderClass();
this.ghostController.setTitle(this.title);
this.ghostController.setLocation(this.location);
this.ghostController.setFolderClass(this.folderClass);
this.onDragStartBound = this.onDragStart.bindAsEventListener(this);
for (var i = 0; i < eventCells.length; i++) {
eventCells[i].observe("mousedown", this.onDragStartBound, false);
if (eventCells[i].editable && !this.eventIsInvitation) {
eventCells[i].addClassName("draggable");
}
}
if (this.eventType == "multiday") {
var topDragGrip = $(document.createElement("div"));
topDragGrip.addClassName("topDragGrip");
eventCells[0].appendChild(topDragGrip);
var bottomDragGrip = $(document.createElement("div"));
bottomDragGrip.addClassName("bottomDragGrip");
eventCells[eventCells.length-1].appendChild(bottomDragGrip);
} else {
var leftDragGrip = $(document.createElement("div"));
leftDragGrip.addClassName("leftDragGrip");
eventCells[0].appendChild(leftDragGrip);
var rightDragGrip = $(document.createElement("div"));
rightDragGrip.addClassName("rightDragGrip");
eventCells[eventCells.length-1].appendChild(rightDragGrip);
}
},
attachToDayNode: function SEDC_attachToDayNode(dayNode) {
this._determineEventType(dayNode);
this._prepareEventType();
this.ghostController = new SOGoEventDragGhostController();
this.ghostController.setTitle(_("New Event"));
this.onDragStartBound = this.onDragStart.bindAsEventListener(this);
dayNode.observe("mousedown", this.onDragStartBound, false);
},
onDragStart: function SEDC_onDragStart(event) {
var target = getTarget(event);
if (eventIsLeftClick(event) && (target.nodeType == 1)) {
if ((!this.eventCells
&& (target.hasClassName("clickableHourCell")
|| target.hasClassName("day"))
&& (target.scrollHeight - target.clientHeight <= 1))
|| (this.eventCells && this.eventCells[0].editable
&& !this.eventIsInvitation)) {
var utilities = SOGoEventDragUtilities();
utilities.setEventType(this.eventType);
this.pointerHandler = new SOGoEventDragPointerHandler();
this.pointerHandler.prepareWithEventType(this.eventType);
this.pointerHandler.initFromEvent(event);
var coordinates = new SOGoEventDragEventCoordinates();
coordinates.setEventType(this.eventType);
if (this.eventCells) {
coordinates.initFromEventCells(this.eventCells);
} else {
var eventViewCoordinates
= this.pointerHandler.getEventViewCoordinates();
coordinates.dayNumber = eventViewCoordinates.x;
coordinates.start = eventViewCoordinates.y;
coordinates.duration = 1;
}
this.ghostController.initWithCoordinates(coordinates);
if (!this.eventCells) {
var folder = getSelectedFolder();
var folderID = folder.readAttribute("id").substr(1);
this.ghostController.setFolderClass("calendarFolder" + folderID);
}
this.ghostController.setDragMode(this._determineDragMode());
this.ghostController.setPointerHandler(this.pointerHandler);
if (this.eventType == "multiday") {
this.scrollController = new SOGoScrollController();
this.scrollController.setPointerHandler(this.pointerHandler);
}
this.onDragStopBound
= this.onDragStop.bindAsEventListener(this);
if (Prototype.Browser.IE)
Event.observe(document.body,
"mouseup", this.onDragStopBound);
else
Event.observe(window, "mouseup", this.onDragStopBound);
this.onDragModeBound = this.onDragMode.bindAsEventListener(this);
Event.observe(document.body, "mousemove", this.onDragModeBound);
Event.stop(event);
}
}
return false;
},
_determineEventInvitation: function SEDC__determineEventType(node) {
var isInvitation = false;
for (var i = 0; !isInvitation && i < userStates.length; i++) {
var inside = node.select("DIV.eventInside")[0];
if (inside.hasClassName(userStates[i]))
isInvitation = true;
}
this.eventIsInvitation = isInvitation;
},
_determineEventType: function SEDC__determineEventType(node) {
var type = "unknown";
var dayNode;
var currentNode = node;
while (!currentNode.hasClassName("day"))
currentNode = currentNode.parentNode;
dayNode = currentNode;
// log("dayNode: " + dayNode.className);
var secondParent = dayNode.parentNode;
// log("secondParent: " + secondParent.className);
if (secondParent.id == "monthDaysView") {
type = "monthly";
} else {
var thirdParent = secondParent.parentNode;
// log("thirdParent: " + thirdParent.id);
if (thirdParent.id == "calendarHeader")
type = "multiday-allday";
else if (thirdParent.id == "daysView")
type = "multiday";
}
// log("type: " + type);
this.eventType = type;
},
_prepareEventType: function SEDC__prepareEventType() {
var methods
= { "multiday": this._determineDragModeMultiDay,
"multiday-allday": this._determineDragModeMultiDayAllDay,
"monthly": this._determineDragModeMonthly,
"unknown": null };
this._determineDragMode = methods[this.eventType];
},
_determineDragModeMultiDay: function SEDC__determineDragModeMultiDay() {
var dragMode;
if (this.eventCells) {
var coordinates = this.pointerHandler.currentCoordinates.clone();
var utilities = SOGoEventDragUtilities();
var scrollView = utilities.getEventsViewNode();
coordinates.y += scrollView.scrollTop;
coordinates.y -= SOGoEventDragVerticalOffset;
var firstCell = this.eventCells[0];
var handleCoords = firstCell.cumulativeOffset();
dragMode = "move-event";
if ((handleCoords[0] <= coordinates.x
&& coordinates.x <= handleCoords[0] + firstCell.clientWidth)
&& (handleCoords[1] <= coordinates.y
&& coordinates.y <= handleCoords[1] + SOGoEventDragHandleSize))
dragMode = "change-start";
else {
var lastCell = this.eventCells[this.eventCells.length-1];
handleCoords = lastCell.cumulativeOffset();
handleCoords[1] += (lastCell.clientHeight
- SOGoEventDragHandleSize - 1);
if ((handleCoords[0] <= coordinates.x
&& coordinates.x <= handleCoords[0] + lastCell.clientWidth)
&& (handleCoords[1] <= coordinates.y
&& coordinates.y <= handleCoords[1] + SOGoEventDragHandleSize))
dragMode = "change-end";
}
} else {
dragMode = "change-end";
}
return dragMode;
},
_determineDragModeMultiDayAllDay: function SEDC__detDMMultiDayAllDay() {
var dragMode;
if (this.eventCells) {
var coordinates = this.pointerHandler.currentCoordinates.clone();
coordinates.x -= SOGoEventDragHorizontalOffset;
coordinates.y -= SOGoEventDragVerticalOffset;
var firstCell = this.eventCells[0];
var handleCoords = firstCell.cumulativeOffset();
dragMode = "move-event";
if (handleCoords[0] <= coordinates.x
&& coordinates.x <= handleCoords[0] + SOGoEventDragHandleSize)
dragMode = "change-start";
else {
var lastCell = this.eventCells[this.eventCells.length-1];
handleCoords = lastCell.cumulativeOffset();
handleCoords[0] += lastCell.clientWidth;
if (handleCoords[0] - SOGoEventDragHandleSize <= coordinates.x
&& coordinates.x <= handleCoords[0])
dragMode = "change-end";
}
} else {
dragMode = "change-end";
}
return dragMode;
},
_determineDragModeMonthly: function SEDC__determineDragModeMultiDay() {
var dragMode;
if (this.eventCells) {
var coordinates = this.pointerHandler.currentCoordinates.clone();
coordinates.x -= SOGoEventDragHorizontalOffset;
coordinates.y -= SOGoEventDragVerticalOffset;
var firstCell = this.eventCells[0];
var handleCoords = firstCell.cumulativeOffset();
dragMode = "move-event";
var eventHeight = 16; /* arbitrary value */
if (handleCoords[1] <= coordinates.y
&& coordinates.y <= handleCoords[1] + eventHeight
&& handleCoords[0] <= coordinates.x
&& coordinates.x <= handleCoords[0] + SOGoEventDragHandleSize)
dragMode = "change-start";
else {
var lastCell = this.eventCells[this.eventCells.length-1];
handleCoords = lastCell.cumulativeOffset();
handleCoords[0] += lastCell.clientWidth;
if (handleCoords[1] <= coordinates.y
&& coordinates.y <= handleCoords[1] + eventHeight
&& handleCoords[0] - SOGoEventDragHandleSize <= coordinates.x
&& coordinates.x <= handleCoords[0])
dragMode = "change-end";
}
} else {
dragMode = "change-end";
}
return dragMode;
},
_determineTitleAndFolderClass: function SEDC__dTAFC() {
var title = "";
var folderClass = "";
var location = null;
if (this.eventCells) {
var firstCell = this.eventCells[0];
var divs = firstCell.childNodesWithTag("div");
for (var i = 0; i < divs.length; i++) {
var div = divs[i];
if (div.hasClassName("eventInside")) {
var titleDIV = this._determineTitleDIV(div);
if (titleDIV) {
title = this._determineTitleFromDIV(titleDIV);
location = this._determineLocationFromDIV(titleDIV);
}
folderClass = this._determineFolderClassFromDIV(div);
}
}
}
this.title = title;
this.location = location;
this.folderClass = folderClass;
},
_determineTitleDIV: function SEDC__determineTitleDIV(div) {
var titleDIV = null;
var insideDivs = div.childNodesWithTag("div");
for (var i = 0; titleDIV == null && i < insideDivs.length; i++) {
var insideDiv = insideDivs[i];
if (insideDiv.hasClassName("text")) {
titleDIV = insideDiv;
}
}
return titleDIV;
},
_determineTitleFromDIV: function SEDC__determineTitleFromDIV(titleDIV) {
var title = "";
var currentNode = titleDIV.firstChild;
while (currentNode) {
if (currentNode.nodeType == Node.TEXT_NODE) {
title += currentNode.nodeValue;
}
currentNode = currentNode.nextSibling;
}
return title.trim();
},
_determineLocationFromDIV: function SEDC__determineLocationFromDIV(titleDIV) {
var location = "";
var spans = titleDIV.select("span.location");
if (spans && spans.length > 0) {
var locationSPAN = spans[0];
var currentNode = locationSPAN.firstChild;
while (currentNode) {
if (currentNode.nodeType == Node.TEXT_NODE) {
location += currentNode.nodeValue;
}
currentNode = currentNode.nextSibling;
}
}
return location.trim();
},
_determineFolderClassFromDIV: function SEDC__detFolderClassFromDIV(div) {
var folderClass = null;
var classes = div.className.split(" ");
for (var i = 0; folderClass == null && i < classes.length; i++) {
var currentClass = classes[i];
if (currentClass.startsWith("calendarFolder")) {
folderClass = currentClass;
}
}
return folderClass;
},
onDragStop: function SEDC_onDragStop(event) {
if (Prototype.Browser.IE)
Event.stopObserving(document.body, "mouseup", this.onDragStopBound);
else
Event.stopObserving(window, "mouseup", this.onDragStopBound);
Event.stopObserving(document.body, "mousemove", this.onDragModeBound);
this.onDragStopBound = null;
this.onDragModeBound = null;
var utilities = SOGoEventDragUtilities();
if (this.dragHasStarted) {
this.ghostController.hideGhosts();
this.dragHasStarted = false;
if (this.eventCells) {
for (var i = 0; i < this.eventCells.length; i++) {
var currentCell = this.eventCells[i];
currentCell.removeClassName("dragging");
}
var delta = this.ghostController
.currentCoordinates
.getDelta(this.ghostController
.originalCoordinates);
this.updateDropCallback(this, this.eventCells, delta);
} else {
var eventContainerNodes = utilities.getEventContainerNodes();
var dayNode = eventContainerNodes[this.ghostController
.currentCoordinates
.dayNumber];
if (dayNode.hasClassName("events"))
dayNode = dayNode.parentNode;
this.createDropCallback(this,
dayNode.readAttribute("day"),
this.ghostController.currentCoordinates);
}
}
utilities.reset();
Event.stop(event);
},
_coordinateToTime: function SEDC_coordinateToTime(coordinate) {
var hours = Math.floor(coordinate / 4);
var minutes = (coordinate % 4) * 15;
if (minutes < 10)
minutes = "0" + minutes;
var time = hours + ":" + minutes;
return time;
},
onDragMode: function SEDC_onDragMode(event) {
this.pointerHandler.updateFromEvent(event);
if (this.scrollController)
this.scrollController.updateFromPointerHandler();
if (this.dragHasStarted) {
this.ghostController.updateFromPointerHandler();
} else {
var distance = this.pointerHandler.getDistance();
if (distance > 3) {
$("eventDialog").hide();
this.dragHasStarted = true;
if (this.eventCells) {
for (var i = 0; i < this.eventCells.length; i++) {
var currentCell = this.eventCells[i];
currentCell.addClassName("dragging");
}
}
this.ghostController.showGhosts();
this.ghostController.updateFromPointerHandler();
}
}
Event.stop(event);
}
};