diff options
Diffstat (limited to '')
-rw-r--r-- | comm/calendar/base/content/calendar-print.js | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/comm/calendar/base/content/calendar-print.js b/comm/calendar/base/content/calendar-print.js new file mode 100644 index 0000000000..17021a0cd9 --- /dev/null +++ b/comm/calendar/base/content/calendar-print.js @@ -0,0 +1,311 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +/** + * This file is loaded into the printing options page by calPrintUtils.jsm if + * we are printing the calendar. It injects a new form (from + * calendar-tab-panels.inc.xhtml) for choosing the print output. It also + * contains the javascript for the form. + */ + +/* import-globals-from ../../../../toolkit/components/printing/content/print.js */ + +const { cal } = ChromeUtils.import("resource:///modules/calendar/calUtils.jsm"); + +// In a block to avoid polluting the global scope. +{ + let ownerWindow = window.browsingContext.topChromeWindow; + let ownerDocument = ownerWindow.document; + + for (let href of [ + "chrome://messenger/skin/icons.css", + "chrome://messenger/skin/variables.css", + "chrome://messenger/skin/widgets.css", + "chrome://calendar/skin/shared/widgets/minimonth.css", + ]) { + let link = document.head.appendChild(document.createElement("link")); + link.rel = "stylesheet"; + link.href = href; + } + + let otherForm = document.querySelector("form"); + otherForm.hidden = true; + + let form = document.importNode( + ownerDocument.getElementById("calendarPrintForm").content.firstElementChild, + true + ); + if (AppConstants.platform != "win") { + // Move the Next button to the end if this isn't Windows. + let nextButton = form.querySelector("#next-button"); + nextButton.parentElement.append(nextButton); + } + form.addEventListener("submit", event => { + event.preventDefault(); + form.hidden = true; + otherForm.hidden = false; + }); + otherForm.parentNode.insertBefore(form, otherForm); + + let backButton = form.querySelector("#back-button"); + backButton.addEventListener("click", () => { + otherForm.hidden = true; + form.hidden = false; + }); + let backButtonContainer = form.querySelector("#back-button-container"); + let printButtonContainer = otherForm.querySelector("#button-container"); + printButtonContainer.parentNode.insertBefore(backButtonContainer, printButtonContainer); + + let eventsCheckbox = form.querySelector("input#events"); + let tasksCheckbox = form.querySelector("input#tasks"); + let tasksNotDueCheckbox = form.querySelector("input#tasks-with-no-due-date"); + let tasksCompletedCheckbox = form.querySelector("input#completed-tasks"); + + let layout = form.querySelector("select#layout"); + + let fromMinimonth = form.querySelector("calendar-minimonth#from-minimonth"); + let fromMonth = form.querySelector("select#from-month"); + let fromYear = form.querySelector("input#from-year"); + let fromDate = form.querySelector("select#from-date"); + + let toMinimonth = form.querySelector("calendar-minimonth#to-minimonth"); + let toMonth = form.querySelector("select#to-month"); + let toYear = form.querySelector("input#to-year"); + let toDate = form.querySelector("select#to-date"); + + for (let i = 0; i < 12; i++) { + let option = document.createElement("option"); + option.value = i; + option.label = cal.l10n.formatMonth(i + 1, "calendar", "monthInYear"); + fromMonth.appendChild(option.cloneNode(false)); + toMonth.appendChild(option); + } + + eventsCheckbox.addEventListener("change", updatePreview); + tasksCheckbox.addEventListener("change", function () { + tasksNotDueCheckbox.disabled = !this.checked; + tasksCompletedCheckbox.disabled = !this.checked; + updatePreview(); + }); + tasksNotDueCheckbox.addEventListener("change", updatePreview); + tasksCompletedCheckbox.addEventListener("change", updatePreview); + + layout.addEventListener("change", onLayoutChange); + + fromMinimonth.addEventListener("change", function () { + if (toMinimonth.value < fromMinimonth.value) { + toMinimonth.value = fromMinimonth.value; + } + + updatePreview(); + }); + toMinimonth.addEventListener("change", updatePreview); + + fromMonth.addEventListener("keydown", function (event) { + if (event.key == "ArrowDown" && fromMonth.selectedIndex == 11) { + fromMonth.selectedIndex = 0; + fromYear.value++; + onMonthChange(); + event.preventDefault(); + } else if (event.key == "ArrowUp" && fromMonth.selectedIndex == 0) { + fromMonth.selectedIndex = 11; + fromYear.value--; + onMonthChange(); + event.preventDefault(); + } + }); + fromMonth.addEventListener("change", onMonthChange); + fromYear.addEventListener("change", onMonthChange); + toMonth.addEventListener("keydown", function (event) { + if (event.key == "ArrowDown" && toMonth.selectedIndex == 11) { + toMonth.selectedIndex = 0; + toYear.value++; + onMonthChange(); + event.preventDefault(); + } else if (event.key == "ArrowUp" && toMonth.selectedIndex == 0) { + toMonth.selectedIndex = 11; + toYear.value--; + onMonthChange(); + event.preventDefault(); + } + }); + toMonth.addEventListener("change", onMonthChange); + toYear.addEventListener("change", onMonthChange); + + fromDate.addEventListener("change", function () { + let fromValue = parseInt(fromDate.value, 10); + for (let option of toDate.options) { + option.hidden = option.value < fromValue; + } + if (toDate.value < fromValue) { + toDate.value = fromValue; + } + + updatePreview(); + }); + toDate.addEventListener("change", updatePreview); + + // Ensure the layout selector is focused and has a focus ring to make it + // more obvious. The ring won't be added if already focused, so blur first. + requestAnimationFrame(() => { + layout.blur(); + Services.focus.setFocus(layout, Services.focus.FLAG_SHOWRING); + }); + + /** Show something in the preview as soon as it is ready. */ + function updateWhenReady() { + document.removeEventListener("page-count", updateWhenReady); + onLayoutChange(); + } + document.addEventListener("page-count", updateWhenReady); + + /** + * Update the available date options to sensible ones for the selected layout. + * It would be nice to use HTML date inputs here but the browser this form is + * loaded into won't allow it. Instead use lists of the most likely values, + * which actually fits better for some print layouts. + */ + function onLayoutChange() { + if (layout.value == "list") { + fromMinimonth.hidden = toMinimonth.hidden = false; + fromMonth.hidden = fromYear.hidden = toMonth.hidden = toYear.hidden = true; + fromDate.hidden = toDate.hidden = true; + } else if (layout.value == "monthGrid") { + let today = new Date(); + fromMonth.value = toMonth.value = today.getMonth(); + fromYear.value = toYear.value = today.getFullYear(); + + fromMinimonth.hidden = toMinimonth.hidden = true; + fromMonth.hidden = fromYear.hidden = toMonth.hidden = toYear.hidden = false; + fromDate.hidden = toDate.hidden = true; + } else { + const FIRST_WEEK = -53; + const LAST_WEEK = 53; + + while (fromDate.lastChild) { + fromDate.lastChild.remove(); + } + while (toDate.lastChild) { + toDate.lastChild.remove(); + } + + // Always use Monday - Sunday week, regardless of prefs, because the layout requires it. + let monday = cal.dtz.now(); + monday.isDate = true; + monday.day = monday.day - monday.weekday + 1 + FIRST_WEEK * 7; + + for (let i = FIRST_WEEK; i < LAST_WEEK; i++) { + let option = document.createElement("option"); + option.value = i; + option.label = cal.dtz.formatter.formatDateLong(monday); + fromDate.appendChild(option.cloneNode(false)); + + let sunday = monday.clone(); + sunday.day += 6; + option.label = cal.dtz.formatter.formatDateLong(sunday); + option.hidden = i < 0; + toDate.appendChild(option); + + monday.day += 7; + } + + fromDate.value = toDate.value = 0; + + fromMinimonth.hidden = toMinimonth.hidden = true; + fromMonth.hidden = fromYear.hidden = toMonth.hidden = toYear.hidden = true; + fromDate.hidden = toDate.hidden = false; + } + + updatePreview(); + } + + function onMonthChange() { + if (parseInt(toYear.value, 10) < fromYear.value) { + toYear.value = fromYear.value; + toMonth.value = fromMonth.value; + } else if (toYear.value == fromYear.value && parseInt(toMonth.value, 10) < fromMonth.value) { + toMonth.value = fromMonth.value; + } + updatePreview(); + } + + /** + * Read the selected options and update the preview document. + */ + async function updatePreview() { + let startDate = cal.dtz.now(); + startDate.isDate = true; + let endDate = cal.dtz.now(); + endDate.isDate = true; + + if (layout.value == "list") { + let fromValue = fromMinimonth.value; + let toValue = toMinimonth.value; + + startDate.resetTo( + fromValue.getFullYear(), + fromValue.getMonth(), + fromValue.getDate(), + 0, + 0, + 0, + cal.dtz.floating + ); + startDate.isDate = true; + if (toValue > fromValue) { + endDate.resetTo( + toValue.getFullYear(), + toValue.getMonth(), + toValue.getDate(), + 0, + 0, + 0, + cal.dtz.floating + ); + endDate.isDate = true; + } else { + endDate = startDate.clone(); + } + endDate.day++; + } else if (layout.value == "monthGrid") { + startDate.day = 1; + startDate.month = parseInt(fromMonth.value, 10); + startDate.year = parseInt(fromYear.value, 10); + endDate.day = 1; + endDate.month = parseInt(toMonth.value, 10); + endDate.year = parseInt(toYear.value, 10); + endDate.month++; + } else { + startDate.day = startDate.day - startDate.weekday + 1; + startDate.day += parseInt(fromDate.value, 10) * 7; + endDate.day = endDate.day - endDate.weekday + 1; + endDate.day += parseInt(toDate.value, 10) * 7 + 7; + } + + let filter = 0; + if (tasksCheckbox.checked) { + filter |= Ci.calICalendar.ITEM_FILTER_TYPE_TODO; + if (tasksCompletedCheckbox.checked) { + filter |= Ci.calICalendar.ITEM_FILTER_COMPLETED_ALL; + } else { + filter |= Ci.calICalendar.ITEM_FILTER_COMPLETED_NO; + } + } + + if (eventsCheckbox.checked) { + filter |= + Ci.calICalendar.ITEM_FILTER_TYPE_EVENT | Ci.calICalendar.ITEM_FILTER_CLASS_OCCURRENCES; + } + + await cal.print.draw( + PrintEventHandler.printPreviewEl.querySelector("browser").contentDocument, + layout.value, + startDate, + endDate, + filter, + tasksNotDueCheckbox.checked + ); + PrintEventHandler._updatePrintPreview(); + } +} |