Fix bug 757902 - Weekly and Monthly print layouts don't work, remove e4x usage (cpg fallout) (regression). r=mmecca/ssitter

This commit is contained in:
Philipp Kewisch 2012-07-26 16:47:06 +02:00
Родитель ac449e09ee
Коммит 126580f1b3
17 изменённых файлов: 1000 добавлений и 810 удалений

Просмотреть файл

@ -59,15 +59,75 @@ function loadCalendarPrintDialog() {
}
/**
* Gets the settings from the dialog's UI widgets.
* notifies an Object with title, layoutCId, eventList, start, and end
* properties containing the appropriate values.
* Retrieves a settings object containing info on what to print. The
* receiverFunc will be called with the settings object containing various print
* settings.
*
* @param receiverFunc The callback function to call on completion.
*/
function getEventsAndDialogSettings(receiverFunc) {
let settings = getWhatToPrintSettings();
if (settings.eventList.length != 0) {
receiverFunc(settings);
} else {
function getPrintSettings(receiverFunc) {
let tempTitle = document.getElementById("title-field").value;
let settings = new Object();
let requiresFetch = true;
settings.title = (tempTitle || calGetString("calendar", "Untitled"));
settings.layoutCId = document.getElementById("layout-field").value;
settings.start = null;
settings.end = null;
settings.eventList = [];
settings.printEvents = document.getElementById("events").checked;
settings.printTasks = document.getElementById("tasks").checked;
settings.printCompletedTasks = document.getElementById("completed-tasks").checked;
settings.printTasksWithNoDueDate = document.getElementById("tasks-with-no-due-date").checked;
var theView = getCalendarView();
switch (document.getElementById("view-field").selectedItem.value) {
case 'currentView':
case '': //just in case
settings.start = theView.startDay.clone();
settings.end = theView.endDay.clone();
settings.end.day += 1;
settings.start.isDate = false;
settings.end.isDate = false;
break;
case 'selected': {
let selectedItems = theView.getSelectedItems({});
settings.eventList = selectedItems.filter(function(item) {
if (cal.isEvent(item) && !settings.printEvents) return false;
if (cal.isToDo(item) && !settings.printTasks) return false;
return true;
});
// If tasks should be printed, also include selected tasks from the
// opening window.
if (settings.printTasks) {
let selectedTasks = window.opener.getSelectedTasks();
for each (var task in selectedTasks) {
settings.eventList.push(task);
}
}
// We've set the event list above, no need to fetch items below.
requiresFetch = false;
break;
}
case 'custom':
// We return the time from the timepickers using the selected
// timezone, as not doing so in timezones with a positive offset
// from UTC may cause the printout to include the wrong days.
var currentTimezone = calendarDefaultTimezone();
settings.start = jsDateToDateTime(document.getElementById("start-date-picker").value);
settings.start = settings.start.getInTimezone(currentTimezone);
settings.end = jsDateToDateTime(document.getElementById("end-date-picker").value);
settings.end = settings.end.getInTimezone(currentTimezone);
settings.end = settings.end.clone();
settings.end.day += 1;
break ;
default:
dump("Error : no case in printDialog.js::printCalendar()");
}
// Some filters above might have filled the events list themselves. If not,
// then fetch the items here.
if (requiresFetch) {
let listener = {
onOperationComplete:
function onOperationComplete(aCalendar, aStatus, aOperationType, aId, aDateTime) {
@ -87,63 +147,16 @@ function getEventsAndDialogSettings(receiverFunc) {
}
}
};
window.opener.getCompositeCalendar().getItems(getFilter(settings), 0, settings.start, settings.end, listener);
}
}
/**
* Retrieves a settings object containing info on what to print
*
* @return The settings object with all print settings
*/
function getWhatToPrintSettings() {
let tempTitle = document.getElementById("title-field").value;
let settings = new Object();
settings.title = (tempTitle || calGetString("calendar", "Untitled"));
settings.layoutCId = document.getElementById("layout-field").value;
settings.start = null;
settings.end = null;
settings.eventList = [];
settings.printEvents = document.getElementById("events").checked;
settings.printTasks = document.getElementById("tasks").checked;
settings.printCompletedTasks = document.getElementById("completed-tasks").checked;
settings.printTasksWithNoDueDate = document.getElementById("tasks-with-no-due-date").checked;
var theView = getCalendarView();
switch (document.getElementById("view-field").selectedItem.value) {
case 'currentView':
case '': //just in case
settings.start = theView.startDay;
settings.end = theView.endDay;
settings.end = settings.end.clone();
settings.end.day += 1;
break;
case 'selected':
if (settings.printEvents) {
settings.eventList = theView.getSelectedItems({});
let filter = getFilter(settings);
if (filter) {
window.opener.getCompositeCalendar().getItems(filter, 0, settings.start, settings.end, listener);
} else {
// No filter means no items, just complete with the empty list set above
receiverFunc(settings);
}
if (settings.printTasks) {
let selectedTasks = window.opener.document.getElementById("unifinder-todo-tree").selectedTasks;
for each (var task in selectedTasks) {
settings.eventList.push(task);
}
}
break;
case 'custom':
// We return the time from the timepickers using the selected
// timezone, as not doing so in timezones with a positive offset
// from UTC may cause the printout to include the wrong days.
var currentTimezone = calendarDefaultTimezone();
settings.start = jsDateToDateTime(document.getElementById("start-date-picker").value);
settings.start = settings.start.getInTimezone(currentTimezone);
settings.end = jsDateToDateTime(document.getElementById("end-date-picker").value);
settings.end = settings.end.getInTimezone(currentTimezone);
settings.end = settings.end.clone();
settings.end.day += 1;
break ;
default:
dump("Error : no case in printDialog.js::printCalendar()");
} else {
receiverFunc(settings);
}
return settings;
}
/**
@ -176,15 +189,7 @@ function getFilter(settings) {
* dialog UI element has changed, since we'll want to refresh the preview.
*/
function refreshHtml(finishFunc) {
if (document.documentElement.getButton("accept").disabled) {
// If the accept button is disabled, then something wants us to not
// print. Bail out before refreshing the html, otherwise errors might
// occur. Don't call the finish func, its expected to be called on
// success.
return;
}
getEventsAndDialogSettings(
function getEventsAndDialogSettings_response(settings) {
getPrintSettings(function getSettingsResponse(settings) {
document.title = calGetString("calendar", "PrintPreviewWindowTitle", [settings.title]);
let printformatter = Components.classes[settings.layoutCId]
@ -286,18 +291,5 @@ function printAndClose() {
*/
function onDatePick() {
calRadioGroupSelectItem("view-field", "custom-range");
refreshHtml();
}
/**
* Update the disabled state of the controls on the dialog, if not all print
* parameters are set (i.e nothing to print).
*/
function updatePrintState() {
let columns = document.getElementById("columns-for-events-and-tasks");
let cboxes = columns.getElementsByTagName("checkbox");
// If no checkboxes are checked, disable the print button
let someChecked = Array.slice(cboxes).some(function(x) x.checked);
document.documentElement.getButton("accept").disabled = !someChecked;
setTimeout(refreshHtml, 0);
}

Просмотреть файл

@ -71,10 +71,10 @@
<grid id="grid-events-and-tasks">
<columns id="columns-for-events-and-tasks">
<column id="column-event">
<checkbox id="events" label="&calendar.print.events.label;" checked="true" oncommand="updatePrintState(); refreshHtml();"/>
<checkbox id="events" label="&calendar.print.events.label;" checked="true" oncommand="refreshHtml();"/>
</column>
<column id="column-tasks">
<checkbox id="tasks" label="&calendar.print.tasks.label;" checked="true" oncommand="updatePrintState(); refreshHtml();"/>
<checkbox id="tasks" label="&calendar.print.tasks.label;" checked="true" oncommand="refreshHtml();"/>
</column>
</columns>
</grid>

Просмотреть файл

@ -6,30 +6,180 @@ Components.utils.import("resource://calendar/modules/calUtils.jsm");
EXPORTED_SYMBOLS = ["cal"]; // even though it's defined in calUtils.jsm, import needs this
cal.print = {
getTasksWithoutDueDate: function getTasksWithoutDueDate(aItems, date) {
function isTaskWithoutDueDate(item) {
return !item.dueDate && !item.endDate;
}
let filteredItems = aItems.filter(isTaskWithoutDueDate);
if (filteredItems.length == 0) {
return "";
}
let tasksDiv = <div class="tasks"/>;
let monthName = cal.calGetString("dateFormat", "month." + (date.month +1)+ ".name");
tasksDiv.appendChild(<h3>{cal.calGetString("calendar","tasksWithNoDueDate")}</h3>);
let list = <ul class="taskList" />;
for each (let task in filteredItems) {
let taskItem = <li class="taskItem" />;
if (task.isCompleted) {
taskItem.appendChild(<input checked="checked" type="checkbox" disabled="true"/>);
taskItem.appendChild(<s>{task.title}</s>);
} else {
taskItem.appendChild(<input type="checkbox" disabled="true"/>);
taskItem.appendChild(task.title);
/**
* Returns a simple key in the format YYYY-MM-DD for use in the table of
* dates to day boxes
*
* @param dt The date to translate
* @return YYYY-MM-DD
*/
getDateKey: function getDateKey(dt) {
return dt.year + "-" + dt.month + "-" + dt.day;
},
/**
* Add category styles to the document's "sheet" element. This is needed
* since the HTML created is serialized, so we can't dynamically set the
* styles and can be changed if the print formatter decides to return a
* DOM document instead.
*
* @param document The document that contains <style id="sheet"/>.
* @param categories Array of categories to insert rules for.
*/
insertCategoryRules: function insertCategoryRules(document, categories) {
let sheet = document.getElementById("sheet");
sheet.insertedCategoryRules = sheet.insertedCategoryRules || {};
for each (let category in categories) {
let prefName = cal.formatStringForCSSRule(category);
let color = cal.getPrefSafe("calendar.category.color." + prefName) || "transparent";
if (!(prefName in sheet.insertedCategoryRules)) {
sheet.insertedCategoryRules[prefName] = true;
let ruleAdd = ' .category-color-box[categories~="' + prefName + '"] { ' +
' border: 2px solid ' + color + '; }' + "\n";
sheet.textContent += ruleAdd;
}
list.appendChild(taskItem);
}
tasksDiv.appendChild(list);
return tasksDiv;
},
/**
* Add calendar styles to the document's "sheet" element. This is needed
* since the HTML created is serialized, so we can't dynamically set the
* styles and can be changed if the print formatter decides to return a
* DOM document instead.
*
* @param document The document that contains <style id="sheet"/>.
* @param categories The calendar to insert a rule for.
*/
insertCalendarRules: function insertCalendarRules(document, calendar) {
let sheet = document.getElementById("sheet");
let color = calendar.getProperty("color") || "#A8C2E1";
sheet.insertedCalendarRules = sheet.insertedCalendarRules || {};
if (!(calendar.id in sheet.insertedCalendarRules)) {
sheet.insertedCalendarRules[calendar.id] = true;
let formattedId = cal.formatStringForCSSRule(calendar.id);
let ruleAdd = ' .calendar-color-box[calendar-id="' + formattedId + '"] { ' +
' background-color: ' + color + '; ' +
' color: ' + cal.getContrastingTextColor(color) + '; }' + "\n";
sheet.textContent += ruleAdd;
}
},
/**
* Serializes the given item by setting marked nodes to the item's content.
* Has some expectations about the DOM document (in CSS-selector-speak), all
* following nodes MUST exist.
*
* - #item-template will be cloned and filled, and modified:
* - .item-interval gets the time interval of the item.
* - .item-title gets the item title
* - .category-color-box gets a 2px solid border in category color
* - .calendar-color-box gets background color of the calendar
*
* @param document The DOM Document to set things on
* @param item The item to serialize
* @param dayContainer The DOM Node to insert the container in
*/
addItemToDaybox: function addItemToDaybox(document, item, dayContainer) {
// Clone our template
let itemNode = document.getElementById("item-template").cloneNode(true);
itemNode.removeAttribute("id");
itemNode.item = item;
// Fill in details of the item
let itemInterval = cal.getDateFormatter().formatItemTimeInterval(item);
itemNode.querySelector(".item-interval").textContent = itemInterval;
itemNode.querySelector(".item-title").textContent = item.title;
// Fill in category details
let categoriesArray = item.getCategories({});
if (categoriesArray.length > 0) {
let cssClassesArray = categoriesArray.map(cal.formatStringForCSSRule);
itemNode.querySelector(".category-color-box")
.setAttribute("categories", cssClassesArray.join(" "));
cal.print.insertCategoryRules(document, categoriesArray);
}
// Fill in calendar color
itemNode.querySelector(".calendar-color-box")
.setAttribute("calendar-id", cal.formatStringForCSSRule(item.calendar.id));
cal.print.insertCalendarRules(document, item.calendar);
// Add it to the day container in the right order
cal.binaryInsertNode(dayContainer, itemNode, item, comparePrintItems);
},
/**
* Serializes the given item by setting marked nodes to the item's
* content. Should be used for tasks with no start and due date. Has
* some expectations about the DOM document (in CSS-selector-speak),
* all following nodes MUST exist.
*
* - Nodes will be added to #task-container.
* - #task-list-box will have the "hidden" attribute removed.
* - #task-template will be cloned and filled, and modified:
* - .task-checkbox gets the "checked" attribute set, if completed
* - .task-title gets the item title.
*
* @param document The DOM Document to set things on
* @param item The item to serialize
*/
addItemToDayboxNodate: function addItemToDayboxNodate(document, item) {
let taskContainer = document.getElementById("task-container");
let taskNode = document.getElementById("task-template").cloneNode(true);
taskNode.removeAttribute("id");
taskNode.item = item;
let taskListBox = document.getElementById("tasks-list-box");
if (taskListBox.hasAttribute("hidden")) {
let tasksTitle = document.getElementById("tasks-title");
taskListBox.removeAttribute("hidden");
tasksTitle.textContent = cal.calGetString("calendar","tasksWithNoDueDate");
}
// Fill in details of the task
if (item.isCompleted) {
taskNode.querySelector(".task-checkbox").setAttribute("checked", "checked");
}
taskNode.querySelector(".task-title").textContent = item.title;
let collator = cal.createLocaleCollator();
cal.binaryInsertNode(taskContainer, taskNode, item, function(a, b) collator.compareString(0, a, b), function(node) node.item.title);
}
}
/**
* Item comparator for inserting items into dayboxes.
*
* TODO This could possibly be replaced with a global item comparator so
* that it matches with the views and such.
*
* @param a The first item
* @param b The second item
* @return The usual -1, 0, 1
*/
function comparePrintItems(a, b) {
if (!a) return -1;
if (!b) return 1;
// 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 dateA = a.entryDate || a.dueDate;
let dateB = b.entryDate || b.dueDate;
return dateA.compare(dateB);
}

Просмотреть файл

@ -349,6 +349,20 @@ let cal = {
return calDateTime.nativeTime;
},
userWeekStart: function userWeekStart(dt) {
let wkst = cal.getPrefSafe("calendar.week.start", 0);
let wkstDate = dt.clone();
wkstDate.day -= (wkstDate.weekday - wkst + 7) % 7;
return wkstDate;
},
userWeekEnd: function userWeekEnd(dt) {
let wkst = cal.getPrefSafe("calendar.week.start", 0);
let wkendDate = dt.clone();
wkendDate.day += (7 - wkendDate.weekday) + wkst;
return wkendDate;
},
sortEntry: function cal_sortEntry(aItem) {
let key = cal.getItemSortKey(aItem, this.mSortKey, this.mSortStartedDate);
return { mSortKey : key, mItem: aItem };

Просмотреть файл

@ -2,11 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Helper functions for parsing and serializing XML */
/** Helper functions for parsing and serializing XML */
Components.utils.import("resource://calendar/modules/calUtils.jsm");
EXPORTED_SYMBOLS = ["cal"]
EXPORTED_SYMBOLS = ["cal"];
cal.xml = {} || cal.xml;
/**
@ -45,7 +45,7 @@ cal.xml.evalXPath = function evaluateXPath(aNode, aExpr, aResolver, aType) {
case XPR.ORDERED_NODE_ITERATOR_TYPE:
case XPR.ORDERED_NODE_ITERATOR_TYPE:
returnResult = [];
while (next = result.iterateNext()) {
while ((next = result.iterateNext())) {
if (next instanceof Components.interfaces.nsIDOMText) {
returnResult.push(next.wholeText);
} else if (next instanceof Components.interfaces.nsIDOMAttr) {
@ -124,6 +124,23 @@ cal.xml.parseString = function(str, docUri, baseUri) {
return parser.parseFromString(str, "application/xml");
};
/**
* Read an XML file synchronously. This method should be avoided, consider
* rewriting the caller to be asynchronous.
*
* @param uri The URI to read.
* @return The DOM Document resulting from the file.
*/
cal.xml.parseFile = function(uri) {
let req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Components.interfaces.nsIXMLHttpRequest);
req.open('GET', uri, false);
req.overrideMimeType("text/xml");
req.send(null);
return req.responseXML;
};
/**
* Serialize the DOM tree into a string.
*

Просмотреть файл

@ -87,20 +87,34 @@ interface calIDateTimeFormatter : nsISupports
AUTF8String formatItemInterval(in calIItemBase aItem);
/**
* Format a time interval. The returned string may assume that the dates
* are so close to each other, that it can leave out some parts of the
* part string denoting the end date
* Format a time interval like formatItemInterval, but only show times.
*
* @param aStartDate
* The start of the interval
* @param aEndDate
* The end of the interval
* @returns
* A String describing the interval in a legible form
* @param aItem The item providing the interval
* @return The string describing the interval
*/
AUTF8String formatItemTimeInterval(in calIItemBase aItem);
/**
* Format a date/time interval. The returned string may assume that the
* dates are so close to each other, that it can leave out some parts of the
* part string denoting the end date.
*
* @param aStartDate The start of the interval
* @param aEndDate The end of the interval
* @return A String describing the interval in a legible form
*/
AUTF8String formatInterval(in calIDateTime aStartDate,
in calIDateTime aEndDate);
/**
* Format a time interval like formatInterval, but show only the time.
*
* @param aStartDate The start of the interval.
* @param aEndDate The end of the interval.
* @return The formatted time interval.
*/
AUTF8String formatTimeInterval(in calIDateTime aStartTime,
in calIDateTime aEndTime);
/**
* Get the month name
*

Просмотреть файл

@ -152,6 +152,17 @@ calDateTimeFormatter.prototype = {
}
},
formatTimeInterval: function formatTimeInterval(aStartDate, aEndDate) {
if (!aStartDate && aEndDate) return this.formatTime(aEndDate);
if (!aEndDate && aStartDate) return this.formatTime(aStartDate);
if (!aStartDate && !aEndDate) return "";
// TODO do we need l10n for this?
// TODO should we check for the same day? The caller should know what
// he is doing...
return this.formatTime(aStartDate) + "\u2013" + this.formatTime(aEndDate);
},
formatInterval: function formatInterval(aStartDate, aEndDate) {
// Check for tasks without start and/or due date
if (aEndDate == null && aStartDate == null ) {
@ -219,7 +230,7 @@ calDateTimeFormatter.prototype = {
}
},
formatItemInterval: function formatItemInterval(aItem) {
_getItemDates: function _getItemDates(aItem) {
let start = aItem[calGetStartDateProp(aItem)];
let end = aItem[calGetEndDateProp(aItem)];
let kDefaultTimezone = calendarDefaultTimezone();
@ -235,7 +246,16 @@ calDateTimeFormatter.prototype = {
if (start && start.isDate && end) {
end.day -= 1;
}
return this.formatInterval(start, end);
return [start, end];
},
formatItemInterval: function formatItemInterval(aItem) {
return this.formatInterval.apply(this, this._getItemDates(aItem));
},
formatItemTimeInterval: function formatItemTimeInterval(aItem) {
return this.formatTimeInterval.apply(this, this._getItemDates(aItem));
},
monthName: function monthName(aMonthIndex) {

Просмотреть файл

@ -0,0 +1,70 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title id="title"></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<style type="text/css" id="sheet">
.vevent {
border: 1px solid black;
padding: 0;
margin-bottom: 10px;
}
.key {
font-style: italic;
margin-left: 3px;
}
.value {
margin-left: 20px;
}
abbr {
border: none;
}
.summarykey {
display: none;
}
.summary {
font-weight: bold;
margin: 0;
padding: 3px;
}
.description {
white-space: pre-wrap;
}
</style>
</head>
<body id="item-container">
<!-- Note on the use of the summarykey class:
This node is hidden by default for better readability. If you would
like to show the key, remove the display style above. -->
<div id="templates">
<div class="vevent" id="item-template">
<div class="row summaryrow">
<div class="key summarykey"></div>
<div class="value summary"></div>
</div>
<div class="row intervalrow">
<div class="key intervalkey"></div>
<div class="value">
<abbr class="dtstart"></abbr>
</div>
</div>
<div class="row locationrow">
<div class="key locationkey"></div>
<div class="value location"></div>
</div>
<div class="row descriptionrow">
<div class="key descriptionkey"></div>
<div class="value description"></div>
</div>
</div>
</div>
</body>
</html>

Просмотреть файл

@ -2,78 +2,47 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Components.utils.import("resource://calendar/modules/calUtils.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
// Export
Components.utils.import("resource://calendar/modules/calUtils.jsm");
Components.utils.import("resource://calendar/modules/calXMLUtils.jsm");
/**
* HTML Export Plugin
*/
function calHtmlExporter() {
}
calHtmlExporter.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=html",
classDescription: "Calendar HTML Exporter",
classID: Components.ID("{72d9ab35-9b1b-442a-8cd0-ae49f00b159b}"),
implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
flags: 0,
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIExporter]),
QueryInterface: function QueryInterface(aIID) {
return cal.doQueryInterface(this, calHtmlExporter.prototype, aIID, null, this);
},
classInfo: XPCOMUtils.generateCI({
classID: Components.ID("{72d9ab35-9b1b-442a-8cd0-ae49f00b159b}"),
contractID: "@mozilla.org/calendar/export;1?type=html",
classDescription: "Calendar HTML Exporter",
interfaces: [Components.interfaces.calIExporter]
}),
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 }];
return [{
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIFileType]),
defaultExtension: 'html',
extensionFilter: wildmat,
description: label
}];
},
exportToStream: function html_exportToStream(aStream, aCount, aItems, aTitle) {
let documentTitle = aTitle || cal.calGetString("calendar", "HTMLTitle");
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.
// 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";
html.head.style += "div.description { white-space: pre-wrap; }\n";
let document = cal.xml.parseFile("chrome://calendar/skin/printing/calHtmlExport.html");
let itemContainer = document.getElementById("item-container");
document.getElementById("title").textContent = aTitle || cal.calGetString("calendar", "HTMLTitle");
// Sort aItems
function sortFunc(a, b) {
aItems.sort(function(a, b) {
let start_a = a[cal.calGetStartDateProp(a)];
if (!start_a) {
return -1;
@ -83,77 +52,61 @@ calHtmlExporter.prototype = {
return 1;
}
return start_a.compare(start_b);
}
aItems.sort(sortFunc);
});
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 each (let item in aItems) {
let itemNode = document.getElementById("item-template").cloneNode(true);
itemNode.removeAttribute("id");
for (let pos = 0; pos < aItems.length; ++pos) {
let item = aItems[pos];
function setupTextRow(classKey, propValue, prefixKey) {
if (propValue) {
let prefix = cal.calGetString("calendar", prefixKey);
itemNode.querySelector("." + classKey + "key").textContent = prefix;
itemNode.querySelector("." + classKey).textContent = propValue;
} else {
let row = itemNode.querySelector("." + classKey + "row");
if (row.nextSibling instanceof Components.interfaces.nsIDOMText) {
row.parentNode.removeChild(row.nextSibling);
}
row.parentNode.removeChild(row);
}
}
// 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>
);
let startDate = item[cal.calGetStartDateProp(item)];
let endDate = item[cal.calGetEndDateProp(item)];
let dateString = cal.getDateFormatter().formatItemInterval(item);
if (startDate != null || endDate != null) {
if (startDate || endDate) {
// 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>
);
}
// Location
if (item.getProperty('LOCATION')) {
ev.appendChild(
<div>
<div class='key'>{prefixLocation}</div>
<div class='value location'>{item.getProperty('LOCATION')}</div>
</div>
);
let prefixWhen = cal.calGetString("calendar", "htmlPrefixWhen");
itemNode.querySelector(".intervalkey").textContent = prefixWhen;
let startNode = itemNode.querySelector(".dtstart");
let dateString = cal.getDateFormatter().formatItemInterval(item);
startNode.setAttribute("title", (startDate ? startDate.icalString : "none"));
startNode.textContent = dateString;
} else {
let row = itemNode.querySelector(".intervalrow");
row.parentNode.removeChild(row);
if (row.nextSibling instanceof Components.interfaces.nsIDOMText) {
row.parentNode.removeChild(row.nextSibling);
}
}
let desc = item.getProperty('DESCRIPTION');
if (desc && desc.length > 0) {
let descnode =
<div>
<div class='key'>{prefixDescription}</div>
<div class='value description'>{desc}</div>
</div>;
let itemTitle = (item.isCompleted ? cal.calGetString("calendar", "htmlTaskCompleted", [item.title]) : item.title);
setupTextRow("summary", itemTitle, "htmlPrefixTitle");
ev.appendChild(descnode);
}
html.body.appendChild(ev);
setupTextRow("location", item.getProperty("LOCATION"), "htmlPrefixLocation");
setupTextRow("description", item.getProperty("DESCRIPTION"), "htmlPrefixDescription");
itemContainer.appendChild(itemNode);
}
// Convert the javascript string to an array of bytes, using the
// utf8 encoder
let templates = document.getElementById("templates");
templates.parentNode.removeChild(templates);
// 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);
convStream.writeString(cal.xml.serializeDOM(document));
}
};

Просмотреть файл

@ -2,16 +2,22 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://calendar/modules/calUtils.jsm");
/**
* ICS Import and Export Plugin
*/
// Shared functions
function getIcsFileTypes(aCount) {
aCount.value = 1;
let wildmat = '*.ics';
let label = cal.calGetString("calendar", 'filterIcs', [wildmat]);
return [{ defaultExtension: 'ics',
extensionFilter: wildmat,
description: label }];
return [{
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIFileType]),
defaultExtension: 'ics',
extensionFilter: '*.ics',
description: cal.calGetString("calendar", 'filterIcs', ['*.ics'])
}];
}
// Importer
@ -19,29 +25,15 @@ function calIcsImporter() {
}
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: XPCOMUtils.generateQI([Components.interfaces.calIImporter]),
QueryInterface: function QueryInterface(aIID) {
return cal.doQueryInterface(this, calIcsImporter.prototype, aIID, null, this);
},
classInfo: XPCOMUtils.generateCI({
classID: Components.ID("{1e3e33dc-445a-49de-b2b6-15b2a050bb9d}"),
contractID: "@mozilla.org/calendar/import;1?type=ics",
classDescription: "Calendar ICS Importer",
interfaces: [Components.interfaces.calIImporter]
}),
getFileTypes: getIcsFileTypes,
@ -58,29 +50,15 @@ function calIcsExporter() {
}
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: XPCOMUtils.generateQI([Components.interfaces.calIExporter]),
QueryInterface: function QueryInterface(aIID) {
return cal.doQueryInterface(this, calIcsExporter.prototype, aIID, null, this);
},
classInfo: XPCOMUtils.generateCI({
classID: Components.ID("{a6a524ce-adff-4a0f-bb7d-d1aaad4adc60}"),
contractID: "@mozilla.org/calendar/export;1?type=ics",
classDescription: "Calendar ICS Exporter",
interfaces: [Components.interfaces.calIExporter]
}),
getFileTypes: getIcsFileTypes,

Просмотреть файл

@ -2,41 +2,27 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://calendar/modules/calUtils.jsm");
/**
* A thin wrapper that is a print formatter, and just calls the html (list)
* exporter
* A thin wrapper around the html list exporter for the list print format.
*/
function calListFormatter() {
}
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: XPCOMUtils.generateQI([Components.interfaces.calIPrintFormatter]),
QueryInterface: function QueryInterface(aIID) {
return cal.doQueryInterface(this, calListFormatter.prototype, aIID, null, this);
},
classInfo: XPCOMUtils.generateCI({
classID: Components.ID("{9ae04413-fee3-45b9-8bbb-1eb39a4cbd1b}"),
contractID: "@mozilla.org/calendar/printformatter;1?type=list",
classDescription: "Calendar List Print Formatter",
interfaces: [Components.interfaces.calIPrintFormatter]
}),
get name() {
return cal.calGetString("calendar", "formatListName");
},
get name() 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"]

Просмотреть файл

@ -0,0 +1,108 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title id="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"/>
<style type="text/css" id="sheet">
.main-table { font-size: 26px; font-weight: bold; }
.day-name { border: 1px solid black; background-color: white; font-size: 12px; font-weight: bold; }
.day-box { border: 1px solid black; vertical-align: top; }
.out-of-month { background-color: white !important; }
.day-off { background-color: white !important; }
</style>
</head>
<body>
<div id="month-container"/>
<div id="tasks-list-box" hidden="true">
<h3 id="tasks-title"/>
<ul class="taskList" id="task-container"/>
</div>
<!-- Templates follow -->
<div id="templates" hidden="true">
<li id="task-template">
<input type="checkbox" class="task-checkbox" disabled="true"/>
<s class="task-title"/>
</li>
<tr id="item-template">
<td valign="top" style="font-size: 11px; text-align: left;" class="category-color-box calendar-color-box">
<span class="item-interval"/>
<span class="item-title"/>
</td>
</tr>
<div id="month-template" style="page-break-after: always;">
<table border="0" width="100%" class="main-table">
<tr>
<td align="center" valign="bottom" class="month-name"/>
</tr>
</table>
<table style="border:1px solid black;" width="100%" class="week-container">
<tr>
<td class="day-name day1-title" align="center" />
<td class="day-name day2-title" align="center" />
<td class="day-name day3-title" align="center" />
<td class="day-name day4-title" align="center" />
<td class="day-name day5-title" align="center" />
<td class="day-name day6-title" align="center" />
<td class="day-name day7-title" align="center" />
</tr>
</table>
</div>
<div id="week-template">
<tr>
<td align="left" valign="top" class="day1-box day-box" height="100" width="100">
<table valign="top" style="font-size: 10px;" class="day1-container">
<tr valign="top">
<td valign="top" align="left" class="day1-number"/>
</tr>
</table>
</td>
<td align="left" valign="top" class="day2-box day-box" height="100" width="100">
<table valign="top" style="font-size: 10px;" class="day2-container">
<tr valign="top">
<td valign="top" align="left" class="day2-number"/>
</tr>
</table>
</td>
<td align="left" valign="top" class="day3-box day-box" height="100" width="100">
<table valign="top" style="font-size: 10px;" class="day3-container">
<tr valign="top">
<td valign="top" align="left" class="day3-number"/>
</tr>
</table>
</td>
<td align="left" valign="top" class="day4-box day-box" height="100" width="100">
<table valign="top" style="font-size: 10px;" class="day4-container">
<tr valign="top">
<td valign="top" align="left" class="day4-number"/>
</tr>
</table>
</td>
<td align="left" valign="top" class="day5-box day-box" height="100" width="100">
<table valign="top" style="font-size: 10px;" class="day5-container">
<tr valign="top">
<td valign="top" align="left" class="day5-number"/>
</tr>
</table>
</td>
<td align="left" valign="top" class="day6-box day-box" height="100" width="100">
<table valign="top" style="font-size: 10px;" class="day6-container">
<tr valign="top">
<td valign="top" align="left" class="day6-number"/>
</tr>
</table>
</td>
<td align="left" valign="top" class="day7-box day-box" height="100" width="100">
<table valign="top" style="font-size: 10px;" class="day7-container">
<tr valign="top">
<td valign="top" align="left" class="day7-number"/>
</tr>
</table>
</td>
</tr>
</div>
</div>
</body>
</html>

Просмотреть файл

@ -2,6 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://calendar/modules/calUtils.jsm");
Components.utils.import("resource://calendar/modules/calXMLUtils.jsm");
Components.utils.import("resource://calendar/modules/calPrintUtils.jsm");
/**
@ -11,306 +15,193 @@ function calMonthPrinter() {
}
calMonthPrinter.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=monthgrid",
classDescription: "Calendar Month Grid Print Formatter",
classID: Components.ID("{f42d5132-92c4-487b-b5c8-38bf292d74c1}"),
implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
flags: 0,
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIPrintFormatter]),
QueryInterface: function QueryInterface(aIID) {
return cal.doQueryInterface(this, calMonthPrinter.prototype, aIID, null, this);
},
classInfo: XPCOMUtils.generateCI({
classID: Components.ID("{f42d5132-92c4-487b-b5c8-38bf292d74c1}"),
contractID: "@mozilla.org/calendar/printformatter;1?type=monthgrid",
classDescription: "Calendar Month Grid Print Formatter",
interfaces: [Components.interfaces.calIPrintFormatter]
}),
get name() {
return cal.calGetString("calendar", "monthPrinterName");
},
get name() cal.calGetString("calendar", "monthPrinterName"),
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";
let document = cal.xml.parseFile("chrome://calendar/skin/printing/calMonthGridPrinter.html");
// If aStart or aEnd weren't passed in, we need to calculate them based on
// aItems data.
// Set page title
document.getElementById("title").textContent = aTitle;
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;
}
// Table that maps YYYY-MM-DD to the DOM node container where items are to be added
let dayTable = {};
// Make sure to create tables from start to end, if passed
if (aStart && aEnd) {
// Make sure the start date is really a date.
let startDate = aStart.clone();
startDate.isDate = true;
// Copy end date, which is exclusive. For our calculations, we will
// only be handling dates and the below code is much cleaner with
// the range being inclusive.
let endDate = aEnd.clone();
endDate.isDate = true;
// Find out if the start date is also shown in the first week of the
// following month. This means we can spare a month printout.
let probeDate = startDate.clone();
probeDate.month++;
probeDate.day = 1;
if (cal.userWeekStart(probeDate).compare(startDate) <= 0) {
startDate = probeDate;
} else {
startDate = startDate.startOfMonth;
}
// Find out if the end date is also shown in the last week of the
// previous month. This also means we can spare a month printout.
probeDate = endDate.clone();
probeDate.month--;
probeDate = probeDate.endOfMonth;
if (cal.userWeekEnd(probeDate).compare(endDate) >= 0) {
endDate = probeDate;
}
// Now set up all the months we need to
for (let current = startDate.clone(); cal.userWeekEnd(current).compare(endDate) <= 0; current.month += 1) {
this.setupMonth(document, current, dayTable);
}
}
// 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);
let maybeNewStart = start.clone();
maybeNewStart.day = 1;
maybeNewStart.month = start.month+1;
for each (let item in aItems) {
let boxDate = item[cal.calGetStartDateProp(item)] || item[cal.calGetEndDateProp(item)];
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.
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.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).
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();
}
// Ignore items outside of the range, i.e tasks without start date
// where the end date is somewhere else.
if (aStart && aEnd && boxDate &&
(boxDate.compare(aStart) < 0 || boxDate.compare(aEnd) >= 0)) {
continue;
}
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.
if (boxDate) {
let boxDateKey = cal.print.getDateKey(boxDate);
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;
if (!(boxDateKey in dayTable)) {
// Doesn't exist, we need to create a new table for it
let startOfMonth = boxDate.startOfMonth;
this.setupMonth(document, startOfMonth, dayTable);
}
// 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.
let dayBoxes = dayTable[boxDateKey];
let addSingleItem = cal.print.addItemToDaybox.bind(cal.print, document, item);
if (dt.compare(end) >= 0) {
dt.day = 1;
if (Array.isArray(dayBoxes)) {
dayBoxes.forEach(addSingleItem);
} else {
addSingleItem(dayBoxes);
}
} else {
dt.day = 1;
cal.print.addItemToDayboxNodate(document, item);
}
} else {
// If start date is after end date, just print empty month.
dt = realEnd.clone();
}
let body = <body/>
// Remove templates from HTML, no longer needed
let templates = document.getElementById("templates");
templates.parentNode.removeChild(templates);
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);
// Stream out the resulting HTML
let html = cal.xml.serializeDOM(document);
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());
convStream.writeString(html);
},
getStringForMonth: function monthPrint_getStringForMonth(aStart, aItems) {
let weekStart = cal.getPrefSafe("calendar.week.start", 0);
setupMonth: function setupMonth(document, startOfMonth, dayTable) {
let monthTemplate = document.getElementById("month-template");
let monthContainer = document.getElementById("month-container");
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);
// Clone the template month and make sure it doesn't have an id
let currentMonth = monthTemplate.cloneNode(true);
currentMonth.removeAttribute("id");
currentMonth.item = startOfMonth.clone();
// 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);
// Set up the month title
let monthName = cal.formatMonth(startOfMonth.month + 1, "calendar", "monthInYear");
let monthTitle = cal.calGetString("calendar", "monthInYear", [monthName, startOfMonth.year]);
currentMonth.querySelector(".month-name").textContent = monthTitle;
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;
// Set up the weekday titles
let wkst = cal.getPrefSafe("calendar.week.start", 0);
for (let i = 1; i <= 7; i++) {
let dayNumber = ((i + wkst - 1) % 7) + 1;
let dayTitle = currentMonth.querySelector(".day" + i + "-title");
dayTitle.textContent = cal.calGetString("dateFormat", "day." + dayNumber + ".Mmm");
}
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;
// Set up each week
let endOfMonthView = cal.userWeekEnd(startOfMonth.endOfMonth);
let startOfMonthView = cal.userWeekStart(startOfMonth);
let mainMonth = startOfMonth.month;
let weekContainer = currentMonth.querySelector(".week-container");
let dt = firstDate.clone();
let itemListIndex = 0;
while (dt.compare(lastDate) != 1) {
monthTable.appendChild(this.makeHTMLWeek(dt, sortedList, aStart.month));
for (let weekStart = startOfMonthView; weekStart.compare(endOfMonthView) < 0; weekStart.day += 7) {
this.setupWeek(document, weekContainer, weekStart, mainMonth, dayTable);
}
return monthTable;
// Now insert the month into the page container, sorting by date (and therefore by month)
function compareDates(a, b) {
if (!a || !b) return -1;
let res = a.compare(b);
return res;
}
cal.binaryInsertNode(monthContainer, currentMonth, currentMonth.item, compareDates);
},
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));
setupWeek: function setupWeek(document, weekContainer, startOfWeek, mainMonth, dayTable) {
const weekdayMap = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
let weekTemplate = document.getElementById("week-template");
// Clone the template week and make sure it doesn't have an id
let currentWeek = weekTemplate.cloneNode(true);
currentWeek.removeAttribute("id");
// Set up day numbers for all days in this week
let currentDate = startOfWeek.clone();
for (let i = 1; i <= 7; i++) {
let dayNumber = currentWeek.querySelector(".day" + i + "-number");
let dayContainer = currentWeek.querySelector(".day" + i + "-container");
let dayBox = currentWeek.querySelector(".day" + i + "-box");
let dateKey = cal.print.getDateKey(currentDate);
dayNumber.textContent = currentDate.day;
// We need to support adding multiple boxes, since the months have
// overlapping days.
if (dateKey in dayTable) {
if (Array.isArray(dayTable[dateKey])) {
dayTable[dateKey].push(dayContainer);
} else {
dayTable[dateKey] = [dayTable[dateKey], dayContainer];
}
} else {
dayTable[dateKey] = dayContainer;
}
let weekDay = currentDate.weekday;
let dayOffPrefName = "calendar.week.d" + weekDay + weekdayMap[weekDay] + "soff";
if (cal.getPrefSafe(dayOffPrefName, false)) {
dayBox.className += " day-off";
}
if (currentDate.month != mainMonth) {
dayBox.className += " out-of-month";
}
currentDate.day++;
}
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 = cal.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;
}
let itemListIndex = i;
if (!sDate || sDate.compare(dt) == 1) {
break;
}
let time = (!sDate.isDate ? cal.getDateFormatter().formatTime(sDate) : "");
let calColor = item.calendar.getProperty('color') || "#A8C2E1";
let pb2 = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
let catColor;
for each (let cat in item.getCategories({})) {
try {
catColor = pb2.getCharPref("calendar.category.color." + cal.formatStringForCSSRule(cat));
break; // take first matching
} catch (ex) {}
}
let style = 'font-size: 11px; text-align: left;';
style += ' background-color: ' + calColor + ';';
style += ' color: ' + cal.getContrastingTextColor(calColor) + ';';
if (catColor) {
style += ' border: solid ' + catColor + ' 2px;';
}
let tableRow = <tr><td valign='top' style={style}>{time} {item.title}</td></tr>;
innerTable.appendChild(tableRow);
}
day.appendChild(innerTable);
weekRow.appendChild(day);
dt.day++;
}
return weekRow;
// No need for sorting, setupWeek will be called in sequence
weekContainer.appendChild(currentWeek);
}
};

Просмотреть файл

@ -0,0 +1,124 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title id="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"/>
<style type="text/css" id="sheet"/>
</head>
<body>
<div id="week-container"/>
<div id="tasks-list-box" hidden="true">
<h3 id="tasks-title"/>
<ul class="taskList" id="task-container"/>
</div>
<!-- Templates follow -->
<div id="templates" hidden="true">
<li id="task-template">
<input type="checkbox" class="task-checkbox" disabled="true"/>
<s class="task-title"/>
</li>
<tr id="item-template">
<td valign="top" align="left" style="font-size: 11px;" class="category-color-box calendar-color-box">
<span class="item-interval"/>
<span class="item-title"/>
</td>
</tr>
<div id="week-template" style="page-break-after: always;">
<table border="0" width="100%" class="main-table">
<tr>
<td align="center" valign="bottom" class="week-number"/>
</tr>
</table>
<table width="100%" height="90%" border="solid 1px;">
<tr height="33%">
<td border="1px solid black;" width="50%" valign="top" class="monday-box">
<table class="day-name" width="100%" style="background-color:white; border: 1px solid black;">
<tr>
<td align="center" valign="bottom" class="monday-title"/>
</tr>
</table>
<table valign="top" style="font-size: 10px;" class="monday-container">
<p/>
</table>
</td>
<td border="1px solid black;" width="50%" valign="top" class="thursday-box">
<table class="day-name" width="100%" style="background-color:white; border: 1px solid black;">
<tr>
<td align="center" valign="bottom" class="thursday-title"/>
</tr>
</table>
<table valign="top" style="font-size: 10px;" class="thursday-container">
<p/>
</table>
</td>
</tr>
<tr height="33%">
<td border="1px solid black;" width="50%" valign="top" class="tuesday-box">
<table class="day-name" width="100%" style="background-color:white; border: 1px solid black;">
<tr>
<td align="center" valign="bottom" class="tuesday-title"/>
</tr>
</table>
<table valign="top" style="font-size: 10px;" class="tuesday-container">
<p/>
</table>
</td>
<td border="1px solid black;" width="50%" valign="top" class="friday-box">
<table class="day-name" width="100%" style="background-color:white; border: 1px solid black;">
<tr>
<td align="center" valign="bottom" class="friday-title"/>
</tr>
</table>
<table valign="top" style="font-size: 10px;" class="friday-container">
<p/>
</table>
</td>
</tr>
<tr height="33%">
<td border="1px solid black;" width="50%" valign="top" class="wednesday-box">
<table class="day-name" width="100%" style="background-color:white; border: 1px solid black;">
<tr>
<td align="center" valign="bottom" class="wednesday-title"/>
</tr>
</table>
<table valign="top" style="font-size: 10px;" class="wednesday-container">
<p/>
</table>
</td>
<td height="33%" style="padding: 0">
<table border="0" width="100%" height="100%">
<tr valign="top">
<td border="1px solid black;" width="50%" valign="top" class="saturday-box">
<table class="day-name" width="100%" style="background-color:white; border: 1px solid black;">
<tr>
<td align="center" valign="bottom" class="saturday-title"/>
</tr>
</table>
<table valign="top" style="font-size: 10px;" class="saturday-container">
<p/>
</table>
</td>
</tr>
<tr valign="top">
<td border="1px solid black;" width="50%" valign="top" class="sunday-box">
<table class="day-name" width="100%" style="background-color:white; border: 1px solid black;">
<tr>
<td align="center" valign="bottom" class="sunday-title"/>
</tr>
</table>
<table valign="top" style="font-size: 10px;" class="sunday-container">
<p/>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</div>
</body>
</html>

Просмотреть файл

@ -2,250 +2,133 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://calendar/modules/calUtils.jsm");
Components.utils.import("resource://calendar/modules/calXMLUtils.jsm");
Components.utils.import("resource://calendar/modules/calPrintUtils.jsm");
/**
* 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() {
}
calWeekPrinter.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=weekplan",
classDescription: "Calendar Week Print Formatter",
classID: Components.ID("{2d6ec97b-9109-4b92-89c5-d4b4806619ce}"),
implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
flags: 0,
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIPrintFormatter]),
QueryInterface: function QueryInterface(aIID) {
return cal.doQueryInterface(this, calWeekPrinter.prototype, aIID, null, this);
},
classInfo: XPCOMUtils.generateCI({
classID: Components.ID("{2d6ec97b-9109-4b92-89c5-d4b4806619ce}"),
contractID: "@mozilla.org/calendar/printformatter;1?type=weekplan",
classDescription: "Calendar Week Print Formatter",
interfaces: [Components.interfaces.calIPrintFormatter]
}),
get name() {
return cal.calGetString("calendar", "weekPrinterName");
},
get name() cal.calGetString("calendar", "weekPrinterName"),
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>);
let body = <body/>;
// 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;
}
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);
}
let sortedList = filteredItems.sort(compareItems);
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().
let start = aStart || sortedList[0].startDate || sortedList[0].entryDate ||
sortList[0].dueDate;
cal.ASSERT(start, "can't find a good starting date to print");
let lastItem = sortedList[sortedList.length-1];
let end = aEnd || lastItem.startDate || lastItem.entryDate ||
lastItem.dueDate;
cal.ASSERT(end, "can't find a good ending date to print");
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;
}
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;'/>
// 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;
}
let monRow = <tr height="33%"/>;
monRow.appendChild(dayTds[1]); // Monday
monRow.appendChild(dayTds[4]); // Thursday
mainWeek.appendChild(monRow);
let tueRow = <tr height="33%"/>;
tueRow.appendChild(dayTds[2]); // Tuesday
tueRow.appendChild(dayTds[5]); // Friday
mainWeek.appendChild(tueRow);
let wedRow = <tr height="33%"/>;
wedRow.appendChild(dayTds[3]); // Wednesday
// Saturday and Sunday are half-size
let satSunTd = <td height="33%"/>;
let weekendTable = <table border="1" width="100%" height="100%"/>;
let satRow = <tr valign='top'/>;
satRow.appendChild(dayTds[6]); // Saturday
weekendTable.appendChild(satRow);
let sunRow = <tr valign='top'/>;
sunRow.appendChild(dayTds[0]); // Sunday
weekendTable.appendChild(sunRow);
satSunTd.appendChild(weekendTable);
wedRow.appendChild(satSunTd);
mainWeek.appendChild(wedRow);
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);
// 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));
let document = cal.xml.parseFile("chrome://calendar/skin/printing/calWeekPrinter.html");
// 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>);
// Set page title
document.getElementById("title").textContent = aTitle;
// Table that maps YYYY-MM-DD to the DOM node container where items are to be added
let dayTable = {};
// Make sure to create tables from start to end, if passed
if (aStart && aEnd) {
let startDate = aStart.clone();
startDate.isDate = true;
for (let current = cal.userWeekStart(startDate); current.compare(aEnd) < 0; current.day += 7) {
this.setupWeek(document, current, dayTable);
}
}
// 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);
}
let boxDate = item[cal.calGetStartDateProp(item)] || item[cal.calGetEndDateProp(item)];
// 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)) {
// Ignore items outside of the range, i.e tasks without start date
// where the end date is somewhere else.
if (aStart && aEnd && boxDate &&
(boxDate.compare(aStart) < 0 || boxDate.compare(aEnd) >= 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;
}
if (boxDate) {
let boxDateKey = cal.print.getDateKey(boxDate);
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);
}
if (!(boxDateKey in dayTable)) {
// Doesn't exist, we need to create a new table for it
let startOfWeek = boxDate.startOfWeek;
this.setupWeek(document, startOfWeek, dayTable);
}
// 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.nsIPrefBranch);
let catColor;
for each (let cat in item.getCategories({})) {
try {
catColor = pb2.getCharPref("calendar.category.color." + cal.formatStringForCSSRule(cat));
break; // take first matching
} catch (ex) {}
cal.print.addItemToDaybox(document, item, dayTable[boxDateKey]);
} else {
cal.print.addItemToDayboxNodate(document, item);
}
let style = 'font-size: 11px; background-color: ' + calColor + ';';
style += ' color: ' + cal.getContrastingTextColor(calColor) + ';';
if (catColor) {
style += ' border: solid ' + catColor + ' 2px;';
}
let tableRow = <tr><td valign='top' align='left' style={style}>{time} {item.title}</td></tr>;
innerTable.appendChild(tableRow);
}
innerTable.appendChild(<p> </p>);
mainTd.appendChild(innerTable);
return mainTd;
// Remove templates from HTML, no longer needed
let templates = document.getElementById("templates");
templates.parentNode.removeChild(templates);
// Stream out the resulting HTML
let html = cal.xml.serializeDOM(document);
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);
},
setupWeek: function setupWeek(document, startOfWeek, dayTable) {
const weekdayMap = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
let weekTemplate = document.getElementById("week-template");
let weekContainer = document.getElementById("week-container");
let defaultTimezone = cal.calendarDefaultTimezone();
// Clone the template week and make sure it doesn't have an id
let currentPage = weekTemplate.cloneNode(true);
let startOfWeekKey = cal.print.getDateKey(startOfWeek);
currentPage.removeAttribute("id");
currentPage.item = startOfWeek.clone();
// Set up the week number title
let weekInfo = cal.getWeekInfoService();
let dateFormatter = cal.getDateFormatter();
let weekno = weekInfo.getWeekTitle(startOfWeek);
let weekTitle = cal.calGetString("calendar", 'WeekTitle', [weekno]);
currentPage.querySelector(".week-number").textContent = weekTitle;
// Set up the day boxes
let endOfWeek = cal.userWeekEnd(startOfWeek);
for (let currentDate = startOfWeek; currentDate.compare(endOfWeek) <= 0; currentDate.day++) {
let weekday = currentDate.weekday;
let weekdayName = weekdayMap[weekday];
let dayOffPrefName = "calendar.week.d" + weekday + weekdayName + "soff";
dayTable[cal.print.getDateKey(currentDate)] = currentPage.querySelector("." + weekdayName + "-container");
let titleNode = currentPage.querySelector("." + weekdayName + "-title");
titleNode.textContent = dateFormatter.formatDateLong(currentDate.getInTimezone(defaultTimezone));
if (cal.getPrefSafe(dayOffPrefName, false)) {
let daysOffNode = currentPage.querySelector("." + weekdayName + "-box");
daysOffNode.className += " day-off";
}
}
// Now insert the week into the week container, sorting by date (and therefore week number)
function compareDates(a, b) {
if (!a || !b) return -1;
let res = a.compare(b);
return res;
}
cal.binaryInsertNode(weekContainer, currentPage, currentPage.item, compareDates);
}
};

Просмотреть файл

@ -0,0 +1,5 @@
#filter substitution
calendar.jar:
skin/calendar/printing/calWeekPrinter.html (calWeekPrinter.html)
skin/calendar/printing/calMonthGridPrinter.html (calMonthGridPrinter.html)
skin/calendar/printing/calHtmlExport.html (calHtmlExport.html)

Просмотреть файл

@ -5,6 +5,7 @@
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://calendar/modules/calUtils.jsm");
Components.utils.import("resource://calendar/modules/calXMLUtils.jsm");
function ltnMimeConverter() {
}
@ -61,22 +62,6 @@ ltnMimeConverter.prototype = {
}
},
/**
* Synchronously read the given uri and return its xml document
*
* @param uri The uri to read.
* @return The response DOM Document.
*/
readChromeUri: function readChromeUri(uri) {
let req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Components.interfaces.nsIXMLHttpRequest);
req.open('GET', uri, false);
req.overrideMimeType("text/xml");
req.send(null);
return req.responseXML;
},
/**
* Returns the html representation of the event as a DOM document.
*
@ -85,7 +70,7 @@ ltnMimeConverter.prototype = {
*/
createHtml: function createHtml(event) {
// Creates HTML using the Node strings in the properties file
let doc = this.readChromeUri("chrome://lightning/content/lightning-invitation.xhtml");
let doc = cal.xml.parseFile("chrome://lightning/content/lightning-invitation.xhtml");
let self = this;
function field(field, contentText, linkify) {
let descr = doc.getElementById("imipHtml-" + field + "-descr");