Monotone-Parent: 14183e9d9367b240b6e0585031a87772c952285a

Monotone-Revision: 6550d093f75808cf03c8781a80f346a0cedf836a

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2010-02-11T02:36:43
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2010-02-11 02:36:43 +00:00
parent e350c7b90b
commit cceeebc234
21 changed files with 1530 additions and 197 deletions

View File

@ -1,3 +1,48 @@
2010-02-10 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* UI/WebServerResources/SchedulerUI.js (newEvent): removed the
useless "sender" parameter and added "day", "hour" and "duration"
parameters to obtain a more generic method.
(newEventFromWidget): new method the previous "newEvent" incarnation.
(minutesToHM): new method that converts an amount of minutes into
a string value suitable for an "hm" query parameter.
(newEventFromDragging): new method suitable as a drag and drop
callback for creating events.
(updateEventFromDragging): new method suitable as a drag and drop
callback for adjusting events.
(_setupEventsDragAndDrop): new method that setups drag and drop
controllers for instances of events per calendar.
(attachDragControllers): new method that instantiate a drag and
drop controller for each day column.
* UI/Scheduler/UIxCalListingActions.m
(_fillBlocks:withEvent:withNumber:): work around the situation
where the event start would occur after its end, causing a crash.
Still emits a warning.
* UI/Scheduler/UIxCalDayTable.m (-currentHourLineId): new method
replacing "currentHourLineClass". The hour identifier now being
the value of the element id, the hourline classes are populated
from the template itself.
* UI/WebServerResources/generic.js (generateQueryString): adjusted
method to take only "string" and "number" typed values into
account when constructing URL parameters.
* UI/WebServerResources/SchedulerUIDnD.js: new js module with
classes implementing drag and drop of events.
* UI/Scheduler/UIxOccurenceDialog.m (-confirmAdjustmentMethod):
new method for displaying a dialog suitable for start and duration
adjustments.
* UI/Scheduler/UIxAppointmentActions.m (-adjustAction): new method
that takes a "days", a "start" and a "duration" relative
parameters to adjust the current event or occurrence.
* UI/Scheduler/UIxAppointmentActions.[hm]: new module implementing
a WODirectAction class for ajax calls for appointments.
2010-02-03 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* UI/MainUI/SOGoRootPage.m (-_standardDefaultAction): add an

View File

@ -36,6 +36,7 @@ SchedulerUI_OBJC_FILES = \
UIxAttendeesEditor.m \
UIxComponentEditor.m \
UIxCalendarSelector.m \
UIxAppointmentActions.m \
UIxAppointmentEditor.m \
UIxTaskEditor.m \
UIxDatePicker.m \

View File

@ -2,13 +2,13 @@
( { link = "#";
isSafe = NO;
label = "New Event";
onclick = "return newEvent(this, 'event');";
onclick = "return newEvent('event');";
image = "new-event.png";
tooltip = "Create a new event"; },
{ link = "new_task";
label="New Task";
image = "new-task.png";
onclick = "return newEvent(this, 'task');";
onclick = "return newEvent('task');";
image = "new-task.png";
tooltip = "Create a new task"; } ),
( { link = "today";

View File

@ -0,0 +1,32 @@
/* UIxAppointmentActions.h - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
*
* 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.
*/
#ifndef UIXAPPOINTMENTACTIONS_H
#define UIXAPPOINTMENTACTIONS_H
#import <NGObjWeb/WODirectAction.h>
@interface UIxAppointmentActions : WODirectAction
@end
#endif /* UIXAPPOINTMENTACTIONS_H */

View File

@ -0,0 +1,97 @@
/* UIxAppointmentActions.m - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
*
* 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/NSCalendarDate.h>
#import <Foundation/NSString.h>
#import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WORequest.h>
#import <NGCards/iCalEvent.h>
#import <SOGo/NSCalendarDate+SOGo.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserDefaults.h>
#import <Appointments/SOGoAppointmentObject.h>
#import <Common/WODirectAction+SOGo.h>
#import "UIxAppointmentActions.h"
@implementation UIxAppointmentActions
- (WOResponse *) adjustAction
{
WOResponse *response;
WORequest *rq;
SOGoAppointmentObject *co;
iCalEvent *event;
NSCalendarDate *start, *newStart, *end, *newEnd;
NSTimeInterval newDuration;
SOGoUserDefaults *ud;
NSString *daysDelta, *startDelta, *durationDelta;
NSTimeZone *tz;
rq = [context request];
daysDelta = [rq formValueForKey: @"days"];
startDelta = [rq formValueForKey: @"start"];
durationDelta = [rq formValueForKey: @"duration"];
if ([daysDelta length] > 0
|| [startDelta length] > 0 || [durationDelta length] > 0)
{
co = [self clientObject];
event = (iCalEvent *) [[self clientObject] occurence];
ud = [[context activeUser] userDefaults];
tz = [ud timeZone];
start = [event startDate];
[start setTimeZone: tz];
newStart = [start dateByAddingYears: 0 months: 0
days: [daysDelta intValue]
hours: 0 minutes: [startDelta intValue]
seconds: 0];
end = [event endDate];
[end setTimeZone: tz];
newDuration = ([end timeIntervalSinceDate: start]
+ [durationDelta intValue] * 60);
newEnd = [newStart addTimeInterval: newDuration];
[event setStartDate: newStart];
[event setEndDate: newEnd];
[co saveComponent: event];
response = [self responseWith204];
}
else
response
= (WOResponse *) [NSException exceptionWithHTTPStatus: 400
reason: @"missing 'days', 'start' and/or 'duration' parameters"];
return response;
}
@end

View File

@ -244,7 +244,7 @@
NSCalendarDate *startDate, *endDate;
NSString *duration;
NSTimeZone *timeZone;
unsigned int minutes;
unsigned int total, hours, minutes;
SOGoObject <SOGoComponentOccurence> *co;
SOGoUserDefaults *ud;
@ -258,14 +258,21 @@
&& [co isKindOfClass: [SOGoCalendarComponent class]])
{
startDate = [self newStartDate];
duration = [self queryParameterForKey:@"dur"];
duration = [self queryParameterForKey:@"duration"];
if ([duration length] > 0)
minutes = [duration intValue];
{
total = [duration intValue];
hours = total / 100;
minutes = total % 100;
}
else
minutes = 60;
{
hours = 1;
minutes = 0;
}
endDate
= [startDate dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: minutes seconds: 0];
hours: hours minutes: minutes seconds: 0];
}
else
{

View File

@ -143,9 +143,9 @@
return hoursToDisplay;
}
- (NSString *) currentHourLineClass
- (NSString *) currentHourLineId
{
return [NSString stringWithFormat: @"hourLine hourLine%d", [currentTableHour intValue]];
return [NSString stringWithFormat: @"hourLine%d", [currentTableHour intValue]];
}
- (NSArray *) daysToDisplay

View File

@ -649,7 +649,7 @@ _userStateInEvent (NSArray *event)
withNumber: (NSNumber *) number
{
int currentDayStart, startSecs, endsSecs, currentStart, eventStart,
eventEnd, offset, recurrenceTime;
eventEnd, offset, recurrenceTime, swap;
NSMutableArray *currentDay;
NSMutableDictionary *eventBlock;
iCalPersonPartStat userState;
@ -667,8 +667,13 @@ _userStateInEvent (NSArray *event)
else
{
if (eventEnd < eventStart)
[self warnWithFormat: @"event '%@' has end < start: %d < %d",
[event objectAtIndex: 0], eventEnd, eventStart];
{
swap = eventStart;
eventStart = eventEnd;
eventEnd = swap;
[self warnWithFormat: @"event '%@' has end < start: %d < %d",
[event objectAtIndex: 0], eventEnd, eventStart];
}
startSecs = (unsigned int) [startDate timeIntervalSince1970];
endsSecs = (unsigned int) [endDate timeIntervalSince1970];

View File

@ -87,6 +87,13 @@
return self;
}
- (id <WOActionResults>) confirmAdjustmentAction
{
ASSIGN (action, @"adjust");
return self;
}
- (WOResponse *) deleteAction
{
SOGoCalendarComponent *component;

View File

@ -232,9 +232,14 @@
};
delegate = {
protectedBy = "RespondToComponent";
actionClass = "UIxAppointmentEditor";
pageName = "UIxAppointmentEditor";
actionName = "delegate";
};
adjust = {
protectedBy = "ModifyComponent";
actionClass = "UIxAppointmentActions";
actionName = "adjust";
};
};
};
@ -283,6 +288,11 @@
protectedBy = "ViewAllComponent";
pageName = "UIxOccurenceDialog";
};
confirmAdjustment = {
protectedBy = "ViewAllComponent";
pageName = "UIxOccurenceDialog";
actionName = "confirmAdjustment";
};
confirmDeletion = {
protectedBy = "Delete Object";
pageName = "UIxOccurenceDialog";
@ -313,6 +323,11 @@
pageName = "UIxOccurenceDialog";
actionName = "delete";
};
adjust = {
protectedBy = "ModifyComponent";
actionClass = "UIxAppointmentActions";
actionName = "adjust";
};
};
};

View File

@ -50,7 +50,7 @@
<div class="hourLines">
<var:foreach list="hoursToDisplay" item="currentTableHour"
><div var:class="currentHourLineClass"><!-- space --></div
><div var:id="currentHourLineId" const:class="hourLine"><!-- space --></div
></var:foreach>
</div>
</div>

View File

@ -7,6 +7,7 @@
xmlns:rsrc="OGo:url"
xmlns:label="OGo:label"
className="UIxPageFrame"
const:jsFiles="SchedulerUIDnD.js"
title="title">
<script type="text/javascript">
var firstDayOfWeek = <var:string value="firstDayOfWeek"/>;

View File

@ -85,7 +85,7 @@ Element.addMethods({
if (additionalKeys)
for (var i = 0; i < additionalKeys.length; i++) {
var value = element.getAttribute(additionalKeys[i]);
var value = element.readAttribute(additionalKeys[i]);
if (value)
str += "; " + additionalKeys[i] + " = " + value;
}

View File

@ -45,7 +45,7 @@ DIV#calendarsList
DIV.colorBox
{ display: inline;
border: 1px solid #333;
font-weight: normal;
font-weight: normal;
margin: 0px;
margin-right: 3px;
font-size: 80%;
@ -291,6 +291,7 @@ TABLE#eventsList TH
DIV#eventDialog
{ width: 200px; }
DIV#eventDialog H1,
DIV#eventDialog P
{ font-size: 10px;
@ -750,107 +751,100 @@ DIV.clickableHourCell0
{ top: 0px; }
DIV.clickableHourCell1,
DIV#daysView > DIV.hourLines > DIV.hourLine0
DIV#daysView > DIV.hourLines > #hourLine0
{ top: 4em; }
DIV.clickableHourCell2,
DIV#daysView > DIV.hourLines > DIV.hourLine1
DIV#daysView > DIV.hourLines > #hourLine1
{ top: 8em; }
DIV.clickableHourCell3,
DIV#daysView > DIV.hourLines > DIV.hourLine2
DIV#daysView > DIV.hourLines > #hourLine2
{ top: 12em; }
DIV.clickableHourCell4,
DIV#daysView > DIV.hourLines > DIV.hourLine3
DIV#daysView > DIV.hourLines > #hourLine3
{ top: 16em; }
DIV.clickableHourCell5,
DIV#daysView > DIV.hourLines > DIV.hourLine4
DIV#daysView > DIV.hourLines > #hourLine4
{ top: 20em; }
DIV.clickableHourCell6,
DIV#daysView > DIV.hourLines > DIV.hourLine5
DIV#daysView > DIV.hourLines > #hourLine5
{ top: 24em; }
DIV.clickableHourCell7,
DIV#daysView > DIV.hourLines > DIV.hourLine6
DIV#daysView > DIV.hourLines > #hourLine6
{ top: 28em; }
DIV.clickableHourCell8,
DIV#daysView > DIV.hourLines > DIV.hourLine7
DIV#daysView > DIV.hourLines > #hourLine7
{ top: 32em; }
DIV.clickableHourCell9,
DIV#daysView > DIV.hourLines > DIV.hourLine8
DIV#daysView > DIV.hourLines > #hourLine8
{ top: 36em; }
DIV.clickableHourCell10,
DIV#daysView > DIV.hourLines > DIV.hourLine9
DIV#daysView > DIV.hourLines > #hourLine9
{ top: 40em; }
DIV.clickableHourCell11,
DIV#daysView > DIV.hourLines > DIV.hourLine10
DIV#daysView > DIV.hourLines > #hourLine10
{ top: 44em; }
DIV.clickableHourCell12,
DIV#daysView > DIV.hourLines > DIV.hourLine11
DIV#daysView > DIV.hourLines > #hourLine11
{ top: 48em; }
DIV.clickableHourCell13,
DIV#daysView > DIV.hourLines > DIV.hourLine12
DIV#daysView > DIV.hourLines > #hourLine12
{ top: 52em; }
DIV.clickableHourCell14,
DIV#daysView > DIV.hourLines > DIV.hourLine13
DIV#daysView > DIV.hourLines > #hourLine13
{ top: 56em; }
DIV.clickableHourCell15,
DIV#daysView > DIV.hourLines > DIV.hourLine14
DIV#daysView > DIV.hourLines > #hourLine14
{ top: 60em; }
DIV.clickableHourCell16,
DIV#daysView > DIV.hourLines > DIV.hourLine15
DIV#daysView > DIV.hourLines > #hourLine15
{ top: 64em; }
DIV.clickableHourCell17,
DIV#daysView > DIV.hourLines > DIV.hourLine16
DIV#daysView > DIV.hourLines > #hourLine16
{ top: 68em; }
DIV.clickableHourCell18,
DIV#daysView > DIV.hourLines > DIV.hourLine17
DIV#daysView > DIV.hourLines > #hourLine17
{ top: 72em; }
DIV.clickableHourCell19,
DIV#daysView > DIV.hourLines > DIV.hourLine18
DIV#daysView > DIV.hourLines > #hourLine18
{ top: 76em; }
DIV.clickableHourCell20,
DIV#daysView > DIV.hourLines > DIV.hourLine19
DIV#daysView > DIV.hourLines > #hourLine19
{ top: 80em; }
DIV.clickableHourCell21,
DIV#daysView > DIV.hourLines > DIV.hourLine20
DIV#daysView > DIV.hourLines > #hourLine20
{ top: 84em; }
DIV.clickableHourCell22,
DIV#daysView > DIV.hourLines > DIV.hourLine21
DIV#daysView > DIV.hourLines > #hourLine21
{ top: 88em; }
DIV.clickableHourCell23,
DIV#daysView > DIV.hourLines > DIV.hourLine22
DIV#daysView > DIV.hourLines > #hourLine22
{ top: 92em; }
DIV#daysView > DIV.hourLines > DIV.hourLine23
DIV#daysView > DIV.hourLines > #hourLine23
{ top: 96em; }
DIV#daysView DIV.events
{ z-index: 2;
left: 0px;
right: 0px;
bottom: 0px;
top: 0px; }
DIV.events > DIV.event
{ cursor: default;
z-index: 1;
@ -860,11 +854,39 @@ DIV.events > DIV.event
margin-top: 0px;
padding: 1px; }
DIV.event DIV.topDragGrip,
DIV.event DIV.bottomDragGrip
{ position: absolute;
border: 0px;
left: 1px;
right: 1px;
height: 4px;
background-repeat: no-repeat;
background-position: center; }
DIV.event.dragging DIV.topDragGrip,
DIV.event.dragging DIV.bottomDragGrip
{ display: none; }
DIV.event DIV.topDragGrip
{ top: 1px; }
DIV.event.draggable:hover DIV.topDragGrip
{ cursor: n-resize;
background-image: url(event-grippy-top.png); }
DIV.event DIV.bottomDragGrip
{ bottom: 1px; }
DIV.event.draggable:hover DIV.bottomDragGrip
{ cursor: s-resize;
background-image: url(event-grippy-bottom.png); }
DIV.event > DIV.eventInside
{ position: absolute;
overflow: hidden;
top: 2px;
bottom: 2px;
top: 3px;
bottom: 3px;
left: 1px;
right: 1px; }
@ -924,10 +946,57 @@ DIV.event.alarm DIV.text
background-repeat: no-repeat;
background-position: top right; }
DIV.event.dragging
{ left: 0px !important;
width: 100% !important; }
DIV.event.dragging > DIV.eventInside
{ border: 1px dashed #555;
-moz-opacity: 1 !important;
opacity: 1 !important;
background-color: transparent !important; }
DIV.event.dragging DIV.text
{ color: #555; }
DIV.event.dragging IMG
{ display: none; }
DIV.eventDragGhost
{ border-top: 0px;
color: #fff;
border-bottom: 0px;
border-left: 1px solid #555;
border-right: 1px solid #555; }
DIV.eventDragGhost.startGhost
{ border-top: 1px solid #555; }
DIV.eventDragGhost.endGhost
{ border-bottom: 1px solid #555; }
DIV.eventDragGhost > DIV
{ position: absolute;
width: 100%;
vertical-align: baseline;
height: 14px;
left: 0px;
padding: 0px;
margin: 0px;
border: 0px;
color: #222;
text-align: center; }
#ghostStartHour
{ top: -14px; }
#ghostEndHour
{ bottom: -14px; }
DIV.eventInside.needs-action
{ border: 2px dotted #666;
{ border: 1px dotted #666;
-moz-opacity: 0.6;
opacity: 0.6; }
opacity: 0.7; }
DIV.eventInside.declined
{ -moz-opacity: 0.3;

View File

@ -25,27 +25,94 @@ var preventAutoScroll = false;
var userStates = [ "needs-action", "accepted", "declined", "tentative" ];
function newEvent(sender, type) {
var day = $(sender).readAttribute("day");
if (!day)
day = currentDay;
var hour = sender.readAttribute("hour");
function newEvent(type, day, hour, duration) {
var folder = getSelectedFolder();
var folderID = folder.readAttribute("id");
var urlstr = ApplicationBaseURL + folderID + "/new" + type;
var params = [];
if (day)
params.push("day=" + day);
if (!day)
day = currentDay;
params.push("day=" + day);
if (hour)
params.push("hm=" + hour);
if (duration)
params.push("duration=" + duration);
if (params.length > 0)
urlstr += "?" + params.join("&");
window.open(urlstr, "", "width=490,height=470,resizable=0");
}
function newEventFromWidget(sender, type) {
var day = $(sender).readAttribute("day");
var hour = sender.readAttribute("hour");
newEvent(type, day, hour);
return false; /* stop following the link */
}
function minutesToHM(minutes) {
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;
}
function newEventFromDragging(controller, day, coordinates) {
var startHm = minutesToHM(coordinates.start * 15);
var lengthHm = minutesToHM(coordinates.duration * 15);
newEvent("event", day, startHm, lengthHm);
}
function updateEventFromDragging(controller, eventCells, eventDelta) {
if (eventDelta.dayNumber || eventDelta.start || eventDelta.duration) {
var params = ("days=" + eventDelta.dayNumber
+ "&start=" + eventDelta.start * 15
+ "&duration=" + eventDelta.duration * 15);
// log("eventCells: " + eventCells.length);
var eventCell = eventCells[0];
// log(" time: " + eventCell.recurrenceTime);
// log(" exception: " + eventCell.isException);
if (eventCell.recurrenceTime && !eventCell.isException)
_editRecurrenceDialog(eventCell, "confirmAdjustment", params);
else {
var urlstr = (ApplicationBaseURL
+ eventCell.calendar + "/" + eventCell.cname);
if (eventCell.recurrenceTime)
urlstr += "/occurence" + eventCell.recurrenceTime;
urlstr += ("/adjust?" + params);
// log(" urlstr: " + urlstr);
triggerAjaxRequest(urlstr, updateEventFromDraggingCallback,
{ controller: controller,
eventCell: eventCell });
}
}
}
function performEventAdjustment(folder, event, recurrence, params) {
var urlstr = ApplicationBaseURL + folder + "/" + event;
if (recurrence)
urlstr += "/" + recurrence;
urlstr += "/adjust" + generateQueryString(params);
triggerAjaxRequest(urlstr, updateEventFromDraggingCallback);
}
function updateEventFromDraggingCallback(http) {
if (http.readyState == 4) {
if (isHttpStatus204(http.status)) {
// var cell = this.callbackData.eventCell;
// cell.parentNode.removeChild(cell);
changeCalendarDisplay();
}
}
}
function getSelectedFolder() {
var folder;
var list = $("calendarList");
@ -59,11 +126,11 @@ function getSelectedFolder() {
}
function onMenuNewEventClick(event) {
newEvent(this, "event");
newEventFromWidget(this, "event");
}
function onMenuNewTaskClick(event) {
newEvent(this, "task");
newEventFromWidget(this, "task");
}
function _editEventId(id, calendar, recurrence) {
@ -199,7 +266,7 @@ function modifyEvent(sender, modification, parameters) {
modification,
parameters,
{ "Content-type": "application/x-www-form-urlencoded" });
return false;
}
@ -298,7 +365,7 @@ function _deleteEventFromTables(calendar, cname, occurenceTime) {
if (occurences) {
var occurence = occurences.first();
var ownerIsOrganizer = occurence[18];
// Delete event from events list
var table = $("eventsList");
var rows = table.tBodies[0].rows;
@ -326,7 +393,7 @@ function _deleteEventFromTables(calendar, cname, occurenceTime) {
}
}
}
// Delete task from tasks list
var row = $(calendar + basename);
if (row) {
@ -339,7 +406,7 @@ function _deleteCalendarEventCache(calendar, cname, occurenceTime) {
var occurences = calendarEvents[calendar][cname];
if (occurences)
ownerIsOrganizer = occurences[0][18];
for (var otherCalendar in calendarEvents) {
var occurences = calendarEvents[otherCalendar][cname];
if (occurences) {
@ -407,10 +474,13 @@ function getEventById(cname, owner) {
return event;
}
function _editRecurrenceDialog(eventDiv, method) {
var targetname = "SOGo_edit_" + eventDiv.cname + eventDiv.recurrenceTime;
var urlstr = (ApplicationBaseURL + eventDiv.calendar + "/" + eventDiv.cname
+ "/occurence" + eventDiv.recurrenceTime + "/" + method);
function _editRecurrenceDialog(eventCell, method, params) {
var targetname = "SOGo_edit_" + eventCell.cname + eventCell.recurrenceTime;
var urlstr = (ApplicationBaseURL + eventCell.calendar + "/" + eventCell.cname
+ "/occurence" + eventCell.recurrenceTime + "/" + method);
if (params && params.length) {
urlstr += "?" + params;
}
var win = window.open(urlstr, "_blank",
"width=490,height=70,resizable=0");
if (win)
@ -440,13 +510,13 @@ function onViewEventCallback(http) {
// });
var cell = http.callbackData;
var cellPosition = cell.cumulativeOffset();
var cellDimensions = cell.getDimensions();
var cellDimensions = cell.getDimensions();
var div = $("eventDialog");
var divDimensions = div.getDimensions();
var view;
var left = cellPosition[0];
var top = cellPosition[1];
if (currentView != "monthview") {
view = $("daysView");
var viewPosition = view.cumulativeOffset();
@ -464,7 +534,7 @@ function onViewEventCallback(http) {
view = $("calendarView");
top -= cell.up("DIV.day").scrollTop;
}
if (left > parseInt(window.width()*0.75)) {
left = left - divDimensions["width"] + 10;
div.removeClassName("left");
@ -504,13 +574,13 @@ function onViewEventCallback(http) {
paras[3].show();
} else
paras[3].hide();
div.setStyle({ left: left + "px", top: top + "px" });
div.show();
}
}
else {
log("onViewEventCallback ajax error (" + http.status + "): " + http.url);
log("onViewEventCallback ajax error (" + http.status + "): " + http.url);
}
}
@ -530,13 +600,13 @@ function performEventEdition(folder, event, recurrence) {
}
function performEventDeletion(folder, event, recurrence) {
if (calendarEvents) {
if (calendarEvents) {
if (recurrence) {
// Only one recurrence
var occurenceTime = recurrence.substring(9);
var nodes = _eventBlocksMatching(folder, event, occurenceTime);
var urlstr = ApplicationBaseURL + folder + "/" + event + "/" + recurrence + "/delete";
if (nodes)
document.deleteEventAjaxRequest = triggerAjaxRequest(urlstr,
performDeleteEventCallback,
@ -563,7 +633,7 @@ function performDeleteEventCallback(http) {
var nodes = http.callbackData.nodes;
var cname = nodes[0].cname;
var calendar = nodes[0].calendar;
_deleteCalendarEventBlocks(calendar, cname, occurenceTime);
_deleteEventFromTables(calendar, cname, occurenceTime);
_deleteCalendarEventCache(calendar, cname, occurenceTime);
@ -664,7 +734,7 @@ function eventsListCallback(http) {
rows.each(function(e) {
e.remove();
});
if (http.responseText.length > 0) {
var data = http.responseText.evalJSON(true);
for (var i = 0; i < data.length; i++) {
@ -709,7 +779,7 @@ function eventsListCallback(http) {
row.appendChild(td);
td.observe("mousedown", listRowMouseDownHandler, true);
td.appendChild(document.createTextNode(data[i][20])); // end date
td = $(document.createElement("td"));
row.appendChild(td);
td.observe("mousedown", listRowMouseDownHandler, true);
@ -719,7 +789,7 @@ function eventsListCallback(http) {
if (sorting["attribute"] && sorting["attribute"].length > 0) {
var sortHeader = $(sorting["attribute"] + "Header");
if (sortHeader) {
var sortImages = $(table.tHead).select(".sortImage");
$(sortImages).each(function(item) {
@ -747,7 +817,7 @@ function tasksListCallback(http) {
&& http.status == 200) {
document.tasksListAjaxRequest = null;
var list = $("tasksList");
if (http.responseText.length > 0) {
var data = http.responseText.evalJSON(true);
@ -899,11 +969,11 @@ function changeCalendarDisplay(data, newView) {
divs.each(function(div) {
div.addClassName('selectedDay');
});
// Deselect day in date selector
if (document.selectedDate)
document.selectedDate.deselect();
// Select day in date selector
var selectedLink = $$('table#dateSelectorTable span[day='+day+']');
if (selectedLink.length > 0) {
@ -981,6 +1051,7 @@ function reloadWebCalendars() {
document.reloadWebCalAjaxRequest
= triggerAjaxRequest(url, reloadWebCalendarsCallback);
}
function reloadWebCalendarsCallback (http) {
changeCalendarDisplay(null, currentView);
}
@ -1017,7 +1088,7 @@ function scrollDayView(scrollEvent) {
}
function onClickableCellsDblClick(event) {
newEvent(this, 'event');
newEventFromWidget(this, 'event');
Event.stop(event);
}
@ -1075,7 +1146,7 @@ function _parseEvents(list) {
var event = list[i];
var cname = event[0];
var calendar = event[1];
// log("parsed cname: " + cname + "; calendar: " + calendar);
// log("parsed cname: " + cname + "; calendar: " + calendar);
var calendarDict = newCalendarEvents[calendar];
if (!calendarDict) {
calendarDict = {};
@ -1093,6 +1164,40 @@ function _parseEvents(list) {
return newCalendarEvents;
}
function _setupEventsDragAndDrop(events) {
/* We setup the drag controllers for all the events.
Since the same events may be listed more than once per calendar
(repeating events), we must keep account of those that have already
been setup. */
var setupFlags = {};
for (var i = 0; i < events.length; i++) {
if (events[i][11] == UserLogin) {
var cname = events[i][0];
var calendar = events[i][1];
var setupId = calendar + "_" + cname;
if (!setupFlags[setupId]) {
var occurrences = calendarEvents[calendar][cname];
for (var j = 0; j < occurrences.length; j++) {
var blocks = occurrences[j].blocks;
var topDragGrip = $(document.createElement("div"));
topDragGrip.addClassName("topDragGrip");
blocks[0].appendChild(topDragGrip);
var bottomDragGrip = $(document.createElement("div"));
bottomDragGrip.addClassName("bottomDragGrip");
blocks[blocks.length-1].appendChild(bottomDragGrip);
var dragController = new SOGoEventDragController();
dragController.updateDropCallback = updateEventFromDragging;
dragController.attachToEventCells(blocks);
}
setupFlags[setupId] = true;
}
}
}
}
function refreshCalendarEventsCallback(http) {
if (http.readyState == 4
&& http.status == 200) {
@ -1104,6 +1209,7 @@ function refreshCalendarEventsCallback(http) {
else {
_drawCalendarAllDayEvents(eventsBlocks[1], eventsBlocks[0]);
_drawCalendarEvents(eventsBlocks[2], eventsBlocks[0]);
_setupEventsDragAndDrop(eventsBlocks[0]);
}
onWindowResize(null);
}
@ -1136,21 +1242,21 @@ function newBaseEventDIV(eventRep, event, eventText) {
// log ("17 erasable = " + event[17]);
// log ("18 ownerisorganizer = " + event[18]);
var eventDiv = $(document.createElement("div"));
eventDiv.cname = event[0];
eventDiv.calendar = event[1];
var eventCell = $(document.createElement("div"));
eventCell.cname = event[0];
eventCell.calendar = event[1];
if (eventRep.recurrenceTime)
eventDiv.recurrenceTime = eventRep.recurrenceTime;
eventDiv.isException = event[15];
eventDiv.editable = event[16];
eventDiv.erasable = event[17];
eventDiv.ownerIsOrganizer = event[18];
eventDiv.addClassName("event");
eventCell.recurrenceTime = eventRep.recurrenceTime;
eventCell.isException = event[15];
eventCell.editable = event[16];
eventCell.erasable = event[17];
eventCell.ownerIsOrganizer = event[18];
eventCell.addClassName("event");
if (event[13] > 0)
eventDiv.addClassName("alarm");
eventCell.addClassName("alarm");
var innerDiv = $(document.createElement("div"));
eventDiv.appendChild(innerDiv);
eventCell.appendChild(innerDiv);
innerDiv.addClassName("eventInside");
innerDiv.addClassName("calendarFolder" + event[1]);
if (eventRep.userState >= 0 && userStates[eventRep.userState])
@ -1170,20 +1276,21 @@ function newBaseEventDIV(eventRep, event, eventText) {
textDiv.update(eventText.replace(/(\\r)?\\n/g, "<BR/>"));
if (event[2] == null) {
eventDiv.observe("selectstart", listRowMouseDownHandler);
eventDiv.observe("click", onCalendarSelectEvent);
eventDiv.observe("dblclick", Event.stop);
eventCell.observe("selectstart", listRowMouseDownHandler);
eventCell.observe("click", onCalendarSelectEvent);
eventCell.observe("dblclick", Event.stop);
}
else {
// Status field is defined -- user can read event
eventDiv.observe("mousedown", listRowMouseDownHandler);
eventDiv.observe("click", onCalendarSelectEvent);
eventDiv.observe("dblclick", editDoubleClickedEvent);
eventDiv.observe("click", onViewEvent);
eventCell.observe("mousedown", listRowMouseDownHandler);
eventCell.observe("click", onCalendarSelectEvent);
eventCell.observe("dblclick", editDoubleClickedEvent);
eventCell.observe("click", onViewEvent);
}
event.blocks.push(eventDiv);
return eventDiv;
event.blocks.push(eventCell);
return eventCell;
}
function _drawCalendarAllDayEvents(events, eventsData) {
@ -1195,8 +1302,8 @@ function _drawCalendarAllDayEvents(events, eventsData) {
for (var j = 0; j < events[i].length; j++) {
var eventRep = events[i][j];
var nbr = eventRep.nbr;
var eventDiv = newAllDayEventDIV(eventRep, eventsData[nbr]);
parentDiv.appendChild(eventDiv);
var eventCell = newAllDayEventDIV(eventRep, eventsData[nbr]);
parentDiv.appendChild(eventCell);
}
}
}
@ -1204,11 +1311,11 @@ function _drawCalendarAllDayEvents(events, eventsData) {
function newAllDayEventDIV(eventRep, event) {
// cname, calendar, starts, lasts,
// startHour, endHour, title) {
var eventDiv = newBaseEventDIV(eventRep, event, event[3]);
var eventCell = newBaseEventDIV(eventRep, event, event[3]);
return eventDiv;
return eventCell;
}
function _drawCalendarEvents(events, eventsData) {
var daysView = $("daysView");
var subdivs = daysView.childNodesWithTag("div");
@ -1218,23 +1325,27 @@ function _drawCalendarEvents(events, eventsData) {
for (var j = 0; j < events[i].length; j++) {
var eventRep = events[i][j];
var nbr = eventRep.nbr;
var eventDiv = newEventDIV(eventRep, eventsData[nbr]);
parentDiv.appendChild(eventDiv);
var eventCell = newEventDIV(eventRep, eventsData[nbr]);
parentDiv.appendChild(eventCell);
if (eventCell.editable) {
eventCell.addClassName("draggable");
}
}
}
}
function newEventDIV(eventRep, event) {
var eventDiv = newBaseEventDIV(eventRep, event, event[3]);
var eventCell = newBaseEventDIV(eventRep, event, event[3]);
var pc = 100 / eventRep.siblings;
eventDiv.style.width = pc + "%";
eventCell.style.width = pc + "%";
var left = eventRep.position * pc;
eventDiv.style.left = left + "%";
eventDiv.addClassName("starts" + eventRep.start);
eventDiv.addClassName("lasts" + eventRep.length);
eventCell.style.left = left + "%";
eventCell.addClassName("starts" + eventRep.start);
eventCell.addClassName("lasts" + eventRep.length);
return eventDiv;
return eventCell;
}
function _drawMonthCalendarEvents(events, eventsData) {
@ -1245,8 +1356,8 @@ function _drawMonthCalendarEvents(events, eventsData) {
for (var j = 0; j < events[i].length; j++) {
var eventRep = events[i][j];
var nbr = eventRep.nbr;
var eventDiv = newMonthEventDIV(eventRep, eventsData[nbr]);
parentDiv.appendChild(eventDiv);
var eventCell = newMonthEventDIV(eventRep, eventsData[nbr]);
parentDiv.appendChild(eventCell);
}
}
}
@ -1258,10 +1369,28 @@ function newMonthEventDIV(eventRep, event) {
else
eventText = eventRep.starthour + " - " + event[3];
var eventDiv = newBaseEventDIV(eventRep, event,
eventText);
var eventCell = newBaseEventDIV(eventRep, event,
eventText);
return eventDiv;
return eventCell;
}
function attachDragControllers(contentView) {
var contentNodes = contentView.childNodesWithTag("div");
for (var i = 0; i < contentNodes.length; i++) {
var contentNode = contentNodes[i];
if (contentNode.hasClassName("days")) {
var dayNodes = contentNode.childNodesWithTag("div");
for (var j = 0; j < dayNodes.length; j++) {
var dayNode = dayNodes[j];
if (dayNode.hasClassName("day")) {
var dragController = new SOGoEventDragController();
dragController.createDropCallback = newEventFromDragging;
dragController.attachToDayNode(dayNode);
}
}
}
}
}
function calendarDisplayCallback(http) {
@ -1273,7 +1402,7 @@ function calendarDisplayCallback(http) {
if (daysView)
position = daysView.scrollTop;
preventAutoScroll = (position != -1);
if (http.readyState == 4
&& http.status == 200) {
document.dayDisplayAjaxRequest = null;
@ -1322,19 +1451,21 @@ function calendarDisplayCallback(http) {
deleteEvent);
observer = $("monthDaysView");
}
initMenu($("currentViewMenu"), menu);
observer.observe("contextmenu", onMenuCurrentView);
var contentView;
if (currentView == "monthview")
contentView = $("calendarContent");
else {
contentView = $("daysView");
attachDragControllers(contentView);
contentView.observe("scroll", onBodyClickHandler);
}
refreshCalendarEvents(http.callbackData.scrollEvent);
var days = contentView.select("DIV.day");
if (currentView == "monthview")
@ -1359,7 +1490,7 @@ function calendarDisplayCallback(http) {
var clickableCells = days[i].select("DIV.clickableHourCell");
for (var j = 0; j < clickableCells.length; j++)
clickableCells[j].observe("dblclick", onClickableCellsDblClick);
clickableCells[j].observe("dblclick", onClickableCellsDblClick);
}
}
}
@ -1457,7 +1588,7 @@ function onHeaderClick(event) {
newSortAttribute = "location";
else
newSortAttribute = "start";
if (sorting["attribute"] == newSortAttribute)
sorting["ascending"] = !sorting["ascending"];
else {
@ -1473,6 +1604,7 @@ function refreshCurrentFolder() {
refreshEvents();
}
/* refreshes the "unifinder" list */
function refreshEvents() {
var titleSearch;
var value = search["value"];
@ -1480,7 +1612,7 @@ function refreshEvents() {
titleSearch = "&search=" + escape(value.utf8encode());
else
titleSearch = "";
refreshAlarms();
return _loadEventHref("eventslist?asc=" + sorting["ascending"]
@ -1611,7 +1743,7 @@ function selectCalendarEvent(calendar, cname, recurrenceTime) {
selection[i].selectElement();
selectedCalendarCell = selection;
}
return selection;
}
@ -1694,7 +1826,7 @@ function changeMonthCalendarDisplayOfSelectedDay(node) {
var daysContainer = node.parentNode;
if (!daysContainer.selectedCell)
findMonthCalendarSelectedCell(daysContainer);
if (daysContainer.selectedCell)
daysContainer.selectedCell.removeClassName("selectedDay");
daysContainer.selectedCell = node;
@ -1720,7 +1852,7 @@ function updateTaskStatus(event) {
function updateCalendarStatus(event) {
var list = [];
var newStatus = (this.checked ? 1 : 0);
if (isSafari() && !isSafari3()) {
newStatus = (newStatus ? 0 : 1);
this.checked = newStatus;
@ -1827,7 +1959,7 @@ function updateCalendarsList(method) {
function onCalendarsMenuPrepareVisibility() {
var folders = $("calendarList");
var selected = folders.getSelectedNodes();
var selected = folders.getSelectedNodes();
if (selected.length > 0) {
var folderOwner = selected[0].getAttribute("owner");
var sharingOption = $(this).down("ul").childElements().last();
@ -1866,7 +1998,7 @@ function getMenus() {
null, "-", null, "-", onMenuSharing);
menus["searchMenu"] = new Array(setSearchCriteria);
menus["tasksListMenu"] = new Array (editEvent, newTask, "-",
menus["tasksListMenu"] = new Array (editEvent, newTask, "-",
marksTasksAsCompleted, deleteEvent);
var calendarsMenu = $("calendarsMenu");
@ -1877,7 +2009,7 @@ function getMenus() {
}
function newTask () {
return newEvent(this, 'task');
return newEventFromWidget(this, 'task');
}
function marksTasksAsCompleted () {
@ -1967,7 +2099,7 @@ function onCalendarModify(event) {
var width = 310;
var height = 266;
var isWebCalendar = false;
if (UserSettings['Calendar']
if (UserSettings['Calendar']
&& UserSettings['Calendar']['WebCalendars']) {
var webCalendars = UserSettings['Calendar']['WebCalendars'];
var realID = calendarID.substr (1, calendarID.length - 1);
@ -2022,7 +2154,7 @@ function onCalendarWebAdd(event) {
document.addWebCalendarRequest.abort ();
}
var url = ApplicationBaseURL + "/addWebCalendar?url=" + escape (calendarUrl);
document.addWebCalendarRequest =
document.addWebCalendarRequest =
triggerAjaxRequest (url, addWebCalendarCallback);
}
}
@ -2094,7 +2226,7 @@ function uploadCompleted(response) {
$("uploadResultsContent").update(getLabel("A total of %{0} events were imported in the calendar.").formatted(data.imported));
refreshEventsAndDisplay();
}
hideCalendarImport();
$("uploadResults").show();
}
@ -2128,12 +2260,12 @@ function appendCalendar(folderName, folderPath) {
var calendarList = $("calendarList");
var items = calendarList.select("li");
var li = document.createElement("li");
// Add the calendar to the proper place
var i = getListIndexForFolder(items, owner, folderName);
if (i != items.length) // User is subscribed to other calendars of the same owner
calendarList.insertBefore(li, items[i]);
else
else
calendarList.appendChild(li);
$(li).writeAttribute("id", folderPath);
$(li).writeAttribute("owner", owner);
@ -2142,7 +2274,7 @@ function appendCalendar(folderName, folderPath) {
{ type: "checkbox" }, li);
li.appendChild(document.createTextNode(" "));
var colorBox = document.createElement("div");
li.appendChild(colorBox);
li.appendChild(document.createTextNode(folderName
@ -2152,7 +2284,7 @@ function appendCalendar(folderName, folderPath) {
$(colorBox).addClassName("colorBox");
$(colorBox).addClassName('calendarFolder' + folderPath.substr(1));
// Check the checkbox (required for IE)
li.getElementsByTagName("input")[0].checked = true;
@ -2161,7 +2293,7 @@ function appendCalendar(folderName, folderPath) {
var url = URLForFolderID(folderPath) + "/canAccessContent";
triggerAjaxRequest(url, calendarEntryCallback, folderPath);
// Update CSS for events color
appendStyleElement(folderPath, "#AAAAAA");
}
@ -2236,7 +2368,7 @@ function onCalendarRemove(event) {
}
}
}
preventDefault(event);
}
@ -2348,12 +2480,12 @@ function drawNowLine () {
if (d < 10)
d = "0" + d;
var day = today.getFullYear () + "" + m + "" + d;
var targets = $$("DIV#daysView DIV.days DIV.day[day=" + day
var targets = $$("DIV#daysView DIV.days DIV.day[day=" + day
+ "] DIV.events DIV.clickableHourCell");
}
else if (currentView == "weekview")
var targets = $$("DIV#daysView DIV.days DIV.dayOfToday DIV.events DIV.clickableHourCell");
if (targets) {
var target = targets[hours];
@ -2361,10 +2493,10 @@ function drawNowLine () {
var div = $("nowLineDisplay");
if (!div)
div = new Element ("div", {'id': 'nowLineDisplay'});
div.style.top = parseInt (((minutes * target.offsetHeight) / 60) - 1) + "px";
target.appendChild (div);
setTimeout ("drawNowLine ();", 60000); // 1 min.
}
}

View File

@ -0,0 +1,933 @@
/* -*- Mode: java; tab-width: 2; c-label-minimum-indentation: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 = {
dayEventNodes: null,
quarterHeight: -1,
dayWidth: -1,
daysOffset: -1,
eventsViewNode: null,
eventsViewNodeCumulativeCoordinates: null,
reset: function() {
this.dayEventNodes = null;
this.quarterHeight = -1;
this.dayWidth = -1;
this.daysOffset = -1;
this.eventsViewNode = null;
this.eventsViewNodeCumulativeCoordinates = null;
},
getDayEventNodes: function() {
if (!this.dayEventNodes)
this._initDayEventNodes();
return this.dayEventNodes;
},
_initDayEventNodes: function() {
this.dayEventNodes = [];
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);
}
}
}
}
},
_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.dayEventNodes.push(daySubnode);
}
}
},
getQuarterHeight: function() {
if (this.quarterHeight == -1) {
var hourLine0 = $("hourLine0");
var hourLine23 = $("hourLine23");
this.quarterHeight = ((hourLine23.offsetTop - hourLine0.offsetTop)
/ (23 * 4));
}
return this.quarterHeight;
},
getDaysOffset: function() {
if (this.daysOffset == -1)
this._initDayEventNodes();
return this.daysOffset;
},
getDayWidth: function() {
if (this.dayWidth == -1) {
var nodes = this.getDayEventNodes();
if (nodes.length > 1) {
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;
},
getEventsViewNode: function() {
if (!this.eventsViewNode)
this.eventsViewNode = $("daysView");
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,
initFromEventCell: 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;
},
initFromEventCells: function(eventCells) {
this.duration = 0;
for (var i = 0; i < eventCells.length; i++) {
var current = new SOGoEventDragEventCoordinates();
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,
currentStart: -1,
currentDuration: -1,
isStartGhost: false,
isEndGhost: false,
show: function SDGI_show() {
if (!this.visible) {
this.removeClassName("hidden");
this.visible = true;
}
},
hide: function SDGI_hide() {
if (this.visible) {
this.addClassName("hidden");
this.visible = false;
}
},
setTitle: function SDGI_setTitle(title) {
if (this.title != title) {
while (this.childNodes.length) {
this.removeChild(this.firstChild);
}
if (title) {
this.appendChild(document.createTextNode(title));
}
this.title = title;
}
},
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) {
this.removeClassName("starts" + this.currentStart);
this.currentStart = start;
this.addClassName("starts" + this.currentStart);
}
},
setDuration: function SDGI_setDuration(duration) {
if (this.currentDuration != duration) {
this.removeClassName("lasts" + this.currentDuration);
this.currentDuration = duration;
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;
},
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.x != this.currentPointerCoordinates.x
|| newCoordinates.y != this.currentPointerCoordinates.y) {
this.currentPointerCoordinates = newCoordinates;
if (this.originalPointerCoordinates) {
this._updateCoordinates();
if (this.ghosts) {
this._updateGhosts();
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;
if (this.dragMode == "move-event") {
this.currentCoordinates.start
= this.originalCoordinates.start + deltaQuarters;
this.currentCoordinates.duration
= this.originalCoordinates.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.getDayEventNodes();
for (var i = 0; i < nodes.length; i++) {
var newGhost = $(document.createElement("div"));
Object.extend(newGhost, SOGoDragGhostInterface);
newGhost.className = "event eventDragGhost";
newGhost.hide();
nodes[i].appendChild(newGhost);
this.ghosts.push(newGhost);
}
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();
this._updateGhostsParas();
}
},
hideGhosts: function SEDGC_hideGhosts() {
if (this.ghosts) {
if (this.startHourPara.parentNode)
this.startHourPara.parentNode.removeChild(this.startHourPara);
this.startHourPara = null;
if (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();
}
// logOnly("update");
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;
if (currentDay > -1) {
ghost = this.ghosts[currentDay];
ghost.setStartGhost();
ghost.unsetEndGhost();
ghost.setTitle(this.eventTitle);
ghost.setFolderClass(this.folderClass);
ghost.setStart(this.currentCoordinates.start);
ghost.setDuration(duration);
ghost.show();
if (this.startHourPara.parentNode != ghost) {
if (this.startHourPara.parentNode)
this.startHourPara.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.parentNode != ghost) {
if (this.endHourPara.parentNode)
this.endHourPara.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,
initFromEvent: function SEDPH_initFromEvent(event) {
this.currentCoordinates = new SOGoCoordinates();
this.updateFromEvent(event);
this.originalCoordinates = this.currentCoordinates.clone();
var utilities = SOGoEventDragUtilities();
this.containerCoordinates = utilities.getEventsViewNodeCumulativeCoordinates();
},
updateFromEvent: function SEDPH_updateFromEvent(event) {
this.currentCoordinates.x = Event.pointerX(event);
this.currentCoordinates.y = Event.pointerY(event);
},
getContainerBasedCoordinates: function SEDPH_getCBC() {
return this.currentCoordinates.getDelta(this.containerCoordinates);
},
/* return the day and quarter coordinates of the pointer cursor within the
day view */
getEventViewCoordinates: function SEDPH_getEventViewCoordinates() {
/* x = day; y = quarter */
var coordinates = new SOGoCoordinates();
var utilities = SOGoEventDragUtilities();
var pxCoordinates = this.getContainerBasedCoordinates();
var dayWidth = utilities.getDayWidth();
var daysOffset = utilities.getDaysOffset();
coordinates.x = Math.floor((pxCoordinates.x - daysOffset) / dayWidth);
var maxX = utilities.getDayEventNodes().length - 1;
if (coordinates.x < 0)
coordinates.x = 0;
else if (coordinates.x > maxX)
coordinates.x = maxX;
var quarterHeight = utilities.getQuarterHeight();
var container = utilities.getEventsViewNode();
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;
},
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 = 2 * utilities.getQuarterHeight();
},
setPointerHandler: function SSC_setPointerHandler(pointerHandler) {
this.pointerHandler = pointerHandler;
},
updateFromPointerHandler: function SSC_updateFromPointerHandler() {
var pointerCoordinates
= this.pointerHandler.getContainerBasedCoordinates();
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,
title: null,
folderClass: null,
draggingModeAreas: null,
ghostController: null,
hasSelected: false,
dragHasStarted: false,
dragMode: null,
originalDayNumber: -1,
pointerHandler: null,
dropCallback: null,
stopEventDraggingBound: null,
moveBound: null,
attachToEventCells: function SEDC_attachToEventCells(eventCells) {
this.eventCells = eventCells;
this.ghostController = new SOGoEventDragGhostController();
this._determineTitleAndFolderClass();
this.ghostController.setTitle(this.title);
this.ghostController.setFolderClass(this.folderClass);
var startEventDraggingBound = this.startEventDragging.bindAsEventListener(this);
for (var i = 0; i < eventCells.length; i++) {
eventCells[i].observe("mousedown", startEventDraggingBound,
false);
}
},
attachToDayNode: function SEDC_attachToDayNode(dayNode) {
this.ghostController = new SOGoEventDragGhostController();
this.ghostController.setTitle(getLabel("New Event"));
var startEventDraggingBound
= this.startEventDragging.bindAsEventListener(this);
dayNode.observe("mousedown", startEventDraggingBound, false);
},
startEventDragging: function SEDC_startEventDragging(event) {
var target = getTarget(event);
if (target.nodeType == 1) {
if ((!this.eventCells && target.hasClassName("clickableHourCell"))
|| (this.eventCells && this.eventCells[0].editable)) {
var utilities = SOGoEventDragUtilities();
utilities.reset();
this.pointerHandler = new SOGoEventDragPointerHandler();
this.pointerHandler.initFromEvent(event);
var coordinates = new SOGoEventDragEventCoordinates();
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);
this.scrollController = new SOGoScrollController();
this.scrollController.setPointerHandler(this.pointerHandler);
// if (!this.eventCell)
// this.originalStart = Math.floor(this.origY / this.quarterHeight);
this.stopEventDraggingBound
= this.stopEventDragging.bindAsEventListener(this);
if (Prototype.Browser.IE)
Event.observe(document.body,
"mouseup", this.stopEventDraggingBound);
else
Event.observe(window, "mouseup", this.stopEventDraggingBound);
this.moveBound = this.move.bindAsEventListener(this);
Event.observe(document.body, "mousemove", this.moveBound);
}
Event.stop(event);
}
return false;
},
_determineDragMode: function SEDC__determineDragMode() {
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();
var 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;
},
_determineTitleAndFolderClass: function SEDC__dTAFC() {
var title = "";
var folderClass = "";
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")) {
title = this._determineTitleFromDIV(div);
folderClass = this._determineFolderClassFromDIV(div);
}
}
}
this.title = title;
this.folderClass = folderClass;
},
_determineTitleFromDIV: function SEDC__determineTitleFromDIV(div) {
var title = "";
var insideDivs = div.childNodesWithTag("div");
for (var i = 0; i < insideDivs.length; i++) {
var insideDiv = insideDivs[i];
if (insideDiv.hasClassName("text")) {
var currentNode = insideDiv.firstChild;
while (currentNode) {
title += currentNode.nodeValue;
currentNode = currentNode.nextSibling;
}
title = title.trim();
}
}
return title;
},
_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;
},
stopEventDragging: function SEDC_stopEventDragging(event) {
if (Prototype.Browser.IE)
Event.stopObserving(document.body, "mouseup", this.stopEventDraggingBound);
else
Event.stopObserving(window, "mouseup", this.stopEventDraggingBound);
Event.stopObserving(document.body, "mousemove", this.moveBound);
this.stopEventDraggingBound = null;
this.moveBound = null;
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 utilities = SOGoEventDragUtilities();
var dayEventNodes = utilities.getDayEventNodes();
var dayNode = dayEventNodes[this.ghostController
.currentCoordinates
.dayNumber]
.parentNode;
this.createDropCallback(this,
dayNode.readAttribute("day"),
this.ghostController.currentCoordinates);
}
}
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;
},
move: function SEDC_move(event) {
this.pointerHandler.updateFromEvent(event);
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);
}
};

View File

@ -11,6 +11,10 @@ function onThisButtonClick(event) {
else if (action == 'delete')
window.opener.performEventDeletion(calendarFolder, componentName,
recurrenceName);
else if (action == 'adjust') {
window.opener.performEventAdjustment(calendarFolder, componentName,
recurrenceName, queryParameters);
}
else
window.alert("Invalid action: " + action);
@ -22,6 +26,9 @@ function onAllButtonClick(event) {
window.opener.performEventEdition(calendarFolder, componentName);
else if (action == 'delete')
window.opener.performEventDeletion(calendarFolder, componentName);
else if (action == 'adjust')
window.opener.performEventAdjustment(calendarFolder, componentName,
null, queryParameters);
else
window.alert("Invalid action: " + action);

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

View File

@ -493,6 +493,9 @@ LI[class~="_selected"].denied
background-color: #f33;
}
DIV.hidden
{ visibility: hidden; };
/* folder tree (js) )*/
DIV.dTreeNode A SPAN.nodeName
{
@ -785,7 +788,6 @@ DIV.tab
margin-top: 24px;
overflow: hidden; }
/* Toolbar */
DIV#toolbar
{ left: 0px;

View File

@ -406,48 +406,6 @@ function refreshOpener() {
}
}
/* query string */
function parseQueryString() {
var queryArray, queryDict
var key, value, s, idx;
queryDict.length = 0;
queryDict = new Array();
queryArray = location.search.substr(1).split('&');
for (var i in queryArray) {
if (!queryArray[i]) continue ;
s = queryArray[i];
idx = s.indexOf("=");
if (idx == -1) {
key = s;
value = "";
}
else {
key = s.substr(0, idx);
value = unescape(s.substr(idx + 1));
}
if (typeof queryDict[key] == 'undefined')
queryDict.length++;
queryDict[key] = value;
}
return queryDict;
}
function generateQueryString(queryDict) {
var s = "";
for (var key in queryDict) {
if (s.length == 0)
s = "?";
else
s = s + "&";
s = s + key + "=" + escape(queryDict[key]);
}
return s;
}
/* selection mechanism */
function deselectAll(parent) {
@ -676,6 +634,24 @@ function onMenuEntryClick(event) {
return false;
}
/* query string */
function generateQueryString(queryDict) {
var s = "";
for (var key in queryDict) {
var value = queryDict[key];
if (typeof(value) == "string"
|| typeof(value) == "number") {
if (s.length == 0)
s = "?";
else
s = s + "&";
s = s + key + "=" + escape(value);
}
}
return s;
}
function parseQueryParameters(url) {
var parameters = new Array();
@ -708,11 +684,6 @@ function onBodyKeyDown(event) {
}
}
function onLogDblClick(event) {
var logConsole = $("logConsole");
logConsole.innerHTML = "";
}
function toggleLogConsole(event) {
var logConsole = $("logConsole");
var display = '' + logConsole.style.display;
@ -749,6 +720,15 @@ function log(message) {
}
}
function logOnly(message) {
log("\c");
log(message);
}
function onLogDblClick(event) {
log("\c");
}
function backtrace() {
var func = backtrace.caller;
var str = "backtrace:\n";