Fix bug 591742 - Import and Export is broken [Exception "Component returned failure code: 0x80570016 (NS_ERROR_XPC_GS_RETURNED_FAILURE) [nsIJSCID.getService]"]. r=simon
This commit is contained in:
Родитель
d3bd453555
Коммит
758b44d6d1
|
@ -1,5 +1,4 @@
|
|||
/* -*- Mode: javascript; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* ***** 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
|
||||
|
@ -68,7 +67,7 @@ function loadEventsFromFile(aCalendar) {
|
|||
nsIFilePicker.modeOpen);
|
||||
fp.defaultExtension = "ics";
|
||||
|
||||
// Get a list of exporters
|
||||
// Get a list of importers
|
||||
let contractids = new Array();
|
||||
let catman = Components.classes["@mozilla.org/categorymanager;1"]
|
||||
.getService(Components.interfaces.nsICategoryManager);
|
||||
|
@ -78,11 +77,16 @@ function loadEventsFromFile(aCalendar) {
|
|||
let entry = catenum.getNext();
|
||||
entry = entry.QueryInterface(Components.interfaces.nsISupportsCString);
|
||||
let contractid = catman.getCategoryEntry('cal-importers', entry);
|
||||
let exporter = Components.classes[contractid]
|
||||
let importer;
|
||||
try {
|
||||
importer = Components.classes[contractid]
|
||||
.getService(Components.interfaces.calIImporter);
|
||||
let types = exporter.getFileTypes({});
|
||||
let type;
|
||||
for each (type in types) {
|
||||
} catch (e) {
|
||||
cal.WARN("Could not initialize importer: " + contractid + "\nError: " + e);
|
||||
continue;
|
||||
}
|
||||
let types = importer.getFileTypes({});
|
||||
for each (let type in types) {
|
||||
fp.appendFilter(type.description, type.extensionFilter);
|
||||
if (type.extensionFilter=="*." + fp.defaultExtension) {
|
||||
fp.filterIndex = currentListLength;
|
||||
|
@ -92,9 +96,10 @@ function loadEventsFromFile(aCalendar) {
|
|||
}
|
||||
}
|
||||
|
||||
fp.show();
|
||||
let rv = fp.show();
|
||||
|
||||
if (fp.file && fp.file.path && fp.file.path.length > 0) {
|
||||
if (rv != nsIFilePicker.returnCancel &&
|
||||
fp.file && fp.file.path && fp.file.path.length > 0) {
|
||||
let filePath = fp.file.path;
|
||||
let importer = Components.classes[contractids[fp.filterIndex]]
|
||||
.getService(Components.interfaces.calIImporter);
|
||||
|
@ -260,10 +265,15 @@ function saveEventsToFile(calendarEventArray, aDefaultFileName) {
|
|||
let entry = catenum.getNext();
|
||||
entry = entry.QueryInterface(Components.interfaces.nsISupportsCString);
|
||||
let contractid = catman.getCategoryEntry('cal-exporters', entry);
|
||||
let exporter = Components.classes[contractid]
|
||||
let exporter;
|
||||
try {
|
||||
exporter = Components.classes[contractid]
|
||||
.getService(Components.interfaces.calIExporter);
|
||||
} catch (e) {
|
||||
cal.WARN("Could not initialize exporter: " + contractid + "\nError: " + e);
|
||||
continue;
|
||||
}
|
||||
let types = exporter.getFileTypes({});
|
||||
let type;
|
||||
for each (let type in types) {
|
||||
fp.appendFilter(type.description, type.extensionFilter);
|
||||
if (type.extensionFilter=="*." + fp.defaultExtension) {
|
||||
|
@ -274,10 +284,11 @@ function saveEventsToFile(calendarEventArray, aDefaultFileName) {
|
|||
}
|
||||
}
|
||||
|
||||
fp.show();
|
||||
let rv = fp.show();
|
||||
|
||||
// Now find out as what to save, convert the events and save to file.
|
||||
if (fp.file && fp.file.path.length > 0) {
|
||||
if (rv != nsIFilePicker.returnCancel &&
|
||||
fp.file && fp.file.path.length > 0) {
|
||||
const UTF8 = "UTF-8";
|
||||
let aDataStream;
|
||||
let extension;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* -*- Mode: javascript; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* ***** 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
|
||||
|
@ -38,173 +37,178 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// Export
|
||||
Components.utils.import("resource://calendar/modules/calUtils.jsm");
|
||||
|
||||
// Export
|
||||
function calHtmlExporter() {
|
||||
this.wrappedJSObject = this;
|
||||
}
|
||||
|
||||
calHtmlExporter.prototype.QueryInterface =
|
||||
function QueryInterface(aIID) {
|
||||
if (!aIID.equals(Components.interfaces.nsISupports) &&
|
||||
!aIID.equals(Components.interfaces.calIExporter)) {
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
calHtmlExporter.prototype = {
|
||||
getInterfaces: function (count) {
|
||||
const ifaces = [
|
||||
Components.interfaces.nsISupports,
|
||||
Components.interfaces.nsIClassInfo,
|
||||
Components.interfaces.calIExporter,
|
||||
];
|
||||
count.value = ifaces.length;
|
||||
return ifaces;
|
||||
},
|
||||
|
||||
return this;
|
||||
};
|
||||
getHelperForLanguage: function (language) {
|
||||
return null;
|
||||
},
|
||||
|
||||
calHtmlExporter.prototype.getFileTypes =
|
||||
function getFileTypes(aCount) {
|
||||
aCount.value = 1;
|
||||
var wildmat = '*.html; *.htm';
|
||||
var label = calGetString("calendar", 'filterHtml', [wildmat]);
|
||||
return([{defaultExtension:'html',
|
||||
extensionFilter: wildmat,
|
||||
description: label}]);
|
||||
};
|
||||
contractID: "@mozilla.org/calendar/export;1?type=html",
|
||||
classDescription: "Calendar HTML Exporter",
|
||||
classID: Components.ID("{72d9ab35-9b1b-442a-8cd0-ae49f00b159b}"),
|
||||
implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: 0,
|
||||
|
||||
// not prototype.export. export is reserved.
|
||||
calHtmlExporter.prototype.exportToStream =
|
||||
function html_exportToStream(aStream, aCount, aItems, aTitle) {
|
||||
var dateFormatter =
|
||||
Components.classes["@mozilla.org/calendar/datetime-formatter;1"]
|
||||
.getService(Components.interfaces.calIDateTimeFormatter);
|
||||
QueryInterface: function QueryInterface(aIID) {
|
||||
return cal.doQueryInterface(this, calHtmlExporter.prototype, aIID, null, this);
|
||||
},
|
||||
|
||||
var documentTitle = aTitle;
|
||||
if (!documentTitle) {
|
||||
documentTitle = calGetString("calendar", "HTMLTitle");
|
||||
}
|
||||
getFileTypes: function getFileTypes(aCount) {
|
||||
aCount.value = 1;
|
||||
let wildmat = '*.html; *.htm';
|
||||
let label = cal.calGetString("calendar", 'filterHtml', [wildmat]);
|
||||
return [{ defaultExtension:'html',
|
||||
extensionFilter: wildmat,
|
||||
description: label }];
|
||||
},
|
||||
|
||||
var html =
|
||||
<html>
|
||||
<head>
|
||||
<title>{documentTitle}</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/>
|
||||
<style type='text/css'/>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Note on the use of the summarykey class: this is a
|
||||
special class, because in the default style, it is hidden.
|
||||
The div is still included for those that want a different
|
||||
style, where the key is visible -->
|
||||
</body>
|
||||
</html>;
|
||||
// XXX The html comment above won't propagate to the resulting html.
|
||||
// Should fix that, one day.
|
||||
exportToStream: function html_exportToStream(aStream, aCount, aItems, aTitle) {
|
||||
let documentTitle = aTitle || cal.calGetString("calendar", "HTMLTitle");
|
||||
|
||||
// Using this way to create the styles, because { and } are special chars
|
||||
// in e4x. They have to be escaped, which doesn't improve readability
|
||||
html.head.style = ".vevent {border: 1px solid black; padding: 0px; margin-bottom: 10px;}\n";
|
||||
html.head.style += "div.key {font-style: italic; margin-left: 3px;}\n";
|
||||
html.head.style += "div.value {margin-left: 20px;}\n";
|
||||
html.head.style += "abbr {border: none;}\n";
|
||||
html.head.style += ".summarykey {display: none;}\n";
|
||||
html.head.style += "div.summary {background: white; font-weight: bold; margin: 0px; padding: 3px;}\n";
|
||||
let html =
|
||||
<html>
|
||||
<head>
|
||||
<title>{documentTitle}</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/>
|
||||
<style type='text/css'/>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Note on the use of the summarykey class: this is a
|
||||
special class, because in the default style, it is hidden.
|
||||
The div is still included for those that want a different
|
||||
style, where the key is visible -->
|
||||
</body>
|
||||
</html>;
|
||||
// XXX The html comment above won't propagate to the resulting html.
|
||||
// Should fix that, one day.
|
||||
|
||||
// Sort aItems
|
||||
function sortFunc(a, b) {
|
||||
var start_a = a[calGetStartDateProp(a)];
|
||||
if (!start_a) {
|
||||
return -1;
|
||||
// Using this way to create the styles, because { and } are special chars
|
||||
// in e4x. They have to be escaped, which doesn't improve readability
|
||||
html.head.style = ".vevent {border: 1px solid black; padding: 0px; margin-bottom: 10px;}\n";
|
||||
html.head.style += "div.key {font-style: italic; margin-left: 3px;}\n";
|
||||
html.head.style += "div.value {margin-left: 20px;}\n";
|
||||
html.head.style += "abbr {border: none;}\n";
|
||||
html.head.style += ".summarykey {display: none;}\n";
|
||||
html.head.style += "div.summary {background: white; font-weight: bold; margin: 0px; padding: 3px;}\n";
|
||||
|
||||
// Sort aItems
|
||||
function sortFunc(a, b) {
|
||||
let start_a = a[cal.calGetStartDateProp(a)];
|
||||
if (!start_a) {
|
||||
return -1;
|
||||
}
|
||||
let start_b = b[cal.calGetStartDateProp(b)];
|
||||
if (!start_b) {
|
||||
return 1;
|
||||
}
|
||||
return start_a.compare(start_b);
|
||||
}
|
||||
var start_b = b[calGetStartDateProp(b)];
|
||||
if (!start_b) {
|
||||
return 1;
|
||||
}
|
||||
return start_a.compare(start_b);
|
||||
}
|
||||
aItems.sort(sortFunc);
|
||||
aItems.sort(sortFunc);
|
||||
|
||||
var prefixTitle = calGetString("calendar", "htmlPrefixTitle");
|
||||
var prefixWhen = calGetString("calendar", "htmlPrefixWhen");
|
||||
var prefixLocation = calGetString("calendar", "htmlPrefixLocation");
|
||||
var prefixDescription = calGetString("calendar", "htmlPrefixDescription");
|
||||
var defaultTimezone = calendarDefaultTimezone();
|
||||
let prefixTitle = cal.calGetString("calendar", "htmlPrefixTitle");
|
||||
let prefixWhen = cal.calGetString("calendar", "htmlPrefixWhen");
|
||||
let prefixLocation = cal.calGetString("calendar", "htmlPrefixLocation");
|
||||
let prefixDescription = cal.calGetString("calendar", "htmlPrefixDescription");
|
||||
let defaultTimezone = cal.calendarDefaultTimezone();
|
||||
|
||||
for (var pos = 0; pos < aItems.length; ++pos) {
|
||||
var item = aItems[pos];
|
||||
for (let pos = 0; pos < aItems.length; ++pos) {
|
||||
let item = aItems[pos];
|
||||
|
||||
// Put properties of the event in a definition list
|
||||
// Use hCalendar classes as bonus
|
||||
var ev = <div class='vevent'/>;
|
||||
var fmtTaskCompleted = calGetString("calendar",
|
||||
"htmlTaskCompleted",
|
||||
[item.title]);
|
||||
// Put properties of the event in a definition list
|
||||
// Use hCalendar classes as bonus
|
||||
let ev = <div class='vevent'/>;
|
||||
let fmtTaskCompleted = cal.calGetString("calendar",
|
||||
"htmlTaskCompleted",
|
||||
[item.title]);
|
||||
|
||||
// Title
|
||||
ev.appendChild(
|
||||
<div>
|
||||
<div class='key summarykey'>{prefixTitle}</div>
|
||||
<div class='value summary'>{item.isCompleted ? fmtTaskCompleted : item.title}</div>
|
||||
</div>
|
||||
);
|
||||
var startDate = item[calGetStartDateProp(item)];
|
||||
var endDate = item[calGetEndDateProp(item)];
|
||||
var dateString = dateFormatter.formatItemInterval(item);
|
||||
|
||||
if (startDate != null || endDate != null) {
|
||||
// This is a task with a start or due date, format accordingly
|
||||
// Title
|
||||
ev.appendChild(
|
||||
<div>
|
||||
<div class='key'>{prefixWhen}</div>
|
||||
<div class='value'>
|
||||
<abbr class='dtstart' title={startDate ? startDate.icalString : "none"}>{dateString}</abbr>
|
||||
<div class='key summarykey'>{prefixTitle}</div>
|
||||
<div class='value summary'>{item.isCompleted ? fmtTaskCompleted : item.title}</div>
|
||||
</div>
|
||||
);
|
||||
let startDate = item[cal.calGetStartDateProp(item)];
|
||||
let endDate = item[cal.calGetEndDateProp(item)];
|
||||
let dateString = cal.getDateFormatter().formatItemInterval(item);
|
||||
|
||||
if (startDate != null || endDate != null) {
|
||||
// This is a task with a start or due date, format accordingly
|
||||
ev.appendChild(
|
||||
<div>
|
||||
<div class='key'>{prefixWhen}</div>
|
||||
<div class='value'>
|
||||
<abbr class='dtstart' title={startDate ? startDate.icalString : "none"}>{dateString}</abbr>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// Location
|
||||
if (item.getProperty('LOCATION')) {
|
||||
ev.appendChild(
|
||||
<div>
|
||||
<div class='key'>{prefixLocation}</div>
|
||||
<div class='value location'>{item.getProperty('LOCATION')}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
// Location
|
||||
if (item.getProperty('LOCATION')) {
|
||||
ev.appendChild(
|
||||
<div>
|
||||
<div class='key'>{prefixLocation}</div>
|
||||
<div class='value location'>{item.getProperty('LOCATION')}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Description, inside a pre to preserve formating when needed.
|
||||
var desc = item.getProperty('DESCRIPTION');
|
||||
if (desc && desc.length > 0) {
|
||||
var usePre = false;
|
||||
if (desc.indexOf("\n ") >= 0 || desc.indexOf("\n\t") >= 0 ||
|
||||
desc.indexOf(" ") == 0 || desc.indexOf("\t") == 0)
|
||||
// (RegExp /^[ \t]/ doesn't work.)
|
||||
// contains indented preformatted text after beginning or newline
|
||||
// so preserve indentation with PRE.
|
||||
usePre = true;
|
||||
// Description, inside a pre to preserve formating when needed.
|
||||
let desc = item.getProperty('DESCRIPTION');
|
||||
if (desc && desc.length > 0) {
|
||||
let usePre = false;
|
||||
if (desc.indexOf("\n ") >= 0 || desc.indexOf("\n\t") >= 0 ||
|
||||
desc.indexOf(" ") == 0 || desc.indexOf("\t") == 0)
|
||||
// (RegExp /^[ \t]/ doesn't work.)
|
||||
// contains indented preformatted text after beginning or newline
|
||||
// so preserve indentation with PRE.
|
||||
usePre = true;
|
||||
|
||||
var descnode =
|
||||
<div>
|
||||
<div class='key'>{prefixDescription}</div>
|
||||
<div class='value'/>
|
||||
</div>;
|
||||
let descnode =
|
||||
<div>
|
||||
<div class='key'>{prefixDescription}</div>
|
||||
<div class='value'/>
|
||||
</div>;
|
||||
|
||||
if (usePre) {
|
||||
descnode.div[1] = <pre class='description'>{desc}</pre>;
|
||||
} else {
|
||||
var lines = desc.split('\n');
|
||||
for (var i in lines) {
|
||||
descnode.div[1].appendChild(lines[i]);
|
||||
// Add a new line, except after the last line
|
||||
if (i != (lines.length-1)) {
|
||||
descnode.div[1].appendChild(<br/>);
|
||||
if (usePre) {
|
||||
descnode.div[1] = <pre class='description'>{desc}</pre>;
|
||||
} else {
|
||||
let lines = desc.split('\n');
|
||||
for (let i in lines) {
|
||||
descnode.div[1].appendChild(lines[i]);
|
||||
// Add a new line, except after the last line
|
||||
if (i != (lines.length-1)) {
|
||||
descnode.div[1].appendChild(<br/>);
|
||||
}
|
||||
}
|
||||
}
|
||||
ev.appendChild(descnode);
|
||||
}
|
||||
ev.appendChild(descnode);
|
||||
html.body.appendChild(ev);
|
||||
}
|
||||
html.body.appendChild(ev);
|
||||
|
||||
// Convert the javascript string to an array of bytes, using the
|
||||
// utf8 encoder
|
||||
let convStream = Components.classes["@mozilla.org/intl/converter-output-stream;1"]
|
||||
.createInstance(Components.interfaces.nsIConverterOutputStream);
|
||||
convStream.init(aStream, 'UTF-8', 0, 0x0000);
|
||||
|
||||
let str = html.toXMLString()
|
||||
convStream.writeString(str);
|
||||
}
|
||||
|
||||
// Convert the javascript string to an array of bytes, using the
|
||||
// utf8 encoder
|
||||
var convStream = Components.classes["@mozilla.org/intl/converter-output-stream;1"]
|
||||
.createInstance(Components.interfaces.nsIConverterOutputStream);
|
||||
convStream.init(aStream, 'UTF-8', 0, 0x0000);
|
||||
|
||||
var str = html.toXMLString()
|
||||
convStream.writeString(str);
|
||||
return;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* -*- Mode: javascript; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* ***** 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
|
||||
|
@ -20,6 +19,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Philipp Kewisch <mozilla@kewis.ch>
|
||||
*
|
||||
* 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
|
||||
|
@ -35,65 +35,92 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// Import
|
||||
|
||||
function calIcsImporter() {
|
||||
this.wrappedJSObject = this;
|
||||
}
|
||||
|
||||
calIcsImporter.prototype.QueryInterface =
|
||||
function QueryInterface(aIID) {
|
||||
if (!aIID.equals(Components.interfaces.nsISupports) &&
|
||||
!aIID.equals(Components.interfaces.calIImporter)) {
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
Components.utils.import("resource://calendar/modules/calUtils.jsm");
|
||||
|
||||
// Shared functions
|
||||
function getIcsFileTypes(aCount) {
|
||||
aCount.value = 1;
|
||||
var wildmat = '*.ics';
|
||||
var label = calGetString("calendar", 'filterIcs', [wildmat]);
|
||||
return([{defaultExtension:'ics',
|
||||
extensionFilter: wildmat,
|
||||
description: label}]);
|
||||
let wildmat = '*.ics';
|
||||
let label = cal.calGetString("calendar", 'filterIcs', [wildmat]);
|
||||
return [{ defaultExtension: 'ics',
|
||||
extensionFilter: wildmat,
|
||||
description: label }];
|
||||
}
|
||||
|
||||
calIcsImporter.prototype.getFileTypes = getIcsFileTypes;
|
||||
|
||||
calIcsImporter.prototype.importFromStream =
|
||||
function ics_importFromStream(aStream, aCount) {
|
||||
var parser = Components.classes["@mozilla.org/calendar/ics-parser;1"].
|
||||
createInstance(Components.interfaces.calIIcsParser);
|
||||
parser.parseFromStream(aStream, null);
|
||||
return parser.getItems(aCount);
|
||||
};
|
||||
|
||||
|
||||
// Export
|
||||
|
||||
function calIcsExporter() {
|
||||
this.wrappedJSObject = this;
|
||||
// Importer
|
||||
function calIcsImporter() {
|
||||
}
|
||||
|
||||
calIcsExporter.prototype.QueryInterface =
|
||||
function QueryInterface(aIID) {
|
||||
if (!aIID.equals(Components.interfaces.nsISupports) &&
|
||||
!aIID.equals(Components.interfaces.calIExporter)) {
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
calIcsImporter.prototype = {
|
||||
getInterfaces: function (count) {
|
||||
const ifaces = [
|
||||
Components.interfaces.nsISupports,
|
||||
Components.interfaces.nsIClassInfo,
|
||||
Components.interfaces.calIImporter,
|
||||
];
|
||||
count.value = ifaces.length;
|
||||
return ifaces;
|
||||
},
|
||||
|
||||
getHelperForLanguage: function (language) {
|
||||
return null;
|
||||
},
|
||||
|
||||
contractID: "@mozilla.org/calendar/import;1?type=ics",
|
||||
classDescription: "Calendar ICS Importer",
|
||||
classID: Components.ID("{1e3e33dc-445a-49de-b2b6-15b2a050bb9d}"),
|
||||
implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: 0,
|
||||
|
||||
QueryInterface: function QueryInterface(aIID) {
|
||||
return cal.doQueryInterface(this, calIcsImporter.prototype, aIID, null, this);
|
||||
},
|
||||
|
||||
getFileTypes: getIcsFileTypes,
|
||||
|
||||
importFromStream: function importFromStream(aStream, aCount) {
|
||||
let parser = Components.classes["@mozilla.org/calendar/ics-parser;1"]
|
||||
.createInstance(Components.interfaces.calIIcsParser);
|
||||
parser.parseFromStream(aStream, null);
|
||||
return parser.getItems(aCount);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
calIcsExporter.prototype.getFileTypes = getIcsFileTypes;
|
||||
// Exporter
|
||||
function calIcsExporter() {
|
||||
}
|
||||
|
||||
// not prototype.export. export is reserved.
|
||||
calIcsExporter.prototype.exportToStream =
|
||||
function ics_exportToStream(aStream, aCount, aItems) {
|
||||
var serializer = Components.classes["@mozilla.org/calendar/ics-serializer;1"].
|
||||
createInstance(Components.interfaces.calIIcsSerializer);
|
||||
serializer.addItems(aItems, aItems.length);
|
||||
serializer.serializeToStream(aStream);
|
||||
calIcsExporter.prototype = {
|
||||
getInterfaces: function (count) {
|
||||
const ifaces = [
|
||||
Components.interfaces.nsISupports,
|
||||
Components.interfaces.nsIClassInfo,
|
||||
Components.interfaces.calIExporter,
|
||||
];
|
||||
count.value = ifaces.length;
|
||||
return ifaces;
|
||||
},
|
||||
|
||||
getHelperForLanguage: function (language) {
|
||||
return null;
|
||||
},
|
||||
|
||||
contractID: "@mozilla.org/calendar/export;1?type=ics",
|
||||
classDescription: "Calendar ICS Exporter",
|
||||
classID: Components.ID("{a6a524ce-adff-4a0f-bb7d-d1aaad4adc60}"),
|
||||
implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: 0,
|
||||
|
||||
QueryInterface: function QueryInterface(aIID) {
|
||||
return cal.doQueryInterface(this, calIcsExporter.prototype, aIID, null, this);
|
||||
},
|
||||
|
||||
getFileTypes: getIcsFileTypes,
|
||||
|
||||
exportToStream: function exportToStream(aStream, aCount, aItems) {
|
||||
let serializer = Components.classes["@mozilla.org/calendar/ics-serializer;1"]
|
||||
.createInstance(Components.interfaces.calIIcsSerializer);
|
||||
serializer.addItems(aItems, aItems.length);
|
||||
serializer.serializeToStream(aStream);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* -*- Mode: javascript; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -38,6 +37,9 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const scriptLoadOrder = [
|
||||
"calIcsImportExport.js",
|
||||
"calHtmlExport.js",
|
||||
|
@ -48,7 +50,6 @@ const scriptLoadOrder = [
|
|||
"calWeekPrinter.js"
|
||||
];
|
||||
|
||||
|
||||
function NSGetFactory(cid) {
|
||||
if (!this.scriptsLoaded) {
|
||||
Services.io.getProtocolHandler("resource")
|
||||
|
@ -70,5 +71,6 @@ function NSGetFactory(cid) {
|
|||
calMonthPrinter,
|
||||
calWeekPrinter
|
||||
];
|
||||
|
||||
return (XPCOMUtils.generateNSGetFactory(components))(cid);
|
||||
}
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
component {1e3e33dc-445a-49de-b2b6-15b2a050bb9d} calIcsImportExport.js
|
||||
component {1e3e33dc-445a-49de-b2b6-15b2a050bb9d} calImportExportModule.js
|
||||
contract @mozilla.org/calendar/import;1?type=ics {1e3e33dc-445a-49de-b2b6-15b2a050bb9d}
|
||||
category cal-importers cal-ics-importer @mozilla.org/calendar/import;1?type=ics
|
||||
|
||||
component {a6a524ce-adff-4a0f-bb7d-d1aaad4adc60} calIcsImportExport.js
|
||||
component {a6a524ce-adff-4a0f-bb7d-d1aaad4adc60} calImportExportModule.js
|
||||
contract @mozilla.org/calendar/export;1?type=ics {a6a524ce-adff-4a0f-bb7d-d1aaad4adc60}
|
||||
category cal-exporters cal-ics-exporter @mozilla.org/calendar/export;1?type=ics
|
||||
|
||||
component {72d9ab35-9b1b-442a-8cd0-ae49f00b159b} calHtmlExport.js
|
||||
component {72d9ab35-9b1b-442a-8cd0-ae49f00b159b} calImportExportModule.js
|
||||
contract @mozilla.org/calendar/export;1?type=htmllist {72d9ab35-9b1b-442a-8cd0-ae49f00b159b}
|
||||
category cal-exporters cal-html-list-exporter @mozilla.org/calendar/export;1?type=htmllist
|
||||
|
||||
component {9ae04413-fee3-45b9-8bbb-1eb39a4cbd1b} calListFormatter.js
|
||||
component {9ae04413-fee3-45b9-8bbb-1eb39a4cbd1b} calImportExportModule.js
|
||||
contract @mozilla.org/calendar/printformatter;1?type=list {9ae04413-fee3-45b9-8bbb-1eb39a4cbd1b}
|
||||
category cal-print-formatters cal-list-printformatter @mozilla.org/calendar/printformatter;1?type=list
|
||||
|
||||
component {f42d5132-92c4-487b-b5c8-38bf292d74c1} calMonthGridPrinter.js
|
||||
component {f42d5132-92c4-487b-b5c8-38bf292d74c1} calImportExportModule.js
|
||||
contract @mozilla.org/calendar/printformatter;1?type=monthgrid {f42d5132-92c4-487b-b5c8-38bf292d74c1}
|
||||
category cal-print-formatters cal-month-printer @mozilla.org/calendar/printformatter;1?type=monthgrid
|
||||
|
||||
component {2d6ec97b-9109-4b92-89c5-d4b4806619ce} calWeekPrinter.js
|
||||
component {2d6ec97b-9109-4b92-89c5-d4b4806619ce} calImportExportModule.js
|
||||
contract @mozilla.org/calendar/printformatter;1?type=weekplan {2d6ec97b-9109-4b92-89c5-d4b4806619ce}
|
||||
category cal-print-formatters cal-week-planner-printer @mozilla.org/calendar/printformatter;1?type=weekplan
|
||||
|
||||
component {64a5d17a-0497-48c5-b54f-72b15c9e9a14} calOutlookCSVImportExport.js
|
||||
component {64a5d17a-0497-48c5-b54f-72b15c9e9a14} calImportExportModule.js
|
||||
contract @mozilla.org/calendar/import;1?type=csv {64a5d17a-0497-48c5-b54f-72b15c9e9a14}
|
||||
category cal-importers cal-outlookcsv-importer @mozilla.org/calendar/import;1?type=csv
|
||||
|
||||
component {48e6d3a6-b41b-4052-9ed2-40b27800bd4b} calOutlookCSVImportExport.js
|
||||
component {48e6d3a6-b41b-4052-9ed2-40b27800bd4b} calImportExportModule.js
|
||||
contract @mozilla.org/calendar/export;1?type=csv {48e6d3a6-b41b-4052-9ed2-40b27800bd4b}
|
||||
category cal-exporters cal-outlookcsv-exporter @mozilla.org/calendar/export;1?type=csv
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* -*- Mode: javascript; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* ***** 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
|
||||
|
@ -20,6 +19,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Philipp Kewisch <mozilla@kewis.ch>
|
||||
*
|
||||
* 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
|
||||
|
@ -36,33 +36,44 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* A thin wrapper that is a print formatter, and just calls the html (list)
|
||||
* A thin wrapper that is a print formatter, and just calls the html (list)
|
||||
* exporter
|
||||
*/
|
||||
|
||||
function calListFormatter() {
|
||||
this.wrappedJSObject = this;
|
||||
}
|
||||
|
||||
calListFormatter.prototype.QueryInterface =
|
||||
function QueryInterface(aIID) {
|
||||
if (!aIID.equals(Components.interfaces.nsISupports) &&
|
||||
!aIID.equals(Components.interfaces.calIPrintFormatter)) {
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
calListFormatter.prototype = {
|
||||
getInterfaces: function (count) {
|
||||
const ifaces = [
|
||||
Components.interfaces.nsISupports,
|
||||
Components.interfaces.nsIClassInfo,
|
||||
Components.interfaces.calIPrintFormatter,
|
||||
];
|
||||
count.value = ifaces.length;
|
||||
return ifaces;
|
||||
},
|
||||
|
||||
getHelperForLanguage: function (language) {
|
||||
return null;
|
||||
},
|
||||
|
||||
contractID: "@mozilla.org/calendar/printformatter;1?type=list",
|
||||
classDescription: "Calendar List Print Formatter",
|
||||
classID: Components.ID("{9ae04413-fee3-45b9-8bbb-1eb39a4cbd1b}"),
|
||||
implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: 0,
|
||||
|
||||
QueryInterface: function QueryInterface(aIID) {
|
||||
return cal.doQueryInterface(this, calListFormatter.prototype, aIID, null, this);
|
||||
},
|
||||
|
||||
get name() {
|
||||
return cal.calGetString("calendar", "formatListName");
|
||||
},
|
||||
|
||||
formatToHtml: function list_formatToHtml(aStream, aStart, aEnd, aCount, aItems, aTitle) {
|
||||
let htmlexporter = Components.classes["@mozilla.org/calendar/export;1?type=htmllist"]
|
||||
.createInstance(Components.interfaces.calIExporter);
|
||||
htmlexporter.exportToStream(aStream, aCount, aItems, aTitle);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
calListFormatter.prototype.getName =
|
||||
function list_getName() {
|
||||
return calGetString("calendar", "formatListName");
|
||||
};
|
||||
calListFormatter.prototype.__defineGetter__("name", calListFormatter.prototype.getName);
|
||||
|
||||
calListFormatter.prototype.formatToHtml =
|
||||
function list_formatToHtml(aStream, aStart, aEnd, aCount, aItems, aTitle) {
|
||||
var htmlexporter = Components.classes["@mozilla.org/calendar/export;1?type=htmllist"]
|
||||
.createInstance(Components.interfaces.calIExporter);
|
||||
htmlexporter.exportToStream(aStream, aCount, aItems, aTitle);
|
||||
};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* -*- Mode: javascript; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* ***** 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
|
||||
|
@ -16,15 +15,16 @@
|
|||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Joey Minta <jminta@gmail.com>
|
||||
* Diego Mira David <diegomd86@gmail.com>
|
||||
* Eduardo Teruo Katayama <eduardo@ime.usp.br>
|
||||
* Glaucus Augustus Grecco Cardoso <glaucus@ime.usp.br>
|
||||
*
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Matthew Willis <mattwillis@gmail.com>
|
||||
* Diego Mira David <diegomd86@gmail.com>
|
||||
* Eduardo Teruo Katayama <eduardo@ime.usp.br>
|
||||
* Glaucus Augustus Grecco Cardoso <glaucus@ime.usp.br>
|
||||
* Philipp Kewisch <mozilla@kewis.ch>
|
||||
*
|
||||
* 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
|
||||
|
@ -45,315 +45,312 @@ Components.utils.import("resource://calendar/modules/calPrintUtils.jsm");
|
|||
/**
|
||||
* Prints a rough month-grid of events/tasks
|
||||
*/
|
||||
|
||||
function calMonthPrinter() {
|
||||
this.wrappedJSObject = this;
|
||||
}
|
||||
|
||||
calMonthPrinter.prototype.QueryInterface =
|
||||
function QueryInterface(aIID) {
|
||||
if (!aIID.equals(Components.interfaces.nsISupports) &&
|
||||
!aIID.equals(Components.interfaces.calIPrintFormatter)) {
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
calMonthPrinter.prototype = {
|
||||
getInterfaces: function (count) {
|
||||
const ifaces = [
|
||||
Components.interfaces.nsISupports,
|
||||
Components.interfaces.nsIClassInfo,
|
||||
Components.interfaces.calIPrintFormatter,
|
||||
];
|
||||
count.value = ifaces.length;
|
||||
return ifaces;
|
||||
},
|
||||
|
||||
return this;
|
||||
};
|
||||
getHelperForLanguage: function (language) {
|
||||
return null;
|
||||
},
|
||||
|
||||
calMonthPrinter.prototype.getName =
|
||||
function monthPrint_getName() {
|
||||
return calGetString("calendar", "monthPrinterName");
|
||||
};
|
||||
calMonthPrinter.prototype.__defineGetter__("name", calMonthPrinter.prototype.getName);
|
||||
contractID: "@mozilla.org/calendar/printformatter;1?type=monthgrid",
|
||||
classDescription: "Calendar Month Grid Print Formatter",
|
||||
classID: Components.ID("{f42d5132-92c4-487b-b5c8-38bf292d74c1}"),
|
||||
implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: 0,
|
||||
|
||||
calMonthPrinter.prototype.formatToHtml =
|
||||
function monthPrint_format(aStream, aStart, aEnd, aCount, aItems, aTitle) {
|
||||
var html = <html/>
|
||||
html.appendChild(
|
||||
<head>
|
||||
<title>{aTitle}</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/>
|
||||
<link rel='stylesheet' type='text/css' href='chrome://calendar/skin/calendar-printing.css'/>
|
||||
</head>);
|
||||
html.head.style = ".main-table { font-size: 26px; font-weight: bold; }\n";
|
||||
html.head.style += ".day-name { border: 1px solid black; background-color: white; font-size: 12px; font-weight: bold; }\n";
|
||||
html.head.style += ".day-box { border: 1px solid black; vertical-align: top; }\n";
|
||||
html.head.style += ".out-of-month { background-color: white !important; }\n";
|
||||
html.head.style += ".day-off { background-color: white !important; }\n";
|
||||
QueryInterface: function QueryInterface(aIID) {
|
||||
return cal.doQueryInterface(this, calMonthPrinter.prototype, aIID, null, this);
|
||||
},
|
||||
|
||||
// If aStart or aEnd weren't passed in, we need to calculate them based on
|
||||
// aItems data.
|
||||
get name() {
|
||||
return cal.calGetString("calendar", "monthPrinterName");
|
||||
},
|
||||
|
||||
var start = aStart;
|
||||
var end = aEnd;
|
||||
if (!start || !end) {
|
||||
for each (var item in aItems) {
|
||||
var itemStart = item.startDate || item.entryDate;
|
||||
var itemEnd = item.endDate || item.dueDate;
|
||||
if (!start || (itemStart && start.compare(itemStart) == 1)) {
|
||||
start = itemStart;
|
||||
}
|
||||
if (!end || (itemEnd && end.compare(itemEnd) == -1)) {
|
||||
end = itemEnd;
|
||||
formatToHtml: function monthPrint_format(aStream, aStart, aEnd, aCount, aItems, aTitle) {
|
||||
let html = <html/>
|
||||
html.appendChild(
|
||||
<head>
|
||||
<title>{aTitle}</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/>
|
||||
<link rel='stylesheet' type='text/css' href='chrome://calendar/skin/calendar-printing.css'/>
|
||||
</head>);
|
||||
html.head.style = ".main-table { font-size: 26px; font-weight: bold; }\n";
|
||||
html.head.style += ".day-name { border: 1px solid black; background-color: white; font-size: 12px; font-weight: bold; }\n";
|
||||
html.head.style += ".day-box { border: 1px solid black; vertical-align: top; }\n";
|
||||
html.head.style += ".out-of-month { background-color: white !important; }\n";
|
||||
html.head.style += ".day-off { background-color: white !important; }\n";
|
||||
|
||||
// If aStart or aEnd weren't passed in, we need to calculate them based on
|
||||
// aItems data.
|
||||
|
||||
let start = aStart;
|
||||
let end = aEnd;
|
||||
if (!start || !end) {
|
||||
for each (let item in aItems) {
|
||||
let itemStart = item[cal.calGetStartDateProp(item)];
|
||||
let itemEnd = item[cal.calGetEndDateProp(item)];
|
||||
if (!start || (itemStart && start.compare(itemStart) == 1)) {
|
||||
start = itemStart;
|
||||
}
|
||||
if (!end || (itemEnd && end.compare(itemEnd) == -1)) {
|
||||
end = itemEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Play around with aStart and aEnd to determine the minimal number of
|
||||
// months we can show to still technically meet their requirements. This
|
||||
// is most useful when someone printed 'Current View' in the month view. If
|
||||
// we take the aStart and aEnd literally, we'll print 3 months (because of
|
||||
// the extra days at the start/end), but we should avoid that.
|
||||
//
|
||||
// Basically, we check whether aStart falls in the same week as the start
|
||||
// of a month (ie aStart is Jan 29, which often is in the same week as
|
||||
// Feb 1), and similarly whether aEnd falls in the same week as the end of
|
||||
// a month.
|
||||
var weekStart = getPrefSafe("calendar.week.start", 0);
|
||||
maybeNewStart = start.clone();
|
||||
maybeNewStart.day = 1;
|
||||
maybeNewStart.month = start.month+1;
|
||||
// Play around with aStart and aEnd to determine the minimal number of
|
||||
// months we can show to still technically meet their requirements. This
|
||||
// is most useful when someone printed 'Current View' in the month view. If
|
||||
// we take the aStart and aEnd literally, we'll print 3 months (because of
|
||||
// the extra days at the start/end), but we should avoid that.
|
||||
//
|
||||
// Basically, we check whether aStart falls in the same week as the start
|
||||
// of a month (ie aStart is Jan 29, which often is in the same week as
|
||||
// Feb 1), and similarly whether aEnd falls in the same week as the end of
|
||||
// a month.
|
||||
let weekStart = cal.getPrefSafe("calendar.week.start", 0);
|
||||
maybeNewStart = start.clone();
|
||||
maybeNewStart.day = 1;
|
||||
maybeNewStart.month = start.month+1;
|
||||
|
||||
var date = start.clone();
|
||||
let dt = start.clone();
|
||||
|
||||
// First we have to adjust the end date for comparison, as the
|
||||
// provided end date is exclusive, i.e. will not be displayed.
|
||||
// First we have to adjust the end date for comparison, as the
|
||||
// provided end date is exclusive, i.e. will not be displayed.
|
||||
|
||||
var realEnd = end.clone();
|
||||
realEnd.day -= 1;
|
||||
let realEnd = end.clone();
|
||||
realEnd.day -= 1;
|
||||
|
||||
if (start.compare(realEnd) <= 0) {
|
||||
// Only adjust dates if start date is earlier than end date.
|
||||
if (start.compare(realEnd) <= 0) {
|
||||
// Only adjust dates if start date is earlier than end date.
|
||||
|
||||
if ((start.month != realEnd.month) || (start.year != realEnd.year)) {
|
||||
// We only need to adjust if start and end are in different months.
|
||||
if ((start.month != realEnd.month) || (start.year != realEnd.year)) {
|
||||
// We only need to adjust if start and end are in different months.
|
||||
|
||||
// We want to check whether or not the start day is in the same
|
||||
// week as the beginning of the next month. To do this, we take
|
||||
// the start date, add seven days and subtract the "day of week"
|
||||
// value (which has to be corrected in case we do not start on
|
||||
// Sunday).
|
||||
var testBegin = start.clone();
|
||||
var startWeekday = testBegin.weekday;
|
||||
if (startWeekday < weekStart) {
|
||||
startWeekday += 7;
|
||||
// We want to check whether or not the start day is in the same
|
||||
// week as the beginning of the next month. To do this, we take
|
||||
// the start date, add seven days and subtract the "day of week"
|
||||
// value (which has to be corrected in case we do not start on
|
||||
// Sunday).
|
||||
let testBegin = start.clone();
|
||||
let startWeekday = testBegin.weekday;
|
||||
if (startWeekday < weekStart) {
|
||||
startWeekday += 7;
|
||||
}
|
||||
testBegin.day += 7 + weekStart - startWeekday;
|
||||
if (testBegin.compare(maybeNewStart) > 0) {
|
||||
start = maybeNewStart;
|
||||
dt = start.clone();
|
||||
}
|
||||
}
|
||||
testBegin.day += 7 + weekStart - startWeekday;
|
||||
if (testBegin.compare(maybeNewStart) > 0) {
|
||||
start = maybeNewStart;
|
||||
date = start.clone();
|
||||
}
|
||||
}
|
||||
if ((start.month != realEnd.month) || (start.year != realEnd.year)) {
|
||||
// We only need to adjust if start and end are in different months.
|
||||
if ((start.month != realEnd.month) || (start.year != realEnd.year)) {
|
||||
// We only need to adjust if start and end are in different months.
|
||||
|
||||
// Next, we want to check whether or not the end day is in the same
|
||||
// week as the end of the previous month. So we have to get the
|
||||
// "day of week" value for the end of the previous month, adjust it
|
||||
// if necessary (when start of week is not Sunday) and check if the
|
||||
// end day is in the same week.
|
||||
// Next, we want to check whether or not the end day is in the same
|
||||
// week as the end of the previous month. So we have to get the
|
||||
// "day of week" value for the end of the previous month, adjust it
|
||||
// if necessary (when start of week is not Sunday) and check if the
|
||||
// end day is in the same week.
|
||||
|
||||
var lastDayOfPreviousMonth = end.clone();
|
||||
lastDayOfPreviousMonth.day = 0;
|
||||
var lastDayWeekday = lastDayOfPreviousMonth.weekday;
|
||||
if (lastDayWeekday < weekStart) {
|
||||
lastDayWeekday += 7;
|
||||
}
|
||||
if (date.month != end.month) {
|
||||
date.day = 1;
|
||||
}
|
||||
if ((lastDayWeekday + end.day - 1) < (7 + weekStart)) {
|
||||
date.day = end.day;
|
||||
}
|
||||
let lastDayOfPreviousMonth = end.clone();
|
||||
lastDayOfPreviousMonth.day = 0;
|
||||
let lastDayWeekday = lastDayOfPreviousMonth.weekday;
|
||||
if (lastDayWeekday < weekStart) {
|
||||
lastDayWeekday += 7;
|
||||
}
|
||||
if (dt.month != end.month) {
|
||||
dt.day = 1;
|
||||
}
|
||||
if ((lastDayWeekday + end.day - 1) < (7 + weekStart)) {
|
||||
dt.day = end.day;
|
||||
}
|
||||
|
||||
// Finally, we have to check whether we adjusted the dates too
|
||||
// well so that nothing is printed. That happens if you print just
|
||||
// one week which has the last day of a month in it.
|
||||
// Finally, we have to check whether we adjusted the dates too
|
||||
// well so that nothing is printed. That happens if you print just
|
||||
// one week which has the last day of a month in it.
|
||||
|
||||
if (date.compare(end) >= 0) {
|
||||
date.day = 1;
|
||||
if (dt.compare(end) >= 0) {
|
||||
dt.day = 1;
|
||||
}
|
||||
} else {
|
||||
dt.day = 1;
|
||||
}
|
||||
} else {
|
||||
date.day = 1;
|
||||
// If start date is after end date, just print empty month.
|
||||
dt = realEnd.clone();
|
||||
}
|
||||
} else {
|
||||
// If start date is after end date, just print empty month.
|
||||
date = realEnd.clone();
|
||||
}
|
||||
|
||||
var body = <body/>
|
||||
let body = <body/>
|
||||
|
||||
while (date.compare(end) < 0) {
|
||||
var monthName = calGetString("dateFormat", "month." + (date.month +1)+ ".name");
|
||||
monthName += " " + date.year;
|
||||
body.appendChild(
|
||||
<table border='0' width='100%' class='main-table'>
|
||||
<tr>
|
||||
<td align='center' valign='bottom'>{monthName}</td>
|
||||
</tr>
|
||||
</table>);
|
||||
body.appendChild(this.getStringForMonth(date, aItems));
|
||||
// Make sure each month gets put on its own page
|
||||
body.appendChild(<br style="page-break-after:always;"/>);
|
||||
date.month++;
|
||||
while (dt.compare(end) < 0) {
|
||||
let monthName = cal.calGetString("dateFormat", "month." + (dt.month +1) + ".name");
|
||||
monthName += " " + dt.year;
|
||||
body.appendChild(
|
||||
<table border='0' width='100%' class='main-table'>
|
||||
<tr>
|
||||
<td align='center' valign='bottom'>{monthName}</td>
|
||||
</tr>
|
||||
</table>);
|
||||
body.appendChild(this.getStringForMonth(dt, aItems));
|
||||
// Make sure each month gets put on its own page
|
||||
body.appendChild(<br style="page-break-after:always;"/>);
|
||||
dt.month++;
|
||||
}
|
||||
let tasks = cal.print.getTasksWithoutDueDate(aItems, dt);
|
||||
body.appendChild(tasks);
|
||||
html.appendChild(body);
|
||||
let convStream = Components.classes["@mozilla.org/intl/converter-output-stream;1"]
|
||||
.createInstance(Components.interfaces.nsIConverterOutputStream);
|
||||
convStream.init(aStream, 'UTF-8', 0, 0x0000);
|
||||
convStream.writeString(html.toXMLString());
|
||||
},
|
||||
|
||||
getStringForMonth: function monthPrint_getStringForMonth(aStart, aItems) {
|
||||
let weekStart = cal.getPrefSafe("calendar.week.start", 0);
|
||||
|
||||
let monthTable = <table style='border:1px solid black;' width='100%'/>
|
||||
let dayNameRow = <tr/>
|
||||
for (let i = 0; i < 7; i++) {
|
||||
let dayName = cal.calGetString("dateFormat", "day."+ (((weekStart+i)%7)+1) + ".Mmm");
|
||||
dayNameRow.appendChild(<td class='day-name' align='center'>{dayName}</td>);
|
||||
}
|
||||
monthTable.appendChild(dayNameRow);
|
||||
|
||||
// Set up the item-list so it's easy to work with.
|
||||
function hasUsableDate(item) item.startDate || item.entryDate || item.dueDate;
|
||||
let filteredItems = aItems.filter(hasUsableDate);
|
||||
|
||||
function compareItems(a, b) {
|
||||
// Sort tasks before events
|
||||
if (cal.isEvent(a) && cal.isToDo(b)) {
|
||||
return 1;
|
||||
}
|
||||
if (cal.isToDo(a) && cal.isEvent(b)) {
|
||||
return -1;
|
||||
}
|
||||
if (cal.isEvent(a)) {
|
||||
let startCompare = a.startDate.compare(b.startDate);
|
||||
if (startCompare != 0) {
|
||||
return startCompare;
|
||||
}
|
||||
return a.endDate.compare(b.endDate);
|
||||
}
|
||||
let aDate = a.entryDate || a.dueDate;
|
||||
let bDate = b.entryDate || b.dueDate;
|
||||
return aDate.compare(bDate);
|
||||
}
|
||||
let sortedList = filteredItems.sort(compareItems);
|
||||
let firstDate = aStart.startOfMonth.startOfWeek.clone();
|
||||
firstDate.day += weekStart;
|
||||
if (aStart.startOfMonth.weekday < weekStart) {
|
||||
// Go back one week to make sure we display this day
|
||||
firstDate.day -= 7;
|
||||
}
|
||||
|
||||
let lastDate = aStart.endOfMonth.endOfWeek.clone();
|
||||
if (aStart.endOfMonth.weekday < weekStart) {
|
||||
// Go back one week so we don't display any extra days
|
||||
lastDate.day -= 7;
|
||||
}
|
||||
firstDate.isDate = true;
|
||||
lastDate.isDate = true;
|
||||
|
||||
let dt = firstDate.clone();
|
||||
let itemListIndex = 0;
|
||||
while (dt.compare(lastDate) != 1) {
|
||||
monthTable.appendChild(this.makeHTMLWeek(dt, sortedList, aStart.month));
|
||||
}
|
||||
return monthTable;
|
||||
},
|
||||
|
||||
makeHTMLWeek: function makeHTMLWeek(dt, sortedList, targetMonth) {
|
||||
let weekRow = <tr/>;
|
||||
const weekPrefix = "calendar.week.";
|
||||
let prefNames = ["d0sundaysoff", "d1mondaysoff", "d2tuesdaysoff",
|
||||
"d3wednesdaysoff", "d4thursdaysoff", "d5fridaysoff", "d6saturdaysoff"];
|
||||
let defaults = [true, false, false, false, false, false, true];
|
||||
let daysOff = [];
|
||||
for (let i in prefNames) {
|
||||
if (cal.getPrefSafe(weekPrefix+prefNames[i], defaults[i])) {
|
||||
daysOff.push(Number(i));
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < 7; i++) {
|
||||
let myClass = 'day-box';
|
||||
if (dt.month != targetMonth) {
|
||||
myClass += ' out-of-month';
|
||||
} else if (daysOff.some(function(a) { return a == dt.weekday; })) {
|
||||
myClass += ' day-off';
|
||||
}
|
||||
let day = <td align='left' valign='top' class={myClass} height='100' width='100'/>
|
||||
let innerTable = <table valign='top' style='font-size: 10px;'/>
|
||||
let dateLabel = <tr valign='top'>
|
||||
<td valign='top' align='left'>{dt.day}</td>
|
||||
</tr>
|
||||
innerTable.appendChild(dateLabel);
|
||||
let defaultTimezone = calendarDefaultTimezone();
|
||||
for each (let item in sortedList) {
|
||||
let sDate = item.startDate || item.entryDate || item.dueDate;
|
||||
let eDate = item.endDate || item.dueDate || item.entryDate;
|
||||
if (sDate) {
|
||||
sDate = sDate.getInTimezone(defaultTimezone);
|
||||
}
|
||||
if (eDate) {
|
||||
eDate = eDate.getInTimezone(defaultTimezone);
|
||||
}
|
||||
|
||||
// end dates are exclusive
|
||||
if (sDate.isDate) {
|
||||
eDate = eDate.clone();
|
||||
eDate.day -= 1;
|
||||
}
|
||||
if (!eDate || eDate.compare(dt) == -1) {
|
||||
continue;
|
||||
}
|
||||
itemListIndex = i;
|
||||
if (!sDate || sDate.compare(dt) == 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
let time = (!s.isDate ? cal.getDateFormatter().formatTime(sDate) : "");
|
||||
let calColor = item.calendar.getProperty('color') || "#A8C2E1";
|
||||
let pb2 = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch2);
|
||||
let catColor;
|
||||
for each (let cat in item.getCategories({})) {
|
||||
try {
|
||||
catColor = pb2.getCharPref("calendar.category.color." + cat.toLowerCase());
|
||||
break; // take first matching
|
||||
} catch (ex) {}
|
||||
}
|
||||
|
||||
let style = 'font-size: 11px; text-align: left;';
|
||||
style += ' background-color: ' + calColor + ';';
|
||||
style += ' color: ' + getContrastingTextColor(calColor);
|
||||
if (catColor) {
|
||||
style += ' border: solid ' + catColor + ' 2px;';
|
||||
}
|
||||
let item = <tr>
|
||||
<td valign='top' style={style}>{time} {item.title}</td>
|
||||
</tr>;
|
||||
innerTable.appendChild(item);
|
||||
}
|
||||
day.appendChild(innerTable);
|
||||
weekRow.appendChild(day);
|
||||
dt.day++;
|
||||
}
|
||||
return weekRow;
|
||||
}
|
||||
let tasks = cal.print.getTasksWithoutDueDate(aItems, date);
|
||||
body.appendChild(tasks);
|
||||
html.appendChild(body);
|
||||
let convStream = Components.classes["@mozilla.org/intl/converter-output-stream;1"].createInstance(Components.interfaces.nsIConverterOutputStream);
|
||||
convStream.init(aStream, 'UTF-8', 0, 0x0000);
|
||||
convStream.writeString(html.toXMLString());
|
||||
};
|
||||
|
||||
calMonthPrinter.prototype.getStringForMonth =
|
||||
function monthPrint_getHTML(aStart, aItems) {
|
||||
var weekStart = getPrefSafe("calendar.week.start", 0);
|
||||
|
||||
var monthTable = <table style='border:1px solid black;' width='100%'/>
|
||||
var dayNameRow = <tr/>
|
||||
for (var i = 0; i < 7; i++) {
|
||||
var dayName = calGetString("dateFormat", "day."+ (((weekStart+i)%7)+1) + ".Mmm");
|
||||
dayNameRow.appendChild(<td class='day-name' align='center'>{dayName}</td>);
|
||||
}
|
||||
monthTable.appendChild(dayNameRow);
|
||||
|
||||
// Set up the item-list so it's easy to work with.
|
||||
function hasUsableDate(item) {
|
||||
return item.startDate || item.entryDate || item.dueDate;
|
||||
}
|
||||
var filteredItems = aItems.filter(hasUsableDate);
|
||||
|
||||
var calIEvent = Components.interfaces.calIEvent;
|
||||
var calITodo = Components.interfaces.calITodo
|
||||
function compareItems(a, b) {
|
||||
// Sort tasks before events
|
||||
if (isEvent(a) && isToDo(b)) {
|
||||
return 1;
|
||||
}
|
||||
if (isToDo(a) && isEvent(b)) {
|
||||
return -1;
|
||||
}
|
||||
if (isEvent(a)) {
|
||||
var startCompare = a.startDate.compare(b.startDate);
|
||||
if (startCompare != 0) {
|
||||
return startCompare;
|
||||
}
|
||||
return a.endDate.compare(b.endDate);
|
||||
}
|
||||
var aDate = a.entryDate || a.dueDate;
|
||||
var bDate = b.entryDate || b.dueDate;
|
||||
return aDate.compare(bDate);
|
||||
}
|
||||
var sortedList = filteredItems.sort(compareItems);
|
||||
var firstDate = aStart.startOfMonth.startOfWeek.clone();
|
||||
firstDate.day += weekStart;
|
||||
if (aStart.startOfMonth.weekday < weekStart) {
|
||||
// Go back one week to make sure we display this day
|
||||
firstDate.day -= 7;
|
||||
}
|
||||
|
||||
var lastDate = aStart.endOfMonth.endOfWeek.clone();
|
||||
if (aStart.endOfMonth.weekday < weekStart) {
|
||||
// Go back one week so we don't display any extra days
|
||||
lastDate.day -= 7;
|
||||
}
|
||||
firstDate.isDate = true;
|
||||
lastDate.isDate = true;
|
||||
|
||||
var date = firstDate.clone();
|
||||
var itemListIndex = 0;
|
||||
while (date.compare(lastDate) != 1) {
|
||||
monthTable.appendChild(this.makeHTMLWeek(date, sortedList, aStart.month));
|
||||
}
|
||||
return monthTable;
|
||||
};
|
||||
|
||||
calMonthPrinter.prototype.makeHTMLWeek =
|
||||
function makeHTMLWeek(date, sortedList, targetMonth) {
|
||||
var weekRow = <tr/>;
|
||||
const weekPrefix = "calendar.week.";
|
||||
var prefNames = ["d0sundaysoff", "d1mondaysoff", "d2tuesdaysoff",
|
||||
"d3wednesdaysoff", "d4thursdaysoff", "d5fridaysoff", "d6saturdaysoff"];
|
||||
var defaults = [true, false, false, false, false, false, true];
|
||||
var daysOff = new Array();
|
||||
for (var i in prefNames) {
|
||||
if (getPrefSafe(weekPrefix+prefNames[i], defaults[i])) {
|
||||
daysOff.push(Number(i));
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < 7; i++) {
|
||||
var myClass = 'day-box';
|
||||
if (date.month != targetMonth) {
|
||||
myClass += ' out-of-month';
|
||||
} else if (daysOff.some(function(a) { return a == date.weekday; })) {
|
||||
myClass += ' day-off';
|
||||
}
|
||||
var day = <td align='left' valign='top' class={myClass} height='100' width='100'/>
|
||||
var innerTable = <table valign='top' style='font-size: 10px;'/>
|
||||
var dateLabel = <tr valign='top'>
|
||||
<td valign='top' align='left'>{date.day}</td>
|
||||
</tr>
|
||||
innerTable.appendChild(dateLabel);
|
||||
var defaultTimezone = calendarDefaultTimezone();
|
||||
for each (var item in sortedList) {
|
||||
var sDate = item.startDate || item.entryDate || item.dueDate;
|
||||
var eDate = item.endDate || item.dueDate || item.entryDate;
|
||||
if (sDate) {
|
||||
sDate = sDate.getInTimezone(defaultTimezone);
|
||||
}
|
||||
if (eDate) {
|
||||
eDate = eDate.getInTimezone(defaultTimezone);
|
||||
}
|
||||
|
||||
// end dates are exclusive
|
||||
if (sDate.isDate) {
|
||||
eDate = eDate.clone();
|
||||
eDate.day -= 1;
|
||||
}
|
||||
if (!eDate || eDate.compare(date) == -1) {
|
||||
continue;
|
||||
}
|
||||
itemListIndex = i;
|
||||
if (!sDate || sDate.compare(date) == 1) {
|
||||
break;
|
||||
}
|
||||
var dateFormatter =
|
||||
Components.classes["@mozilla.org/calendar/datetime-formatter;1"]
|
||||
.getService(Components.interfaces.calIDateTimeFormatter);
|
||||
var time = "";
|
||||
if (!sDate.isDate) {
|
||||
time = dateFormatter.formatTime(sDate);
|
||||
}
|
||||
|
||||
var calColor = item.calendar.getProperty('color');
|
||||
if (!calColor) {
|
||||
calColor = "#A8C2E1";
|
||||
}
|
||||
var pb2 = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch2);
|
||||
var catColor;
|
||||
for each (var cat in item.getCategories({})) {
|
||||
try {
|
||||
catColor = pb2.getCharPref("calendar.category.color." + cat.toLowerCase());
|
||||
break; // take first matching
|
||||
} catch(ex) {}
|
||||
}
|
||||
|
||||
var style = 'font-size: 11px; text-align: left;';
|
||||
style += ' background-color: ' + calColor + ';';
|
||||
style += ' color: ' + getContrastingTextColor(calColor);
|
||||
if (catColor) {
|
||||
style += ' border: solid ' + catColor + ' 2px;';
|
||||
}
|
||||
var item = <tr>
|
||||
<td valign='top' style={style}>{time} {item.title}</td>
|
||||
</tr>;
|
||||
innerTable.appendChild(item);
|
||||
}
|
||||
day.appendChild(innerTable);
|
||||
weekRow.appendChild(day);
|
||||
date.day++;
|
||||
}
|
||||
return weekRow;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* -*- Mode: javascript; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* ***** 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
|
||||
|
@ -40,33 +39,6 @@
|
|||
|
||||
Components.utils.import("resource://calendar/modules/calAlarmUtils.jsm");
|
||||
|
||||
// Import
|
||||
|
||||
function calOutlookCSVImporter() {
|
||||
this.wrappedJSObject = this;
|
||||
}
|
||||
|
||||
calOutlookCSVImporter.prototype.QueryInterface =
|
||||
function QueryInterface(aIID) {
|
||||
if (!aIID.equals(Components.interfaces.nsISupports) &&
|
||||
!aIID.equals(Components.interfaces.calIImporter)) {
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
function getOutlookCsvFileTypes(aCount) {
|
||||
aCount.value = 1;
|
||||
var wildmat = '*.csv';
|
||||
var label = calGetString("calendar", 'filterOutlookCsv', [wildmat]);
|
||||
return([{defaultExtension:'csv',
|
||||
extensionFilter: wildmat,
|
||||
description: label}]);
|
||||
}
|
||||
|
||||
calOutlookCSVImporter.prototype.getFileTypes = getOutlookCsvFileTypes;
|
||||
|
||||
const localeEn = {
|
||||
headTitle : "Subject",
|
||||
headStartDate : "Start Date",
|
||||
|
@ -84,7 +56,7 @@ const localeEn = {
|
|||
|
||||
valueTrue : "True",
|
||||
valueFalse : "False",
|
||||
|
||||
|
||||
dateRe : /^(\d+)\/(\d+)\/(\d+)$/,
|
||||
dateDayIndex : 2,
|
||||
dateMonthIndex : 1,
|
||||
|
@ -118,7 +90,7 @@ const localeNl = {
|
|||
|
||||
valueTrue : "Waar",
|
||||
valueFalse : "Onwaar",
|
||||
|
||||
|
||||
dateRe : /^(\d+)-(\d+)-(\d+)$/,
|
||||
dateDayIndex : 1,
|
||||
dateMonthIndex : 2,
|
||||
|
@ -137,414 +109,451 @@ const locales = [localeEn, localeNl];
|
|||
// Windows line endings, CSV files with LF only can't be read by Outlook.
|
||||
const exportLineEnding = "\r\n";
|
||||
|
||||
/**
|
||||
* Takes a text block of Outlook-exported Comma Separated Values and tries to
|
||||
* parse that into individual events.
|
||||
*
|
||||
* First line is field names, all quoted with double quotes. Field names are
|
||||
* locale dependendent. In English the recognized field names are:
|
||||
* "Title","Start Date","Start Time","End Date","End Time","All day event",
|
||||
* "Reminder on/off","Reminder Date","Reminder Time","Categories",
|
||||
* "Description","Location","Private"
|
||||
* The fields "Title" and "Start Date" are mandatory. If "Start Time" misses
|
||||
* the event is set as all day event. If "End Date" or "End Time" miss the
|
||||
* default durations are set.
|
||||
*
|
||||
* The rest of the lines are events, one event per line, with fields in the
|
||||
* order descibed by the first line. All non-empty values must be quoted.
|
||||
*
|
||||
* Returns: an array of parsed calendarEvents.
|
||||
* If the parse is cancelled, a zero length array is returned.
|
||||
*/
|
||||
// Shared functions
|
||||
function getOutlookCsvFileTypes(aCount) {
|
||||
aCount.value = 1;
|
||||
let wildmat = '*.csv';
|
||||
let label = cal.calGetString("calendar", 'filterOutlookCsv', [wildmat]);
|
||||
return [{ defaultExtension: 'csv',
|
||||
extensionFilter: wildmat,
|
||||
description: label }];
|
||||
}
|
||||
|
||||
calOutlookCSVImporter.prototype.importFromStream =
|
||||
function csv_importFromStream(aStream, aCount) {
|
||||
var scriptableInputStream = Components.classes["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(Components.interfaces.nsIScriptableInputStream);
|
||||
scriptableInputStream.init(aStream);
|
||||
var str = scriptableInputStream.read(-1);
|
||||
// Importer
|
||||
function calOutlookCSVImporter() {
|
||||
}
|
||||
|
||||
parse: {
|
||||
// parse header line of quoted comma separated column names.
|
||||
var trimEndQuotesRegExp = /^"(.*)"$/m;
|
||||
var trimResults = trimEndQuotesRegExp.exec( str );
|
||||
var header = trimResults && trimResults[1].split(/","/);
|
||||
if (header == null)
|
||||
break parse;
|
||||
calOutlookCSVImporter.prototype = {
|
||||
getInterfaces: function (count) {
|
||||
const ifaces = [
|
||||
Components.interfaces.nsISupports,
|
||||
Components.interfaces.nsIClassInfo,
|
||||
Components.interfaces.calIImporter,
|
||||
];
|
||||
count.value = ifaces.length;
|
||||
return ifaces;
|
||||
},
|
||||
|
||||
//strip header from string
|
||||
str = str.slice(trimResults[0].length);
|
||||
getHelperForLanguage: function (language) {
|
||||
return null;
|
||||
},
|
||||
|
||||
var args = new Object();
|
||||
//args.fieldList contains the field names from the first row of CSV
|
||||
args.fieldList = header;
|
||||
contractID: "@mozilla.org/calendar/import;1?type=csv",
|
||||
classDescription: "Calendar Outlook CSV Importer",
|
||||
classID: Components.ID("{64a5d17a-0497-48c5-b54f-72b15c9e9a14}"),
|
||||
implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: 0,
|
||||
|
||||
var locale;
|
||||
var i;
|
||||
for (i in locales) {
|
||||
locale = locales[i];
|
||||
var knownIndxs = 0;
|
||||
args.titleIndex = 0;
|
||||
args.startDateIndex = 0;
|
||||
for (var i = 1; i <= header.length; ++i) {
|
||||
switch( header[i-1] ) {
|
||||
case locale.headTitle: args.titleIndex = i; knownIndxs++; break;
|
||||
case locale.headStartDate: args.startDateIndex = i; knownIndxs++; break;
|
||||
case locale.headStartTime: args.startTimeIndex = i; knownIndxs++; break;
|
||||
case locale.headEndDate: args.endDateIndex = i; knownIndxs++; break;
|
||||
case locale.headEndTime: args.endTimeIndex = i; knownIndxs++; break;
|
||||
case locale.headAllDayEvent: args.allDayIndex = i; knownIndxs++; break;
|
||||
case locale.headAlarm: args.alarmIndex = i; knownIndxs++; break;
|
||||
case locale.headAlarmDate: args.alarmDateIndex = i; knownIndxs++; break;
|
||||
case locale.headAlarmTime: args.alarmTimeIndex = i; knownIndxs++; break;
|
||||
case locale.headCategories: args.categoriesIndex = i; knownIndxs++; break;
|
||||
case locale.headDescription: args.descriptionIndex = i; knownIndxs++; break;
|
||||
case locale.headLocation: args.locationIndex = i; knownIndxs++; break;
|
||||
case locale.headPrivate: args.privateIndex = i; knownIndxs++; break;
|
||||
QueryInterface: function QueryInterface(aIID) {
|
||||
return cal.doQueryInterface(this, calOutlookCSVImporter.prototype, aIID, null, this);
|
||||
},
|
||||
|
||||
getFileTypes: getOutlookCsvFileTypes,
|
||||
|
||||
/**
|
||||
* Takes a text block of Outlook-exported Comma Separated Values and tries to
|
||||
* parse that into individual events.
|
||||
*
|
||||
* First line is field names, all quoted with double quotes. Field names are
|
||||
* locale dependendent. In English the recognized field names are:
|
||||
* "Title","Start Date","Start Time","End Date","End Time","All day event",
|
||||
* "Reminder on/off","Reminder Date","Reminder Time","Categories",
|
||||
* "Description","Location","Private"
|
||||
* The fields "Title" and "Start Date" are mandatory. If "Start Time" misses
|
||||
* the event is set as all day event. If "End Date" or "End Time" miss the
|
||||
* default durations are set.
|
||||
*
|
||||
* The rest of the lines are events, one event per line, with fields in the
|
||||
* order descibed by the first line. All non-empty values must be quoted.
|
||||
*
|
||||
* Returns: an array of parsed calendarEvents.
|
||||
* If the parse is cancelled, a zero length array is returned.
|
||||
*/
|
||||
importFromStream: function csv_importFromStream(aStream, aCount) {
|
||||
let scriptableInputStream = Components.classes["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(Components.interfaces.nsIScriptableInputStream);
|
||||
scriptableInputStream.init(aStream);
|
||||
let str = scriptableInputStream.read(-1);
|
||||
|
||||
parse: {
|
||||
// parse header line of quoted comma separated column names.
|
||||
let trimEndQuotesRegExp = /^"(.*)"$/m;
|
||||
let trimResults = trimEndQuotesRegExp.exec( str );
|
||||
let header = trimResults && trimResults[1].split(/","/);
|
||||
if (header == null) {
|
||||
break parse;
|
||||
}
|
||||
|
||||
//strip header from string
|
||||
str = str.slice(trimResults[0].length);
|
||||
|
||||
let args = {};
|
||||
//args.fieldList contains the field names from the first row of CSV
|
||||
args.fieldList = header;
|
||||
|
||||
let locale;
|
||||
let i;
|
||||
for (i in locales) {
|
||||
locale = locales[i];
|
||||
let knownIndxs = 0;
|
||||
args.titleIndex = 0;
|
||||
args.startDateIndex = 0;
|
||||
for (let i = 1; i <= header.length; ++i) {
|
||||
switch( header[i-1] ) {
|
||||
case locale.headTitle: args.titleIndex = i; knownIndxs++; break;
|
||||
case locale.headStartDate: args.startDateIndex = i; knownIndxs++; break;
|
||||
case locale.headStartTime: args.startTimeIndex = i; knownIndxs++; break;
|
||||
case locale.headEndDate: args.endDateIndex = i; knownIndxs++; break;
|
||||
case locale.headEndTime: args.endTimeIndex = i; knownIndxs++; break;
|
||||
case locale.headAllDayEvent: args.allDayIndex = i; knownIndxs++; break;
|
||||
case locale.headAlarm: args.alarmIndex = i; knownIndxs++; break;
|
||||
case locale.headAlarmDate: args.alarmDateIndex = i; knownIndxs++; break;
|
||||
case locale.headAlarmTime: args.alarmTimeIndex = i; knownIndxs++; break;
|
||||
case locale.headCategories: args.categoriesIndex = i; knownIndxs++; break;
|
||||
case locale.headDescription: args.descriptionIndex = i; knownIndxs++; break;
|
||||
case locale.headLocation: args.locationIndex = i; knownIndxs++; break;
|
||||
case locale.headPrivate: args.privateIndex = i; knownIndxs++; break;
|
||||
}
|
||||
}
|
||||
// Were both mandatory fields recognized?
|
||||
if (args.titleIndex != 0 && args.startDateIndex != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Were both mandatory fields recognized?
|
||||
if (args.titleIndex != 0 && args.startDateIndex != 0) {
|
||||
break;
|
||||
|
||||
if (knownIndxs == 0 && header.length == 22) {
|
||||
// set default indexes for a default Outlook2000 CSV file
|
||||
args.titleIndex = 1;
|
||||
args.startDateIndex = 2;
|
||||
args.startTimeIndex = 3;
|
||||
args.endDateIndex = 4;
|
||||
args.endTimeIndex = 5;
|
||||
args.allDayIndex = 6;
|
||||
args.alarmIndex = 7;
|
||||
args.alarmDateIndex = 8;
|
||||
args.alarmTimeIndex = 9;
|
||||
args.categoriesIndex = 15;
|
||||
args.descriptionIndex = 16;
|
||||
args.locationIndex = 17;
|
||||
args.privateIndex = 20;
|
||||
}
|
||||
}
|
||||
|
||||
if (knownIndxs == 0 && header.length == 22) {
|
||||
// set default indexes for a default Outlook2000 CSV file
|
||||
args.titleIndex = 1;
|
||||
args.startDateIndex = 2;
|
||||
args.startTimeIndex = 3;
|
||||
args.endDateIndex = 4;
|
||||
args.endTimeIndex = 5;
|
||||
args.allDayIndex = 6;
|
||||
args.alarmIndex = 7;
|
||||
args.alarmDateIndex = 8;
|
||||
args.alarmTimeIndex = 9;
|
||||
args.categoriesIndex = 15;
|
||||
args.descriptionIndex = 16;
|
||||
args.locationIndex = 17;
|
||||
args.privateIndex = 20;
|
||||
}
|
||||
if (args.titleIndex == 0 || args.startDateIndex == 0) {
|
||||
dump("Can't import. Life sucks\n")
|
||||
break parse;
|
||||
}
|
||||
|
||||
if (args.titleIndex == 0 || args.startDateIndex == 0) {
|
||||
dump("Can't import. Life sucks\n")
|
||||
break parse;
|
||||
}
|
||||
// Construct event regexp according to field indexes. The regexp can
|
||||
// be made stricter, if it seems this matches too loosely.
|
||||
let regExpStr = "^";
|
||||
for (i = 1; i <= header.length; i++) {
|
||||
if (i > 1)
|
||||
regExpStr += ",";
|
||||
regExpStr += "(?:\"((?:[^\"]|\"\")*)\")?";
|
||||
}
|
||||
regExpStr += "$";
|
||||
|
||||
// Construct event regexp according to field indexes. The regexp can
|
||||
// be made stricter, if it seems this matches too loosely.
|
||||
var regExpStr = "^";
|
||||
for (i = 1; i <= header.length; i++) {
|
||||
if (i > 1)
|
||||
regExpStr += ",";
|
||||
regExpStr += "(?:\"((?:[^\"]|\"\")*)\")?";
|
||||
}
|
||||
regExpStr += "$";
|
||||
// eventRegExp: regexp for reading events (this one'll be constructed on fly)
|
||||
const eventRegExp = new RegExp(regExpStr, "gm");
|
||||
|
||||
// eventRegExp: regexp for reading events (this one'll be constructed on fly)
|
||||
const eventRegExp = new RegExp(regExpStr, "gm");
|
||||
// match first line
|
||||
let eventFields = eventRegExp(str);
|
||||
|
||||
// match first line
|
||||
var eventFields = eventRegExp(str);
|
||||
if (eventFields == null)
|
||||
break parse;
|
||||
|
||||
if (eventFields == null)
|
||||
break parse;
|
||||
args.boolStr = localeEn.valueTrue;
|
||||
args.boolIsTrue = true;
|
||||
|
||||
args.boolStr = localeEn.valueTrue;
|
||||
args.boolIsTrue = true;
|
||||
let dateParseConfirmed = false;
|
||||
let eventArray = new Array();
|
||||
do {
|
||||
// At this point eventFields contains following fields. Position
|
||||
// of fields is in args.[fieldname]Index.
|
||||
// subject, start date, start time, end date, end time,
|
||||
// all day, alarm on, alarm date, alarm time,
|
||||
// Description, Categories, Location, Private
|
||||
// Unused fields (could maybe be copied to Description):
|
||||
// Meeting Organizer, Required Attendees, Optional Attendees,
|
||||
// Meeting Resources, Billing Information, Mileage, Priority,
|
||||
// Sensitivity, Show time as
|
||||
|
||||
var dateParseConfirmed = false;
|
||||
var eventArray = new Array();
|
||||
do {
|
||||
// At this point eventFields contains following fields. Position
|
||||
// of fields is in args.[fieldname]Index.
|
||||
// subject, start date, start time, end date, end time,
|
||||
// all day, alarm on, alarm date, alarm time,
|
||||
// Description, Categories, Location, Private
|
||||
// Unused fields (could maybe be copied to Description):
|
||||
// Meeting Organizer, Required Attendees, Optional Attendees,
|
||||
// Meeting Resources, Billing Information, Mileage, Priority,
|
||||
// Sensitivity, Show time as
|
||||
let title = ("titleIndex" in args
|
||||
? this.parseTextField(eventFields[args.titleIndex]) : "");
|
||||
let sDate = this.parseDateTime(eventFields[args.startDateIndex],
|
||||
eventFields[args.startTimeIndex],
|
||||
locale);
|
||||
let eDate = this.parseDateTime(eventFields[args.endDateIndex],
|
||||
eventFields[args.endTimeIndex],
|
||||
locale);
|
||||
// Create an event only if we have a startDate. No more checks
|
||||
// on sDate needed in the following process.
|
||||
if (sDate) {
|
||||
let event = cal.createEvent();
|
||||
|
||||
var title = ("titleIndex" in args
|
||||
? parseTextField(eventFields[args.titleIndex]) : "");
|
||||
var sDate = parseDateTime(eventFields[args.startDateIndex],
|
||||
eventFields[args.startTimeIndex],
|
||||
locale);
|
||||
var eDate = parseDateTime(eventFields[args.endDateIndex],
|
||||
eventFields[args.endTimeIndex],
|
||||
locale);
|
||||
// Create an event only if we have a startDate. No more checks
|
||||
// on sDate needed in the following process.
|
||||
if (sDate) {
|
||||
var event = createEvent();
|
||||
|
||||
// Use column head in brackets if event title misses in data.
|
||||
if (title) {
|
||||
event.title = title;
|
||||
} else {
|
||||
event.title = "[" + locale.headTitle + "]";
|
||||
}
|
||||
|
||||
// Check data for all day event. Additionally sDate.isDate
|
||||
// may have been set in parseDateTime() if no time was found
|
||||
if (eventFields[args.allDayIndex] == locale.valueTrue) {
|
||||
sDate.isDate = true;
|
||||
}
|
||||
if (locale.valueTrue == eventFields[args.privateIndex])
|
||||
event.privacy = "PRIVATE";
|
||||
|
||||
if (!eDate) {
|
||||
// No endDate was found. All day events last one day and
|
||||
// timed events last the default length.
|
||||
eDate = sDate.clone();
|
||||
if (sDate.isDate) {
|
||||
// end date is exclusive, so set to next day after start.
|
||||
eDate.day += 1;
|
||||
// Use column head in brackets if event title misses in data.
|
||||
if (title) {
|
||||
event.title = title;
|
||||
} else {
|
||||
eDate.minute += getPrefSafe(
|
||||
"calendar.event.defaultlength", 60);
|
||||
event.title = "[" + locale.headTitle + "]";
|
||||
}
|
||||
} else {
|
||||
// An endDate was found.
|
||||
if (sDate.isDate) {
|
||||
// A time part for the startDate is missing or was
|
||||
// not recognized. We have to throw away the endDates
|
||||
// time part too for obtaining a valid event.
|
||||
eDate.isDate = true;
|
||||
// Correct the eDate if duration is less than one day.
|
||||
if (1 > eDate.subtractDate(sDate).days) {
|
||||
eDate = sDate.clone();
|
||||
eDate.day += 1;
|
||||
}
|
||||
} else {
|
||||
// We now have a timed startDate and an endDate. If the
|
||||
// end time is invalid set it to 23:59:00
|
||||
if (eDate.isDate) {
|
||||
eDate.isDate = false;
|
||||
eDate.hour = 23;
|
||||
eDate.minute = 59;
|
||||
}
|
||||
// Correct the duration to 0 seconds if it is negative.
|
||||
if (eDate.subtractDate(sDate).isNegative ) {
|
||||
eDate = sDate.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
event.startDate = sDate;
|
||||
event.endDate = eDate;
|
||||
|
||||
// Exists an alarm true/false column?
|
||||
if ("alarmIndex" in args) {
|
||||
// Is an alarm wanted for this event?
|
||||
if (locale.valueTrue == eventFields[args.alarmIndex]) {
|
||||
let alarmDate =
|
||||
parseDateTime(eventFields[args.alarmDateIndex],
|
||||
eventFields[args.alarmTimeIndex],
|
||||
locale);
|
||||
// Only set the alarm if a date was parsed
|
||||
if (alarmDate) {
|
||||
let alarm = cal.createAlarm();
|
||||
alarm.related = alarm.ALARM_RELATED_ABSOLUTE;
|
||||
alarm.alarmDate = alarmDate;
|
||||
event.addAlarm(alarm);
|
||||
} else {
|
||||
// XXX Is this really wanted here?
|
||||
cal.alarms.setDefaultValues(event);
|
||||
}
|
||||
// Check data for all day event. Additionally sDate.isDate
|
||||
// may have been set in parseDateTime() if no time was found
|
||||
if (eventFields[args.allDayIndex] == locale.valueTrue) {
|
||||
sDate.isDate = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Using the "Private" field only for getting privacy status.
|
||||
// "Sensitivity" is neglected for now.
|
||||
if ("privateIndex" in args) {
|
||||
if (locale.valueTrue == eventFields[args.privateIndex]) {
|
||||
event.privacy = "PRIVATE";
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid setting empty properties
|
||||
var txt = "";
|
||||
if ("descriptionIndex" in args) {
|
||||
txt = parseTextField(eventFields[args.descriptionIndex])
|
||||
if (txt) {
|
||||
event.setProperty("DESCRIPTION", txt);
|
||||
|
||||
if (!eDate) {
|
||||
// No endDate was found. All day events last one day and
|
||||
// timed events last the default length.
|
||||
eDate = sDate.clone();
|
||||
if (sDate.isDate) {
|
||||
// end date is exclusive, so set to next day after start.
|
||||
eDate.day += 1;
|
||||
} else {
|
||||
eDate.minute += cal.getPrefSafe("calendar.event.defaultlength", 60);
|
||||
}
|
||||
} else {
|
||||
// An endDate was found.
|
||||
if (sDate.isDate) {
|
||||
// A time part for the startDate is missing or was
|
||||
// not recognized. We have to throw away the endDates
|
||||
// time part too for obtaining a valid event.
|
||||
eDate.isDate = true;
|
||||
// Correct the eDate if duration is less than one day.
|
||||
if (1 > eDate.subtractDate(sDate).days) {
|
||||
eDate = sDate.clone();
|
||||
eDate.day += 1;
|
||||
}
|
||||
} else {
|
||||
// We now have a timed startDate and an endDate. If the
|
||||
// end time is invalid set it to 23:59:00
|
||||
if (eDate.isDate) {
|
||||
eDate.isDate = false;
|
||||
eDate.hour = 23;
|
||||
eDate.minute = 59;
|
||||
}
|
||||
// Correct the duration to 0 seconds if it is negative.
|
||||
if (eDate.subtractDate(sDate).isNegative ) {
|
||||
eDate = sDate.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ("categoriesIndex" in args) {
|
||||
txt = parseTextField(eventFields[args.categoriesIndex])
|
||||
if (txt) {
|
||||
var categories = categoriesStringToArray(txt);
|
||||
event.setCategories(categories.length, categories);
|
||||
event.startDate = sDate;
|
||||
event.endDate = eDate;
|
||||
|
||||
// Exists an alarm true/false column?
|
||||
if ("alarmIndex" in args) {
|
||||
// Is an alarm wanted for this event?
|
||||
if (locale.valueTrue == eventFields[args.alarmIndex]) {
|
||||
let alarmDate =
|
||||
this.parseDateTime(eventFields[args.alarmDateIndex],
|
||||
eventFields[args.alarmTimeIndex],
|
||||
locale);
|
||||
// Only set the alarm if a date was parsed
|
||||
if (alarmDate) {
|
||||
let alarm = cal.createAlarm();
|
||||
alarm.related = alarm.ALARM_RELATED_ABSOLUTE;
|
||||
alarm.alarmDate = alarmDate;
|
||||
event.addAlarm(alarm);
|
||||
} else {
|
||||
// XXX Is this really wanted here?
|
||||
cal.alarms.setDefaultValues(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ("locationIndex" in args) {
|
||||
txt = parseTextField(eventFields[args.locationIndex])
|
||||
if (txt) {
|
||||
event.setProperty("LOCATION", txt);
|
||||
|
||||
// Using the "Private" field only for getting privacy status.
|
||||
// "Sensitivity" is neglected for now.
|
||||
if ("privateIndex" in args) {
|
||||
if (locale.valueTrue == eventFields[args.privateIndex]) {
|
||||
event.privacy = "PRIVATE";
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid setting empty properties
|
||||
let txt = "";
|
||||
if ("descriptionIndex" in args) {
|
||||
txt = this.parseTextField(eventFields[args.descriptionIndex])
|
||||
if (txt) {
|
||||
event.setProperty("DESCRIPTION", txt);
|
||||
}
|
||||
}
|
||||
if ("categoriesIndex" in args) {
|
||||
txt = this.parseTextField(eventFields[args.categoriesIndex])
|
||||
if (txt) {
|
||||
let categories = categoriesStringToArray(txt);
|
||||
event.setCategories(categories.length, categories);
|
||||
}
|
||||
}
|
||||
if ("locationIndex" in args) {
|
||||
txt = this.parseTextField(eventFields[args.locationIndex])
|
||||
if (txt) {
|
||||
event.setProperty("LOCATION", txt);
|
||||
}
|
||||
}
|
||||
|
||||
//save the event into return array
|
||||
eventArray.push(event);
|
||||
}
|
||||
|
||||
//save the event into return array
|
||||
eventArray.push(event);
|
||||
//get next events fields
|
||||
eventFields = eventRegExp(str);
|
||||
|
||||
} while (eventRegExp.lastIndex != 0);
|
||||
|
||||
// return results
|
||||
aCount.value = eventArray.length;
|
||||
return eventArray;
|
||||
|
||||
} // end parse
|
||||
|
||||
// The parse was cancelled, return an empty array of events.
|
||||
aCount.value = 0;
|
||||
return [];
|
||||
},
|
||||
|
||||
parseDateTime: function parseDateTime(aDate, aTime, aLocale) {
|
||||
let dt = cal.createDateTime();
|
||||
|
||||
//XXX Can we do better?
|
||||
dt.timezone = cal.floating();
|
||||
|
||||
let rd = aLocale.dateRe.exec(aDate);
|
||||
let rt = aLocale.timeRe.exec(aTime);
|
||||
|
||||
if (!rd || !rt) {
|
||||
return null;
|
||||
}
|
||||
|
||||
dt.year = rd[aLocale.dateYearIndex];
|
||||
dt.month = rd[aLocale.dateMonthIndex] - 1;
|
||||
dt.day = rd[aLocale.dateDayIndex];
|
||||
if (rt) {
|
||||
dt.hour = Number(rt[aLocale.timeHourIndex]);
|
||||
dt.minute = rt[aLocale.timeMinuteIndex];
|
||||
dt.second = rt[aLocale.timeSecondIndex];
|
||||
} else {
|
||||
dt.isDate = true;
|
||||
}
|
||||
|
||||
if (rt && aLocale.timeAmPmIndex &&
|
||||
rt[aLocale.timeAmPmIndex] != aLocale.timePmString) {
|
||||
// AM
|
||||
if (dt.hour == 12) {
|
||||
dt.hour = 0;
|
||||
}
|
||||
} else {
|
||||
// PM
|
||||
if (dt.hour < 12) {
|
||||
dt.hour += 12;
|
||||
}
|
||||
}
|
||||
return dt;
|
||||
},
|
||||
|
||||
//get next events fields
|
||||
eventFields = eventRegExp(str);
|
||||
|
||||
} while (eventRegExp.lastIndex != 0);
|
||||
|
||||
// return results
|
||||
aCount.value = eventArray.length;
|
||||
return eventArray;
|
||||
|
||||
} // end parse
|
||||
|
||||
aCount.value = 0;
|
||||
return new Array();
|
||||
parseTextField: function parseTextField(aTextField) {
|
||||
return aTextField ? aTextField.replace(/""/g, "\"") : "";
|
||||
}
|
||||
};
|
||||
|
||||
function parseDateTime(aDate, aTime, aLocale)
|
||||
{
|
||||
var date = Components.classes["@mozilla.org/calendar/datetime;1"]
|
||||
.createInstance(Components.interfaces.calIDateTime);
|
||||
|
||||
//XXX Can we do better?
|
||||
date.timezone = floating();
|
||||
|
||||
var rd = aLocale.dateRe.exec(aDate);
|
||||
var rt = aLocale.timeRe.exec(aTime);
|
||||
|
||||
if (!rd || !rt) {
|
||||
return null;
|
||||
}
|
||||
|
||||
date.year = rd[aLocale.dateYearIndex];
|
||||
date.month = rd[aLocale.dateMonthIndex] - 1;
|
||||
date.day = rd[aLocale.dateDayIndex];
|
||||
if (rt) {
|
||||
date.hour = Number(rt[aLocale.timeHourIndex]);
|
||||
date.minute = rt[aLocale.timeMinuteIndex];
|
||||
date.second = rt[aLocale.timeSecondIndex];
|
||||
} else {
|
||||
date.isDate = true;
|
||||
}
|
||||
|
||||
if (rt && aLocale.timeAmPmIndex)
|
||||
if (rt[aLocale.timeAmPmIndex] != aLocale.timePmString) {
|
||||
// AM
|
||||
if (date.hour == 12)
|
||||
date.hour = 0;
|
||||
} else {
|
||||
// PM
|
||||
if (date.hour < 12)
|
||||
date.hour += 12;
|
||||
}
|
||||
|
||||
dump(date+"\n");
|
||||
return date;
|
||||
}
|
||||
|
||||
function parseTextField(aTextField)
|
||||
{
|
||||
return aTextField ? aTextField.replace(/""/g, "\"") : "";
|
||||
}
|
||||
|
||||
|
||||
// Export
|
||||
|
||||
// Exporter
|
||||
function calOutlookCSVExporter() {
|
||||
this.wrappedJSObject = this;
|
||||
}
|
||||
|
||||
calOutlookCSVExporter.prototype.QueryInterface =
|
||||
function QueryInterface(aIID) {
|
||||
if (!aIID.equals(Components.interfaces.nsISupports) &&
|
||||
!aIID.equals(Components.interfaces.calIExporter)) {
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
calOutlookCSVExporter.prototype = {
|
||||
getInterfaces: function (count) {
|
||||
const ifaces = [
|
||||
Components.interfaces.nsISupports,
|
||||
Components.interfaces.nsIClassInfo,
|
||||
Components.interfaces.calIExporter,
|
||||
];
|
||||
count.value = ifaces.length;
|
||||
return ifaces;
|
||||
},
|
||||
|
||||
return this;
|
||||
};
|
||||
getHelperForLanguage: function (language) {
|
||||
return null;
|
||||
},
|
||||
|
||||
calOutlookCSVExporter.prototype.getFileTypes = getOutlookCsvFileTypes;
|
||||
contractID: "@mozilla.org/calendar/export;1?type=csv",
|
||||
classDescription: "Calendar Outlook CSV Exporter",
|
||||
classID: Components.ID("{48e6d3a6-b41b-4052-9ed2-40b27800bd4b}"),
|
||||
implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: 0,
|
||||
|
||||
// not prototype.export. export is reserved.
|
||||
calOutlookCSVExporter.prototype.exportToStream =
|
||||
function csv_exportToStream(aStream, aCount, aItems) {
|
||||
var str = "";
|
||||
var headers = [];
|
||||
// Not using a loop here, since we need to be sure the order here matches
|
||||
// with the orders the field data is added later on
|
||||
headers.push(localeEn['headTitle']);
|
||||
headers.push(localeEn['headStartDate']);
|
||||
headers.push(localeEn['headStartTime']);
|
||||
headers.push(localeEn['headEndDate']);
|
||||
headers.push(localeEn['headEndTime']);
|
||||
headers.push(localeEn['headAllDayEvent']);
|
||||
headers.push(localeEn['headAlarm']);
|
||||
headers.push(localeEn['headAlarmDate']);
|
||||
headers.push(localeEn['headAlarmTime']);
|
||||
headers.push(localeEn['headCategories']);
|
||||
headers.push(localeEn['headDescription']);
|
||||
headers.push(localeEn['headLocation']);
|
||||
headers.push(localeEn['headPrivate']);
|
||||
headers = headers.map(function(v) {
|
||||
return '"' + v + '"';
|
||||
});
|
||||
str = headers.join(',');
|
||||
str += exportLineEnding;
|
||||
aStream.write(str, str.length);
|
||||
QueryInterface: function QueryInterface(aIID) {
|
||||
return cal.doQueryInterface(this, calOutlookCSVExporter.prototype, aIID, null, this);
|
||||
},
|
||||
|
||||
for each (item in aItems) {
|
||||
if (!isEvent(item)) {
|
||||
// XXX TODO: warn the user (once) that tasks are not supported
|
||||
// (bug 336175)
|
||||
continue;
|
||||
}
|
||||
var line = [];
|
||||
line.push(item.title);
|
||||
line.push(dateString(item.startDate));
|
||||
line.push(timeString(item.startDate));
|
||||
line.push(dateString(item.endDate));
|
||||
line.push(timeString(item.endDate));
|
||||
line.push(item.startDate.isDate ? localeEn.valueTrue : localeEn.valueFalse);
|
||||
let alarmDate;
|
||||
let alarms = item.getAlarms({});
|
||||
if (alarms.length) {
|
||||
alarmDate = cal.alarms.calculateAlarmDate(item, alarms[0]);
|
||||
}
|
||||
line.push(alarmDate ? localeEn.valueTrue : localeEn.valueFalse);
|
||||
line.push(alarmDate ? dateString(alarmDate) : "");
|
||||
line.push(alarmDate ? timeString(alarmDate) : "");
|
||||
line.push(txtString(categoriesArrayToString(item.getCategories({})))); // xxx todo: what's the correct way to encode ',' in csv?, how are multi-values expressed?
|
||||
line.push(txtString(item.getProperty("DESCRIPTION")));
|
||||
line.push(txtString(item.getProperty("LOCATION")));
|
||||
line.push((item.privacy=="PRIVATE") ? localeEn.valueTrue : localeEn.valueFalse);
|
||||
getFileTypes: getOutlookCsvFileTypes,
|
||||
|
||||
line = line.map(function(v) {
|
||||
v = String(v).replace(/"/g,'""');
|
||||
return '"'+v+'"';
|
||||
})
|
||||
str = line.join(',') + exportLineEnding;
|
||||
exportToStream: function csv_exportToStream(aStream, aCount, aItems) {
|
||||
// Helper functions
|
||||
function dateString(aDateTime) aDateTime.jsDate.toLocaleFormat(localeEn.dateFormat);
|
||||
function timeString(aDateTime) aDateTime.jsDate.toLocaleFormat(localeEn.timeFormat);
|
||||
function txtString(aString) aString || "";
|
||||
|
||||
let str = "";
|
||||
let headers = [];
|
||||
// Not using a loop here, since we need to be sure the order here matches
|
||||
// with the orders the field data is added later on
|
||||
headers.push(localeEn['headTitle']);
|
||||
headers.push(localeEn['headStartDate']);
|
||||
headers.push(localeEn['headStartTime']);
|
||||
headers.push(localeEn['headEndDate']);
|
||||
headers.push(localeEn['headEndTime']);
|
||||
headers.push(localeEn['headAllDayEvent']);
|
||||
headers.push(localeEn['headAlarm']);
|
||||
headers.push(localeEn['headAlarmDate']);
|
||||
headers.push(localeEn['headAlarmTime']);
|
||||
headers.push(localeEn['headCategories']);
|
||||
headers.push(localeEn['headDescription']);
|
||||
headers.push(localeEn['headLocation']);
|
||||
headers.push(localeEn['headPrivate']);
|
||||
headers = headers.map(function(v) {
|
||||
return '"' + v + '"';
|
||||
});
|
||||
str = headers.join(',');
|
||||
str += exportLineEnding;
|
||||
aStream.write(str, str.length);
|
||||
}
|
||||
|
||||
return;
|
||||
for each (item in aItems) {
|
||||
if (!cal.isEvent(item)) {
|
||||
// XXX TODO: warn the user (once) that tasks are not supported
|
||||
// (bug 336175)
|
||||
continue;
|
||||
}
|
||||
let line = [];
|
||||
line.push(item.title);
|
||||
line.push(dateString(item.startDate));
|
||||
line.push(timeString(item.startDate));
|
||||
line.push(dateString(item.endDate));
|
||||
line.push(timeString(item.endDate));
|
||||
line.push(item.startDate.isDate ? localeEn.valueTrue : localeEn.valueFalse);
|
||||
let alarmDate;
|
||||
let alarms = item.getAlarms({});
|
||||
if (alarms.length) {
|
||||
alarmDate = cal.alarms.calculateAlarmDate(item, alarms[0]);
|
||||
}
|
||||
line.push(alarmDate ? localeEn.valueTrue : localeEn.valueFalse);
|
||||
line.push(alarmDate ? dateString(alarmDate) : "");
|
||||
line.push(alarmDate ? timeString(alarmDate) : "");
|
||||
line.push(txtString(categoriesArrayToString(item.getCategories({})))); // xxx todo: what's the correct way to encode ',' in csv?, how are multi-values expressed?
|
||||
line.push(txtString(item.getProperty("DESCRIPTION")));
|
||||
line.push(txtString(item.getProperty("LOCATION")));
|
||||
line.push((item.privacy=="PRIVATE") ? localeEn.valueTrue : localeEn.valueFalse);
|
||||
|
||||
line = line.map(function(v) {
|
||||
v = String(v).replace(/"/g,'""');
|
||||
return '"'+v+'"';
|
||||
})
|
||||
str = line.join(',') + exportLineEnding;
|
||||
aStream.write(str, str.length);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function dateString(aDateTime) {
|
||||
return aDateTime.jsDate.toLocaleFormat(localeEn.dateFormat);
|
||||
}
|
||||
|
||||
function timeString(aDateTime) {
|
||||
return aDateTime.jsDate.toLocaleFormat(localeEn.timeFormat);
|
||||
}
|
||||
|
||||
function txtString(aString) {
|
||||
if (aString) {
|
||||
return aString;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* -*- Mode: javascript; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
/* ***** 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
|
||||
|
@ -24,6 +23,7 @@
|
|||
* Diego Mira David <diegomd86@gmail.com>
|
||||
* Eduardo Teruo Katayama <eduardo@ime.usp.br>
|
||||
* Glaucus Augustus Grecco Cardoso <glaucus@ime.usp.br>
|
||||
* Philipp Kewisch <mozilla@kewis.ch>
|
||||
*
|
||||
* 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
|
||||
|
@ -42,247 +42,249 @@
|
|||
/**
|
||||
* Prints a two column view of a week of events, much like a paper day-planner
|
||||
*/
|
||||
|
||||
Components.utils.import("resource://calendar/modules/calPrintUtils.jsm");
|
||||
|
||||
function calWeekPrinter() {
|
||||
this.wrappedJSObject = this;
|
||||
}
|
||||
|
||||
calWeekPrinter.prototype.QueryInterface =
|
||||
function QueryInterface(aIID) {
|
||||
if (!aIID.equals(Components.interfaces.nsISupports) &&
|
||||
!aIID.equals(Components.interfaces.calIPrintFormatter)) {
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
calWeekPrinter.prototype = {
|
||||
getInterfaces: function (count) {
|
||||
const ifaces = [
|
||||
Components.interfaces.nsISupports,
|
||||
Components.interfaces.nsIClassInfo,
|
||||
Components.interfaces.calIPrintFormatter,
|
||||
];
|
||||
count.value = ifaces.length;
|
||||
return ifaces;
|
||||
},
|
||||
|
||||
return this;
|
||||
};
|
||||
getHelperForLanguage: function (language) {
|
||||
return null;
|
||||
},
|
||||
|
||||
calWeekPrinter.prototype.getName =
|
||||
function weekPrint_getName() {
|
||||
return calGetString("calendar", "weekPrinterName");
|
||||
};
|
||||
calWeekPrinter.prototype.__defineGetter__("name", calWeekPrinter.prototype.getName);
|
||||
contractID: "@mozilla.org/calendar/printformatter;1?type=weekplan",
|
||||
classDescription: "Calendar Week Print Formatter",
|
||||
classID: Components.ID("{2d6ec97b-9109-4b92-89c5-d4b4806619ce}"),
|
||||
implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: 0,
|
||||
|
||||
calWeekPrinter.prototype.formatToHtml =
|
||||
function weekPrint_format(aStream, aStart, aEnd, aCount, aItems, aTitle) {
|
||||
// Create the e4x framework of the HTML document
|
||||
var html = <html/>;
|
||||
html.appendChild(
|
||||
<head>
|
||||
<title>{aTitle}</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/>
|
||||
<link rel='stylesheet' type='text/css' href='chrome://calendar/skin/calendar-printing.css'/>
|
||||
</head>);
|
||||
QueryInterface: function QueryInterface(aIID) {
|
||||
return cal.doQueryInterface(this, calWeekPrinter.prototype, aIID, null, this);
|
||||
},
|
||||
|
||||
var body = <body/>;
|
||||
get name() {
|
||||
return cal.calGetString("calendar", "weekPrinterName");
|
||||
},
|
||||
|
||||
// helper: returns the passed item's startDate, entryDate or dueDate, in
|
||||
// that order. If the item doesn't have one of those dates, this
|
||||
// doesn't return.
|
||||
function hasUsableDate(item) {
|
||||
return item.startDate || item.entryDate || item.dueDate;
|
||||
}
|
||||
formatToHtml: function weekPrint_format(aStream, aStart, aEnd, aCount, aItems, aTitle) {
|
||||
// Create the e4x framework of the HTML document
|
||||
let html = <html/>;
|
||||
html.appendChild(
|
||||
<head>
|
||||
<title>{aTitle}</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/>
|
||||
<link rel='stylesheet' type='text/css' href='chrome://calendar/skin/calendar-printing.css'/>
|
||||
</head>);
|
||||
|
||||
// Clean out the item list so it only contains items we will want to
|
||||
// include in the printout.
|
||||
var filteredItems = aItems.filter(hasUsableDate);
|
||||
let body = <body/>;
|
||||
|
||||
var calIEvent = Components.interfaces.calIEvent;
|
||||
var calITodo = Components.interfaces.calITodo
|
||||
function compareItems(a, b) {
|
||||
// Sort tasks before events
|
||||
if (isEvent(a) && isToDo(b)) {
|
||||
return 1;
|
||||
}
|
||||
if (isToDo(a) && isEvent(b)) {
|
||||
return -1;
|
||||
}
|
||||
if (isEvent(a)) {
|
||||
var startCompare = a.startDate.compare(b.startDate);
|
||||
if (startCompare != 0) {
|
||||
return startCompare;
|
||||
// helper: returns the passed item's startDate, entryDate or dueDate, in
|
||||
// that order. If the item doesn't have one of those dates, this
|
||||
// doesn't return.
|
||||
function hasUsableDate(item) item.startDate || item.entryDate || item.dueDate;
|
||||
|
||||
// Clean out the item list so it only contains items we will want to
|
||||
// include in the printout.
|
||||
let filteredItems = aItems.filter(hasUsableDate);
|
||||
|
||||
function compareItems(a, b) {
|
||||
// Sort tasks before events
|
||||
if (cal.isEvent(a) && cal.isToDo(b)) {
|
||||
return 1;
|
||||
}
|
||||
return a.endDate.compare(b.endDate);
|
||||
if (cal.isToDo(a) && cal.isEvent(b)) {
|
||||
return -1;
|
||||
}
|
||||
if (cal.isEvent(a)) {
|
||||
let startCompare = a.startDate.compare(b.startDate);
|
||||
if (startCompare != 0) {
|
||||
return startCompare;
|
||||
}
|
||||
return a.endDate.compare(b.endDate);
|
||||
}
|
||||
let dateA = a.entryDate || a.dueDate;
|
||||
let dateB = b.entryDate || b.dueDate;
|
||||
return dateA.compare(dateB);
|
||||
}
|
||||
var dateA = a.entryDate || a.dueDate;
|
||||
var dateB = b.entryDate || b.dueDate;
|
||||
return dateA.compare(dateB);
|
||||
}
|
||||
var sortedList = filteredItems.sort(compareItems);
|
||||
let sortedList = filteredItems.sort(compareItems);
|
||||
|
||||
var weekInfo = getWeekInfoService();
|
||||
let weekInfo = cal.getWeekInfoService();
|
||||
|
||||
// Start at the beginning of the week that aStart is in, and loop until
|
||||
// we're at aEnd. In the loop we build the HTML table for each day, and
|
||||
// get the day's items using getDayTd().
|
||||
var start = aStart || sortedList[0].startDate || sortedList[0].entryDate ||
|
||||
sortList[0].dueDate;
|
||||
ASSERT(start, "can't find a good starting date to print");
|
||||
// Start at the beginning of the week that aStart is in, and loop until
|
||||
// we're at aEnd. In the loop we build the HTML table for each day, and
|
||||
// get the day's items using getDayTd().
|
||||
let start = aStart || sortedList[0].startDate || sortedList[0].entryDate ||
|
||||
sortList[0].dueDate;
|
||||
ASSERT(start, "can't find a good starting date to print");
|
||||
|
||||
var lastItem = sortedList[sortedList.length-1];
|
||||
var end = aEnd || lastItem.startDate || lastItem.entryDate ||
|
||||
lastItem.dueDate;
|
||||
ASSERT(end, "can't find a good ending date to print");
|
||||
let lastItem = sortedList[sortedList.length-1];
|
||||
let end = aEnd || lastItem.startDate || lastItem.entryDate ||
|
||||
lastItem.dueDate;
|
||||
ASSERT(end, "can't find a good ending date to print");
|
||||
|
||||
var date = start.startOfWeek;
|
||||
var startOfWeek = getPrefSafe("calendar.week.start", 0);
|
||||
date.day += startOfWeek;
|
||||
// Make sure we didn't go too far ahead
|
||||
if (date.compare(start) == 1) {
|
||||
date.day -= 7;
|
||||
}
|
||||
|
||||
while(date.compare(end) == -1) {
|
||||
var weekno = weekInfo.getWeekTitle(date);
|
||||
var weekTitle = calGetString("calendar", 'WeekTitle', [weekno]);
|
||||
body.appendChild(
|
||||
<table border='0' width='100%' class='main-table'>
|
||||
<tr>
|
||||
<td align='center' valign='bottom'>{weekTitle}</td>
|
||||
</tr>
|
||||
</table>);
|
||||
var mainWeek = <table width='100%' height="90%" border='solid 1px;'/>
|
||||
|
||||
// Create the <td> for each day, and put it into an array.
|
||||
var dayTds = new Array();
|
||||
for (var i = 0; i < 7 ; i++) {
|
||||
dayTds[date.weekday] = this.getDayTd(date, sortedList);
|
||||
date.day += 1;
|
||||
let dt = start.startOfWeek;
|
||||
let startOfWeek = cal.getPrefSafe("calendar.week.start", 0);
|
||||
dt.day += startOfWeek;
|
||||
// Make sure we didn't go too far ahead
|
||||
if (dt.compare(start) == 1) {
|
||||
dt.day -= 7;
|
||||
}
|
||||
|
||||
var monRow = <tr height="33%"/>;
|
||||
monRow.appendChild(dayTds[1]); // Monday
|
||||
monRow.appendChild(dayTds[4]); // Thursday
|
||||
mainWeek.appendChild(monRow);
|
||||
while (dt.compare(end) == -1) {
|
||||
let weekno = weekInfo.getWeekTitle(dt);
|
||||
let weekTitle = cal.calGetString("calendar", 'WeekTitle', [weekno]);
|
||||
body.appendChild(
|
||||
<table border='0' width='100%' class='main-table'>
|
||||
<tr>
|
||||
<td align='center' valign='bottom'>{weekTitle}</td>
|
||||
</tr>
|
||||
</table>);
|
||||
let mainWeek = <table width='100%' height="90%" border='solid 1px;'/>
|
||||
|
||||
var tueRow = <tr height="33%"/>;
|
||||
tueRow.appendChild(dayTds[2]); // Tuesday
|
||||
tueRow.appendChild(dayTds[5]); // Friday
|
||||
mainWeek.appendChild(tueRow);
|
||||
// Create the <td> for each day, and put it into an array.
|
||||
let dayTds = [];
|
||||
for (let i = 0; i < 7 ; i++) {
|
||||
dayTds[dt.weekday] = this.getDayTd(dt, sortedList);
|
||||
dt.day += 1;
|
||||
}
|
||||
|
||||
var wedRow = <tr height="33%"/>;
|
||||
wedRow.appendChild(dayTds[3]); // Wednesday
|
||||
let monRow = <tr height="33%"/>;
|
||||
monRow.appendChild(dayTds[1]); // Monday
|
||||
monRow.appendChild(dayTds[4]); // Thursday
|
||||
mainWeek.appendChild(monRow);
|
||||
|
||||
// Saturday and Sunday are half-size
|
||||
var satSunTd = <td height="33%"/>;
|
||||
var weekendTable = <table border="1" width="100%" height="100%"/>;
|
||||
let tueRow = <tr height="33%"/>;
|
||||
tueRow.appendChild(dayTds[2]); // Tuesday
|
||||
tueRow.appendChild(dayTds[5]); // Friday
|
||||
mainWeek.appendChild(tueRow);
|
||||
|
||||
var satRow = <tr valign='top'/>;
|
||||
satRow.appendChild(dayTds[6]); // Saturday
|
||||
weekendTable.appendChild(satRow);
|
||||
let wedRow = <tr height="33%"/>;
|
||||
wedRow.appendChild(dayTds[3]); // Wednesday
|
||||
|
||||
var sunRow = <tr valign='top'/>;
|
||||
sunRow.appendChild(dayTds[0]); // Sunday
|
||||
weekendTable.appendChild(sunRow);
|
||||
// Saturday and Sunday are half-size
|
||||
let satSunTd = <td height="33%"/>;
|
||||
let weekendTable = <table border="1" width="100%" height="100%"/>;
|
||||
|
||||
satSunTd.appendChild(weekendTable);
|
||||
wedRow.appendChild(satSunTd);
|
||||
mainWeek.appendChild(wedRow);
|
||||
let satRow = <tr valign='top'/>;
|
||||
satRow.appendChild(dayTds[6]); // Saturday
|
||||
weekendTable.appendChild(satRow);
|
||||
|
||||
body.appendChild(mainWeek);
|
||||
// Make sure each month gets put on its own page
|
||||
body.appendChild(<br style="page-break-after: always;"/>);
|
||||
}
|
||||
let tasks = cal.print.getTasksWithoutDueDate(aItems, date);
|
||||
body.appendChild(tasks);
|
||||
html.appendChild(body);
|
||||
let sunRow = <tr valign='top'/>;
|
||||
sunRow.appendChild(dayTds[0]); // Sunday
|
||||
weekendTable.appendChild(sunRow);
|
||||
|
||||
// Stream out the resulting HTML
|
||||
var convStream = Components.classes["@mozilla.org/intl/converter-output-stream;1"]
|
||||
.createInstance(Components.interfaces.nsIConverterOutputStream);
|
||||
convStream.init(aStream, 'UTF-8', 0, 0x0000);
|
||||
convStream.writeString(html.toXMLString());
|
||||
};
|
||||
satSunTd.appendChild(weekendTable);
|
||||
wedRow.appendChild(satSunTd);
|
||||
mainWeek.appendChild(wedRow);
|
||||
|
||||
calWeekPrinter.prototype.getDayTd =
|
||||
/**
|
||||
* Given a calIDateTime and an array of items, this function creates an HTML
|
||||
* table containing the items, using the appropriate formatting and colours.
|
||||
*/
|
||||
function weekPrint_getDayTable(aDate, aItems) {
|
||||
// mainTd is the <td> element from the parent HTML table that will hold
|
||||
// the child HTML tables containing the date string and this day's items.
|
||||
var mainTd = <td border='1px solid black;' width="50%" valign='top'/>
|
||||
var dateFormatter = Components.classes["@mozilla.org/calendar/datetime-formatter;1"]
|
||||
.getService(Components.interfaces.calIDateTimeFormatter);
|
||||
var defaultTimezone = calendarDefaultTimezone();
|
||||
var dateString = dateFormatter.formatDateLong(aDate.getInTimezone(defaultTimezone));
|
||||
body.appendChild(mainWeek);
|
||||
// Make sure each month gets put on its own page
|
||||
body.appendChild(<br style="page-break-after: always;"/>);
|
||||
}
|
||||
let tasks = cal.print.getTasksWithoutDueDate(aItems, dt);
|
||||
body.appendChild(tasks);
|
||||
html.appendChild(body);
|
||||
|
||||
// Add the formatted date string (in its own child HTML table)
|
||||
mainTd.appendChild(
|
||||
<table class='day-name' width='100%' style='background-color:white; border: 1px solid black;'>
|
||||
<tr>
|
||||
// Stream out the resulting HTML
|
||||
let convStream = Components.classes["@mozilla.org/intl/converter-output-stream;1"]
|
||||
.createInstance(Components.interfaces.nsIConverterOutputStream);
|
||||
convStream.init(aStream, 'UTF-8', 0, 0x0000);
|
||||
convStream.writeString(html.toXMLString());
|
||||
},
|
||||
|
||||
/**
|
||||
* Given a calIDateTime and an array of items, this function creates an HTML
|
||||
* table containing the items, using the appropriate formatting and colours.
|
||||
*/
|
||||
getDayTd: function weekPrint_getDayTable(aDate, aItems) {
|
||||
// mainTd is the <td> element from the parent HTML table that will hold
|
||||
// the child HTML tables containing the date string and this day's items.
|
||||
let mainTd = <td border='1px solid black;' width="50%" valign='top'/>
|
||||
let dateFormatter = cal.getDateFormatter();
|
||||
let defaultTimezone = cal.calendarDefaultTimezone();
|
||||
let dateString = dateFormatter.formatDateLong(aDate.getInTimezone(defaultTimezone));
|
||||
|
||||
// Add the formatted date string (in its own child HTML table)
|
||||
mainTd.appendChild(
|
||||
<table class='day-name' width='100%' style='background-color:white; border: 1px solid black;'>
|
||||
<tr>
|
||||
<td align='center' valign='bottom'>{dateString}</td>
|
||||
</tr>
|
||||
</table>);
|
||||
</tr>
|
||||
</table>);
|
||||
|
||||
// Add the formatted items (in their child HTML table)
|
||||
var innerTable = <table valign='top' style='font-size: 10px;'/>;
|
||||
for each (var item in aItems) {
|
||||
var sDate = item.startDate || item.entryDate || item.dueDate;
|
||||
var eDate = item.endDate || item.dueDate || item.entryDate;
|
||||
if (sDate) {
|
||||
sDate = sDate.getInTimezone(defaultTimezone);
|
||||
}
|
||||
if (eDate) {
|
||||
eDate = eDate.getInTimezone(defaultTimezone);
|
||||
}
|
||||
// Add the formatted items (in their child HTML table)
|
||||
let innerTable = <table valign='top' style='font-size: 10px;'/>;
|
||||
for each (let item in aItems) {
|
||||
let sDate = item.startDate || item.entryDate || item.dueDate;
|
||||
let eDate = item.endDate || item.dueDate || item.entryDate;
|
||||
if (sDate) {
|
||||
sDate = sDate.getInTimezone(defaultTimezone);
|
||||
}
|
||||
if (eDate) {
|
||||
eDate = eDate.getInTimezone(defaultTimezone);
|
||||
}
|
||||
|
||||
// End dates are exclusive. Adjust the eDate accordingly.
|
||||
if (sDate && sDate.isDate && eDate) {
|
||||
eDate = eDate.clone();
|
||||
eDate.day -= 1;
|
||||
}
|
||||
// End dates are exclusive. Adjust the eDate accordingly.
|
||||
if (sDate && sDate.isDate && eDate) {
|
||||
eDate = eDate.clone();
|
||||
eDate.day -= 1;
|
||||
}
|
||||
|
||||
// If the item has no end date, or if the item's end date is aDate or
|
||||
// is before aDate, skip to the next item.
|
||||
if (!eDate || (eDate.compare(aDate) < 0)) {
|
||||
continue;
|
||||
}
|
||||
// If the item has no end date, or if the item's end date is aDate or
|
||||
// is before aDate, skip to the next item.
|
||||
if (!eDate || (eDate.compare(aDate) < 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// No start date or a start date that's after the date we want is bad.
|
||||
if (!sDate || (sDate.compare(aDate) > 0)) {
|
||||
break;
|
||||
}
|
||||
// No start date or a start date that's after the date we want is bad.
|
||||
if (!sDate || (sDate.compare(aDate) > 0)) {
|
||||
break;
|
||||
}
|
||||
|
||||
var time = "";
|
||||
if (sDate && eDate && !sDate.isDate) {
|
||||
time = dateFormatter.formatTime(sDate) + '-' + dateFormatter.formatTime(eDate);
|
||||
} else if (sDate && !sDate.isDate) {
|
||||
time = dateFormatter.formatTime(sDate);
|
||||
} else if (eDate && !eDate.isDate) {
|
||||
time = dateFormatter.formatTime(eDate);
|
||||
}
|
||||
let time = "";
|
||||
if (sDate && eDate && !sDate.isDate) {
|
||||
time = dateFormatter.formatTime(sDate) + '-' + dateFormatter.formatTime(eDate);
|
||||
} else if (sDate && !sDate.isDate) {
|
||||
time = dateFormatter.formatTime(sDate);
|
||||
} else if (eDate && !eDate.isDate) {
|
||||
time = dateFormatter.formatTime(eDate);
|
||||
}
|
||||
|
||||
// Get calendar and category colours and apply them to the item's
|
||||
// table cell.
|
||||
var calColor = item.calendar.getProperty('color');
|
||||
if (!calColor) {
|
||||
calColor = "#A8C2E1";
|
||||
}
|
||||
var pb2 = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch2);
|
||||
var catColor;
|
||||
for each (var cat in item.getCategories({})) {
|
||||
try {
|
||||
catColor = pb2.getCharPref("calendar.category.color." + cat.toLowerCase());
|
||||
break; // take first matching
|
||||
} catch(ex) {}
|
||||
}
|
||||
// Get calendar and category colours and apply them to the item's
|
||||
// table cell.
|
||||
let calColor = item.calendar.getProperty('color') || "#A8C2E1";
|
||||
let pb2 = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch2);
|
||||
let catColor;
|
||||
for each (let cat in item.getCategories({})) {
|
||||
try {
|
||||
catColor = pb2.getCharPref("calendar.category.color." + cat.toLowerCase());
|
||||
break; // take first matching
|
||||
} catch (ex) {}
|
||||
}
|
||||
|
||||
var style = 'font-size: 11px; background-color: ' + calColor + ';';
|
||||
style += ' color: ' + getContrastingTextColor(calColor);
|
||||
if (catColor) {
|
||||
style += ' border: solid ' + catColor + ' 2px;';
|
||||
let style = 'font-size: 11px; background-color: ' + calColor + ';';
|
||||
style += ' color: ' + getContrastingTextColor(calColor);
|
||||
if (catColor) {
|
||||
style += ' border: solid ' + catColor + ' 2px;';
|
||||
}
|
||||
let item = <tr>
|
||||
<td valign='top' align='left' style={style}>{time} {item.title}</td>
|
||||
</tr>;
|
||||
innerTable.appendChild(item);
|
||||
}
|
||||
var item = <tr>
|
||||
<td valign='top' align='left' style={style}>{time} {item.title}</td>
|
||||
</tr>;
|
||||
innerTable.appendChild(item);
|
||||
innerTable.appendChild(<p> </p>);
|
||||
mainTd.appendChild(innerTable);
|
||||
return mainTd;
|
||||
}
|
||||
innerTable.appendChild(<p> </p>);
|
||||
mainTd.appendChild(innerTable);
|
||||
return mainTd;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче