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:
Родитель
ac449e09ee
Коммит
126580f1b3
|
@ -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");
|
||||
|
|
Загрузка…
Ссылка в новой задаче