diff --git a/.eslintignore b/.eslintignore
index 6f5ac23baa..9c46e25e34 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -16,10 +16,11 @@ db/**
other-licenses/**
testing/**
-# Temporarily disabled until the XUL parser is fixed.
+# Temporarily disabled until the XUL parser is fixed (see bug 1542548).
calendar/lightning/content/messenger-overlay-sidebar.xul
calendar/providers/gdata/content/gdata-calendar-creation.xul
common/src/viewSource.xul
+calendar/base/content/today-pane.xul
# We ignore all these directories by default, until we get them enabled.
# If you are enabling a directory, please add directory specific exclusions
diff --git a/calendar/base/content/dialogs/calendar-event-dialog-attendees.xul b/calendar/base/content/dialogs/calendar-event-dialog-attendees.xul
index 3ce4194fad..342795845e 100644
--- a/calendar/base/content/dialogs/calendar-event-dialog-attendees.xul
+++ b/calendar/base/content/dialogs/calendar-event-dialog-attendees.xul
@@ -33,6 +33,7 @@
+
diff --git a/calendar/base/content/dialogs/calendar-event-dialog-recurrence.js b/calendar/base/content/dialogs/calendar-event-dialog-recurrence.js
index 11002a279d..bd90cb01a0 100644
--- a/calendar/base/content/dialogs/calendar-event-dialog-recurrence.js
+++ b/calendar/base/content/dialogs/calendar-event-dialog-recurrence.js
@@ -57,7 +57,7 @@ const RecurrencePreview = {
* Updates #recurrence-preview node layout on window resize.
*/
onResize() {
- let minimonth = this.node.querySelector("minimonth");
+ let minimonth = this.node.querySelector("calendar-minimonth");
let row = this.node.querySelector("row");
let rows = row.parentNode;
@@ -147,7 +147,7 @@ const RecurrencePreview = {
* Updates preview of #recurrence-preview node.
*/
updatePreview(recurrenceInfo) {
- let minimonth = this.node.querySelector("minimonth");
+ let minimonth = this.node.querySelector("calendar-minimonth");
this.node.style.minHeight = minimonth.getBoundingClientRect().height + "px";
this.mRecurrenceInfo = recurrenceInfo;
diff --git a/calendar/base/content/dialogs/calendar-event-dialog-recurrence.xul b/calendar/base/content/dialogs/calendar-event-dialog-recurrence.xul
index aa435232b9..47421ea597 100644
--- a/calendar/base/content/dialogs/calendar-event-dialog-recurrence.xul
+++ b/calendar/base/content/dialogs/calendar-event-dialog-recurrence.xul
@@ -32,6 +32,7 @@
+
@@ -559,9 +560,9 @@
-
-
-
+
+
+
diff --git a/calendar/base/content/dialogs/calendar-event-dialog-reminder.xul b/calendar/base/content/dialogs/calendar-event-dialog-reminder.xul
index 2a19d6cf28..9b5f770f5d 100644
--- a/calendar/base/content/dialogs/calendar-event-dialog-reminder.xul
+++ b/calendar/base/content/dialogs/calendar-event-dialog-reminder.xul
@@ -26,6 +26,7 @@
+
diff --git a/calendar/base/content/dialogs/calendar-event-dialog-timezone.xul b/calendar/base/content/dialogs/calendar-event-dialog-timezone.xul
index e001afa1e3..d0c9d44840 100644
--- a/calendar/base/content/dialogs/calendar-event-dialog-timezone.xul
+++ b/calendar/base/content/dialogs/calendar-event-dialog-timezone.xul
@@ -25,6 +25,7 @@
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml">
+
diff --git a/calendar/base/content/dialogs/calendar-print-dialog.xul b/calendar/base/content/dialogs/calendar-print-dialog.xul
index 3d60be38dc..8c111ef446 100644
--- a/calendar/base/content/dialogs/calendar-print-dialog.xul
+++ b/calendar/base/content/dialogs/calendar-print-dialog.xul
@@ -29,6 +29,7 @@
+
diff --git a/calendar/base/content/today-pane.js b/calendar/base/content/today-pane.js
index 3816e156c3..3c3a393f4f 100644
--- a/calendar/base/content/today-pane.js
+++ b/calendar/base/content/today-pane.js
@@ -346,7 +346,7 @@ var TodayPane = {
currentweeklabel.value = cal.l10n.getCalString("shortcalendarweek") + " " + cal.getWeekInfoService().getWeekTitle(this.start);
if (!aDontUpdateMinimonth) {
- document.getElementById("today-Minimonth").value = cal.dtz.dateTimeToJsDate(this.start);
+ document.getElementById("today-minimonth").value = cal.dtz.dateTimeToJsDate(this.start);
}
this.updatePeriod();
this.setDay.alreadySettingDay = false;
@@ -390,7 +390,7 @@ var TodayPane = {
document.getElementById("today-minimonth-box").setVisible(aSection == "minimonth");
document.getElementById("mini-day-box").setVisible(aSection == "miniday");
document.getElementById("today-none-box").setVisible(aSection == "none");
- setBooleanAttribute(document.getElementById("today-Minimonth"), "freebusy", aSection == "minimonth");
+ setBooleanAttribute(document.getElementById("today-minimonth"), "freebusy", aSection == "minimonth");
},
/**
diff --git a/calendar/base/content/today-pane.xul b/calendar/base/content/today-pane.xul
index 00b5655843..1a86d2ee1c 100644
--- a/calendar/base/content/today-pane.xul
+++ b/calendar/base/content/today-pane.xul
@@ -68,7 +68,9 @@
collapsedinmodes="mail,calendar,task"
refcontrol="ltnTodayPaneDisplayMinimonth"
persist="collapsedinmodes">
-
+
-
+
diff --git a/calendar/base/content/widgets/calendar-minimonth.js b/calendar/base/content/widgets/calendar-minimonth.js
new file mode 100644
index 0000000000..c698227115
--- /dev/null
+++ b/calendar/base/content/widgets/calendar-minimonth.js
@@ -0,0 +1,959 @@
+/* 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/. */
+
+/* globals cal MozXULElement setBooleanAttribute */
+
+"use strict";
+
+// Wrap in a block to prevent leaking to window scope.
+{
+ const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+ /**
+ * MiniMonth Calendar: day-of-month grid component.
+ * Displays month name and year above grid of days of month by week rows.
+ * Arrows move forward or back a month or a year.
+ * Clicking on a day cell selects that day.
+ * At site, can provide id, and code to run when value changed by picker.
+ *
+ *
+ * May get/set value in javascript with
+ * document.querySelector("#my-date-picker").value = new Date();
+ *
+ * @implements {calIOperationListener}
+ * @implements {calIObserver}
+ * @implements {calICompositeObserver}
+ * @implements {nsIObserver}
+ */
+ class CalendarMinimonth extends MozXULElement {
+ constructor() {
+ super();
+ // Set up custom interfaces.
+ // calIObserver is not used like the others are, so it is not set up here.
+ this.calICompositeObserver = this.getCustomInterfaceCallback(Ci.calICompositeObserver);
+ this.calIOperationListener = this.getCustomInterfaceCallback(Ci.calIOperationListener);
+ this.nsIObserver = this.getCustomInterfaceCallback(Ci.nsIObserver);
+ }
+
+ static get inheritedAttributes() {
+ return {
+ ".minimonth-header": "readonly,month,year",
+ ".minimonth-month-name": "selectedIndex=month",
+ ".minimonth-year-name": "value=year",
+ };
+ }
+
+ connectedCallback() {
+ if (this.delayConnectedCallback() || this.hasChildNodes()) {
+ return;
+ }
+
+ const minimonthHeader = `
+
+ `;
+
+ const minimonthWeekRow = `
+
+
+
+
+
+
+
+
+
+
+ `;
+
+ this.appendChild(MozXULElement.parseXULToFragment(`
+ ${minimonthHeader}
+
+
+
+
+
+
+
+
+
+
+
+
+ ${minimonthWeekRow}
+ ${minimonthWeekRow}
+ ${minimonthWeekRow}
+ ${minimonthWeekRow}
+ ${minimonthWeekRow}
+ ${minimonthWeekRow}
+
+ `,
+ [
+ "chrome://calendar/locale/global.dtd",
+ "chrome://global/locale/global.dtd"
+ ]
+ ));
+ this.initializeAttributeInheritance();
+ this.setAttribute("orient", "vertical");
+
+ // Set up header buttons.
+ const kMinimonth = this.closest("calendar-minimonth");
+ this.querySelector(".months-back-button").kMinimonth = kMinimonth;
+ this.querySelector(".months-forward-button").kMinimonth = kMinimonth;
+ this.querySelector(".years-back-button").kMinimonth = kMinimonth;
+ this.querySelector(".years-forward-button").kMinimonth = kMinimonth;
+ this.querySelector(".today-button").kMinimonth = kMinimonth;
+
+ this.mDaymap = null;
+ this.mValue = null;
+ this.mEditorDate = null;
+ this.mExtraDate = null;
+ this.mPixelScrollDelta = 0;
+ this.mObservesComposite = false;
+ this.mShowWeekNumber = true;
+ this.mToday = false;
+ this.mSelected = false;
+ this.mExtra = false;
+ this.mValue = new Date(); // Default to "today".
+ this.mFocused = null;
+
+ this.refreshDisplay();
+ if (this.hasAttribute("freebusy")) {
+ this._setFreeBusy(this.getAttribute("freebusy") == "true");
+ }
+ this.mShowWeekNumber = Services.prefs.getBoolPref("calendar.view-minimonth.showWeekNumber", true);
+
+ // Add pref observer.
+ Services.prefs.getBranch("").addObserver("calendar.", this.nsIObserver);
+
+ // Add event listeners.
+ this.addEventListener("click", (event) => {
+ if (event.button == 0 &&
+ event.originalTarget.classList.contains("minimonth-day")) {
+ this.onDayActivate(event);
+ event.stopPropagation();
+ event.preventDefault();
+ }
+ });
+
+ this.addEventListener("keypress", (event) => {
+ if (event.originalTarget.classList.contains("minimonth-day")) {
+ switch (event.keyCode) {
+ case KeyEvent.DOM_VK_LEFT:
+ this.moveDateByOffset(0, 0, -1);
+ break;
+ case KeyEvent.DOM_VK_RIGHT:
+ this.moveDateByOffset(0, 0, 1);
+ break;
+ case KeyEvent.DOM_VK_UP:
+ this.moveDateByOffset(0, 0, -7);
+ break;
+ case KeyEvent.DOM_VK_DOWN:
+ this.moveDateByOffset(0, 0, 7);
+ break;
+ case KeyEvent.DOM_VK_PAGE_UP:
+ this.moveDateByOffset(0, -1, 0);
+ break;
+ case KeyEvent.DOM_VK_PAGE_DOWN:
+ this.moveDateByOffset(0, 1, 0);
+ break;
+ case KeyEvent.DOM_VK_ESCAPE:
+ this.focusDate(this.mValue || this.mExtraDate);
+ break;
+ case KeyEvent.DOM_VK_HOME: {
+ const today = new Date();
+ this.update(today);
+ this.focusDate(today);
+ break;
+ }
+ case KeyEvent.DOM_VK_RETURN:
+ this.onDayActivate(event);
+ break;
+ }
+ event.stopPropagation();
+ event.preventDefault();
+ }
+ });
+
+ this.addEventListener("wheel", (event) => {
+ const pixelThreshold = 150;
+ let deltaView = 0;
+ if (this.getAttribute("readonly") == "true") {
+ // No scrolling on readonly months.
+ return;
+ }
+ if (event.deltaMode == event.DOM_DELTA_LINE ||
+ event.deltaMode == event.DOM_DELTA_PAGE) {
+ if (event.deltaY != 0) {
+ deltaView = event.deltaY > 0 ? 1 : -1;
+ }
+ } else if (event.deltaMode == event.DOM_DELTA_PIXEL) {
+ this.mPixelScrollDelta += event.deltaY;
+ if (this.mPixelScrollDelta > pixelThreshold) {
+ deltaView = 1;
+ this.mPixelScrollDelta = 0;
+ } else if (this.mPixelScrollDelta < -pixelThreshold) {
+ deltaView = -1;
+ this.mPixelScrollDelta = 0;
+ }
+ }
+
+ if (deltaView != 0) {
+ const classList = event.originalTarget.classList;
+
+ if (classList.contains("years-forward-button") ||
+ classList.contains("yearcell") ||
+ classList.contains("years-back-button")) {
+ this.advanceYear(deltaView);
+ } else if (!classList.contains("today-button")) {
+ this.advanceMonth(deltaView);
+ }
+ }
+
+ event.stopPropagation();
+ event.preventDefault();
+ });
+ }
+
+ set value(val) {
+ this.update(val);
+ }
+
+ get value() {
+ return this.mValue;
+ }
+
+ set extra(val) {
+ this.mExtraDate = val;
+ }
+
+ get extra() {
+ return this.mExtraDate;
+ }
+
+ /**
+ * Returns the first (inclusive) date of the minimonth as a calIDateTime object.
+ */
+ get firstDate() {
+ let date = this._getCalBoxNode(1, 1).date;
+ return cal.dtz.jsDateToDateTime(date);
+ }
+
+ /**
+ * Returns the last (exclusive) date of the minimonth as a calIDateTime object.
+ */
+ get lastDate() {
+ let date = this._getCalBoxNode(6, 7).date;
+ let lastDateTime = cal.dtz.jsDateToDateTime(date);
+ lastDateTime.day = lastDateTime.day + 1;
+ return lastDateTime;
+ }
+
+ get mReadOnlyHeader() {
+ return this.querySelector(".minimonth-readonly-header");
+ }
+
+ // calIOperationListener methods.
+
+ onOperationComplete(aCalendar, aStatus, aOperationType, aId, aDetail) {}
+
+ onGetResult(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
+ if (Components.isSuccessCode(aStatus)) {
+ aItems.forEach(item => this.setBusyDaysForOccurrence(item, true));
+ }
+ }
+
+ setBusyDaysForItem(aItem, aState) {
+ let items = aItem.recurrenceInfo
+ ? aItem.getOccurrencesBetween(this.firstDate, this.lastDate, {})
+ : [aItem];
+ items.forEach(item => this.setBusyDaysForOccurrence(item, aState));
+ }
+
+ parseBoxBusy(aBox) {
+ let boxBusy = {};
+
+ let busyStr = aBox.getAttribute("busy");
+ if (busyStr && busyStr.length > 0) {
+ let calChunks = busyStr.split("\u001A");
+ for (let chunk of calChunks) {
+ let expr = chunk.split("=");
+ boxBusy[expr[0]] = parseInt(expr[1], 10);
+ }
+ }
+
+ return boxBusy;
+ }
+
+ updateBoxBusy(aBox, aBoxBusy) {
+ let calChunks = [];
+
+ for (let calId in aBoxBusy) {
+ if (aBoxBusy[calId]) {
+ calChunks.push(calId + "=" + aBoxBusy[calId]);
+ }
+ }
+
+ if (calChunks.length > 0) {
+ let busyStr = calChunks.join("\u001A");
+ aBox.setAttribute("busy", busyStr);
+ } else {
+ aBox.removeAttribute("busy");
+ }
+ }
+
+ removeCalendarFromBoxBusy(aBox, aCalendar) {
+ let boxBusy = this.parseBoxBusy(aBox);
+ if (boxBusy[aCalendar.id]) {
+ delete boxBusy[aCalendar.id];
+ }
+ this.updateBoxBusy(aBox, boxBusy);
+ }
+
+ setBusyDaysForOccurrence(aOccurrence, aState) {
+ if (aOccurrence.getProperty("TRANSP") == "TRANSPARENT") {
+ // Skip transparent events.
+ return;
+ }
+ let start = aOccurrence[cal.dtz.startDateProp(aOccurrence)] || aOccurrence.dueDate;
+ let end = aOccurrence[cal.dtz.endDateProp(aOccurrence)] || start;
+ if (!start) {
+ return;
+ }
+
+ if (start.compare(this.firstDate) < 0) {
+ start = this.firstDate.clone();
+ }
+
+ if (end.compare(this.lastDate) > 0) {
+ end = this.lastDate.clone();
+ end.day++;
+ }
+
+ // We need to compare with midnight of the current day, so reset the
+ // time here.
+ let current = start.clone().getInTimezone(cal.dtz.defaultTimezone);
+ current.hour = 0;
+ current.minute = 0;
+ current.second = 0;
+
+ // Cache the result so the compare isn't called in each iteration.
+ let compareResult = (start.compare(end) == 0 ? 1 : 0);
+
+ // Setup the busy days.
+ while (current.compare(end) < compareResult) {
+ let box = this.getBoxForDate(current);
+ if (box) {
+ let busyCalendars = this.parseBoxBusy(box);
+ if (!busyCalendars[aOccurrence.calendar.id]) {
+ busyCalendars[aOccurrence.calendar.id] = 0;
+ }
+ busyCalendars[aOccurrence.calendar.id] += (aState ? 1 : -1);
+ this.updateBoxBusy(box, busyCalendars);
+ }
+ current.day++;
+ }
+ }
+
+ // End of calIOperationListener methods.
+ // calIObserver methods.
+
+ onStartBatch(aCalendar) {}
+
+ onEndBatch(aCalendar) {}
+
+ onLoad(aCalendar) {}
+
+ onAddItem(aItem) {
+ this.setBusyDaysForItem(aItem, true);
+ }
+
+ onDeleteItem(aItem) {
+ this.setBusyDaysForItem(aItem, false);
+ }
+
+ onModifyItem(aNewItem, aOldItem) {
+ this.setBusyDaysForItem(aOldItem, false);
+ this.setBusyDaysForItem(aNewItem, true);
+ }
+
+ onError(aCalendar, aErrNo, aMessage) {}
+
+ onPropertyChanged(aCalendar, aName, aValue, aOldValue) {
+ switch (aName) {
+ case "disabled":
+ this.resetAttributesForDate();
+ this.getItems();
+ break;
+ }
+ }
+
+ onPropertyDeleting(aCalendar, aName) {
+ this.onPropertyChanged(aCalendar, aName, null, null);
+ }
+
+ // End of calIObserver methods.
+ // calICompositeObserver methods.
+
+ onCalendarAdded(aCalendar) {
+ this.getItems(aCalendar);
+ }
+
+ onCalendarRemoved(aCalendar) {
+ for (let day in this.mDayMap) {
+ this.removeCalendarFromBoxBusy(this.mDayMap[day], aCalendar);
+ }
+ }
+
+ onDefaultCalendarChanged(aCalendar) {}
+
+ // End calICompositeObserver methods.
+ // nsIObserver methods.
+
+ observe(aSubject, aTopic, aData) {
+ switch (aData) {
+ case "calendar.week.start":
+ case "calendar.view-minimonth.showWeekNumber":
+ this.refreshDisplay();
+ break;
+ }
+ }
+
+ // End nsIObserver methods.
+
+ refreshDisplay() {
+ // Find out which should be the first day of the week.
+ this.weekStart = Services.prefs.getIntPref("calendar.week.start", 0);
+ this.mShowWeekNumber = Services.prefs.getBoolPref("calendar.view-minimonth.showWeekNumber", true);
+ if (!this.mValue) {
+ this.mValue = new Date();
+ }
+ this.setHeader();
+ this.showMonth(this.mValue);
+ this.updateAccessibleLabel();
+ }
+
+ _getCalBoxNode(aRow, aCol) {
+ if (!this.mCalBox) {
+ this.mCalBox = this.querySelector(".minimonth-calendar");
+ }
+ return this.mCalBox.children[aRow].children[aCol];
+ }
+
+ setHeader() {
+ // Reset the headers.
+ let dayList = new Array(7);
+ let longDayList = new Array(7);
+ let tempDate = new Date();
+ let i, j;
+ let useOSFormat;
+ tempDate.setDate(tempDate.getDate() - (tempDate.getDay() - this.weekStart));
+ for (i = 0; i < 7; i++) {
+ // If available, use UILocale days, else operating system format.
+ try {
+ dayList[i] = cal.l10n.getDateFmtString(`day.${tempDate.getDay() + 1}.short`);
+ } catch (e) {
+ dayList[i] = tempDate.toLocaleDateString(undefined, { weekday: "short" });
+ useOSFormat = true;
+ }
+ longDayList[i] = tempDate.toLocaleDateString(undefined, { weekday: "long" });
+ tempDate.setDate(tempDate.getDate() + 1);
+ }
+
+ if (useOSFormat) {
+ // To keep datepicker popup compact, shrink localized weekday
+ // abbreviations down to 1 or 2 chars so each column of week can
+ // be as narrow as 2 digits.
+ //
+ // 1. Compute the minLength of the day name abbreviations.
+ let minLength = dayList
+ .map(name => name.length)
+ .reduce((min, len) => Math.min(min, len));
+
+ // 2. If some day name abbrev. is longer than 2 chars (not Catalan),
+ // and ALL localized day names share same prefix (as in Chinese),
+ // then trim shared "day-" prefix.
+ if (dayList.some(dayAbbr => dayAbbr.length > 2)) {
+ for (let endPrefix = 0; endPrefix < minLength; endPrefix++) {
+ let suffix = dayList[0][endPrefix];
+ if (dayList.some(dayAbbr => dayAbbr[endPrefix] != suffix)) {
+ if (endPrefix > 0) {
+ for (i = 0; i < dayList.length; i++) { // trim prefix chars.
+ dayList[i] = dayList[i].substring(endPrefix);
+ }
+ }
+ break;
+ }
+ }
+ }
+ // 3. Trim each day abbreviation to 1 char if unique, else 2 chars.
+ for (i = 0; i < dayList.length; i++) {
+ let foundMatch = 1;
+ for (j = 0; j < dayList.length; j++) {
+ if (i != j) {
+ if (dayList[i].substring(0, 1) == dayList[j].substring(0, 1)) {
+ foundMatch = 2;
+ break;
+ }
+ }
+ }
+ dayList[i] = dayList[i].substring(0, foundMatch);
+ }
+ }
+
+ setBooleanAttribute(this._getCalBoxNode(0, 0), "hidden", !this.mShowWeekNumber);
+ for (let column = 1; column < 8; column++) {
+ let node = this._getCalBoxNode(0, column);
+ node.textContent = dayList[column - 1];
+ node.setAttribute("aria-label", longDayList[column - 1]);
+ }
+ }
+
+ showMonth(aDate) {
+ // Use mExtraDate if aDate is null.
+ aDate = new Date(aDate || this.mExtraDate);
+
+ aDate.setDate(1);
+ // We set the hour and minute to something highly unlikely to be the
+ // exact change point of DST, so timezones like America/Sao Paulo
+ // don't display some days twice.
+ aDate.setHours(12);
+ aDate.setMinutes(34);
+ aDate.setSeconds(0);
+ aDate.setMilliseconds(0);
+ // Don't fire onmonthchange event upon initialization
+ let monthChanged = this.mEditorDate && (this.mEditorDate.valueOf() != aDate.valueOf());
+ this.mEditorDate = aDate; // Only place mEditorDate is set.
+
+ if (this.mToday) {
+ this.mToday.removeAttribute("today");
+ this.mToday = null;
+ }
+
+ if (this.mSelected) {
+ this.mSelected.removeAttribute("selected");
+ this.mSelected = null;
+ }
+
+ if (this.mExtra) {
+ this.mExtra.removeAttribute("extra");
+ this.mExtra = null;
+ }
+
+ // Update the month and year title.
+ this.setAttribute("month", aDate.getMonth());
+ this.setAttribute("year", aDate.getFullYear());
+
+ let dateString = cal.l10n.getDateFmtString(`month.${aDate.getMonth() + 1}.name`);
+ this.mReadOnlyHeader.textContent = dateString + " " + aDate.getFullYear();
+
+ // Update the calendar.
+ let calbox = this.querySelector(".minimonth-calendar");
+ let date = this._getStartDate(aDate);
+
+ // Get today's date.
+ let today = new Date();
+
+ if (aDate.getFullYear() == (this.mValue || this.mExtraDate).getFullYear()) {
+ calbox.setAttribute("aria-label", dateString);
+ } else {
+ let monthName = cal.l10n.formatMonth(aDate.getMonth() + 1, "calendar", "monthInYear");
+ let label = cal.l10n.getCalString("monthInYear", [monthName, aDate.getFullYear()]);
+ calbox.setAttribute("aria-label", label);
+ }
+
+ this.mDayMap = {};
+ let defaultTz = cal.dtz.defaultTimezone;
+ let dateFormatter = new Services.intl.DateTimeFormat(undefined, { dateStyle: "long" });
+ for (let k = 1; k < 7; k++) {
+ // Set the week number.
+ let firstElement = this._getCalBoxNode(k, 0);
+ setBooleanAttribute(firstElement, "hidden", !this.mShowWeekNumber);
+ if (this.mShowWeekNumber) {
+ let weekNumber = cal.getWeekInfoService().getWeekTitle(
+ cal.dtz.jsDateToDateTime(date, defaultTz)
+ );
+ let weekTitle = cal.l10n.getCalString("WeekTitle", [weekNumber]);
+ firstElement.textContent = weekNumber;
+ firstElement.setAttribute("aria-label", weekTitle);
+ }
+
+ for (let i = 1; i < 8; i++) {
+ let day = this._getCalBoxNode(k, i);
+ let ymd = date.getFullYear() + "-" + date.getMonth() + "-" + date.getDate();
+ this.mDayMap[ymd] = day;
+
+ if (this.getAttribute("readonly") != "true") {
+ day.setAttribute("interactive", "true");
+ }
+
+ if (aDate.getMonth() == date.getMonth()) {
+ day.removeAttribute("othermonth");
+ } else {
+ day.setAttribute("othermonth", "true");
+ }
+
+ // Highlight today.
+ if (this._sameDay(today, date)) {
+ this.mToday = day;
+ day.setAttribute("today", "true");
+ }
+
+ // Highlight the current date.
+ let val = this.value;
+ if (this._sameDay(val, date)) {
+ this.mSelected = day;
+ day.setAttribute("selected", "true");
+ }
+
+ // Highlight the extra date.
+ if (this._sameDay(this.mExtraDate, date)) {
+ this.mExtra = day;
+ day.setAttribute("extra", "true");
+ }
+
+ if (aDate.getMonth() == date.getMonth() &&
+ aDate.getFullYear() == date.getFullYear()) {
+ day.setAttribute("aria-label", date.toLocaleDateString(undefined, { day: "numeric" })
+ );
+ } else {
+ day.setAttribute("aria-label", dateFormatter.format(date));
+ }
+
+ day.removeAttribute("busy");
+
+ day.date = new Date(date);
+ day.textContent = date.getDate();
+ date.setDate(date.getDate() + 1);
+
+ if (monthChanged) {
+ this.resetAttributesForDate(day.date);
+ }
+ }
+ }
+
+ if (!this.mFocused) {
+ this.setFocusedDate(this.mValue || this.mExtraDate);
+ }
+
+ if (monthChanged) {
+ this.fireEvent("monthchange");
+ }
+
+ if (this.getAttribute("freebusy") == "true") {
+ this.getItems();
+ }
+ }
+
+ /**
+ * Attention - duplicate!!!!
+ */
+ fireEvent(aEventName) {
+ this.dispatchEvent(new CustomEvent(aEventName, { bubbles: true }));
+ }
+
+ getBoxForDate(aDate) {
+ // aDate is a calIDateTime.
+ let ymd = [aDate.year, aDate.month, aDate.day].join("-");
+ return (ymd in this.mDayMap ? this.mDayMap[ymd] : null);
+ }
+
+ resetAttributesForDate(aDate) {
+ function removeForBox(aBox) {
+ let allowedAttributes = 0;
+ while (aBox.attributes.length > allowedAttributes) {
+ switch (aBox.attributes[allowedAttributes].nodeName) {
+ case "selected":
+ case "othermonth":
+ case "today":
+ case "extra":
+ case "interactive":
+ case "class":
+ case "tabindex":
+ case "role":
+ case "aria-label":
+ allowedAttributes++;
+ break;
+ default:
+ aBox.removeAttribute(aBox.attributes[allowedAttributes].nodeName);
+ break;
+ }
+ }
+ }
+
+ if (aDate) {
+ let box = this.getBoxForDate(cal.dtz.jsDateToDateTime(aDate, cal.dtz.defaultTimezone));
+ if (box) {
+ removeForBox(box);
+ }
+ } else {
+ for (let k = 1; k < 7; k++) {
+ for (let i = 1; i < 8; i++) {
+ removeForBox(this._getCalBoxNode(k, i));
+ }
+ }
+ }
+ }
+
+ _setFreeBusy(aFreeBusy) {
+ if (aFreeBusy) {
+ if (!this.mObservesComposite) {
+ cal.view.getCompositeCalendar(window).addObserver(this.calICompositeObserver);
+ this.mObservesComposite = true;
+ this.getItems();
+ }
+ } else if (this.mObservesComposite) {
+ cal.view.getCompositeCalendar(window).removeObserver(this.calICompositeObserver);
+ this.mObservesComposite = false;
+ }
+ }
+
+ removeAttribute(aAttr) {
+ if (aAttr == "freebusy") {
+ this._setFreeBusy(false);
+ }
+ return super.removeAttribute(aAttr);
+ }
+
+ setAttribute(aAttr, aVal) {
+ if (aAttr == "freebusy") {
+ this._setFreeBusy(aVal == "true");
+ }
+ return super.setAttribute(aAttr, aVal);
+ }
+
+ getItems(aCalendar) {
+ // The minimonth automatically clears extra styles on a month change.
+ // Therefore we only need to fill the minimonth with new info.
+
+ let calendar = aCalendar || cal.view.getCompositeCalendar(window);
+ let filter = calendar.ITEM_FILTER_COMPLETED_ALL |
+ calendar.ITEM_FILTER_CLASS_OCCURRENCES |
+ calendar.ITEM_FILTER_ALL_ITEMS;
+
+ // Get new info.
+ calendar.getItems(filter, 0, this.firstDate, this.lastDate, this.calIOperationListener);
+ }
+
+ updateAccessibleLabel() {
+ let label;
+ if (this.mValue) {
+ let dateFormatter = new Services.intl.DateTimeFormat(
+ undefined,
+ { dateStyle: "long" }
+ );
+ label = dateFormatter.format(this.mValue);
+ } else {
+ label = cal.l10n.getCalString("minimonthNoSelectedDate");
+ }
+ this.setAttribute("aria-label", label);
+ }
+
+ update(aValue) {
+ let changed = this.mValue && aValue && (
+ this.mValue.getFullYear() != aValue.getFullYear() ||
+ this.mValue.getMonth() != aValue.getMonth() ||
+ this.mValue.getDate() != aValue.getDate());
+
+ this.mValue = aValue;
+ if (changed) {
+ this.fireEvent("change");
+ }
+ this.showMonth(aValue);
+ if (aValue) {
+ this.setFocusedDate(aValue);
+ }
+ this.updateAccessibleLabel();
+ }
+
+ setFocusedDate(aDate, aForceFocus) {
+ let newFocused = this.getBoxForDate(
+ cal.dtz.jsDateToDateTime(aDate, cal.dtz.defaultTimezone)
+ );
+ if (!newFocused) {
+ return;
+ }
+ if (this.mFocused) {
+ this.mFocused.setAttribute("tabindex", "-1");
+ }
+ this.mFocused = newFocused;
+ this.mFocused.setAttribute("tabindex", "0");
+ // Only actually move the focus if it is already in the calendar box.
+ if (!aForceFocus) {
+ let calbox = this.querySelector(".minimonth-calendar");
+ aForceFocus = calbox.contains(document.commandDispatcher.focusedElement);
+ }
+ if (aForceFocus) {
+ this.mFocused.focus();
+ }
+ }
+
+ focusDate(aDate) {
+ this.showMonth(aDate);
+ this.setFocusedDate(aDate);
+ }
+
+ switchMonth(aMonth) {
+ let newMonth = new Date(this.mEditorDate);
+ newMonth.setMonth(aMonth);
+ this.showMonth(newMonth);
+ }
+
+ switchYear(aYear) {
+ let newMonth = new Date(this.mEditorDate);
+ newMonth.setFullYear(aYear);
+ this.showMonth(newMonth);
+ }
+
+ selectDate(aDate, aMainDate) {
+ if (!aMainDate ||
+ aDate < this._getStartDate(aMainDate) ||
+ aDate > this._getEndDate(aMainDate)) {
+ aMainDate = new Date(aDate);
+ aMainDate.setDate(1);
+ }
+ // Note that aMainDate and this.mEditorDate refer to the first day
+ // of the corresponding month.
+ let sameMonth = this._sameDay(aMainDate, this.mEditorDate);
+ let sameDate = this._sameDay(aDate, this.mValue);
+ if (!sameMonth && !sameDate) {
+ // Change month and select day.
+ this.mValue = aDate;
+ this.showMonth(aMainDate);
+ } else if (!sameMonth) {
+ // Change month only.
+ this.showMonth(aMainDate);
+ } else if (!sameDate) {
+ // Select day only.
+ let day = this.getBoxForDate(
+ cal.dtz.jsDateToDateTime(aDate, cal.dtz.defaultTimezone)
+ );
+ if (this.mSelected) {
+ this.mSelected.removeAttribute("selected");
+ }
+ this.mSelected = day;
+ day.setAttribute("selected", "true");
+ this.mValue = aDate;
+ this.setFocusedDate(aDate);
+ }
+ }
+
+ _getStartDate(aMainDate) {
+ let date = new Date(aMainDate);
+ let firstWeekday = (7 + aMainDate.getDay() - this.weekStart) % 7;
+ date.setDate(date.getDate() - firstWeekday);
+ return date;
+ }
+
+ _getEndDate(aMainDate) {
+ let date = this._getStartDate(aMainDate);
+ let calbox = this.querySelector(".minimonth-calendar");
+ let days = (calbox.childNodes.length - 1) * 7;
+ date.setDate(date.getDate() + days - 1);
+ return date;
+ }
+
+ _sameDay(aDate1, aDate2) {
+ if (aDate1 && aDate2 &&
+ (aDate1.getDate() == aDate2.getDate()) &&
+ (aDate1.getMonth() == aDate2.getMonth()) &&
+ (aDate1.getFullYear() == aDate2.getFullYear())) {
+ return true;
+ }
+ return false;
+ }
+
+ advanceMonth(aDir) {
+ let advEditorDate = new Date(this.mEditorDate); // At 1st of month.
+ let advMonth = this.mEditorDate.getMonth() + aDir;
+ advEditorDate.setMonth(advMonth);
+ this.showMonth(advEditorDate);
+ }
+
+ advanceYear(aDir) {
+ let advEditorDate = new Date(this.mEditorDate); // At 1st of month.
+ let advYear = this.mEditorDate.getFullYear() + aDir;
+ advEditorDate.setFullYear(advYear);
+ this.showMonth(advEditorDate);
+ }
+
+ moveDateByOffset(aYears, aMonths, aDays) {
+ const date = new Date(
+ this.mFocused.date.getFullYear() + aYears,
+ this.mFocused.date.getMonth() + aMonths,
+ this.mFocused.date.getDate() + aDays
+ );
+ this.focusDate(date);
+ }
+
+ focusCalendar() {
+ this.mFocused.focus();
+ }
+
+ onDayActivate(aEvent) {
+ // The associated date might change when setting this.value if month changes.
+ const date = aEvent.originalTarget.date;
+ if (this.getAttribute("readonly") != "true") {
+ this.value = date;
+ this.fireEvent("select");
+ }
+ this.setFocusedDate(date, true);
+ }
+
+ disconnectedCallback() {
+ if (this.mObservesComposite) {
+ cal.view.getCompositeCalendar(window).removeObserver(this.calICompositeObserver);
+ }
+
+ // Remove pref observer.
+ Services.prefs.getBranch("").removeObserver("calendar.", this.nsIObserver);
+ }
+ }
+
+ MozXULElement.implementCustomInterface(CalendarMinimonth, [
+ // Ci.calIObserver is omitted since it is not used like the others are.
+ Ci.calICompositeObserver,
+ Ci.calIOperationListener,
+ Ci.nsIObserver
+ ]);
+ customElements.define("calendar-minimonth", CalendarMinimonth);
+}
diff --git a/calendar/base/content/widgets/calendar-widget-bindings.css b/calendar/base/content/widgets/calendar-widget-bindings.css
index dd1a2f8de9..efee4e857c 100644
--- a/calendar/base/content/widgets/calendar-widget-bindings.css
+++ b/calendar/base/content/widgets/calendar-widget-bindings.css
@@ -13,14 +13,6 @@ modevbox {
-moz-box-orient: vertical;
}
-minimonth {
- -moz-binding: url("chrome://calendar/content/widgets/minimonth.xml#minimonth");
-}
-
-minimonth-header {
- -moz-binding: url("chrome://calendar/content/widgets/minimonth.xml#minimonth-header");
-}
-
dragndropContainer {
-moz-binding: url(chrome://calendar/content/widgets/calendar-widgets.xml#dragndropContainer);
}
diff --git a/calendar/base/content/widgets/minimonth.xml b/calendar/base/content/widgets/minimonth.xml
deleted file mode 100644
index e46ba370cb..0000000000
--- a/calendar/base/content/widgets/minimonth.xml
+++ /dev/null
@@ -1,1176 +0,0 @@
-
-
-
-
-
-
-
- %dtd1;
- %dtd2;
-]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- null
- null
- null
- null
- 0
- false
- false
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 0) {
- let calChunks = busyStr.split("\u001A");
- for (let chunk of calChunks) {
- let expr = chunk.split("=");
- boxBusy[expr[0]] = parseInt(expr[1], 10);
- }
- }
-
- return boxBusy;
- ]]>
-
-
-
-
-
- 0) {
- let busyStr = calChunks.join("\u001A");
- aBox.setAttribute("busy", busyStr);
- } else {
- aBox.removeAttribute("busy");
- }
- ]]>
-
-
-
-
-
-
-
-
-
-
-
- 0) {
- end = this.lastDate.clone();
- end.day++;
- }
-
- // We need to compare with midnight of the current day, so reset the
- // time here.
- let current = start.clone().getInTimezone(cal.dtz.defaultTimezone);
- current.hour = 0;
- current.minute = 0;
- current.second = 0;
-
- // Cache the result so the compare isn't called in each iteration.
- let compareResult = (start.compare(end) == 0 ? 1 : 0);
-
- // Setup the busy days.
- while (current.compare(end) < compareResult) {
- let box = this.getBoxForDate(current);
- if (box) {
- let busyCalendars = this.parseBoxBusy(box);
- if (!busyCalendars[aOccurrence.calendar.id]) {
- busyCalendars[aOccurrence.calendar.id] = 0;
- }
- busyCalendars[aOccurrence.calendar.id] += (aState ? 1 : -1);
- this.updateBoxBusy(box, busyCalendars);
- }
- current.day++;
- }
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- dayAbbr.length > 2)) {
- for (let endPrefix = 0; endPrefix < minLength; endPrefix++) {
- let suffix = dayList[0][endPrefix];
- if (dayList.some(dayAbbr => dayAbbr[endPrefix] != suffix)) {
- if (endPrefix > 0) {
- for (i = 0; i < dayList.length; i++) { // trim prefix chars.
- dayList[i] = dayList[i].substring(endPrefix);
- }
- }
- break;
- }
- }
- }
- // 3. trim each day abbreviation to 1 char if unique, else 2 chars.
- for (i = 0; i < dayList.length; i++) {
- let foundMatch = 1;
- for (j = 0; j < dayList.length; j++) {
- if (i != j) {
- if (dayList[i].substring(0, 1) == dayList[j].substring(0, 1)) {
- foundMatch = 2;
- break;
- }
- }
- }
- dayList[i] = dayList[i].substring(0, foundMatch);
- }
- }
-
- setBooleanAttribute(this._getCalBoxNode(0, 0), "hidden", !this.mShowWeekNumber);
- for (let column = 1; column < 8; column++) {
- let node = this._getCalBoxNode(0, column);
- node.textContent = dayList[column - 1];
- node.setAttribute("aria-label", longDayList[column - 1]);
- }
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- allowedAttributes) {
- switch (aBox.attributes[allowedAttributes].nodeName) {
- case "selected":
- case "othermonth":
- case "today":
- case "extra":
- case "interactive":
- case "class":
- case "tabindex":
- case "role":
- case "aria-label":
- allowedAttributes++;
- break;
- default:
- aBox.removeAttribute(aBox.attributes[allowedAttributes].nodeName);
- break;
- }
- }
- }
-
- if (aDate) {
- let box = this.getBoxForDate(cal.dtz.jsDateToDateTime(aDate, cal.dtz.defaultTimezone));
- if (box) {
- removeForBox(box);
- }
- } else {
- for (let k = 1; k < 7; k++) {
- for (let i = 1; i < 8; i++) {
- removeForBox(this._getCalBoxNode(k, i));
- }
- }
- }
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- this._getEndDate(aMainDate)) {
- aMainDate = new Date(aDate);
- aMainDate.setDate(1);
- }
- // note, that aMainDate and this.mEditorDate refer to the first day
- // of the corresponding month
- let sameMonth = this._sameDay(aMainDate, this.mEditorDate);
- let sameDate = this._sameDay(aDate, this.mValue);
- if (!sameMonth && !sameDate) {
- // change month and select day
- this.mValue = aDate;
- this.showMonth(aMainDate);
- } else if (!sameMonth) {
- // change month only
- this.showMonth(aMainDate);
- } else if (!sameDate) {
- // select day only
- let day = this.getBoxForDate(cal.dtz.jsDateToDateTime(aDate, cal.dtz.defaultTimezone));
- if (this.mSelected) {
- this.mSelected.removeAttribute("selected");
- }
- this.mSelected = day;
- day.setAttribute("selected", "true");
- this.mValue = aDate;
- this.setFocusedDate(aDate);
- }
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 0 ? 1 : -1;
- }
- } else if (event.deltaMode == event.DOM_DELTA_PIXEL) {
- this.mPixelScrollDelta += event.deltaY;
- if (this.mPixelScrollDelta > pixelThreshold) {
- deltaView = 1;
- this.mPixelScrollDelta = 0;
- } else if (this.mPixelScrollDelta < -pixelThreshold) {
- deltaView = -1;
- this.mPixelScrollDelta = 0;
- }
- }
-
- if (deltaView != 0) {
- switch (event.originalTarget.getAttribute("anonid")) {
- case "today-button":
- break;
- case "years-forward-button":
- case "yearcell":
- case "years-back-button":
- this.advanceYear(deltaView);
- break;
- default:
- this.advanceMonth(deltaView);
- break;
- }
- }
-
- event.stopPropagation();
- event.preventDefault();
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/calendar/base/jar.mn b/calendar/base/jar.mn
index 95d2b36dd0..fd55a10ced 100644
--- a/calendar/base/jar.mn
+++ b/calendar/base/jar.mn
@@ -92,8 +92,8 @@ calendar.jar:
content/calendar/preferences/editCategory.js (content/preferences/editCategory.js)
content/calendar/preferences/general.js (content/preferences/general.js)
content/calendar/preferences/views.js (content/preferences/views.js)
- content/calendar/widgets/minimonth.xml (content/widgets/minimonth.xml)
content/calendar/widgets/calendar-alarm-widget.js (content/widgets/calendar-alarm-widget.js)
+ content/calendar/widgets/calendar-minimonth.js (content/widgets/calendar-minimonth.js)
content/calendar/widgets/calendar-widgets.xml (content/widgets/calendar-widgets.xml)
content/calendar/widgets/calendar-list-tree.js (content/widgets/calendar-list-tree.js)
content/calendar/calendar-subscriptions-list.js (content/widgets/calendar-subscriptions-list.js)
diff --git a/calendar/base/themes/common/widgets/minimonth.css b/calendar/base/themes/common/widgets/minimonth.css
index d81e8075ec..a0e7817cde 100644
--- a/calendar/base/themes/common/widgets/minimonth.css
+++ b/calendar/base/themes/common/widgets/minimonth.css
@@ -2,7 +2,7 @@
* 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/. */
-minimonth {
+calendar-minimonth {
--mmMainColor: WindowText;
--mmMainBackground: #fff;
--mmHighlightColor: HighlightText;
@@ -24,7 +24,7 @@ minimonth {
--mmDaySelectedTodayBorderColor: #67acd8;
}
-:root[systemcolors] minimonth {
+:root[systemcolors] calendar-minimonth {
--mmMainBackground: -moz-field;
--mmBoxBackground: -moz-Dialog;
--mmBoxBorderColor: ThreeDShadow;
@@ -42,7 +42,7 @@ minimonth {
--mmDaySelectedTodayBorderColor: ButtonFace;
}
-minimonth {
+calendar-minimonth {
background-color: var(--mmMainBackground);
border-width: 0;
color: var(--mmMainColor);
@@ -50,11 +50,17 @@ minimonth {
min-width: 175px;
}
-minimonth:not([readonly="true"]) [anonid="minimonth-readonly-header"],
-minimonth[readonly="true"] [anonid="minimonth-header"] {
+calendar-minimonth:not([readonly="true"]) .minimonth-readonly-header,
+calendar-minimonth[readonly="true"] .minimonth-header {
display: none;
}
+calendar-minimonth[readonly="true"] .minimonth-readonly-header {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
.minimonth-month-box {
background-color: var(--mmBoxBackground);
border: 1px dotted var(--mmBoxBorderColor);
diff --git a/calendar/lightning/content/lightning-item-iframe.xul b/calendar/lightning/content/lightning-item-iframe.xul
index 0a15e17c72..e7b4952b6c 100755
--- a/calendar/lightning/content/lightning-item-iframe.xul
+++ b/calendar/lightning/content/lightning-item-iframe.xul
@@ -48,6 +48,7 @@
+
diff --git a/calendar/lightning/content/messenger-overlay-sidebar.xul b/calendar/lightning/content/messenger-overlay-sidebar.xul
index f948882a5c..7051d442a9 100644
--- a/calendar/lightning/content/messenger-overlay-sidebar.xul
+++ b/calendar/lightning/content/messenger-overlay-sidebar.xul
@@ -60,6 +60,7 @@
+
@@ -204,7 +205,7 @@
-
+
diff --git a/calendar/resources/content/datetimepickers/datetimepickers.js b/calendar/resources/content/datetimepickers/datetimepickers.js
index f71960c38a..f7c22cbd89 100644
--- a/calendar/resources/content/datetimepickers/datetimepickers.js
+++ b/calendar/resources/content/datetimepickers/datetimepickers.js
@@ -747,7 +747,7 @@
this._menulist = this.querySelector(".datepicker-menulist");
this._inputField = this._menulist._inputField;
this._popup = this._menulist.menupopup;
- this._minimonth = this.querySelector("minimonth");
+ this._minimonth = this.querySelector("calendar-minimonth");
if (this.getAttribute("type") == "forever") {
this._valueIsForever = false;
@@ -799,9 +799,7 @@
});
this._popup.addEventListener("popupshown", () => {
this._minimonth.focusDate(this._minimonthValue);
- let calendar = document.getAnonymousElementByAttribute(
- this._minimonth, "anonid", "minimonth-calendar"
- );
+ const calendar = this._minimonth.querySelector(".minimonth-calendar");
calendar.querySelector("td[selected]").focus();
});
this._minimonth.addEventListener("change", (event) => {
@@ -838,7 +836,7 @@
let frag = document.importNode(MozXULElement.parseXULToFragment(`
`), true);
diff --git a/calendar/test/mozmill/cal-recurrence/testAnnualRecurrence.js b/calendar/test/mozmill/cal-recurrence/testAnnualRecurrence.js
index dee9ef52e1..ca0ca2510f 100755
--- a/calendar/test/mozmill/cal-recurrence/testAnnualRecurrence.js
+++ b/calendar/test/mozmill/cal-recurrence/testAnnualRecurrence.js
@@ -71,12 +71,13 @@ function testAnnualRecurrence() {
}
// Delete event.
- goToDate(controller, checkYears[0], 1, 1);
switchToView(controller, "day");
- let box = getEventBoxPath("day", ALLDAY, null, 1, null) + EVENTPATH;
- controller.click(lookup(box));
- handleOccurrencePrompt(controller, eid("day-view"), "delete", true);
- controller.waitForElementNotPresent(lookup(box));
+ goToDate(controller, checkYears[0], 1, 1);
+ const boxPath = getEventBoxPath("day", ALLDAY, null, 1, null) + EVENTPATH;
+ const box = lookup(boxPath);
+ controller.click(box);
+ handleOccurrencePrompt(controller, box, "delete", true);
+ controller.waitForElementNotPresent(box);
}
function teardownTest(module) {
diff --git a/calendar/test/mozmill/cal-recurrence/testBiweeklyRecurrence.js b/calendar/test/mozmill/cal-recurrence/testBiweeklyRecurrence.js
index c95e4b3973..5a7b96d2e5 100755
--- a/calendar/test/mozmill/cal-recurrence/testBiweeklyRecurrence.js
+++ b/calendar/test/mozmill/cal-recurrence/testBiweeklyRecurrence.js
@@ -98,7 +98,7 @@ function testBiweeklyRecurrence() {
// Delete event.
let box = lookupEventBox("month", EVENT_BOX, 4, 7, null, EVENTPATH);
controller.click(box);
- handleOccurrencePrompt(controller, eid("month-view"), "delete", true);
+ handleOccurrencePrompt(controller, box, "delete", true);
controller.waitForElementNotPresent(box);
}
diff --git a/calendar/test/mozmill/cal-recurrence/testDailyRecurrence.js b/calendar/test/mozmill/cal-recurrence/testDailyRecurrence.js
index fd5587b24c..80bf9d7b44 100755
--- a/calendar/test/mozmill/cal-recurrence/testDailyRecurrence.js
+++ b/calendar/test/mozmill/cal-recurrence/testDailyRecurrence.js
@@ -109,7 +109,7 @@ function testDailyRecurrence() {
// Delete 3rd January occurrence.
let saturday = lookupEventBox("month", EVENT_BOX, 1, 7, null, EVENTPATH);
controller.click(saturday);
- handleOccurrencePrompt(controller, eid("month-view"), "delete", false);
+ handleOccurrencePrompt(controller, saturday, "delete", false);
// Verify in all views.
controller.waitForElementNotPresent(saturday);
@@ -186,7 +186,7 @@ function testDailyRecurrence() {
// Delete event.
day = lookupEventBox("month", EVENT_BOX, 1, 5, null, EVENTPATH);
controller.click(day);
- handleOccurrencePrompt(controller, eid("month-view"), "delete", true);
+ handleOccurrencePrompt(controller, day, "delete", true);
controller.waitForElementNotPresent(day);
}
diff --git a/calendar/test/mozmill/cal-recurrence/testLastDayOfMonthRecurrence.js b/calendar/test/mozmill/cal-recurrence/testLastDayOfMonthRecurrence.js
index 10777153ed..5fdc0ccd3a 100755
--- a/calendar/test/mozmill/cal-recurrence/testLastDayOfMonthRecurrence.js
+++ b/calendar/test/mozmill/cal-recurrence/testLastDayOfMonthRecurrence.js
@@ -110,7 +110,7 @@ function testLastDayOfMonthRecurrence() {
switchToView(controller, "day");
let box = lookupEventBox("day", EVENT_BOX, null, 1, null, EVENTPATH);
controller.waitThenClick(box);
- handleOccurrencePrompt(controller, eid("day-view"), "delete", true);
+ handleOccurrencePrompt(controller, box, "delete", true);
controller.waitForElementNotPresent(box);
}
diff --git a/calendar/test/mozmill/cal-recurrence/testWeeklyUntilRecurrence.js b/calendar/test/mozmill/cal-recurrence/testWeeklyUntilRecurrence.js
index 8a0c92ea5c..995b2eafba 100755
--- a/calendar/test/mozmill/cal-recurrence/testWeeklyUntilRecurrence.js
+++ b/calendar/test/mozmill/cal-recurrence/testWeeklyUntilRecurrence.js
@@ -128,7 +128,7 @@ function testWeeklyUntilRecurrence() {
// Delete event.
box = lookupEventBox("month", EVENT_BOX, 2, 2, null, EVENTPATH);
controller.click(box);
- handleOccurrencePrompt(controller, eid("month-view"), "delete", true);
+ handleOccurrencePrompt(controller, box, "delete", true);
controller.waitForElementNotPresent(box);
}
diff --git a/calendar/test/mozmill/cal-recurrence/testWeeklyWithExceptionRecurrence.js b/calendar/test/mozmill/cal-recurrence/testWeeklyWithExceptionRecurrence.js
index 39fa06ff69..861242acfe 100755
--- a/calendar/test/mozmill/cal-recurrence/testWeeklyWithExceptionRecurrence.js
+++ b/calendar/test/mozmill/cal-recurrence/testWeeklyWithExceptionRecurrence.js
@@ -193,7 +193,7 @@ function testWeeklyWithExceptionRecurrence() {
goToDate(controller, 2009, 1, 12);
path = lookupEventBox("day", EVENT_BOX, null, 1, null, EVENTPATH);
controller.click(path);
- handleOccurrencePrompt(controller, eid("day-view"), "delete", true);
+ handleOccurrencePrompt(controller, path, "delete", true);
controller.waitForElementNotPresent(path);
}
diff --git a/calendar/test/mozmill/recurrenceRotated/testAnnualRecurrence.js b/calendar/test/mozmill/recurrenceRotated/testAnnualRecurrence.js
index e956533e5b..b50d664571 100755
--- a/calendar/test/mozmill/recurrenceRotated/testAnnualRecurrence.js
+++ b/calendar/test/mozmill/recurrenceRotated/testAnnualRecurrence.js
@@ -76,10 +76,11 @@ function testAnnualRecurrence() {
// Delete event.
goToDate(controller, checkYears[0], 1, 1);
switchToView(controller, "day");
- let box = getEventBoxPath("day", ALLDAY, null, 1, null) + EVENTPATH;
- controller.click(lookup(box));
- handleOccurrencePrompt(controller, eid("day-view"), "delete", true);
- controller.waitForElementNotPresent(lookup(box));
+ const boxPath = getEventBoxPath("day", ALLDAY, null, 1, null) + EVENTPATH;
+ const box = lookup(boxPath);
+ controller.click(box);
+ handleOccurrencePrompt(controller, box, "delete", true);
+ controller.waitForElementNotPresent(box);
}
function teardownTest(module) {
diff --git a/calendar/test/mozmill/recurrenceRotated/testBiweeklyRecurrence.js b/calendar/test/mozmill/recurrenceRotated/testBiweeklyRecurrence.js
index 5fa0dc42fb..a1d85b6ced 100755
--- a/calendar/test/mozmill/recurrenceRotated/testBiweeklyRecurrence.js
+++ b/calendar/test/mozmill/recurrenceRotated/testBiweeklyRecurrence.js
@@ -52,6 +52,7 @@ function testBiweeklyRecurrence() {
});
// Check day view.
+ switchToView(controller, "day");
for (let i = 0; i < 4; i++) {
controller.waitForElement(lookupEventBox("day", EVENT_BOX, null, 1, null, EVENTPATH));
viewForward(controller, 14);
@@ -101,7 +102,7 @@ function testBiweeklyRecurrence() {
// Delete event.
let box = lookupEventBox("month", EVENT_BOX, 4, 7, null, EVENTPATH);
controller.click(box);
- handleOccurrencePrompt(controller, eid("month-view"), "delete", true);
+ handleOccurrencePrompt(controller, box, "delete", true);
controller.waitForElementNotPresent(box);
}
diff --git a/calendar/test/mozmill/recurrenceRotated/testDailyRecurrence.js b/calendar/test/mozmill/recurrenceRotated/testDailyRecurrence.js
index d3424a2a18..78b84a23c8 100755
--- a/calendar/test/mozmill/recurrenceRotated/testDailyRecurrence.js
+++ b/calendar/test/mozmill/recurrenceRotated/testDailyRecurrence.js
@@ -113,7 +113,7 @@ function testDailyRecurrence() {
// Delete 3rd January occurrence.
let saturday = lookupEventBox("month", EVENT_BOX, 1, 7, null, EVENTPATH);
controller.click(saturday);
- handleOccurrencePrompt(controller, eid("month-view"), "delete", false);
+ handleOccurrencePrompt(controller, saturday, "delete", false);
// Verify in all views.
controller.waitForElementNotPresent(saturday);
@@ -190,7 +190,7 @@ function testDailyRecurrence() {
// Delete event.
day = lookupEventBox("month", EVENT_BOX, 1, 5, null, EVENTPATH);
controller.click(day);
- handleOccurrencePrompt(controller, eid("month-view"), "delete", true);
+ handleOccurrencePrompt(controller, day, "delete", true);
controller.waitForElementNotPresent(day);
}
diff --git a/calendar/test/mozmill/recurrenceRotated/testLastDayOfMonthRecurrence.js b/calendar/test/mozmill/recurrenceRotated/testLastDayOfMonthRecurrence.js
index 77bd30869d..a313ef29c1 100755
--- a/calendar/test/mozmill/recurrenceRotated/testLastDayOfMonthRecurrence.js
+++ b/calendar/test/mozmill/recurrenceRotated/testLastDayOfMonthRecurrence.js
@@ -44,6 +44,7 @@ function setupModule(module) {
createCalendar(controller, CALENDARNAME);
// Rotate view.
+ switchToView(controller, "day");
controller.mainMenu.click("#ltnViewRotated");
controller.waitFor(() => eid("day-view").getNode().orient == "horizontal");
}
@@ -113,7 +114,7 @@ function testLastDayOfMonthRecurrence() {
switchToView(controller, "day");
let box = lookupEventBox("day", EVENT_BOX, null, 1, null, EVENTPATH);
controller.waitThenClick(box);
- handleOccurrencePrompt(controller, eid("day-view"), "delete", true);
+ handleOccurrencePrompt(controller, box, "delete", true);
controller.waitForElementNotPresent(box);
}
diff --git a/calendar/test/mozmill/recurrenceRotated/testWeeklyUntilRecurrence.js b/calendar/test/mozmill/recurrenceRotated/testWeeklyUntilRecurrence.js
index d545443a6c..e06844744f 100755
--- a/calendar/test/mozmill/recurrenceRotated/testWeeklyUntilRecurrence.js
+++ b/calendar/test/mozmill/recurrenceRotated/testWeeklyUntilRecurrence.js
@@ -131,7 +131,7 @@ function testWeeklyUntilRecurrence() {
// Delete event.
box = lookupEventBox("month", EVENT_BOX, 2, 2, null, EVENTPATH);
controller.click(box);
- handleOccurrencePrompt(controller, eid("month-view"), "delete", true);
+ handleOccurrencePrompt(controller, box, "delete", true);
controller.waitForElementNotPresent(box);
}
diff --git a/calendar/test/mozmill/recurrenceRotated/testWeeklyWithExceptionRecurrence.js b/calendar/test/mozmill/recurrenceRotated/testWeeklyWithExceptionRecurrence.js
index 995768d2f8..6d90b69425 100755
--- a/calendar/test/mozmill/recurrenceRotated/testWeeklyWithExceptionRecurrence.js
+++ b/calendar/test/mozmill/recurrenceRotated/testWeeklyWithExceptionRecurrence.js
@@ -196,7 +196,7 @@ function testWeeklyWithExceptionRecurrence() {
goToDate(controller, 2009, 1, 12);
path = lookupEventBox("day", EVENT_BOX, null, 1, null, EVENTPATH);
controller.click(path);
- handleOccurrencePrompt(controller, eid("day-view"), "delete", true);
+ handleOccurrencePrompt(controller, path, "delete", true);
controller.waitForElementNotPresent(path);
}
diff --git a/calendar/test/mozmill/shared-modules/test-calendar-utils.js b/calendar/test/mozmill/shared-modules/test-calendar-utils.js
index 06c7ba2294..a3a5212eaa 100755
--- a/calendar/test/mozmill/shared-modules/test-calendar-utils.js
+++ b/calendar/test/mozmill/shared-modules/test-calendar-utils.js
@@ -47,7 +47,8 @@ var MINIMONTH = `
id("calMinimonthBox")/id("calMinimonth")
`;
var TODAY_BUTTON = `
- ${MINIMONTH}/anon({"anonid":"minimonth-header"})/anon({"anonid":"today-button"})
+ ${MINIMONTH}/{"class":"minimonth-header minimonth-month-box"}/
+ {"class":"today-button minimonth-nav-btns"}
`;
var CALENDARLIST = `
${CALENDAR_PANEL}/id("ltnSidebar")/id("calendar-panel")/id("calendar-list-pane")/
@@ -226,20 +227,25 @@ function goToDate(controller, year, month, day) {
let { lookup } = helpersForController(controller);
let activeYear = lookup(`
- ${MINIMONTH}/anon({"anonid":"minimonth-header"})/anon({"anonid":"yearcell"})
+ ${MINIMONTH}/{"class":"minimonth-header minimonth-month-box"}/
+ {"class":"yearcell minimonth-year-name"}
`).getNode().getAttribute("value");
let activeMonth = lookup(`
- ${MINIMONTH}/anon({"anonid":"minimonth-header"})/anon({"anonid":"monthheader"})
+ ${MINIMONTH}/{"class":"minimonth-header minimonth-month-box"}/
+ {"class":"monthheader minimonth-month-name"}
`).getNode().getAttribute("selectedIndex");
let yearDifference = activeYear - year;
let monthDifference = activeMonth - (month - 1);
if (yearDifference != 0) {
- let scrollArrow = (yearDifference > 0) ? "years-back-button" : "years-forward-button";
+ let scrollArrow = (yearDifference > 0)
+ ? "years-back-button minimonth-nav-btns"
+ : "years-forward-button minimonth-nav-btns";
scrollArrow = lookup(
- `${MINIMONTH}/anon({"anonid":"minimonth-header"})/anon({"anonid":"${scrollArrow}"})`
+ `${MINIMONTH}/{"class":"minimonth-header minimonth-month-box"}/
+ {"class":"${scrollArrow}"}`
);
controller.waitForElement(scrollArrow);
@@ -252,9 +258,12 @@ function goToDate(controller, year, month, day) {
}
if (monthDifference != 0) {
- let scrollArrow = (monthDifference > 0) ? "months-back-button" : "months-forward-button";
+ let scrollArrow = (monthDifference > 0)
+ ? "months-back-button minimonth-nav-btns"
+ : "months-forward-button minimonth-nav-btns";
scrollArrow = lookup(
- `${MINIMONTH}/anon({"anonid":"minimonth-header"})/anon({"anonid":"${scrollArrow}"})`
+ `${MINIMONTH}/{"class":"minimonth-header minimonth-month-box"}/
+ {"class":"${scrollArrow}"}`
);
controller.waitForElement(scrollArrow);
@@ -267,7 +276,7 @@ function goToDate(controller, year, month, day) {
}
let lastDayInFirstRow = lookup(`
- ${MINIMONTH}/anon({"anonid":"minimonth-calendar"})/[3]/[15]
+ ${MINIMONTH}/{"class":"minimonth-calendar minimonth-cal-box"}/[1]/[7]
`).getNode().innerHTML;
let positionOfFirst = 7 - lastDayInFirstRow;
@@ -276,8 +285,8 @@ function goToDate(controller, year, month, day) {
// Pick day.
controller.click(lookup(`
- ${MINIMONTH}/anon({"anonid":"minimonth-calendar"})/[${(dateRow + 1) * 2 + 1}]/
- [${(dateColumn + 1) * 2 + 1}]
+ ${MINIMONTH}/{"class":"minimonth-calendar minimonth-cal-box"}/
+ [${dateRow + 1}]/[${dateColumn + 1}]
`));
ensureViewLoaded(controller);
}
diff --git a/calendar/test/mozmill/testBasicFunctionality.js b/calendar/test/mozmill/testBasicFunctionality.js
index 598c4d6e1b..128e29d47f 100755
--- a/calendar/test/mozmill/testBasicFunctionality.js
+++ b/calendar/test/mozmill/testBasicFunctionality.js
@@ -40,7 +40,7 @@ function testSmokeTest() {
controller.waitForElement(eid("calMinimonth"));
// Every month has a first.
controller.assertNode(lookup(`
- ${MINIMONTH}/anon({"anonid":"minimonth-calendar"})/[3]/{"aria-label":"1"}
+ ${MINIMONTH}/{"class":"minimonth-calendar minimonth-cal-box"}/[1]/{"aria-label":"1"}
`));
// Check for calendar list.
diff --git a/calendar/test/mozmill/views/testMonthView.js b/calendar/test/mozmill/views/testMonthView.js
index 5cee66ff81..845b9593e8 100755
--- a/calendar/test/mozmill/views/testMonthView.js
+++ b/calendar/test/mozmill/views/testMonthView.js
@@ -111,7 +111,7 @@ function testMonthView() {
// Delete event.
controller.click(eventBox);
- controller.keypress(eid("month-view"), "VK_DELETE", {});
+ controller.keypress(eventBox, "VK_DELETE", {});
controller.waitForElementNotPresent(eventBox);
}
diff --git a/calendar/test/mozmill/views/testMultiweekView.js b/calendar/test/mozmill/views/testMultiweekView.js
index 90241f3c84..ad9062713a 100755
--- a/calendar/test/mozmill/views/testMultiweekView.js
+++ b/calendar/test/mozmill/views/testMultiweekView.js
@@ -112,7 +112,7 @@ function testMultiWeekView() {
// Delete event.
controller.click(eventBox);
- controller.keypress(eid("multiweek-view"), "VK_DELETE", {});
+ controller.keypress(eventBox, "VK_DELETE", {});
controller.waitForElementNotPresent(eventBox);
}