summaryrefslogtreecommitdiffstats
path: root/browser/components/aboutlogins/content/components/confirmation-dialog.mjs
blob: 91a9c3a9d74fd59d321331c5445ab65776ce86ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/* 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 { setKeyboardAccessForNonDialogElements } from "../aboutLoginsUtils.mjs";

export default class ConfirmationDialog extends HTMLElement {
  constructor() {
    super();
    this._promise = null;
  }

  connectedCallback() {
    if (this.shadowRoot) {
      return;
    }
    let template = document.querySelector("#confirmation-dialog-template");
    let shadowRoot = this.attachShadow({ mode: "open" });
    document.l10n.connectRoot(shadowRoot);
    shadowRoot.appendChild(template.content.cloneNode(true));

    this._buttons = this.shadowRoot.querySelector(".buttons");
    this._cancelButton = this.shadowRoot.querySelector(".cancel-button");
    this._confirmButton = this.shadowRoot.querySelector(".confirm-button");
    this._dismissButton = this.shadowRoot.querySelector(".dismiss-button");
    this._message = this.shadowRoot.querySelector(".message");
    this._overlay = this.shadowRoot.querySelector(".overlay");
    this._title = this.shadowRoot.querySelector(".title");
  }

  handleEvent(event) {
    switch (event.type) {
      case "keydown":
        if (event.repeat) {
          // Prevent repeat keypresses from accidentally confirming the
          // dialog since the confirmation button is focused by default.
          event.preventDefault();
          return;
        }
        if (event.key === "Escape" && !event.defaultPrevented) {
          this.onCancel();
        }
        break;
      case "click":
        if (
          event.target.classList.contains("cancel-button") ||
          event.currentTarget.classList.contains("dismiss-button") ||
          event.target.classList.contains("overlay")
        ) {
          this.onCancel();
        } else if (event.target.classList.contains("confirm-button")) {
          this.onConfirm();
        }
    }
  }

  hide() {
    setKeyboardAccessForNonDialogElements(true);
    this._cancelButton.removeEventListener("click", this);
    this._confirmButton.removeEventListener("click", this);
    this._dismissButton.removeEventListener("click", this);
    this._overlay.removeEventListener("click", this);
    window.removeEventListener("keydown", this);

    this.hidden = true;
  }

  show({ title, message, confirmButtonLabel }) {
    setKeyboardAccessForNonDialogElements(false);
    this.hidden = false;

    document.l10n.setAttributes(this._title, title);
    document.l10n.setAttributes(this._message, message);
    document.l10n.setAttributes(this._confirmButton, confirmButtonLabel);

    this._cancelButton.addEventListener("click", this);
    this._confirmButton.addEventListener("click", this);
    this._dismissButton.addEventListener("click", this);
    this._overlay.addEventListener("click", this);
    window.addEventListener("keydown", this);

    // For speed-of-use, focus the confirm button when the
    // dialog loads. Showing the dialog itself provides enough
    // of a buffer for accidental deletions.
    this._confirmButton.focus();

    this._promise = new Promise((resolve, reject) => {
      this._resolve = resolve;
      this._reject = reject;
    });

    return this._promise;
  }

  onCancel() {
    this._reject();
    this.hide();
  }

  onConfirm() {
    this._resolve();
    this.hide();
  }
}
customElements.define("confirmation-dialog", ConfirmationDialog);