connectedCallback()

in calendar/base/content/widgets/calendar-minimonth.js [68:297]


    connectedCallback() {
      if (this.delayConnectedCallback() || this.hasChildNodes()) {
        return;
      }

      MozXULElement.insertFTLIfNeeded("calendar/calendar-widgets.ftl");
      MozXULElement.insertFTLIfNeeded("calendar/calendar.ftl");

      const minimonthHeader = `
        <html:div class="minimonth-header minimonth-month-box"
                  xmlns="http://www.w3.org/1999/xhtml">
          <div class="minimonth-nav-section">
            <button class="button icon-button icon-only minimonth-nav-btn today-button"
                    data-l10n-id="calendar-today-button-tooltip"
                    type="button"
                    dir="0">
            </button>
          </div>
          <div class="minimonth-nav-section">
            <button class="button icon-button icon-only minimonth-nav-btn months-back-button"
                    data-l10n-id="calendar-nav-button-prev-tooltip-month"
                    type="button"
                    dir="-1">
            </button>
            <div class="minimonth-nav-item">
              <input class="minimonth-month-name" tabindex="-1" readonly="true" disabled="disabled" />
            </div>
            <button class="button icon-button icon-only minimonth-nav-btn months-forward-button"
                    data-l10n-id="calendar-nav-button-next-tooltip-month"
                    type="button"
                    dir="1">
            </button>
          </div>
          <div class="minimonth-nav-section">
            <button class="button icon-button icon-only minimonth-nav-btn years-back-button"
                    data-l10n-id="calendar-nav-button-prev-tooltip-year"
                    type="button"
                    dir="-1">
            </button>
            <div class="minimonth-nav-item">
              <input class="yearcell minimonth-year-name" tabindex="-1" readonly="true" disabled="disabled" />
            </div>
            <button class="button icon-button icon-only minimonth-nav-btn years-forward-button"
                    data-l10n-id="calendar-nav-button-next-tooltip-year"
                    type="button"
                    dir="1">
            </button>
          </div>
        </html:div>
      `;

      const minimonthWeekRow = `
        <html:tr class="minimonth-row-body">
          <html:th class="minimonth-week" scope="row"></html:th>
          <html:td class="minimonth-day" tabindex="-1"></html:td>
          <html:td class="minimonth-day" tabindex="-1"></html:td>
          <html:td class="minimonth-day" tabindex="-1"></html:td>
          <html:td class="minimonth-day" tabindex="-1"></html:td>
          <html:td class="minimonth-day" tabindex="-1"></html:td>
          <html:td class="minimonth-day" tabindex="-1"></html:td>
          <html:td class="minimonth-day" tabindex="-1"></html:td>
        </html:tr>
      `;

      this.appendChild(
        MozXULElement.parseXULToFragment(
          `
          ${minimonthHeader}
          <html:div class="minimonth-readonly-header minimonth-month-box"></html:div>
          <html:table class="minimonth-calendar minimonth-cal-box">
            <html:tr class="minimonth-row-head">
              <html:th class="minimonth-row-header-week" scope="col"></html:th>
              <html:th class="minimonth-row-header" scope="col"></html:th>
              <html:th class="minimonth-row-header" scope="col"></html:th>
              <html:th class="minimonth-row-header" scope="col"></html:th>
              <html:th class="minimonth-row-header" scope="col"></html:th>
              <html:th class="minimonth-row-header" scope="col"></html:th>
              <html:th class="minimonth-row-header" scope="col"></html:th>
              <html:th class="minimonth-row-header" scope="col"></html:th>
            </html:tr>
            ${minimonthWeekRow}
            ${minimonthWeekRow}
            ${minimonthWeekRow}
            ${minimonthWeekRow}
            ${minimonthWeekRow}
            ${minimonthWeekRow}
          </html:table>
          `,
          ["chrome://calendar/locale/global.dtd"]
        )
      );
      this.initializeAttributeInheritance();
      this.setAttribute("orient", "vertical");

      // Set up header buttons.
      this.querySelector(".months-back-button").addEventListener("click", () =>
        this.advanceMonth(-1)
      );
      this.querySelector(".months-forward-button").addEventListener("click", () =>
        this.advanceMonth(1)
      );
      this.querySelector(".years-back-button").addEventListener("click", () =>
        this.advanceYear(-1)
      );
      this.querySelector(".years-forward-button").addEventListener("click", () =>
        this.advanceYear(1)
      );
      this.querySelector(".today-button").addEventListener("click", () => {
        this.value = new Date();
      });

      this.dayBoxes = new Map();
      this.mEditorDate = null;
      this.mExtraDate = null;
      this.mPixelScrollDelta = 0;
      this.mObservesComposite = false;
      this.mToday = null;
      this.mSelected = null;
      this.mExtra = null;
      this.mValue = new Date(); // Default to "today".
      this.mShowsToday = true;
      this.mFocused = null;

      const width = Math.max(...cal.dtz.formatter.monthNames.map(n => n.length));
      this.querySelector(".minimonth-month-name").style.width = `${width + 1}ch`;

      this.refreshDisplay();
      if (this.hasAttribute("freebusy")) {
        this._setFreeBusy(this.getAttribute("freebusy") == "true");
      }

      // Add event listeners.
      this.addEventListener("click", event => {
        if (event.button == 0 && event.target.classList.contains("minimonth-day")) {
          this.onDayActivate(event);
        }
      });

      this.addEventListener("keypress", event => {
        if (event.target.classList.contains("minimonth-day")) {
          if (event.altKey || event.metaKey) {
            return;
          }
          switch (event.keyCode) {
            case KeyEvent.DOM_VK_LEFT:
              this.onDayMovement(event, 0, 0, -1);
              break;
            case KeyEvent.DOM_VK_RIGHT:
              this.onDayMovement(event, 0, 0, 1);
              break;
            case KeyEvent.DOM_VK_UP:
              this.onDayMovement(event, 0, 0, -7);
              break;
            case KeyEvent.DOM_VK_DOWN:
              this.onDayMovement(event, 0, 0, 7);
              break;
            case KeyEvent.DOM_VK_PAGE_UP:
              if (event.shiftKey) {
                this.onDayMovement(event, -1, 0, 0);
              } else {
                this.onDayMovement(event, 0, -1, 0);
              }
              break;
            case KeyEvent.DOM_VK_PAGE_DOWN:
              if (event.shiftKey) {
                this.onDayMovement(event, 1, 0, 0);
              } else {
                this.onDayMovement(event, 0, 1, 0);
              }
              break;
            case KeyEvent.DOM_VK_ESCAPE:
              this.focusDate(this.mValue || this.mExtraDate);
              event.stopPropagation();
              event.preventDefault();
              break;
            case KeyEvent.DOM_VK_HOME: {
              const today = new Date();
              this.update(today);
              this.focusDate(today);
              event.stopPropagation();
              event.preventDefault();
              break;
            }
            case KeyEvent.DOM_VK_RETURN:
              this.onDayActivate(event);
              break;
          }
        }
      });

      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.target.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();
      });
    }