2004-10-26 22:25:41 +04:00
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is OEone Calendar Code, released October 31st, 2001.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* OEone Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2001
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s): Garth Smedley <garths@oeone.com>
|
|
|
|
* Mike Potter <mikep@oeone.com>
|
|
|
|
* Chris Charabaruk <coldacid@meldstar.com>
|
|
|
|
* Colin Phillips <colinp@oeone.com>
|
|
|
|
* Karl Guertin <grayrest@grayrest.com>
|
|
|
|
* Mike Norton <xor@ivwnet.com>
|
|
|
|
* ArentJan Banck <ajbanck@planet.nl>
|
|
|
|
* Eric Belhaire <belhaire@ief.u-psud.fr>
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
/** Code which generates event and task (todo) preview tooltips/titletips
|
|
|
|
when the mouse hovers over either the event list, the task list, or
|
|
|
|
an event or task box in one of the grid views.
|
|
|
|
|
|
|
|
(Portions of this code were previously in calendar.js and unifinder.js,
|
|
|
|
some of it duplicated.)
|
|
|
|
**/
|
|
|
|
|
2005-06-01 17:33:25 +04:00
|
|
|
/** PUBLIC
|
|
|
|
*
|
|
|
|
* This changes the mouseover preview based on the start and end dates
|
|
|
|
* of an occurrence of a (one-time or recurring) calEvent or calToDo.
|
|
|
|
* Used by all grid views.
|
|
|
|
*/
|
|
|
|
|
|
|
|
function onMouseOverGridOccurrence( occurrenceBoxMouseEvent )
|
|
|
|
{
|
|
|
|
if ("occurrence" in occurrenceBoxMouseEvent.currentTarget) {
|
|
|
|
// occurrence of repeating event or todo
|
|
|
|
var occurrence = occurrenceBoxMouseEvent.currentTarget.occurrence;
|
2005-06-16 13:23:41 +04:00
|
|
|
var item = occurrence;
|
|
|
|
var start = occurrence.startDate.jsDate;
|
|
|
|
var endEx = occurrence.endDate.jsDate;
|
2005-06-01 17:33:25 +04:00
|
|
|
|
|
|
|
const toolTip = document.getElementById( "gridOccurrenceTooltip" );
|
|
|
|
var holderBox = null;
|
|
|
|
if (isEvent(item)) {
|
|
|
|
holderBox = getPreviewForEvent(item, start, endEx);
|
|
|
|
} else if (isToDo(item)) {
|
|
|
|
holderBox = getPreviewForToDo(item, start, endEx);
|
|
|
|
}
|
|
|
|
if (holderBox) {
|
|
|
|
setToolTipContent(toolTip, holderBox);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-06-01 16:55:50 +04:00
|
|
|
/** For all instances of an event, as displayed by unifinder. **/
|
|
|
|
function onMouseOverEventTree( toolTip, mouseEvent )
|
|
|
|
{
|
|
|
|
var item = getCalendarEventFromEvent( mouseEvent );
|
|
|
|
if (isEvent(item)) {
|
|
|
|
var holderBox = getPreviewForEvent(item);
|
|
|
|
if (holderBox) {
|
|
|
|
setToolTipContent(toolTip, holderBox);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** For all instances of a task, as displayed by unifinderToDo. **/
|
|
|
|
function onMouseOverTaskTree( toolTip, mouseEvent )
|
|
|
|
{
|
|
|
|
var item = getToDoFromEvent( mouseEvent );
|
|
|
|
if (isToDo(item)) {
|
|
|
|
var holderBox = getPreviewForTask(item);
|
|
|
|
if (holderBox) {
|
|
|
|
setToolTipContent(toolTip, holderBox);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** add newContentBox,
|
|
|
|
*/
|
|
|
|
function setToolTipContent(toolTip, holderBox)
|
|
|
|
{
|
|
|
|
while (toolTip.hasChildNodes())
|
|
|
|
toolTip.removeChild( toolTip.firstChild );
|
|
|
|
toolTip.appendChild( holderBox );
|
|
|
|
}
|
|
|
|
|
2004-10-26 22:25:41 +04:00
|
|
|
/**
|
|
|
|
* Called when a user hovers over a todo element and the text for the mouse over is changed.
|
|
|
|
*/
|
|
|
|
|
|
|
|
function getPreviewForTask( toDoItem )
|
|
|
|
{
|
|
|
|
if( toDoItem )
|
|
|
|
{
|
|
|
|
const vbox = document.createElement( "vbox" );
|
|
|
|
boxInitializeHeaderGrid(vbox);
|
|
|
|
|
|
|
|
var hasHeader = false;
|
|
|
|
|
|
|
|
if (toDoItem.title)
|
|
|
|
{
|
|
|
|
boxAppendLabeledText(vbox, "tooltipTitle", toDoItem.title);
|
|
|
|
hasHeader = true;
|
|
|
|
}
|
|
|
|
|
2005-05-24 23:07:19 +04:00
|
|
|
var location = toDoItem.getProperty("LOCATION");
|
|
|
|
if (location)
|
2004-10-26 22:25:41 +04:00
|
|
|
{
|
2005-05-24 23:07:19 +04:00
|
|
|
boxAppendLabeledText(vbox, "tooltipLocation", location);
|
2004-10-26 22:25:41 +04:00
|
|
|
hasHeader = true;
|
|
|
|
}
|
|
|
|
|
2005-06-16 13:23:41 +04:00
|
|
|
if (toDoItem.entryDate && toDoItem.entryDate.isValid)
|
2004-10-26 22:25:41 +04:00
|
|
|
{
|
2005-01-05 01:49:12 +03:00
|
|
|
var startDate = toDoItem.entryDate.jsDate;
|
|
|
|
boxAppendLabeledDateTime(vbox, "tooltipStart", startDate, false);
|
2004-10-26 22:25:41 +04:00
|
|
|
hasHeader = true;
|
|
|
|
}
|
|
|
|
|
2005-06-16 13:23:41 +04:00
|
|
|
if (toDoItem.dueDat && toDoItem.dueDate.isValid)
|
2004-10-26 22:25:41 +04:00
|
|
|
{
|
2005-01-05 01:49:12 +03:00
|
|
|
var dueDate = toDoItem.dueDate.jsDate;
|
|
|
|
boxAppendLabeledDateTime(vbox, "tooltipDue", dueDate, false);
|
2004-10-26 22:25:41 +04:00
|
|
|
hasHeader = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (toDoItem.priority && toDoItem.priority != 0)
|
|
|
|
{
|
|
|
|
boxAppendLabeledText(vbox, "tooltipPriority", String(toDoItem.priority));
|
|
|
|
hasHeader = true;
|
|
|
|
}
|
|
|
|
|
2005-01-05 01:49:12 +03:00
|
|
|
if (toDoItem.status && toDoItem.status != "NONE")
|
2004-10-26 22:25:41 +04:00
|
|
|
{
|
|
|
|
var status = getToDoStatusString(toDoItem);
|
|
|
|
boxAppendLabeledText(vbox, "tooltipStatus", status);
|
|
|
|
hasHeader = true;
|
|
|
|
}
|
|
|
|
|
2005-01-05 01:49:12 +03:00
|
|
|
if (toDoItem.percentComplete != 0 && toDoItem.percentComplete != 100)
|
2004-10-26 22:25:41 +04:00
|
|
|
{
|
2005-01-05 01:49:12 +03:00
|
|
|
boxAppendLabeledText(vbox, "tooltipPercent", String(toDoItem.percentComplete)+"%");
|
2004-10-26 22:25:41 +04:00
|
|
|
hasHeader = true;
|
2005-01-05 01:49:12 +03:00
|
|
|
} else if (toDoItem.percentComplete == 100)
|
2004-10-26 22:25:41 +04:00
|
|
|
{
|
2005-01-05 01:49:12 +03:00
|
|
|
var completedDate = toDoItem.completedDate.jsDate;
|
|
|
|
boxAppendLabeledDateTime(vbox, "tooltipCompleted", completedDate, false);
|
2004-10-26 22:25:41 +04:00
|
|
|
hasHeader = true;
|
|
|
|
}
|
|
|
|
|
2005-05-24 23:07:19 +04:00
|
|
|
var description = toDoItem.getProperty("DESCRIPTION");
|
2005-01-05 01:49:12 +03:00
|
|
|
if (description)
|
2004-10-26 22:25:41 +04:00
|
|
|
{
|
|
|
|
// display up to 4 description lines like body of message below headers
|
|
|
|
if (hasHeader)
|
|
|
|
boxAppendText(vbox, "");
|
|
|
|
|
2005-01-05 01:49:12 +03:00
|
|
|
boxAppendLines(vbox, description, 4);
|
2004-10-26 22:25:41 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return ( vbox );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called when mouse moves over a different, or
|
|
|
|
* when mouse moves over event in event list.
|
|
|
|
* The instStartDate is date of instance displayed at event box
|
|
|
|
* (recurring or multiday events may be displayed by more than one event box
|
|
|
|
* for different days), or null if should compute next instance from now.
|
|
|
|
*/
|
|
|
|
function getPreviewForEvent( event, instStartDate, instEndDate )
|
|
|
|
{
|
|
|
|
const vbox = document.createElement( "vbox" );
|
|
|
|
boxInitializeHeaderGrid(vbox);
|
2005-03-26 14:19:20 +03:00
|
|
|
|
2004-10-26 22:25:41 +04:00
|
|
|
if (event)
|
|
|
|
{
|
|
|
|
if (event.title)
|
|
|
|
{
|
|
|
|
boxAppendLabeledText(vbox, "tooltipTitle", event.title);
|
|
|
|
}
|
|
|
|
|
2005-03-27 18:34:46 +04:00
|
|
|
var location = event.getProperty("LOCATION");
|
|
|
|
if (location)
|
2004-10-26 22:25:41 +04:00
|
|
|
{
|
2005-03-26 14:19:20 +03:00
|
|
|
boxAppendLabeledText(vbox, "tooltipLocation", location);
|
2004-10-26 22:25:41 +04:00
|
|
|
}
|
|
|
|
|
2005-04-05 01:04:42 +04:00
|
|
|
if (event.startDate || instStartDate)
|
2004-10-26 22:25:41 +04:00
|
|
|
{
|
2005-04-05 01:04:42 +04:00
|
|
|
var eventStart = new Date(event.startDate.jsDate);
|
|
|
|
var eventEnd = event.endDate && new Date(event.endDate.jsDate);
|
|
|
|
if (event.isAllDay && eventEnd) {
|
2004-10-26 22:25:41 +04:00
|
|
|
eventEnd.setDate(eventEnd.getDate() - 1);
|
|
|
|
}
|
|
|
|
var relativeToDate;
|
|
|
|
|
|
|
|
if (!eventEnd ||
|
|
|
|
gCalendarWindow.dateFormater.isOnSameDate(eventStart, eventEnd)) {
|
|
|
|
// event within single day, ok to omit dates if same as relativeToDate
|
|
|
|
relativeToDate = instStartDate || new Date(); // today
|
|
|
|
} else {
|
|
|
|
// event spanning multiple days, do not omit dates.
|
|
|
|
relativeToDate = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
var startDate, endDate;
|
|
|
|
if (instStartDate && instEndDate) {
|
|
|
|
startDate = instStartDate;
|
|
|
|
endDate = instEndDate;
|
|
|
|
} else {
|
|
|
|
// Event may be recurrent event. If no displayed instance specified,
|
|
|
|
// use next instance, or previous instance if no next instance.
|
|
|
|
startDate = instStartDate || getCurrentNextOrPreviousRecurrence(event);
|
2005-04-05 01:04:42 +04:00
|
|
|
var eventDuration = (event.endDate
|
|
|
|
? event.endDate.jsDate - event.startDate.jsDate
|
2004-10-26 22:25:41 +04:00
|
|
|
: 0);
|
|
|
|
endDate = new Date(startDate.getTime() + eventDuration);
|
|
|
|
}
|
|
|
|
boxAppendLabeledDateTimeInterval(vbox, "tooltipDate",
|
2005-04-05 01:04:42 +04:00
|
|
|
startDate, endDate, event.isAllDay,
|
2004-10-26 22:25:41 +04:00
|
|
|
relativeToDate);
|
|
|
|
}
|
|
|
|
|
2005-04-12 19:46:00 +04:00
|
|
|
if (event.status && event.status != "NONE")
|
2004-10-26 22:25:41 +04:00
|
|
|
{
|
|
|
|
var statusString = getEventStatusString(event);
|
|
|
|
boxAppendLabeledText(vbox, "tooltipStatus", statusString);
|
|
|
|
}
|
|
|
|
|
2005-03-27 18:34:46 +04:00
|
|
|
var description = event.getProperty("DESCRIPTION");
|
|
|
|
if (description)
|
2004-10-26 22:25:41 +04:00
|
|
|
{
|
|
|
|
// display up to 4 description lines, like body of message below headers
|
|
|
|
boxAppendText(vbox, "");
|
2005-03-26 14:19:20 +03:00
|
|
|
boxAppendLines(vbox, description, 4);
|
2004-10-26 22:25:41 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return ( vbox );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** String for event status: (none), Tentative, Confirmed, or Cancelled **/
|
|
|
|
function getEventStatusString(calendarEvent)
|
|
|
|
{
|
|
|
|
switch( calendarEvent.status )
|
|
|
|
{
|
2005-04-12 19:46:00 +04:00
|
|
|
// Event status value keywords are specified in RFC2445sec4.8.1.11
|
|
|
|
case "TENTATIVE":
|
|
|
|
return gCalendarBundle.getString("statusTentative");
|
|
|
|
case "CONFIRMED":
|
|
|
|
return gCalendarBundle.getString("statusConfirmed");
|
|
|
|
case "CANCELLED":
|
|
|
|
return gCalendarBundle.getString("statusCancelled");
|
2004-10-26 22:25:41 +04:00
|
|
|
default:
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** String for todo status: (none), NeedsAction, InProcess, Cancelled, or Completed **/
|
|
|
|
function getToDoStatusString(iCalToDo)
|
|
|
|
{
|
|
|
|
switch( iCalToDo.status )
|
|
|
|
{
|
2005-04-12 19:46:00 +04:00
|
|
|
// Todo status keywords are specified in RFC2445sec4.8.1.11
|
|
|
|
case "NEEDS-ACTION":
|
|
|
|
return gCalendarBundle.getString("statusNeedsAction");
|
|
|
|
case "IN-PROCESS":
|
|
|
|
return gCalendarBundle.getString("statusInProcess");
|
|
|
|
case "CANCELLED":
|
|
|
|
return gCalendarBundle.getString("statusCancelled");
|
|
|
|
case "COMPLETED":
|
|
|
|
return gCalendarBundle.getString("statusCompleted");
|
2004-10-26 22:25:41 +04:00
|
|
|
default:
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** PRIVATE: Append 1 line of text to box inside an xul description node containing a single text node **/
|
|
|
|
function boxAppendText(box, textString)
|
|
|
|
{
|
|
|
|
var textNode = document.createTextNode(textString);
|
|
|
|
var xulDescription = document.createElement("description");
|
|
|
|
xulDescription.setAttribute("class", "tooltipBody");
|
|
|
|
xulDescription.appendChild(textNode);
|
|
|
|
box.appendChild(xulDescription);
|
|
|
|
}
|
|
|
|
/** PRIVATE: Append multiple lines of text to box, each line inside an xul description node containing a single text node **/
|
|
|
|
function boxAppendLines(vbox, textString, maxLineCount)
|
|
|
|
{
|
|
|
|
if (!maxLineCount)
|
|
|
|
maxLineCount = 4;
|
|
|
|
|
|
|
|
// trim trailing whitespace
|
|
|
|
var end = textString.length;
|
|
|
|
for (; end > 0; end--)
|
|
|
|
if (" \t\r\n".indexOf(textString.charAt(end - 1)) == -1)
|
|
|
|
break;
|
|
|
|
textString = textString.substring(0, end);
|
|
|
|
|
|
|
|
var lines = textString.split("\n");
|
|
|
|
var lineCount = lines.length;
|
|
|
|
if( lineCount > maxLineCount ) {
|
|
|
|
lineCount = maxLineCount;
|
|
|
|
lines[ maxLineCount ] = "..." ;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (var i = 0; i < lineCount; i++) {
|
|
|
|
boxAppendText(vbox, lines[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/** PRIVATE: Use dateFormater to format date and time.
|
|
|
|
Append date to box inside an xul description node containing a single text node. **/
|
|
|
|
function boxAppendLabeledDateTime(box, labelProperty, date, isAllDay )
|
|
|
|
{
|
|
|
|
var jsDate = new Date(date.getTime());
|
|
|
|
var formattedDateTime = gCalendarWindow.dateFormater.formatDateTime( jsDate, true, isAllDay );
|
|
|
|
boxAppendLabeledText(box, labelProperty, formattedDateTime);
|
|
|
|
}
|
|
|
|
/** PRIVATE: Use dateFormater to format date and time interval.
|
|
|
|
Append interval to box inside an xul description node containing a single text node. **/
|
|
|
|
function boxAppendLabeledDateTimeInterval(box, labelProperty, start, end, isAllDay, relativeToDate)
|
|
|
|
{
|
|
|
|
var formattedInterval = gCalendarWindow.dateFormater.formatInterval( start, end, isAllDay, relativeToDate);
|
|
|
|
boxAppendLabeledText(box, labelProperty, formattedInterval);
|
|
|
|
}
|
|
|
|
|
|
|
|
function boxInitializeHeaderGrid(box)
|
|
|
|
{
|
|
|
|
var grid = document.createElement("grid");
|
|
|
|
var rows;
|
|
|
|
{
|
|
|
|
var columns = document.createElement("columns");
|
|
|
|
{
|
|
|
|
columns.appendChild(document.createElement("column"));
|
|
|
|
columns.appendChild(document.createElement("column"));
|
|
|
|
}
|
|
|
|
grid.appendChild(columns);
|
|
|
|
rows = document.createElement("rows");
|
|
|
|
grid.appendChild(rows);
|
|
|
|
}
|
|
|
|
box.appendChild(grid);
|
|
|
|
}
|
|
|
|
|
|
|
|
function boxAppendLabeledText(box, labelProperty, textString)
|
|
|
|
{
|
|
|
|
var labelText = gCalendarBundle.getString(labelProperty);
|
|
|
|
var rows = box.getElementsByTagName("rows")[0];
|
|
|
|
{
|
|
|
|
var row = document.createElement("row");
|
|
|
|
{
|
|
|
|
row.appendChild(createTooltipHeaderLabel(labelText));
|
|
|
|
row.appendChild(createTooltipHeaderDescription(textString));
|
|
|
|
}
|
|
|
|
rows.appendChild(row);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function createTooltipHeaderLabel(text)
|
|
|
|
{
|
|
|
|
var label = document.createElement("label");
|
|
|
|
label.setAttribute("class", "tooltipHeaderLabel");
|
|
|
|
label.appendChild(document.createTextNode(text));
|
|
|
|
return label;
|
|
|
|
}
|
|
|
|
|
|
|
|
function createTooltipHeaderDescription(text)
|
|
|
|
{
|
|
|
|
var label = document.createElement("description");
|
|
|
|
label.setAttribute("class", "tooltipHeaderDescription");
|
|
|
|
label.appendChild(document.createTextNode(text));
|
|
|
|
return label;
|
|
|
|
}
|