/**
 * @file menu-button.js
 * /
importiere Button aus '../button.js';
importiere Komponente aus '../component.js';
importiere das Menü aus '. /menu.js ';
import * as Dom from '../utils/dom.js';
import * as Events aus '../utils/events.js';
importiere {toTitleCase} aus '../utils/string-cases.js';
importiere {IS_IOS} aus '.. /utils/browser.js ';
dokument aus 'global/document' importieren;
import keycode from 'keycode';

/**
 * Eine `MenuButton`-Klasse für jedes Popup {@link Menu}.
 *
 * @erweitert Komponente
 * /
Klasse MenuButton erweitert Komponente {

  /**
   * Erzeugt eine Instanz dieser Klasse.
   *
   * @param {Player} Spieler
   *        Der `Player`, dem diese Klasse zugeordnet werden soll.
   *
   * @param {Object} [options={}]
   *        Der Schlüssel/Wertspeicher der Playeroptionen.
   * /
  constructor(player, options = {}) {
    super(Spieler, Optionen);

    this.MenuButton_ = neuer Button (Spieler, Optionen);

    this.menuButton_.controlText (this.controlText_);
    this.menuButton_.el_.setAttribute ('aria-haspopup', 'wahr');

    //Füge buildCssClass-Werte zur Schaltfläche hinzu, nicht zum Wrapper
    const buttonClass = Button.prototype.buildCSSClass();

    this.menuButton_.el_.className = this.buildCSSClass () + '' + ButtonClass;
    this.menuButton_.removeClass ('vjs-control');

    this.addChild (this.MenuButton_);

    this.update();

    this.enabled_ = true;

    const handleClick = (e) => this.handleClick (e);

    this.handleMenuKeyUp_ = (e) => this.handleMenuKeyUp (e);

    this.on (this.menuButton_, 'tippen', HandleClick);
    this.on (this.menuButton_, 'klick', handleClick);
    this.on (this.MenuButton_, 'keydown', (e) => this.handleKeyDown (e));
    this.on (this.menuButton_, 'mouseenter', () => {
      this.addClass('vjs-hover');
      this.menu.show();
      events.on (document, 'keyup', this.handleMenuKeyup_);
    });
    this.on ('mouseleave', (e) => this.handleMouseleave (e));
    this.on ('keydown', (e) => this.handleSubmenuKeyDown (e));
  }

  /**
   * Aktualisierung des Menüs auf der Grundlage des aktuellen Zustands seiner Elemente.
   * /
  update() {
    const menu = this.createMenu ();

    wenn (this.menu) {
      this.menu.dispose ();
      this.removeChild (this.menu);
    }

    this.menu = Menü;
    this.addChild (Menü);

    /**
     * Verfolge den Status der Menütaste
     *
     * @Typ {Boolean}
     * @privat
     * /
    this.buttonPressed_ = false;
    this.menuButton_.el_.setAttribute('aria-expanded', 'false');

    wenn (this.items && this.items.length <= this.hideThreshold_) {
      this.hide();
      this.menu.contentel_.removeAttribute ('Rolle');

    } sonst {
      this.show();
      this.menu.contentel_.setAttribute ('Rolle', 'Menü');
    }
  }

  /**
   * Erstellen Sie das Menü und fügen Sie alle Elemente hinzu.
   *
   * @return {Menu}
   * Das konstruierte Menü
   * /
  createMenu() {
    const menu = neues Menü (this.player_, {MenuButton: this});

    /**
     * Blenden Sie das Menü aus, wenn die Anzahl der Elemente unter oder gleich diesem Schwellenwert ist. Dies ist standardmäßig
     * auf 0 und jedes Mal, wenn wir Elemente hinzufügen, die ausgeblendet werden können, erhöhen wir sie. Wir listen auf
     * ist hier, weil wir jedes Mal, wenn wir `createMenu` starten, den Wert zurücksetzen müssen.
     *
     * @protected
     * @Typ {Zahl}
     * /
    this.hideThreshold_ = 0;

    //Füge einen Eintrag in der Titelliste oben hinzu
    wenn (this.options_.title) {
      const titleEl = dom.createEl ('li', {
        Klassenname: 'vjs-menu-title',
        TextInhalt: toTitleCase (this.options_.title),
        tabIndex: -1
      });

      const titleComponent = neue Komponente (this.player_, {el: titleEL});

      menu.AddItem (TitleComponent);
    }

    this.items = this.createItems ();

    wenn (this.items) {
      //Menüelemente zum Menü hinzufügen
      für (sei i = 0; i < this.items.length; i++) {
        menu.addItem (this.items [i]);
      }
    }

    Rückgabemenü;
  }

  /**
   * Erstellen Sie die Liste der Menüpunkte. Spezifisch für jede Unterklasse.
   *
   * @Abstrakt
   * /
  Artikel erstellen () {}

  /**
   * Erstellen Sie das DOM-Element von `MenuButtons.
   *
   * @return {Element}
   *         Das Element, das erstellt wird.
   * /
  createEl() {
    return super.createEl('div', {
      Klassenname: this.buildWrapperCssClass ()
    }, {
    });
  }

  /**
   * Erlaube Unterkomponenten, CSS-Klassennamen für das Wrapper-Element zu stapeln
   *
   * @return {string}
   * Das konstruierte Wrapper-DOM `className`
   * /
  buildWrapperCSSClass() {
    let menuButtonClass = 'vjs-menu-button';

    // Wenn die Option "inline" übergeben wird, wollen wir ganz andere Stile verwenden.
    if (this.options_.inline === true) {
      menuButtonClass += '-inline';
    } sonst {
      menuButtonClass += '-popup';
    }

    // TODO: Korrigiere das CSS so, dass dies nicht notwendig ist
    const buttonClass = Button.prototype.buildCSSClass();

    `vjs-menu-button $ {menuButtonClass} $ {buttonClass} $ {super.buildCssClass ()} `zurückgeben;
  }

  /**
   * Erzeugt den Standard-DOM "Klassenname".
   *
   * @return {string}
   *         Der DOM `className` für dieses Objekt.
   * /
  buildCSSClass() {
    let menuButtonClass = 'vjs-menu-button';

    // Wenn die Option "inline" übergeben wird, wollen wir ganz andere Stile verwenden.
    if (this.options_.inline === true) {
      menuButtonClass += '-inline';
    } sonst {
      menuButtonClass += '-popup';
    }

    `vjs-menu-button $ {menuButtonClass} $ {super.buildCssClass ()} `zurückgeben;
  }

  /**
   * Ruft den lokalisierten Steuertext ab, der aus Gründen der Barrierefreiheit verwendet wird, oder legt ihn fest.
   *
   * > HINWEIS: Dies wird aus dem internen `MenuButton_` -Element kommen.
   *
   * @param {string} [text]
   *        Kontrolltext für das Element.
   *
   * @param {Element} [el=this.MenuButton_.el ()]
   *        Element, auf das der Titel gesetzt wird.
   *
   * @return {string}
   *         - Der Kontrolltext, wenn er
   * /
  ControlText (text, el = this.MenuButton_.el ()) {
    gib this.menuButton_.controlText (text, el) zurück;
  }

  /**
   * Entsorgen Sie die `Menü-Button` und alle untergeordneten Komponenten.
   * /
  dispose() {
    this.handleMouseLeave ();
    super.dispose();
  }

  /**
   * Bearbeite einen Klick auf einen `MenuButton`.
   * Siehe {@link ClickableComponent#handleClick} für Instanzen, in denen dies aufgerufen wird.
   *
   * @param {EventTarget~Event} event
   *        Das `Keydown`-, `Tap`- oder `Click`-Ereignis, das diese Funktion ausgelöst hat
   *        genannt.
   *
   * @listens tap
   * @listens klicken
   * /
  handleClick(event) {
    if (this.buttonPressed_) {
      this.unpressButton();
    } sonst {
      this.pressButton();
    }
  }

  /**
   * Benütze `mouseleave` für `MenuButton`.
   *
   * @param {EventTarget~Event} event
   * Das `mouseleave`-Ereignis, das den Aufruf dieser Funktion verursacht hat.
   *
   * @listens Mauszeiger
   * /
  handleMouseLeave (Ereignis) {
    this.removeClass('vjs-hover');
    events.off (document, 'keyup', this.handleMenuKeyup_);
  }

  /**
   * Stellen Sie den Fokus auf die eigentliche Schaltfläche, nicht auf dieses Element
   * /
  focus() {
    this.menuButton_.focus();
  }

  /**
   * Entferne den Fokus von der eigentlichen Schaltfläche, nicht von diesem Element
   * /
  blur() {
    this.menuButton_.blur ();
  }

  /**
   * Benutze die Tabulator-, Escape-, Abwärts- und Aufwärtspfeiltasten für `MenuButton`. Sehen
   * {@link ClickableComponent#handleKeyDown} für Instanzen, in denen dies aufgerufen wird.
   *
   * @param {EventTarget~Event} event
   *        Das "Keydown"-Ereignis, das zum Aufruf dieser Funktion geführt hat.
   *
   * @listens keydown
   * /
  handleKeyDown(event) {

    // Escape oder Tabulator heben das Drücken der "Taste" auf
    if (keycode.isEventKey(event, 'Esc') || keycode.isEventKey(event, 'Tab')) {
      if (this.buttonPressed_) {
        this.unpressButton();
      }

      // Nicht preventDefault für Tabulator-Taste - wir wollen trotzdem den Fokus verlieren
      if (!keycode.isEventKey(event, 'Tab')) {
        event.preventDefault();
        // Fokus zurück auf die Schaltfläche der Menütaste setzen
        this.menuButton_.focus();
      }
    //Nach oben oder nach unten 'drücken' Sie auch die Taste, um das Menü zu öffnen
    } sonst if (keyCode.isEventKey (event, 'Up') || keycode.isEventKey (event, 'Down')) {
      wenn (! diese.Taste gedrückt _) {
        event.preventDefault();
        this.pressButton();
      }
    }
  }

  /**
   * Behandelt ein `keyup`-Ereignis auf einem `MenuButton`. Der Hörer dafür wird hinzugefügt in
   * der Konstrukteur.
   *
   * @param {EventTarget~Event} event
   *        Wichtigstes Presseereignis
   *
   * @listens keyup
   * /
  handleMenuKeyUp (Ereignis) {
    //Escape versteckt das Popup-Menü
    if (keycode.isEventKey(event, 'Esc') || keycode.isEventKey(event, 'Tab')) {
      this.removeClass('vjs-hover');
    }
  }

  /**
   * Dieser Methodenname delegiert jetzt an `handleSubmenuKeyDown`. Dies bedeutet
   * jeder, der `handleSubmenuKeyPress` aufruft, wird seine Methodenaufrufe nicht sehen
   * hör auf zu arbeiten.
   *
   * @param {EventTarget~Event} event
   *        Das Ereignis, das zum Aufruf dieser Funktion geführt hat.
   * /
  handleSubmenuKeypress (Ereignis) {
    this.handleSubmenuKeyDown (Ereignis);
  }

  /**
   * Behandelt ein `Keydown`-Ereignis in einem Untermenü. Der Hörer dafür wird hinzugefügt in
   * der Konstrukteur.
   *
   * @param {EventTarget~Event} event
   *        Wichtigstes Presseereignis
   *
   * @listens keydown
   * /
  handleSubmenuKeyDown (Ereignis) {
    // Escape oder Tabulator heben das Drücken der "Taste" auf
    if (keycode.isEventKey(event, 'Esc') || keycode.isEventKey(event, 'Tab')) {
      if (this.buttonPressed_) {
        this.unpressButton();
      }
      // Nicht preventDefault für Tabulator-Taste - wir wollen trotzdem den Fokus verlieren
      if (!keycode.isEventKey(event, 'Tab')) {
        event.preventDefault();
        // Fokus zurück auf die Schaltfläche der Menütaste setzen
        this.menuButton_.focus();
      }
    } sonst {
      //HINWEIS: Dies ist ein Sonderfall, in dem wir nicht unbehandelt bleiben.
      //Keydown-Ereignisse bis zum Component-Handler, denn das ist
      //nur das Keydown-Behandling des `MenuItem` beenden
      //im `Menu`, das bereits ungenutzte Tasten weitergibt.
    }
  }

  /**
   * Versetzt den aktuellen `MenuButton` in einen gedrückten Zustand.
   * /
  Drücken Sie die Taste () {
    if (this.enabled_) {
      this.buttonPressed_ = wahr;
      this.menu.show();
      this.menu.lockShowing ();
      this.menuButton_.el_.setAttribute ('aria-expanded', 'wahr');

      //setze den Fokus in das Untermenü, außer auf iOS, wo es dazu führt
      //unerwünschtes Scrollverhalten, wenn sich der Spieler in einem Iframe befindet
      wenn (IS_IOS && dom.isFrame ()) {
        //Komm früh zurück, damit das Menü nicht fokussiert ist
        rückkehr;
      }

      this.menu.focus ();
    }
  }

  /**
   * Nimmt den aktuellen `MenuButton` aus einem gedrückten Zustand.
   * /
  Drücken Sie die Taste () {
    if (this.enabled_) {
      this.buttonPressed_ = false;
      this.menu.unlockShowing ();
      this.menu.hide ();
      this.menuButton_.el_.setAttribute('aria-expanded', 'false');
    }
  }

  /**
   * Deaktiviere den `MenuButton`. Lassen Sie nicht zu, dass es angeklickt wird.
   * /
  deaktivieren() {
    this.unpressButton();

    this.enabled_ = false;
    this.addClass('vjs-disabled');

    this.menuButton_.disable ();
  }

  /**
   * Aktiviere den `MenuButton`. Lassen Sie es anklicken.
   * /
  enable() {
    this.enabled_ = true;
    this.removeClass('vjs-disabled');

    this.menuButton_.enable ();
  }
}

component.registerComponent ('MenuButton', MenuButton);
Standard-MenuButton exportieren;