Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/toolkit/content/widgets/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 17 kB image not shown  

Quelle  datepicker.js   Sprache: JAVA

 
/* 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/. */


/* import-globals-from datekeeper.js */
/* import-globals-from calendar.js */
/* import-globals-from spinner.js */

"use strict";

function DatePicker(context) {
  this.context = context;
  this._attachEventListeners();
}

{
  const CAL_VIEW_SIZE = 42;

  DatePicker.prototype = {
    /**
     * Initializes the date picker. Set the default states and properties.
     * @param  {Object} props
     *         {
     *           {Number} year [optional]
     *           {Number} month [optional]
     *           {Number} date [optional]
     *           {Number} min
     *           {Number} max
     *           {Number} step
     *           {Number} stepBase
     *           {Number} firstDayOfWeek
     *           {Array<Number>} weekends
     *           {Array<String>} monthStrings
     *           {Array<String>} weekdayStrings
     *           {String} locale [optional]: User preferred locale
     *         }
     */

    init(props = {}) {
      this.props = props;
      this._setDefaultState();
      this._createComponents();
      this._update();
      this.components.calendar.focusDay();
      // TODO(bug 1828721): This is a bit sad.
      window.PICKER_READY = true;
      document.dispatchEvent(new CustomEvent("PickerReady"));
    },

    /*
     * Set initial date picker states.
     */

    _setDefaultState() {
      const {
        year,
        month,
        day,
        min,
        max,
        step,
        stepBase,
        firstDayOfWeek,
        weekends,
        monthStrings,
        weekdayStrings,
        locale,
        dir,
      } = this.props;
      const dateKeeper = new DateKeeper({
        year,
        month,
        day,
        min,
        max,
        step,
        stepBase,
        firstDayOfWeek,
        weekends,
        calViewSize: CAL_VIEW_SIZE,
      });

      document.dir = dir;

      this.state = {
        dateKeeper,
        locale,
        isMonthPickerVisible: false,
        datetimeOrders: new Intl.DateTimeFormat(locale)
          .formatToParts(new Date(0))
          .map(part => part.type),
        getDayString: day =>
          day ? new Intl.NumberFormat(locale).format(day) : "",
        getWeekHeaderString: weekday => weekdayStrings[weekday],
        getMonthString: month => monthStrings[month],
        setSelection: date => {
          dateKeeper.setSelection({
            year: date.getUTCFullYear(),
            month: date.getUTCMonth(),
            day: date.getUTCDate(),
          });
          this._update();
          this._dispatchState();
          this._closePopup();
        },
        setMonthByOffset: offset => {
          dateKeeper.setMonthByOffset(offset);
          this._update();
        },
        setYear: year => {
          dateKeeper.setYear(year);
          dateKeeper.setSelection({
            year,
            month: dateKeeper.selection.month,
            day: dateKeeper.selection.day,
          });
          this._update();
          this._dispatchState();
        },
        setMonth: month => {
          dateKeeper.setMonth(month);
          dateKeeper.setSelection({
            year: dateKeeper.selection.year,
            month,
            day: dateKeeper.selection.day,
          });
          this._update();
          this._dispatchState();
        },
        toggleMonthPicker: () => {
          this.state.isMonthPickerVisible = !this.state.isMonthPickerVisible;
          this._update();
        },
      };
    },

    /**
     * Initalize the date picker components.
     */

    _createComponents() {
      this.components = {
        calendar: new Calendar(
          {
            calViewSize: CAL_VIEW_SIZE,
            locale: this.state.locale,
            setSelection: this.state.setSelection,
            // Year and month could be changed without changing a selection
            setCalendarMonth: (year, month) => {
              this.state.dateKeeper.setCalendarMonth({
                year,
                month,
              });
              this._update();
            },
            getDayString: this.state.getDayString,
            getWeekHeaderString: this.state.getWeekHeaderString,
          },
          {
            weekHeader: this.context.weekHeader,
            daysView: this.context.daysView,
          }
        ),
        monthYear: new MonthYear(
          {
            setYear: this.state.setYear,
            setMonth: this.state.setMonth,
            getMonthString: this.state.getMonthString,
            datetimeOrders: this.state.datetimeOrders,
            locale: this.state.locale,
          },
          {
            monthYear: this.context.monthYear,
            monthYearView: this.context.monthYearView,
          }
        ),
      };
    },

    /**
     * Update date picker and its components.
     */

    _update(options = {}) {
      const { dateKeeper, isMonthPickerVisible } = this.state;

      const calendarEls = [
        this.context.buttonPrev,
        this.context.buttonNext,
        this.context.weekHeader.parentNode,
        this.context.buttonClear,
      ];
      // Update MonthYear state and toggle visibility for sighted users
      // and for assistive technology:
      this.context.monthYearView.hidden = !isMonthPickerVisible;
      for (let el of calendarEls) {
        el.hidden = isMonthPickerVisible;
      }
      this.context.monthYearNav.toggleAttribute(
        "monthPickerVisible",
        isMonthPickerVisible
      );
      if (isMonthPickerVisible) {
        this.state.months = dateKeeper.getMonths();
        this.state.years = dateKeeper.getYears();
      } else {
        this.state.days = dateKeeper.getDays();
      }

      this.components.monthYear.setProps({
        isVisible: isMonthPickerVisible,
        dateObj: dateKeeper.state.dateObj,
        months: this.state.months,
        years: this.state.years,
        toggleMonthPicker: this.state.toggleMonthPicker,
        noSmoothScroll: options.noSmoothScroll,
      });
      this.components.calendar.setProps({
        isVisible: !isMonthPickerVisible,
        days: this.state.days,
        weekHeaders: dateKeeper.state.weekHeaders,
      });
    },

    /**
     * Use postMessage to close the picker.
     */

    _closePopup(clear = false) {
      window.postMessage(
        {
          name: "ClosePopup",
          detail: clear,
        },
        "*"
      );
    },

    /**
     * Use postMessage to pass the state of picker to the panel.
     */

    _dispatchState() {
      const { year, month, day } = this.state.dateKeeper.selection;

      // The panel is listening to window for postMessage event, so we
      // do postMessage to itself to send data to input boxes.
      window.postMessage(
        {
          name: "PickerPopupChanged",
          detail: {
            year,
            month,
            day,
          },
        },
        "*"
      );
    },

    /**
     * Attach event listeners
     */

    _attachEventListeners() {
      window.addEventListener("message"this);
      document.addEventListener("mouseup"this, { passive: true });
      document.addEventListener("pointerdown"this, { passive: true });
      document.addEventListener("mousedown"this);
      document.addEventListener("keydown"this);
    },

    /**
     * Handle events.
     *
     * @param  {Event} event
     */

    handleEvent(event) {
      switch (event.type) {
        case "message": {
          this.handleMessage(event);
          break;
        }
        case "keydown": {
          switch (event.key) {
            case "Enter":
            case " ":
            case "Escape": {
              // If the target is a toggle or a spinner on the month-year panel
              const isOnMonthPicker =
                this.context.monthYearView.parentNode.contains(event.target);

              if (this.state.isMonthPickerVisible && isOnMonthPicker) {
                // While a control on the month-year picker panel is focused,
                // keep the spinner's selection and close the month-year dialog
                event.stopPropagation();
                event.preventDefault();
                this.state.toggleMonthPicker();
                this.components.calendar.focusDay();
                break;
              }
              if (event.key == "Escape") {
                // Close the date picker on Escape from within the picker
                this._closePopup();
                break;
              }
              if (event.target == this.context.buttonPrev) {
                event.target.classList.add("active");
                this.state.setMonthByOffset(-1);
                this.context.buttonPrev.focus();
              } else if (event.target == this.context.buttonNext) {
                event.target.classList.add("active");
                this.state.setMonthByOffset(1);
                this.context.buttonNext.focus();
              } else if (event.target == this.context.buttonClear) {
                event.target.classList.add("active");
                this._closePopup(/* clear = */ true);
              }
              break;
            }
            case "Tab": {
              // Manage tab order of a daysView to prevent keyboard trap
              if (event.target.tagName === "td") {
                if (event.shiftKey) {
                  this.context.buttonNext.focus();
                } else if (!event.shiftKey) {
                  this.context.buttonClear.focus();
                }
                event.stopPropagation();
                event.preventDefault();
              }
              break;
            }
          }
          break;
        }
        case "pointerdown": {
          if (event.pointerType == "mouse") {
            event.target.setPointerCapture(event.pointerId);
          }
          break;
        }
        case "mousedown": {
          // Use preventDefault to keep focus on input boxes
          event.preventDefault();

          if (event.target == this.context.buttonClear) {
            event.target.classList.add("active");
            this._closePopup(/* clear = */ true);
          } else if (event.target == this.context.buttonPrev) {
            event.target.classList.add("active");
            this.state.dateKeeper.setMonthByOffset(-1);
            this._update();
          } else if (event.target == this.context.buttonNext) {
            event.target.classList.add("active");
            this.state.dateKeeper.setMonthByOffset(1);
            this._update();
          }
          break;
        }
        case "mouseup": {
          event.target.releasePointerCapture(event.pointerId);

          if (
            event.target == this.context.buttonPrev ||
            event.target == this.context.buttonNext
          ) {
            event.target.classList.remove("active");
          }
          break;
        }
      }
    },

    /**
     * Handle postMessage events.
     *
     * @param {Event} event
     */

    handleMessage(event) {
      switch (event.data.name) {
        case "PickerSetValue": {
          this.set(event.data.detail);
          break;
        }
        case "PickerInit": {
          this.init(event.data.detail);
          break;
        }
      }
    },

    /**
     * Set the date state and update the components with the new state.
     *
     * @param {Object} dateState
     *        {
     *          {Number} year [optional]
     *          {Number} month [optional]
     *          {Number} date [optional]
     *        }
     */

    set({ year, month, day }) {
      if (!this.state) {
        return;
      }

      const { dateKeeper } = this.state;

      dateKeeper.setCalendarMonth({
        year,
        month,
      });
      dateKeeper.setSelection({
        year,
        month,
        day,
      });
      this._update({ noSmoothScroll: true });
    },
  };

  /**
   * MonthYear is a component that handles the month & year spinners
   *
   * @param {Object} options
   *        {
   *          {String} locale
   *          {Function} setYear
   *          {Function} setMonth
   *          {Function} getMonthString
   *          {Array<String>} datetimeOrders
   *        }
   * @param {DOMElement} context
   */

  function MonthYear(options, context) {
    const spinnerSize = 5;
    const yearFormat = new Intl.DateTimeFormat(options.locale, {
      year: "numeric",
      timeZone: "UTC",
    }).format;
    const dateFormat = new Intl.DateTimeFormat(options.locale, {
      year: "numeric",
      month: "long",
      timeZone: "UTC",
    }).format;
    const spinnerOrder =
      options.datetimeOrders.indexOf("month") <
      options.datetimeOrders.indexOf("year")
        ? "order-month-year"
        : "order-year-month";

    context.monthYearView.classList.add(spinnerOrder);

    this.context = context;
    this.state = { dateFormat };
    this.props = {};
    this.components = {
      month: new Spinner(
        {
          id: "spinner-month",
          setValue: month => {
            this.state.isMonthSet = true;
            options.setMonth(month);
          },
          getDisplayString: options.getMonthString,
          viewportSize: spinnerSize,
        },
        context.monthYearView
      ),
      year: new Spinner(
        {
          id: "spinner-year",
          setValue: year => {
            this.state.isYearSet = true;
            options.setYear(year);
          },
          getDisplayString: year =>
            yearFormat(new Date(new Date(0).setUTCFullYear(year))),
          viewportSize: spinnerSize,
        },
        context.monthYearView
      ),
    };

    this._updateButtonLabels();
    this._attachEventListeners();
  }

  MonthYear.prototype = {
    /**
     * Set new properties and pass them to components
     *
     * @param {Object} props
     *        {
     *          {Boolean} isVisible
     *          {Date} dateObj
     *          {Array<Object>} months
     *          {Array<Object>} years
     *          {Function} toggleMonthPicker
     *         }
     */

    setProps(props) {
      this.context.monthYear.textContent = this.state.dateFormat(props.dateObj);
      const spinnerDialog = this.context.monthYearView.parentNode;

      if (props.isVisible) {
        this.context.monthYear.classList.add("active");
        this.context.monthYear.setAttribute("aria-expanded""true");
        // To prevent redundancy, as spinners will announce their value on change
        this.context.monthYear.setAttribute("aria-live""off");
        this.components.month.setState({
          value: props.dateObj.getUTCMonth(),
          items: props.months,
          isInfiniteScroll: true,
          isValueSet: this.state.isMonthSet,
          smoothScroll: !(this.state.firstOpened || props.noSmoothScroll),
        });
        this.components.year.setState({
          value: props.dateObj.getUTCFullYear(),
          items: props.years,
          isInfiniteScroll: false,
          isValueSet: this.state.isYearSet,
          smoothScroll: !(this.state.firstOpened || props.noSmoothScroll),
        });
        this.state.firstOpened = false;

        // Set up spinner dialog container properties for assistive technology:
        spinnerDialog.setAttribute("role""dialog");
        spinnerDialog.setAttribute("aria-modal""true");
      } else {
        this.context.monthYear.classList.remove("active");
        this.context.monthYear.setAttribute("aria-expanded""false");
        // To ensure calendar month's changes are announced:
        this.context.monthYear.setAttribute("aria-live""polite");
        // Remove spinner dialog container properties to ensure this hidden
        // modal will be ignored by assistive technology, because even though
        // the dialog is hidden, the toggle button is a visible descendant,
        // so we must not treat its container as a dialog:
        spinnerDialog.removeAttribute("role");
        spinnerDialog.removeAttribute("aria-modal");
        this.state.isMonthSet = false;
        this.state.isYearSet = false;
        this.state.firstOpened = true;
      }

      this.props = Object.assign(this.props, props);
    },

    /**
     * Handle events
     * @param  {DOMEvent} event
     */

    handleEvent(event) {
      switch (event.type) {
        case "click": {
          this.props.toggleMonthPicker();
          break;
        }
        case "keydown": {
          if (event.key === "Enter" || event.key === " ") {
            event.stopPropagation();
            event.preventDefault();
            this.props.toggleMonthPicker();
          }
          break;
        }
      }
    },

    /**
     * Update localizable IDs of the spinner and its Prev/Next buttons
     */

    _updateButtonLabels() {
      document.l10n.setAttributes(
        this.components.month.elements.spinner,
        "date-spinner-month"
      );
      document.l10n.setAttributes(
        this.components.year.elements.spinner,
        "date-spinner-year"
      );
      document.l10n.setAttributes(
        this.components.month.elements.up,
        "date-spinner-month-previous"
      );
      document.l10n.setAttributes(
        this.components.month.elements.down,
        "date-spinner-month-next"
      );
      document.l10n.setAttributes(
        this.components.year.elements.up,
        "date-spinner-year-previous"
      );
      document.l10n.setAttributes(
        this.components.year.elements.down,
        "date-spinner-year-next"
      );
      document.l10n.translateRoots();
    },

    /**
     * Attach event listener to monthYear button
     */

    _attachEventListeners() {
      this.context.monthYear.addEventListener("click"this);
      this.context.monthYear.addEventListener("keydown"this);
    },
  };
}

Messung V0.5
C=92 H=93 G=92

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.