Fixing import export bugs.

This commit is contained in:
mikep%oeone.com 2002-08-15 20:14:46 +00:00
parent 959f7765c8
commit 231abc4a95
15 changed files with 1143 additions and 117 deletions

View File

@ -78,7 +78,7 @@ h1 {
<td id="mozver">
<h1>
<a id="mozlink" href="http://www.mozilla.org/projects/calendar/" target="_new">Mozilla Calendar 2002073111-cal</a>
<a id="mozlink" href="http://www.mozilla.org/projects/calendar/" target="_new">Mozilla Calendar 2002081513-cal</a>
</h1>
<script type="application/x-javascript">
// using try..catch to handle empty useragents and other cases where the regex fails to apply

View File

@ -664,9 +664,9 @@ function changeToolTipTextForToDo( event )
DateHtml.appendChild( DateText );
HolderBox.appendChild( DateHtml );
var DateHtml = document.createElement( "description" );
DateHtml = document.createElement( "description" );
var dueDate = new Date( toDoItem.due.getTime() );
var DateText = document.createTextNode( "Due Date: "+gCalendarWindow.dateFormater.getFormatedDate( dueDate ) );
DateText = document.createTextNode( "Due Date: "+gCalendarWindow.dateFormater.getFormatedDate( dueDate ) );
DateHtml.appendChild( DateText );
HolderBox.appendChild( DateHtml );
@ -720,9 +720,9 @@ function getPreviewText( calendarEvent )
DateHtml.appendChild( DateText );
HolderBox.appendChild( DateHtml );
var DateHtml = document.createElement( "description" );
DateHtml = document.createElement( "description" );
var endDate = new Date( calendarEvent.end.getTime() );
var DateText = document.createTextNode( "End: "+gCalendarWindow.dateFormater.getFormatedDate( endDate )+" "+gCalendarWindow.dateFormater.getFormatedTime( endDate ) );
DateText = document.createTextNode( "End: "+gCalendarWindow.dateFormater.getFormatedDate( endDate )+" "+gCalendarWindow.dateFormater.getFormatedTime( endDate ) );
DateHtml.appendChild( DateText );
HolderBox.appendChild( DateHtml );
@ -774,3 +774,80 @@ function reloadApplication()
{
gCalendarWindow.currentView.refreshEvents();
}
/** PUBLIC
*
* Print events using a stylesheet.
* Mostly Hack to get going, Should probably be rewritten later when stylesheets are available
* XXX Is it possible to directly load the document into a window without tempfile?
*/
var printWindow;
var tempfile;
// the print is called with a timeout, otherwise the document isn't loaded before printing.
// onload event didn't seem to fire.
function delayedPrint()
{
printWindow.print();
printWindow.close();
if( tempfile.exists() )
tempfile.remove( false );
}
// returns a nsIFile object of a unique file in the temp directory
function makeTempFile( extension )
{
const osTempDir = "TmpD";
const flContractID = "@mozilla.org/file/directory_service;1";
const flIID = Components.interfaces.nsIProperties;
var fileLocator = Components.classes[flContractID].getService(flIID);
var tempFile = fileLocator.get(osTempDir, Components.interfaces.nsIFile);
tempFile.append("~tmp" + Math.floor(Math.random() * 1000) + extension );
return tempFile;
}
function printEventArray( calendarEventArray, stylesheet )
{
var xcsDocument = getXcsDocument( calendarEventArray );
var newProcessInstruction = xcsDocument.createProcessingInstruction(
"xml-stylesheet",
"href=\"" + stylesheet + "\" type=\"text/xsl\"");
xcsDocument.insertBefore(newProcessInstruction, xcsDocument.firstChild);
newProcessInstruction = xcsDocument.createProcessingInstruction(
"xml", "version=\"1.0\" encoding=\"UTF-8\"");
xcsDocument.insertBefore(newProcessInstruction, xcsDocument.firstChild);
var serializer = new XMLSerializer;
var serialDocument = serializer.serializeToString ( xcsDocument );
// XXX TODO Can we directly load the xml-document into a window???
tempfile = makeTempFile( ".xml" );
saveDataToFile(tempfile.path, serialDocument);
var tempfileUrl = Components.classes["@mozilla.org/network/standard-url;1"].createInstance(Components.interfaces.nsIFileURL);
tempfileUrl.file = tempfile;
printWindow = window.open( tempfileUrl.spec );
if( printWindow )
{
printWindow.locationbar.visible = false;
printWindow.personalbar.visible = false;
printWindow.statusbar.visible = false;
printWindow.toolbar.visible = false;
// XXX HACK open is async, find a way to detect if content is loaded
// using onload doesn't fire?
setTimeout("delayedPrint()", 1000);
}
}
function print()
{
printEventArray(
gCalendarWindow.EventSelection.selectedEvents, "chrome://calendar/content/converters/sortEvents.xsl" );
}

View File

@ -87,6 +87,7 @@
<command id="delete_command_no_confirm" oncommand="unifinderDeleteCommand( true )" disabled="true"/>
<command id="modify_command" oncommand="unifinderEditCommand()" disabled="true"/>
<command id="send_event_command" oncommand="sendEvent()" disabled="true"/>
<command id="print_command" oncommand="print()" disabled="true"/>
<command id="cut_command" oncommand="cutToClipboard()" disabled="true"/>
<command id="copy_command" oncommand="copyToClipboard()" disabled="true"/>
<command id="paste_command" oncommand="pasteFromClipboard()"/>
@ -114,6 +115,7 @@
<key id="new_event_key" key="N" modifiers="control" observes="new_command"/>
<key id="new_todo_key" key="M" modifiers="control" observes="new_todo_command"/>
<key id="modify_event_key" key="E" modifiers="control" observes="modify_command"/>
<key id="print_key" key="P" modifiers="control" observes="print_command"/>
<key id="import_key" key="I" modifiers="control" observes="import_command"/>
<key id="export_key" key="O" modifiers="control" observes="export_command"/>

View File

@ -155,10 +155,6 @@ DayView.prototype.refreshEvents = function( )
//}
//TextNode.setAttribute( "value", "All-Day Events: " );
//set the seperator to nothing. After the first one, we'll change it to ", " so that we add commas between text.
var Seperator = " ";
// get the events for the day and loop through them
var dayEventList = this.calendarWindow.eventSource.getEventsForDay( this.calendarWindow.getSelectedDate() );
@ -247,10 +243,6 @@ DayView.prototype.refreshEvents = function( )
//note the use of the AllDayText Attribute.
//This is used to remove the text when the day is changed.
SeperatorNode = document.createElement( "label" );
SeperatorNode.setAttribute( "value", Seperator );
//SeperatorNode.setAttribute( "AllDayText", "true" );
newTextNode = document.createElement( "label" );
newTextNode.setAttribute( "value", eventText );
newTextNode.calendarEventDisplay = calendarEventDisplay;
@ -258,8 +250,7 @@ DayView.prototype.refreshEvents = function( )
newTextNode.setAttribute( "onclick", "dayEventItemClick( this, event )" );
newTextNode.setAttribute( "ondblclick", "dayEventItemDoubleClick( this, event )" );
newTextNode.setAttribute( "tooltip", "savetip" );
//newTextNode.setAttribute( "AllDayText", "true" );
newTextNode.setAttribute( "AllDayText", "true" );
newImage = document.createElement("image");
newImage.setAttribute( "class", "all-day-event-class" );
@ -270,12 +261,8 @@ DayView.prototype.refreshEvents = function( )
newImage.setAttribute( "tooltip", "savetip" );
//newImage.setAttribute( "AllDayText", "true" );
AllDayBox.appendChild( SeperatorNode );
AllDayBox.appendChild( newImage );
AllDayBox.appendChild( newTextNode );
//change the seperator to add commas after the text.
Seperator = ", ";
}
else
{

View File

@ -39,6 +39,8 @@
*
****/
// XSL stylesheet directory
var convertersDirectory = "chrome://calendar/content/converters/";
// File constants copied from file-utils.js
const MODE_RDONLY = 0x01;
@ -50,6 +52,21 @@ const MODE_TRUNCATE = 0x20;
const MODE_SYNC = 0x40;
const MODE_EXCL = 0x80;
const filterCalendar = "Calendar Files";
const extensionCalendar = ".ics";
const filterXcs = "iCalendar XML Document";
const extensionXcs = ".xcs";
const filterXml = "XML Document";
const extensionXml = ".xml";
const filterRtf = "Rich Text Format (RTF)";
const extensionRtf = ".rtf";
const filterHtml = "HTML Files";
const extensionHtml = ".html";
const filterCsv = "Comma Separated";
const extensionCsv = ".csv";
const filterRdf = "iCalendar RDF";
const extensionRdf = ".rdf";
/**** loadEventsFromFile
* shows a file dialog, read the selected file and tries to parse events from it.
@ -63,18 +80,27 @@ function loadEventsFromFile()
fp.init(window, "Open", nsIFilePicker.modeOpen);
// fp.defaultString = "*.ics";
fp.defaultExtension = "ics"
fp.appendFilter( "Calendar Files", "*.ics" );
fp.appendFilter( filterCalendar, "*" + extensionCalendar );
fp.appendFilter( filterXcs, "*" + extensionXcs );
fp.show();
if (fp.file && fp.file.path.length > 0)
{
var aDataStream = readDataFromFile( fp.file.path );
var calendarEventArray = parseIcalData( aDataStream );
var calendarEventArray;
switch (fp.filterIndex) {
case 0 : // ics
calendarEventArray = parseIcalData( aDataStream );
break;
case 1 : // xcs
calendarEventArray = parseXCSData( aDataStream );
break;
}
// Show a dialog with option to import events with or without dialogs
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
@ -89,17 +115,20 @@ function loadEventsFromFile()
null,null,null,null, result);
if(buttonPressed == 0) // YES
{
addEventsToCalendar( calendarEventArray );
}
addEventsToCalendar( calendarEventArray );
return true;
}
else if(buttonPressed == 1) // NO
{
addEventsToCalendar( calendarEventArray, true );
addEventsToCalendar( calendarEventArray, true );
return true;
}
else if(buttonPressed == 2) // CANCEL
{
return false;
}
}
return false;
}
@ -247,13 +276,13 @@ function parseIcalData( icalStr )
calendarEvent = createEvent();
// if parsing import iCalendar failed, add date as description
if ( !calendarEvent.parseIcalString(eventData) )
// parsing import iCalendar failed.
{
// initialize start and end dates.
initCalendarEvent( calendarEvent );
// Save clipboard text into description.
// Save the parsed text as description.
calendarEvent.description = icalStr;
}
@ -265,6 +294,20 @@ function parseIcalData( icalStr )
return calendarEventArray;
}
/**** parseXCSData
*
*/
function parseXCSData( xcsString )
{
var gParser = new DOMParser;
var xmlDocument = gParser.parseFromString(xcsString, 'text/xml');
var result = serializeDocument(xmlDocument, "xcs2ics.xsl");
return parseIcalData( result );
}
/**** readDataFromFile
*
@ -318,7 +361,7 @@ function readDataFromFile( aFilePath )
function saveEventsToFile( calendarEventArray )
{
if( !calendarEventArray)
var calendarEventArray = gCalendarWindow.EventSelection.selectedEvents;
calendarEventArray = gCalendarWindow.EventSelection.selectedEvents;
if (calendarEventArray.length == 0)
{
@ -328,38 +371,65 @@ function saveEventsToFile( calendarEventArray )
// No show the 'Save As' dialog and ask for a filename to save to
const nsIFilePicker = Components.interfaces.nsIFilePicker;
var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
// caller can force disable of sand box, even if ON globally
fp.init(window, "Save As", nsIFilePicker.modeSave);
fp.defaultString = "Mozilla Calendar events";
if(calendarEventArray.length == 1 && calendarEventArray[0].title)
fp.defaultString = calendarEventArray[0].title;
else
fp.defaultString = "Mozilla Calendar events";
fp.defaultExtension = "ics";
fp.appendFilter( "Calendar Files", "*.ics" );
fp.appendFilter( "Rich Text Format (RTF)", "*.rtf" );
fp.appendFilter( filterCalendar, "*" + extensionCalendar );
fp.appendFilter( filterRtf, "*" + extensionRtf );
fp.appendFilters(nsIFilePicker.filterHTML);
fp.appendFilter( filterCsv, "*" + extensionCsv );
fp.appendFilter( filterXcs, "*" + extensionXcs );
fp.appendFilter( filterRdf, "*" + extensionRdf );
fp.show();
// Now find out as what to save, convert the events and save to file.
if (fp.file && fp.file.path.length > 0)
{
var aDataStream;
var extension;
switch (fp.filterIndex) {
case 0 : // ics
aDataStream = eventArrayToICalString( calendarEventArray, true );
extension = extensionCalendar;
break;
case 1 : // rtf
aDataStream = eventArrayToRTF( calendarEventArray );
extension = extensionRtf;
break;
case 2 : // html
aDataStream = eventArrayToHTML( calendarEventArray );
extension = ".htm";
break;
case 3 : // csv
aDataStream = eventArrayToCsv( calendarEventArray );
extension = extensionCsv;
break;
case 4 : // xCal
aDataStream = eventArrayToXCS( calendarEventArray );
extension = extensionXcs;
break;
case 5 : // rdf
aDataStream = eventArrayToRdf( calendarEventArray );
extension = extensionRdf;
break;
}
saveDataToFile(fp.file.path, aDataStream);
var filePath = fp.file.path;
if(filePath.indexOf(".") == -1 )
filePath += extension;
saveDataToFile(filePath, aDataStream);
}
}
@ -485,6 +555,74 @@ function eventArrayToRTF( calendarEventArray )
}
/**** eventArrayToXML
* Converts a array of events to a XML string
*/
/*
function eventArrayToXML( calendarEventArray )
{
var xmlDocument = getXmlDocument( calendarEventArray );
var serializer = new XMLSerializer;
return serializer.serializeToString (xmlDocument )
}
*/
/**** eventArrayToCsv
* Converts a array of events to comma delimited text.
*/
function eventArrayToCsv( calendarEventArray )
{
var xcsDocument = getXcsDocument( calendarEventArray );
return serializeDocument( xcsDocument, "xcs2csv.xsl" );
}
/**** eventArrayToRdf
* Converts a array of events to RDF
*/
function eventArrayToRdf( calendarEventArray )
{
var xcsDocument = getXcsDocument( calendarEventArray );
return serializeDocument( xcsDocument, "xcs2rdf.xsl" );
}
/**** eventArrayToXCS
* Converts a array of events to a xCal string
*/
function eventArrayToXCS( calendarEventArray )
{
var xmlDoc = getXmlDocument( calendarEventArray );
var xcsDoc = transformXML( xmlDoc, "xml2xcs.xsl" );
// add the doctype
/* Doctype uri blocks excel import
var newdoctype = xcsDoc.implementation.createDocumentType(
"iCalendar",
"-//IETF//DTD XCAL//iCalendar XML//EN",
"http://www.ietf.org/internet-drafts/draft-ietf-calsch-many-xcal-02.txt");
if (newdoctype)
xcsDoc.insertBefore(newdoctype, xcsDoc.firstChild);
*/
var serializer = new XMLSerializer;
// XXX MAJOR UGLY HACK!! Serializer doesn't insert XML Declaration
// http://bugzilla.mozilla.org/show_bug.cgi?id=63558
var serialDocument = serializer.serializeToString ( xcsDoc );
if( serialDocument.indexOf( "<?xml" ) == -1 )
serialDocument = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + serialDocument;
return serialDocument;
// return serializer.serializeToString ( xcsDoc )
}
/**** saveDataToFile
*
* Save data to a file. Creates a new file or overwrites an existing file.
@ -500,7 +638,7 @@ function saveDataToFile(aFilePath, aDataStream)
var localFileInstance;
var outputStream;
LocalFileInstance = Components.classes[LOCALFILE_CTRID].createInstance(nsILocalFile);
var LocalFileInstance = Components.classes[LOCALFILE_CTRID].createInstance(nsILocalFile);
LocalFileInstance.initWithPath(aFilePath);
outputStream = Components.classes[FILEOUT_CTRID].createInstance(nsIFileOutputStream);
@ -516,3 +654,332 @@ function saveDataToFile(aFilePath, aDataStream)
alert("Unable to write to file: " + aFilePath );
}
}
////////////////////////////////////
// XML/XSL functions //
////////////////////////////////////
/**
* Get the local path to the chrome directory
*/
/*
function getChromeDir()
{
const JS_DIR_UTILS_FILE_DIR_CID = "@mozilla.org/file/directory_service;1";
const JS_DIR_UTILS_I_PROPS = "nsIProperties";
const JS_DIR_UTILS_DIR = new Components.Constructor(JS_DIR_UTILS_FILE_DIR_CID, JS_DIR_UTILS_I_PROPS);
const JS_DIR_UTILS_CHROME_DIR = "AChrom";
var rv;
try
{
rv=(new JS_DIR_UTILS_DIR()).get(JS_DIR_UTILS_CHROME_DIR, Components.interfaces.nsIFile);
}
catch (e)
{
//jslibError(e, "(unexpected error)", "NS_ERROR_FAILURE", JS_DIR_UTILS_FILE+":getChromeDir");
rv=null;
}
return rv;
}
function getTemplatesPath( templateName )
{
var templatesDir = getChromeDir();
templatesDir.append( "calendar" );
templatesDir.append( "content" );
templatesDir.append( "templates" );
templatesDir.append( templateName );
return templatesDir.path;
}
function xslt(xmlUri, xslUri)
{
// TODO: Check uri's for CHROME:// and convert path to local path
var xslProc = new XSLTProcessor();
var result = document.implementation.createDocument("", "", null);
var xmlDoc = document.implementation.createDocument("", "", null);
var xslDoc = document.implementation.createDocument("", "", null);
xmlDoc.load(xmlUri, "text/xml");
xslDoc.load(xslUri, "text/xml");
xslProc.transformDocument(xmlDoc, xslDoc, result, null);
return result;
}
*/
/** PRIVATE
*
* Opens a file and returns the content
* It supports Uri's like chrome://
*/
function loadFile(aUriSpec)
{
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var serv = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
if (!serv) {
throw Components.results.ERR_FAILURE;
}
var chan = serv.newChannel(aUriSpec, null, null);
var instream =
Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
instream.init(chan.open());
return instream.read(instream.available());
}
/** PUBLIC GetXcsDocument
*
*/
function getXcsDocument( calendarEventArray )
{
var xmlDocument = getXmlDocument( calendarEventArray );
var xcsDocument = transformXML( xmlDocument, "xml2xcs.xsl" );
var processingInstruction = xcsDocument.createProcessingInstruction(
"xml", "version=\"1.0\" encoding=\"UTF-8\"");
// xcsDocument.insertBefore(processingInstruction, xcsDocument.firstChild);
return xcsDocument;
}
/** PUBLIC
*
* Opens a xsl transformation file and applies it to xmlDocuments.
* xslFile can be in the convertersDirectory, or a full Uri
* Returns the resulting document
*/
function transformXML( xmlDocument, xslFilename )
{
var xslProc = new XSLTProcessor();
var gParser = new DOMParser;
// .load isn't synchrone
// var xslDoc = document.implementation.createDocument("", "", null);
// xslDoc.load(path, "text/xml");
// if only passsed a filename, assume it is a file in the default directory
if( xslFilename.indexOf( ":" ) == -1 )
xslFilename = convertersDirectory + xslFilename;
var xslContent = loadFile( xslFilename );
var xslDocument = gParser.parseFromString(xslContent, 'text/xml');
var result = document.implementation.createDocument("", "", null);
xslProc.transformDocument(xmlDocument, xslDocument, result, null);
return result;
}
/** PUBLIC
*
* Serializes a DOM document.if stylesheet is null, returns the document serialized
* Applies the stylesheet when available, and return the serialized transformed document,
* or the transformiix data
*/
function serializeDocument( xmlDocument, stylesheet )
{
var serializer = new XMLSerializer;
if( stylesheet )
{
var resultDocument = transformXML( xmlDocument, stylesheet );
var transformiixResult = resultDocument.getElementById( "transformiixResult" );
if( transformiixResult && transformiixResult.hasChildNodes() )
{ // It's a document starting with:
// <a0:html xmlns:a0="http://www.w3.org/1999/xhtml">
// <a0:head/><a0:body><a0:pre id="transformiixResult">
var textNode = transformiixResult.firstChild;
if( textNode.nodeType == textNode.TEXT_NODE )
return textNode.nodeValue;
else
return serializer.serializeString( transformiixResult );
}
else
// No transformiixResult, return the serialized transformed document
return serializer.serializeToString ( resultDocument );
}
else
// No transformation, return the serialized xmlDocument
return serializer.serializeToString ( xmlDocument );
}
/** PUBLIC
*
* not used?
*/
function deserializeDocument(text, stylesheet )
{
var gParser = new DOMParser;
var xmlDocument = gParser.parseFromString(text, 'text/xml');
}
/** PRIVATE
*
* transform a calendar event into a dom node.
* hack, this is going to be part of libical
*/
function makeXmlNode( xmlDocument, calendarEvent )
{
// Adds a property node to a event node
// do not add empty properties, valueType is optional
var addPropertyNode = function( xmlDocument, eventNode, name, value, valueType )
{
if(!value)
return;
var propertyNode = xmlDocument.createElement( "property" );
propertyNode.setAttribute( "name", name );
var valueNode = xmlDocument.createElement( "value" );
var textNode = xmlDocument.createTextNode( value );
if( valueType )
valueNode.setAttribute( "value", valueType );
valueNode.appendChild( textNode );
propertyNode.appendChild( valueNode );
eventNode.appendChild( propertyNode );
}
var checkString = function( str )
{
if( typeof( str ) == "string" )
return str;
else
return ""
}
var checkNumber = function( num )
{
if( typeof( num ) == "undefined" || num == null )
return "";
else
return num
}
var checkBoolean = function( bool )
{
if( bool == "false")
return "false"
else if( bool ) // this is false for: false, 0, undefined, null, ""
return "true";
else
return "false"
}
// create a string in the iCalendar format, UTC time '20020412T121314Z'
var checkDate = function ( dt, isDate )
{ var dateObj = new Date( dt.getTime() );
var result = "";
result += dateObj.getUTCFullYear();
if( dateObj.getMonth() + 1 < 10 )
result += "0";
result += dateObj.getUTCMonth() + 1;
if( dateObj.getUTCDate() < 10 )
result += "0";
result += dateObj.getUTCDate();
if( !isDate )
{
result += "T"
if( dateObj.getUTCHours() < 10 )
result += "0";
result += dateObj.getUTCHours();
if( dateObj.getUTCMinutes() < 10 )
result += "0";
result += dateObj.getUTCMinutes();
if( dateObj.getUTCSeconds() < 10 )
result += "0";
result += dateObj.getUTCSeconds();
result += "Z";
}
return result;
}
// make the event tag
var calendarNode = xmlDocument.createElement( "component" );
calendarNode.setAttribute( "name", "VCALENDAR" );
addPropertyNode( xmlDocument, calendarNode, "PRODID", "-//Mozilla.org/NONSGML Mozilla Calendar V 1.0 //EN" );
addPropertyNode( xmlDocument, calendarNode, "VERSION", "2.0" );
if(calendarEvent.method == calendarEvent.ICAL_METHOD_PUBLISH)
addPropertyNode( xmlDocument, calendarNode, "METHOD", "PUBLISH" );
else if(calendarEvent.method == calendarEvent.ICAL_METHOD_REQUEST )
addPropertyNode( xmlDocument, calendarNode, "METHOD", "REQUEST" );
var eventNode = xmlDocument.createElement( "component" );
eventNode.setAttribute( "name", "VEVENT" );
addPropertyNode( xmlDocument, eventNode, "UID", calendarEvent.id );
addPropertyNode( xmlDocument, eventNode, "SUMMARY", checkString( calendarEvent.title ) );
addPropertyNode( xmlDocument, eventNode, "DTSTAMP", checkDate( calendarEvent.stamp ) );
if( calendarEvent.allDay )
addPropertyNode( xmlDocument, eventNode, "DTSTART", checkDate( calendarEvent.start, true ), "DATE" );
else
{
addPropertyNode( xmlDocument, eventNode, "DTSTART", checkDate( calendarEvent.start ) );
addPropertyNode( xmlDocument, eventNode, "DTEND", checkDate( calendarEvent.end ) );
}
addPropertyNode( xmlDocument, eventNode, "DESCRIPTION", checkString( calendarEvent.description ) );
addPropertyNode( xmlDocument, eventNode, "CATEGORIES", checkString( calendarEvent.categories ) );
addPropertyNode( xmlDocument, eventNode, "LOCATION", checkString( calendarEvent.location ) );
addPropertyNode( xmlDocument, eventNode, "PRIVATEEVENT", checkString( calendarEvent.privateEvent ) );
addPropertyNode( xmlDocument, eventNode, "URL", checkString( calendarEvent.url ) );
addPropertyNode( xmlDocument, eventNode, "PRIORITY", checkNumber( calendarEvent.priority ) );
calendarNode.appendChild( eventNode );
return calendarNode;
}
/** PUBLIC
*
* Transforms an array of calendar events into a dom-document
* hack, this is going to be part of libical
*/
function getXmlDocument ( eventList )
{
// use the domparser to create the XML
var domParser = new DOMParser;
// start with one tag
var xmlDocument = domParser.parseFromString( "<libical/>", "text/xml" );
// get the top tag, there will only be one.
var topNodeList = xmlDocument.getElementsByTagName( "libical" );
var topNode = topNodeList[0];
// add each event as an element
for( var index = 0; index < eventList.length; ++index )
{
var calendarEvent = eventList[ index ];
var eventNode = this.makeXmlNode( xmlDocument, calendarEvent );
topNode.appendChild( eventNode );
}
return xmlDocument;
}

View File

@ -105,6 +105,8 @@
<menuseparator/>
<menuitem id="calendar-mail-event" observes="send_event_command" label="&event.mail.event;"/>
<menuseparator/>
<menuitem id="calendar-print-menu" observes="print_command" label="&calendar.print.label;"/>
<menuseparator/>
<menuitem id="calendar-close" observes="close_calendar_command" label="&calendar.menu.options.close;"/>
</menupopup>
</menu>

View File

@ -156,6 +156,8 @@ CalendarEventSelection.prototype.onSelectionChanged = function ( )
{
document.getElementById("send_event_command").removeAttribute("disabled");
}
document.getElementById( "print_command" ).removeAttribute( "disabled" );
}
else
{
@ -169,6 +171,8 @@ CalendarEventSelection.prototype.onSelectionChanged = function ( )
document.getElementById( "modify_command" ).setAttribute( "disabled", "true" );
document.getElementById("send_event_command").setAttribute("disabled", "true");
document.getElementById("print_command").setAttribute("disabled", "true");
}
for( var index in this.observerList )

View File

@ -155,10 +155,6 @@ DayView.prototype.refreshEvents = function( )
//}
//TextNode.setAttribute( "value", "All-Day Events: " );
//set the seperator to nothing. After the first one, we'll change it to ", " so that we add commas between text.
var Seperator = " ";
// get the events for the day and loop through them
var dayEventList = this.calendarWindow.eventSource.getEventsForDay( this.calendarWindow.getSelectedDate() );
@ -247,10 +243,6 @@ DayView.prototype.refreshEvents = function( )
//note the use of the AllDayText Attribute.
//This is used to remove the text when the day is changed.
SeperatorNode = document.createElement( "label" );
SeperatorNode.setAttribute( "value", Seperator );
//SeperatorNode.setAttribute( "AllDayText", "true" );
newTextNode = document.createElement( "label" );
newTextNode.setAttribute( "value", eventText );
newTextNode.calendarEventDisplay = calendarEventDisplay;
@ -258,8 +250,7 @@ DayView.prototype.refreshEvents = function( )
newTextNode.setAttribute( "onclick", "dayEventItemClick( this, event )" );
newTextNode.setAttribute( "ondblclick", "dayEventItemDoubleClick( this, event )" );
newTextNode.setAttribute( "tooltip", "savetip" );
//newTextNode.setAttribute( "AllDayText", "true" );
newTextNode.setAttribute( "AllDayText", "true" );
newImage = document.createElement("image");
newImage.setAttribute( "class", "all-day-event-class" );
@ -270,12 +261,8 @@ DayView.prototype.refreshEvents = function( )
newImage.setAttribute( "tooltip", "savetip" );
//newImage.setAttribute( "AllDayText", "true" );
AllDayBox.appendChild( SeperatorNode );
AllDayBox.appendChild( newImage );
AllDayBox.appendChild( newTextNode );
//change the seperator to add commas after the text.
Seperator = ", ";
}
else
{

View File

@ -39,6 +39,8 @@
*
****/
// XSL stylesheet directory
var convertersDirectory = "chrome://calendar/content/converters/";
// File constants copied from file-utils.js
const MODE_RDONLY = 0x01;
@ -50,6 +52,21 @@ const MODE_TRUNCATE = 0x20;
const MODE_SYNC = 0x40;
const MODE_EXCL = 0x80;
const filterCalendar = "Calendar Files";
const extensionCalendar = ".ics";
const filterXcs = "iCalendar XML Document";
const extensionXcs = ".xcs";
const filterXml = "XML Document";
const extensionXml = ".xml";
const filterRtf = "Rich Text Format (RTF)";
const extensionRtf = ".rtf";
const filterHtml = "HTML Files";
const extensionHtml = ".html";
const filterCsv = "Comma Separated";
const extensionCsv = ".csv";
const filterRdf = "iCalendar RDF";
const extensionRdf = ".rdf";
/**** loadEventsFromFile
* shows a file dialog, read the selected file and tries to parse events from it.
@ -63,18 +80,27 @@ function loadEventsFromFile()
fp.init(window, "Open", nsIFilePicker.modeOpen);
// fp.defaultString = "*.ics";
fp.defaultExtension = "ics"
fp.appendFilter( "Calendar Files", "*.ics" );
fp.appendFilter( filterCalendar, "*" + extensionCalendar );
fp.appendFilter( filterXcs, "*" + extensionXcs );
fp.show();
if (fp.file && fp.file.path.length > 0)
{
var aDataStream = readDataFromFile( fp.file.path );
var calendarEventArray = parseIcalData( aDataStream );
var calendarEventArray;
switch (fp.filterIndex) {
case 0 : // ics
calendarEventArray = parseIcalData( aDataStream );
break;
case 1 : // xcs
calendarEventArray = parseXCSData( aDataStream );
break;
}
// Show a dialog with option to import events with or without dialogs
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
@ -89,17 +115,20 @@ function loadEventsFromFile()
null,null,null,null, result);
if(buttonPressed == 0) // YES
{
addEventsToCalendar( calendarEventArray );
}
addEventsToCalendar( calendarEventArray );
return true;
}
else if(buttonPressed == 1) // NO
{
addEventsToCalendar( calendarEventArray, true );
addEventsToCalendar( calendarEventArray, true );
return true;
}
else if(buttonPressed == 2) // CANCEL
{
return false;
}
}
return false;
}
@ -247,13 +276,13 @@ function parseIcalData( icalStr )
calendarEvent = createEvent();
// if parsing import iCalendar failed, add date as description
if ( !calendarEvent.parseIcalString(eventData) )
// parsing import iCalendar failed.
{
// initialize start and end dates.
initCalendarEvent( calendarEvent );
// Save clipboard text into description.
// Save the parsed text as description.
calendarEvent.description = icalStr;
}
@ -265,6 +294,20 @@ function parseIcalData( icalStr )
return calendarEventArray;
}
/**** parseXCSData
*
*/
function parseXCSData( xcsString )
{
var gParser = new DOMParser;
var xmlDocument = gParser.parseFromString(xcsString, 'text/xml');
var result = serializeDocument(xmlDocument, "xcs2ics.xsl");
return parseIcalData( result );
}
/**** readDataFromFile
*
@ -318,7 +361,7 @@ function readDataFromFile( aFilePath )
function saveEventsToFile( calendarEventArray )
{
if( !calendarEventArray)
var calendarEventArray = gCalendarWindow.EventSelection.selectedEvents;
calendarEventArray = gCalendarWindow.EventSelection.selectedEvents;
if (calendarEventArray.length == 0)
{
@ -328,38 +371,65 @@ function saveEventsToFile( calendarEventArray )
// No show the 'Save As' dialog and ask for a filename to save to
const nsIFilePicker = Components.interfaces.nsIFilePicker;
var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
// caller can force disable of sand box, even if ON globally
fp.init(window, "Save As", nsIFilePicker.modeSave);
fp.defaultString = "Mozilla Calendar events";
if(calendarEventArray.length == 1 && calendarEventArray[0].title)
fp.defaultString = calendarEventArray[0].title;
else
fp.defaultString = "Mozilla Calendar events";
fp.defaultExtension = "ics";
fp.appendFilter( "Calendar Files", "*.ics" );
fp.appendFilter( "Rich Text Format (RTF)", "*.rtf" );
fp.appendFilter( filterCalendar, "*" + extensionCalendar );
fp.appendFilter( filterRtf, "*" + extensionRtf );
fp.appendFilters(nsIFilePicker.filterHTML);
fp.appendFilter( filterCsv, "*" + extensionCsv );
fp.appendFilter( filterXcs, "*" + extensionXcs );
fp.appendFilter( filterRdf, "*" + extensionRdf );
fp.show();
// Now find out as what to save, convert the events and save to file.
if (fp.file && fp.file.path.length > 0)
{
var aDataStream;
var extension;
switch (fp.filterIndex) {
case 0 : // ics
aDataStream = eventArrayToICalString( calendarEventArray, true );
extension = extensionCalendar;
break;
case 1 : // rtf
aDataStream = eventArrayToRTF( calendarEventArray );
extension = extensionRtf;
break;
case 2 : // html
aDataStream = eventArrayToHTML( calendarEventArray );
extension = ".htm";
break;
case 3 : // csv
aDataStream = eventArrayToCsv( calendarEventArray );
extension = extensionCsv;
break;
case 4 : // xCal
aDataStream = eventArrayToXCS( calendarEventArray );
extension = extensionXcs;
break;
case 5 : // rdf
aDataStream = eventArrayToRdf( calendarEventArray );
extension = extensionRdf;
break;
}
saveDataToFile(fp.file.path, aDataStream);
var filePath = fp.file.path;
if(filePath.indexOf(".") == -1 )
filePath += extension;
saveDataToFile(filePath, aDataStream);
}
}
@ -485,6 +555,74 @@ function eventArrayToRTF( calendarEventArray )
}
/**** eventArrayToXML
* Converts a array of events to a XML string
*/
/*
function eventArrayToXML( calendarEventArray )
{
var xmlDocument = getXmlDocument( calendarEventArray );
var serializer = new XMLSerializer;
return serializer.serializeToString (xmlDocument )
}
*/
/**** eventArrayToCsv
* Converts a array of events to comma delimited text.
*/
function eventArrayToCsv( calendarEventArray )
{
var xcsDocument = getXcsDocument( calendarEventArray );
return serializeDocument( xcsDocument, "xcs2csv.xsl" );
}
/**** eventArrayToRdf
* Converts a array of events to RDF
*/
function eventArrayToRdf( calendarEventArray )
{
var xcsDocument = getXcsDocument( calendarEventArray );
return serializeDocument( xcsDocument, "xcs2rdf.xsl" );
}
/**** eventArrayToXCS
* Converts a array of events to a xCal string
*/
function eventArrayToXCS( calendarEventArray )
{
var xmlDoc = getXmlDocument( calendarEventArray );
var xcsDoc = transformXML( xmlDoc, "xml2xcs.xsl" );
// add the doctype
/* Doctype uri blocks excel import
var newdoctype = xcsDoc.implementation.createDocumentType(
"iCalendar",
"-//IETF//DTD XCAL//iCalendar XML//EN",
"http://www.ietf.org/internet-drafts/draft-ietf-calsch-many-xcal-02.txt");
if (newdoctype)
xcsDoc.insertBefore(newdoctype, xcsDoc.firstChild);
*/
var serializer = new XMLSerializer;
// XXX MAJOR UGLY HACK!! Serializer doesn't insert XML Declaration
// http://bugzilla.mozilla.org/show_bug.cgi?id=63558
var serialDocument = serializer.serializeToString ( xcsDoc );
if( serialDocument.indexOf( "<?xml" ) == -1 )
serialDocument = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + serialDocument;
return serialDocument;
// return serializer.serializeToString ( xcsDoc )
}
/**** saveDataToFile
*
* Save data to a file. Creates a new file or overwrites an existing file.
@ -500,7 +638,7 @@ function saveDataToFile(aFilePath, aDataStream)
var localFileInstance;
var outputStream;
LocalFileInstance = Components.classes[LOCALFILE_CTRID].createInstance(nsILocalFile);
var LocalFileInstance = Components.classes[LOCALFILE_CTRID].createInstance(nsILocalFile);
LocalFileInstance.initWithPath(aFilePath);
outputStream = Components.classes[FILEOUT_CTRID].createInstance(nsIFileOutputStream);
@ -516,3 +654,332 @@ function saveDataToFile(aFilePath, aDataStream)
alert("Unable to write to file: " + aFilePath );
}
}
////////////////////////////////////
// XML/XSL functions //
////////////////////////////////////
/**
* Get the local path to the chrome directory
*/
/*
function getChromeDir()
{
const JS_DIR_UTILS_FILE_DIR_CID = "@mozilla.org/file/directory_service;1";
const JS_DIR_UTILS_I_PROPS = "nsIProperties";
const JS_DIR_UTILS_DIR = new Components.Constructor(JS_DIR_UTILS_FILE_DIR_CID, JS_DIR_UTILS_I_PROPS);
const JS_DIR_UTILS_CHROME_DIR = "AChrom";
var rv;
try
{
rv=(new JS_DIR_UTILS_DIR()).get(JS_DIR_UTILS_CHROME_DIR, Components.interfaces.nsIFile);
}
catch (e)
{
//jslibError(e, "(unexpected error)", "NS_ERROR_FAILURE", JS_DIR_UTILS_FILE+":getChromeDir");
rv=null;
}
return rv;
}
function getTemplatesPath( templateName )
{
var templatesDir = getChromeDir();
templatesDir.append( "calendar" );
templatesDir.append( "content" );
templatesDir.append( "templates" );
templatesDir.append( templateName );
return templatesDir.path;
}
function xslt(xmlUri, xslUri)
{
// TODO: Check uri's for CHROME:// and convert path to local path
var xslProc = new XSLTProcessor();
var result = document.implementation.createDocument("", "", null);
var xmlDoc = document.implementation.createDocument("", "", null);
var xslDoc = document.implementation.createDocument("", "", null);
xmlDoc.load(xmlUri, "text/xml");
xslDoc.load(xslUri, "text/xml");
xslProc.transformDocument(xmlDoc, xslDoc, result, null);
return result;
}
*/
/** PRIVATE
*
* Opens a file and returns the content
* It supports Uri's like chrome://
*/
function loadFile(aUriSpec)
{
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var serv = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
if (!serv) {
throw Components.results.ERR_FAILURE;
}
var chan = serv.newChannel(aUriSpec, null, null);
var instream =
Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
instream.init(chan.open());
return instream.read(instream.available());
}
/** PUBLIC GetXcsDocument
*
*/
function getXcsDocument( calendarEventArray )
{
var xmlDocument = getXmlDocument( calendarEventArray );
var xcsDocument = transformXML( xmlDocument, "xml2xcs.xsl" );
var processingInstruction = xcsDocument.createProcessingInstruction(
"xml", "version=\"1.0\" encoding=\"UTF-8\"");
// xcsDocument.insertBefore(processingInstruction, xcsDocument.firstChild);
return xcsDocument;
}
/** PUBLIC
*
* Opens a xsl transformation file and applies it to xmlDocuments.
* xslFile can be in the convertersDirectory, or a full Uri
* Returns the resulting document
*/
function transformXML( xmlDocument, xslFilename )
{
var xslProc = new XSLTProcessor();
var gParser = new DOMParser;
// .load isn't synchrone
// var xslDoc = document.implementation.createDocument("", "", null);
// xslDoc.load(path, "text/xml");
// if only passsed a filename, assume it is a file in the default directory
if( xslFilename.indexOf( ":" ) == -1 )
xslFilename = convertersDirectory + xslFilename;
var xslContent = loadFile( xslFilename );
var xslDocument = gParser.parseFromString(xslContent, 'text/xml');
var result = document.implementation.createDocument("", "", null);
xslProc.transformDocument(xmlDocument, xslDocument, result, null);
return result;
}
/** PUBLIC
*
* Serializes a DOM document.if stylesheet is null, returns the document serialized
* Applies the stylesheet when available, and return the serialized transformed document,
* or the transformiix data
*/
function serializeDocument( xmlDocument, stylesheet )
{
var serializer = new XMLSerializer;
if( stylesheet )
{
var resultDocument = transformXML( xmlDocument, stylesheet );
var transformiixResult = resultDocument.getElementById( "transformiixResult" );
if( transformiixResult && transformiixResult.hasChildNodes() )
{ // It's a document starting with:
// <a0:html xmlns:a0="http://www.w3.org/1999/xhtml">
// <a0:head/><a0:body><a0:pre id="transformiixResult">
var textNode = transformiixResult.firstChild;
if( textNode.nodeType == textNode.TEXT_NODE )
return textNode.nodeValue;
else
return serializer.serializeString( transformiixResult );
}
else
// No transformiixResult, return the serialized transformed document
return serializer.serializeToString ( resultDocument );
}
else
// No transformation, return the serialized xmlDocument
return serializer.serializeToString ( xmlDocument );
}
/** PUBLIC
*
* not used?
*/
function deserializeDocument(text, stylesheet )
{
var gParser = new DOMParser;
var xmlDocument = gParser.parseFromString(text, 'text/xml');
}
/** PRIVATE
*
* transform a calendar event into a dom node.
* hack, this is going to be part of libical
*/
function makeXmlNode( xmlDocument, calendarEvent )
{
// Adds a property node to a event node
// do not add empty properties, valueType is optional
var addPropertyNode = function( xmlDocument, eventNode, name, value, valueType )
{
if(!value)
return;
var propertyNode = xmlDocument.createElement( "property" );
propertyNode.setAttribute( "name", name );
var valueNode = xmlDocument.createElement( "value" );
var textNode = xmlDocument.createTextNode( value );
if( valueType )
valueNode.setAttribute( "value", valueType );
valueNode.appendChild( textNode );
propertyNode.appendChild( valueNode );
eventNode.appendChild( propertyNode );
}
var checkString = function( str )
{
if( typeof( str ) == "string" )
return str;
else
return ""
}
var checkNumber = function( num )
{
if( typeof( num ) == "undefined" || num == null )
return "";
else
return num
}
var checkBoolean = function( bool )
{
if( bool == "false")
return "false"
else if( bool ) // this is false for: false, 0, undefined, null, ""
return "true";
else
return "false"
}
// create a string in the iCalendar format, UTC time '20020412T121314Z'
var checkDate = function ( dt, isDate )
{ var dateObj = new Date( dt.getTime() );
var result = "";
result += dateObj.getUTCFullYear();
if( dateObj.getMonth() + 1 < 10 )
result += "0";
result += dateObj.getUTCMonth() + 1;
if( dateObj.getUTCDate() < 10 )
result += "0";
result += dateObj.getUTCDate();
if( !isDate )
{
result += "T"
if( dateObj.getUTCHours() < 10 )
result += "0";
result += dateObj.getUTCHours();
if( dateObj.getUTCMinutes() < 10 )
result += "0";
result += dateObj.getUTCMinutes();
if( dateObj.getUTCSeconds() < 10 )
result += "0";
result += dateObj.getUTCSeconds();
result += "Z";
}
return result;
}
// make the event tag
var calendarNode = xmlDocument.createElement( "component" );
calendarNode.setAttribute( "name", "VCALENDAR" );
addPropertyNode( xmlDocument, calendarNode, "PRODID", "-//Mozilla.org/NONSGML Mozilla Calendar V 1.0 //EN" );
addPropertyNode( xmlDocument, calendarNode, "VERSION", "2.0" );
if(calendarEvent.method == calendarEvent.ICAL_METHOD_PUBLISH)
addPropertyNode( xmlDocument, calendarNode, "METHOD", "PUBLISH" );
else if(calendarEvent.method == calendarEvent.ICAL_METHOD_REQUEST )
addPropertyNode( xmlDocument, calendarNode, "METHOD", "REQUEST" );
var eventNode = xmlDocument.createElement( "component" );
eventNode.setAttribute( "name", "VEVENT" );
addPropertyNode( xmlDocument, eventNode, "UID", calendarEvent.id );
addPropertyNode( xmlDocument, eventNode, "SUMMARY", checkString( calendarEvent.title ) );
addPropertyNode( xmlDocument, eventNode, "DTSTAMP", checkDate( calendarEvent.stamp ) );
if( calendarEvent.allDay )
addPropertyNode( xmlDocument, eventNode, "DTSTART", checkDate( calendarEvent.start, true ), "DATE" );
else
{
addPropertyNode( xmlDocument, eventNode, "DTSTART", checkDate( calendarEvent.start ) );
addPropertyNode( xmlDocument, eventNode, "DTEND", checkDate( calendarEvent.end ) );
}
addPropertyNode( xmlDocument, eventNode, "DESCRIPTION", checkString( calendarEvent.description ) );
addPropertyNode( xmlDocument, eventNode, "CATEGORIES", checkString( calendarEvent.categories ) );
addPropertyNode( xmlDocument, eventNode, "LOCATION", checkString( calendarEvent.location ) );
addPropertyNode( xmlDocument, eventNode, "PRIVATEEVENT", checkString( calendarEvent.privateEvent ) );
addPropertyNode( xmlDocument, eventNode, "URL", checkString( calendarEvent.url ) );
addPropertyNode( xmlDocument, eventNode, "PRIORITY", checkNumber( calendarEvent.priority ) );
calendarNode.appendChild( eventNode );
return calendarNode;
}
/** PUBLIC
*
* Transforms an array of calendar events into a dom-document
* hack, this is going to be part of libical
*/
function getXmlDocument ( eventList )
{
// use the domparser to create the XML
var domParser = new DOMParser;
// start with one tag
var xmlDocument = domParser.parseFromString( "<libical/>", "text/xml" );
// get the top tag, there will only be one.
var topNodeList = xmlDocument.getElementsByTagName( "libical" );
var topNode = topNodeList[0];
// add each event as an element
for( var index = 0; index < eventList.length; ++index )
{
var calendarEvent = eventList[ index ];
var eventNode = this.makeXmlNode( xmlDocument, calendarEvent );
topNode.appendChild( eventNode );
}
return xmlDocument;
}

View File

@ -105,6 +105,8 @@
<menuseparator/>
<menuitem id="calendar-mail-event" observes="send_event_command" label="&event.mail.event;"/>
<menuseparator/>
<menuitem id="calendar-print-menu" observes="print_command" label="&calendar.print.label;"/>
<menuseparator/>
<menuitem id="calendar-close" observes="close_calendar_command" label="&calendar.menu.options.close;"/>
</menupopup>
</menu>

View File

@ -225,6 +225,7 @@ function unifinderMouseDownToDo( event )
// TODO HACK notifiers should be rewritten to integrate events and todos
document.getElementById( "delete_command" ).removeAttribute( "disabled" );
document.getElementById( "delete_command_no_confirm" ).removeAttribute( "disabled" );
document.getElementById( "print_command" ).setAttribute( "disabled", "true" );
} else
{
if(event.button == 2)
@ -234,6 +235,8 @@ function unifinderMouseDownToDo( event )
// TODO HACK notifiers should be rewritten to integrate events and todos
document.getElementById( "delete_command" ).setAttribute( "disabled", "true" );
document.getElementById( "delete_command_no_confirm" ).setAttribute( "disabled", "true" );
// printing tasks not supported
document.getElementById( "print_command" ).setAttribute( "disabled", "true" );
}
}

View File

@ -31,14 +31,21 @@ calendar.jar:
content/calendar/sound.wav (content/sound.wav)
content/calendar/unifinder.js (content/unifinder.js)
content/calendar/unifinderToDo.js (content/unifinderToDo.js)
content/calendar/converters/date-time.xsl (content/converters/date-time.xsl)
content/calendar/converters/ecsJune.xsl (content/converters/ecsJune.xsl)
content/calendar/converters/sortEvents.xsl (content/converters/sortEvents.xsl)
content/calendar/converters/xcs2csv.xsl (content/converters/xcs2csv.xsl)
content/calendar/converters/xcs2ics.xsl (content/converters/xcs2ics.xsl)
content/calendar/converters/xcs2rdf.xsl (content/converters/xcs2rdf.xsl)
content/calendar/converters/xml2xcs.xsl (content/converters/xml2xcs.xsl)
content/calendar/datepicker/datepicker-overlay.xul (content/datepicker/datepicker-overlay.xul)
content/calendar/datepicker/datepicker.js (content/datepicker/datepicker.js)
content/calendar/timepicker/timepicker-overlay.xul (content/timepicker/timepicker-overlay.xul)
content/calendar/timepicker/timepicker.js (content/timepicker/timepicker.js)
content/calendar/pref/calendarPrefOverlay.xul (content/pref/calendarPrefOverlay.xul)
content/calendar/pref/rootCalendarPref.js (content/pref/rootCalendarPref.js)
content/calendar/pref/calendarPref.js (content/pref/calendarPref.js)
content/calendar/pref/calendarPref.xul (content/pref/calendarPref.xul)
content/calendar/pref/calendarPrefOverlay.xul (content/pref/calendarPrefOverlay.xul)
content/calendar/pref/rootCalendarPref.js (content/pref/rootCalendarPref.js)
content/calendar/timepicker/timepicker-overlay.xul (content/timepicker/timepicker-overlay.xul)
content/calendar/timepicker/timepicker.js (content/timepicker/timepicker.js)
locale/en-US/calendar/calendar.dtd (locale/en-US/calendar.dtd)
locale/en-US/calendar/calendarMenuOverlay.dtd (locale/en-US/calendarMenuOverlay.dtd)
locale/en-US/calendar/calendarOverlay.dtd (locale/en-US/calendarOverlay.dtd)
@ -48,6 +55,49 @@ calendar.jar:
locale/en-US/calendar/contents.rdf (locale/en-US/contents.rdf)
locale/en-US/calendar/dateFormat.properties (locale/en-US/dateFormat.properties)
locale/en-US/calendar/global.dtd (locale/en-US/global.dtd)
skin/classic/calendar/all_day_event.gif (skin/classic/all_day_event.gif)
skin/classic/calendar/all_day_event_down.gif (skin/classic/all_day_event_down.gif)
skin/classic/calendar/all_day_event_hover.gif (skin/classic/all_day_event_hover.gif)
skin/classic/calendar/btn1.png (skin/classic/btn1.png)
skin/classic/calendar/calendar-16.gif (skin/classic/calendar-16.gif)
skin/classic/calendar/calendar.css (skin/classic/calendar.css)
skin/classic/calendar/calendarOverlay.css (skin/classic/calendarOverlay.css)
skin/classic/calendar/calendarEventAlertDialog.css (skin/classic/calendarEventAlertDialog.css)
skin/classic/calendar/calendarEventDialog.css (skin/classic/calendarEventDialog.css)
skin/classic/calendar/calendar_topbar.gif (skin/classic/calendar_topbar.gif)
skin/classic/calendar/contactsSelectAddressesDialog.css (skin/classic/contactsSelectAddressesDialog.css)
skin/classic/calendar/contents.rdf (skin/classic/contents.rdf)
skin/classic/calendar/day_left_gradient.png (skin/classic/day_left_gradient.png)
skin/classic/calendar/dialogOverlay.css (skin/classic/dialogOverlay.css)
skin/classic/calendar/dot.png (skin/classic/dot.png)
skin/classic/calendar/dot_selected.png (skin/classic/dot_selected.png)
skin/classic/calendar/event.png (skin/classic/event.png)
skin/classic/calendar/event_alarm.png (skin/classic/event_alarm.png)
skin/classic/calendar/event_attachment.png (skin/classic/event_attachment.png)
skin/classic/calendar/event_repeating.png (skin/classic/event_repeating.png)
skin/classic/calendar/prevnextarrow.png (skin/classic/prevnextarrow.png)
skin/classic/calendar/taskbar-cal.gif (skin/classic/taskbar-cal.gif)
skin/classic/calendar/taskbar-cal-act.gif (skin/classic/taskbar-cal-act.gif)
skin/classic/calendar/ca-event-dialog/calendar_disabled.gif (skin/classic/ca-event-dialog/calendar_disabled.gif)
skin/classic/calendar/ca-event-dialog/calendar_down.gif (skin/classic/ca-event-dialog/calendar_down.gif)
skin/classic/calendar/ca-event-dialog/calendar_hover.gif (skin/classic/ca-event-dialog/calendar_hover.gif)
skin/classic/calendar/ca-event-dialog/calendar_up.gif (skin/classic/ca-event-dialog/calendar_up.gif)
skin/classic/calendar/ca-event-dialog/clock_disabled.gif (skin/classic/ca-event-dialog/clock_disabled.gif)
skin/classic/calendar/ca-event-dialog/clock_down.gif (skin/classic/ca-event-dialog/clock_down.gif)
skin/classic/calendar/ca-event-dialog/clock_hover.gif (skin/classic/ca-event-dialog/clock_hover.gif)
skin/classic/calendar/ca-event-dialog/clock_up.gif (skin/classic/ca-event-dialog/clock_up.gif)
skin/classic/calendar/ca-event-dialog/new_event_icon.png (skin/classic/ca-event-dialog/new_event_icon.png)
skin/classic/calendar/datepicker/datepicker.css (skin/classic/datepicker/datepicker.css)
skin/classic/calendar/datepicker/day_grid.png (skin/classic/datepicker/day_grid.png)
skin/classic/calendar/datepicker/left_arrow.png (skin/classic/datepicker/left_arrow.png)
skin/classic/calendar/datepicker/right_arrow.png (skin/classic/datepicker/right_arrow.png)
skin/classic/calendar/timepicker/time_picker_minutes_bottom.png (skin/classic/timepicker/time_picker_minutes_bottom.png)
skin/classic/calendar/timepicker/timepicker.css (skin/classic/timepicker/timepicker.css)
skin/classic/calendar/unifinder/checkbox_checked.png (skin/classic/unifinder/checkbox_checked.png)
skin/classic/calendar/unifinder/checkbox_unchecked.png (skin/classic/unifinder/checkbox_unchecked.png)
skin/classic/calendar/unifinder/priority_header.png (skin/classic/unifinder/priority_header.png)
skin/classic/calendar/unifinder/priority_high.png (skin/classic/unifinder/priority_high.png)
skin/classic/calendar/unifinder/priority_low.png (skin/classic/unifinder/priority_low.png)
skin/modern/calendar/all_day_event.gif (skin/modern/all_day_event.gif)
skin/modern/calendar/all_day_event_down.gif (skin/modern/all_day_event_down.gif)
skin/modern/calendar/all_day_event_hover.gif (skin/modern/all_day_event_hover.gif)
@ -92,45 +142,3 @@ calendar.jar:
skin/modern/calendar/unifinder/priority_header.png (skin/modern/unifinder/priority_header.png)
skin/modern/calendar/unifinder/priority_high.png (skin/modern/unifinder/priority_high.png)
skin/modern/calendar/unifinder/priority_low.png (skin/modern/unifinder/priority_low.png)
skin/classic/calendar/all_day_event.gif (skin/classic/all_day_event.gif)
skin/classic/calendar/all_day_event_down.gif (skin/classic/all_day_event_down.gif)
skin/classic/calendar/all_day_event_hover.gif (skin/classic/all_day_event_hover.gif)
skin/classic/calendar/btn1.png (skin/classic/btn1.png)
skin/classic/calendar/calendar-16.gif (skin/classic/calendar-16.gif)
skin/classic/calendar/calendar.css (skin/classic/calendar.css)
skin/classic/calendar/calendarOverlay.css (skin/classic/calendarOverlay.css)
skin/classic/calendar/calendarEventAlertDialog.css (skin/classic/calendarEventAlertDialog.css)
skin/classic/calendar/calendarEventDialog.css (skin/classic/calendarEventDialog.css)
skin/classic/calendar/calendar_topbar.gif (skin/classic/calendar_topbar.gif)
skin/classic/calendar/contactsSelectAddressesDialog.css (skin/classic/contactsSelectAddressesDialog.css)
skin/classic/calendar/contents.rdf (skin/classic/contents.rdf)
skin/classic/calendar/day_left_gradient.png (skin/classic/day_left_gradient.png)
skin/classic/calendar/dialogOverlay.css (skin/classic/dialogOverlay.css)
skin/classic/calendar/dot.png (skin/classic/dot.png)
skin/classic/calendar/dot_selected.png (skin/classic/dot_selected.png)
skin/classic/calendar/event.png (skin/classic/event.png)
skin/classic/calendar/event_alarm.png (skin/classic/event_alarm.png)
skin/classic/calendar/event_attachment.png (skin/classic/event_attachment.png)
skin/classic/calendar/prevnextarrow.png (skin/classic/prevnextarrow.png)
skin/classic/calendar/taskbar-cal.gif (skin/classic/taskbar-cal.gif)
skin/classic/calendar/taskbar-cal-act.gif (skin/classic/taskbar-cal-act.gif)
skin/classic/calendar/ca-event-dialog/calendar_disabled.gif (skin/classic/ca-event-dialog/calendar_disabled.gif)
skin/classic/calendar/ca-event-dialog/calendar_down.gif (skin/classic/ca-event-dialog/calendar_down.gif)
skin/classic/calendar/ca-event-dialog/calendar_hover.gif (skin/classic/ca-event-dialog/calendar_hover.gif)
skin/classic/calendar/ca-event-dialog/calendar_up.gif (skin/classic/ca-event-dialog/calendar_up.gif)
skin/classic/calendar/ca-event-dialog/clock_disabled.gif (skin/classic/ca-event-dialog/clock_disabled.gif)
skin/classic/calendar/ca-event-dialog/clock_down.gif (skin/classic/ca-event-dialog/clock_down.gif)
skin/classic/calendar/ca-event-dialog/clock_hover.gif (skin/classic/ca-event-dialog/clock_hover.gif)
skin/classic/calendar/ca-event-dialog/clock_up.gif (skin/classic/ca-event-dialog/clock_up.gif)
skin/classic/calendar/ca-event-dialog/new_event_icon.png (skin/classic/ca-event-dialog/new_event_icon.png)
skin/classic/calendar/datepicker/datepicker.css (skin/classic/datepicker/datepicker.css)
skin/classic/calendar/datepicker/day_grid.png (skin/classic/datepicker/day_grid.png)
skin/classic/calendar/datepicker/left_arrow.png (skin/classic/datepicker/left_arrow.png)
skin/classic/calendar/datepicker/right_arrow.png (skin/classic/datepicker/right_arrow.png)
skin/classic/calendar/timepicker/time_picker_minutes_bottom.png (skin/classic/timepicker/time_picker_minutes_bottom.png)
skin/classic/calendar/timepicker/timepicker.css (skin/classic/timepicker/timepicker.css)
skin/classic/calendar/unifinder/checkbox_checked.png (skin/classic/unifinder/checkbox_checked.png)
skin/classic/calendar/unifinder/checkbox_unchecked.png (skin/classic/unifinder/checkbox_unchecked.png)
skin/classic/calendar/unifinder/priority_header.png (skin/classic/unifinder/priority_header.png)
skin/classic/calendar/unifinder/priority_high.png (skin/classic/unifinder/priority_high.png)
skin/classic/calendar/unifinder/priority_low.png (skin/classic/unifinder/priority_low.png)

View File

@ -55,6 +55,15 @@
<!ENTITY event.mail.event "Mail Calendar Event">
<!ENTITY event.mail.event.accesskey "m">
<!ENTITY calendar.print.label "Print...">
<!ENTITY calendar.print.accesskey "r">
<!ENTITY calendar.print.label "Print Preview">
<!ENTITY calendar.print.accesskey "v">
<!ENTITY calendar.print.label "Page Setup...">
<!ENTITY calendar.print.accesskey "u">
<!ENTITY calendar.import.label "Import...">
<!ENTITY calendar.import.accesskey "i">

View File

@ -59,6 +59,8 @@
<!ENTITY time.22 "10:00 PM" >
<!ENTITY time.23 "11:00 PM" >
<!ENTITY allDayEvents.label "All Day Events">
<!-- Month Names -->
<!ENTITY day.1.Ddd "Sun" >
<!ENTITY day.2.Ddd "Mon" >

View File

@ -55,6 +55,15 @@
<!ENTITY event.mail.event "Mail Calendar Event">
<!ENTITY event.mail.event.accesskey "m">
<!ENTITY calendar.print.label "Print...">
<!ENTITY calendar.print.accesskey "r">
<!ENTITY calendar.print.label "Print Preview">
<!ENTITY calendar.print.accesskey "v">
<!ENTITY calendar.print.label "Page Setup...">
<!ENTITY calendar.print.accesskey "u">
<!ENTITY calendar.import.label "Import...">
<!ENTITY calendar.import.accesskey "i">