diff --git a/ext/bg/js/settings/anki-templates-controller.js b/ext/bg/js/settings/anki-templates-controller.js
index f2e5be43..65900336 100644
--- a/ext/bg/js/settings/anki-templates-controller.js
+++ b/ext/bg/js/settings/anki-templates-controller.js
@@ -23,8 +23,9 @@
*/
class AnkiTemplatesController {
- constructor(settingsController, ankiController) {
+ constructor(settingsController, modalController, ankiController) {
this._settingsController = settingsController;
+ this._modalController = modalController;
this._ankiController = ankiController;
this._cachedDefinitionValue = null;
this._cachedDefinitionText = null;
@@ -36,7 +37,7 @@ class AnkiTemplatesController {
async prepare() {
this._defaultFieldTemplates = await api.getDefaultAnkiFieldTemplates();
- this._fieldTemplateResetModal = new Modal(document.querySelector('#field-template-reset-modal'));
+ this._fieldTemplateResetModal = this._modalController.getModal('field-template-reset-modal');
const markers = new Set([
...this._ankiController.getFieldMarkers('terms'),
diff --git a/ext/bg/js/settings/backup-controller.js b/ext/bg/js/settings/backup-controller.js
index 80f83eb7..50390d5c 100644
--- a/ext/bg/js/settings/backup-controller.js
+++ b/ext/bg/js/settings/backup-controller.js
@@ -22,8 +22,9 @@
*/
class BackupController {
- constructor(settingsController) {
+ constructor(settingsController, modalController) {
this._settingsController = settingsController;
+ this._modalController = modalController;
this._settingsExportToken = null;
this._settingsExportRevoke = null;
this._currentVersion = 0;
@@ -36,9 +37,9 @@ class BackupController {
async prepare() {
await this._optionsUtil.prepare();
- this._settingsResetModal = new Modal(document.querySelector('#settings-reset-modal'));
- this._settingsImportErrorModal = new Modal(document.querySelector('#settings-import-error-modal'));
- this._settingsImportWarningModal = new Modal(document.querySelector('#settings-import-warning-modal'));
+ this._settingsResetModal = this._modalController.getModal('settings-reset-modal');
+ this._settingsImportErrorModal = this._modalController.getModal('settings-import-error-modal');
+ this._settingsImportWarningModal = this._modalController.getModal('settings-import-warning-modal');
document.querySelector('#settings-export').addEventListener('click', this._onSettingsExportClick.bind(this), false);
document.querySelector('#settings-import').addEventListener('click', this._onSettingsImportClick.bind(this), false);
diff --git a/ext/bg/js/settings/dictionary-controller.js b/ext/bg/js/settings/dictionary-controller.js
index cbbd0a8e..34a4b933 100644
--- a/ext/bg/js/settings/dictionary-controller.js
+++ b/ext/bg/js/settings/dictionary-controller.js
@@ -144,8 +144,9 @@ class DictionaryEntry {
}
class DictionaryController {
- constructor(settingsController) {
+ constructor(settingsController, modalController) {
this._settingsController = settingsController;
+ this._modalController = modalController;
this._dictionaries = null;
this._dictionaryEntries = [];
this._databaseStateToken = null;
@@ -166,7 +167,7 @@ class DictionaryController {
this._checkIntegrityButton = document.querySelector('#dict-check-integrity');
this._dictionaryEntryContainer = document.querySelector('#dict-groups');
this._integrityExtraInfoContainer = document.querySelector('#dict-groups-extra');
- this._deleteDictionaryModal = new Modal(document.querySelector('#dict-delete-modal'));
+ this._deleteDictionaryModal = this._modalController.getModal('dict-delete-modal');
yomichan.on('databaseUpdated', this._onDatabaseUpdated.bind(this));
diff --git a/ext/bg/js/settings/dictionary-import-controller.js b/ext/bg/js/settings/dictionary-import-controller.js
index a78378e8..2c954ef8 100644
--- a/ext/bg/js/settings/dictionary-import-controller.js
+++ b/ext/bg/js/settings/dictionary-import-controller.js
@@ -24,8 +24,9 @@
*/
class DictionaryImportController {
- constructor(settingsController, storageController) {
+ constructor(settingsController, modalController, storageController) {
this._settingsController = settingsController;
+ this._modalController = modalController;
this._storageController = storageController;
this._modifying = false;
this._purgeButton = null;
@@ -54,7 +55,7 @@ class DictionaryImportController {
this._purgeConfirmButton = document.querySelector('#dict-purge-confirm');
this._importFileButton = document.querySelector('#dict-file-button');
this._importFileInput = document.querySelector('#dict-file');
- this._purgeConfirmModal = new Modal(document.querySelector('#dict-purge-modal'));
+ this._purgeConfirmModal = this._modalController.getModal('dict-purge-modal');
this._errorContainer = document.querySelector('#dict-error');
this._spinner = document.querySelector('#dict-spinner');
this._progressContainer = document.querySelector('#dict-import-progress');
diff --git a/ext/bg/js/settings/main.js b/ext/bg/js/settings/main.js
index 37c6375d..3b2ff29d 100644
--- a/ext/bg/js/settings/main.js
+++ b/ext/bg/js/settings/main.js
@@ -24,6 +24,7 @@
* DictionaryController
* DictionaryImportController
* GenericSettingController
+ * ModalController
* PopupPreviewController
* ProfileController
* ScanInputsController
@@ -57,6 +58,9 @@ async function setupEnvironmentInfo() {
const optionsFull = await api.optionsGetFull();
+ const modalController = new ModalController();
+ modalController.prepare();
+
const settingsController = new SettingsController(optionsFull.profileCurrent);
settingsController.prepare();
@@ -75,22 +79,22 @@ async function setupEnvironmentInfo() {
const audioController = new AudioController(settingsController);
audioController.prepare();
- const profileController = new ProfileController(settingsController);
+ const profileController = new ProfileController(settingsController, modalController);
profileController.prepare();
- const dictionaryController = new DictionaryController(settingsController);
+ const dictionaryController = new DictionaryController(settingsController, modalController);
dictionaryController.prepare();
- const dictionaryImportController = new DictionaryImportController(settingsController, storageController);
+ const dictionaryImportController = new DictionaryImportController(settingsController, modalController, storageController);
dictionaryImportController.prepare();
const ankiController = new AnkiController(settingsController);
ankiController.prepare();
- const ankiTemplatesController = new AnkiTemplatesController(settingsController, ankiController);
+ const ankiTemplatesController = new AnkiTemplatesController(settingsController, modalController, ankiController);
ankiTemplatesController.prepare();
- const settingsBackup = new BackupController(settingsController);
+ const settingsBackup = new BackupController(settingsController, modalController);
settingsBackup.prepare();
const scanInputsController = new ScanInputsController(settingsController);
diff --git a/ext/bg/js/settings/modal-controller.js b/ext/bg/js/settings/modal-controller.js
new file mode 100644
index 00000000..d604b050
--- /dev/null
+++ b/ext/bg/js/settings/modal-controller.js
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 Yomichan Authors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/* global
+ * Modal
+ */
+
+class ModalController {
+ constructor() {
+ this._modals = [];
+ this._modalMap = new Map();
+ }
+
+ prepare() {
+ for (const node of document.querySelectorAll('.modal')) {
+ const {id} = node;
+ const modal = new Modal(node);
+ this._modalMap.set(id, modal);
+ this._modals.push(modal);
+ }
+
+ for (const node of document.querySelectorAll('.modal-container')) {
+ const {id} = node;
+ const modal = new Modal(node);
+ this._modalMap.set(id, modal);
+ this._modals.push(modal);
+ node.addEventListener('click', this._onModalContainerClick.bind(this, modal), false);
+ }
+ }
+
+ getModal(name) {
+ const modal = this._modalMap.get(name);
+ return (typeof modal !== 'undefined' ? modal : null);
+ }
+
+ getTopVisibleModal() {
+ for (let i = this._modals.length - 1; i >= 0; --i) {
+ const modal = this._modals[i];
+ if (modal.isVisible()) {
+ return modal;
+ }
+ }
+ return null;
+ }
+
+ // Private
+
+ _onModalContainerClick(modal, e) {
+ if (e.currentTarget !== e.target) { return; }
+ modal.setVisible(false);
+ }
+}
diff --git a/ext/bg/js/settings/profile-controller.js b/ext/bg/js/settings/profile-controller.js
index 7c6dfae5..63a82c40 100644
--- a/ext/bg/js/settings/profile-controller.js
+++ b/ext/bg/js/settings/profile-controller.js
@@ -22,8 +22,9 @@
*/
class ProfileController {
- constructor(settingsController) {
+ constructor(settingsController, modalController) {
this._settingsController = settingsController;
+ this._modalController = modalController;
this._profileConditionsUI = new ProfileConditionsUI(settingsController);
this._profileActiveSelect = null;
this._profileTargetSelect = null;
@@ -52,8 +53,8 @@ class ProfileController {
this._profileCopyButton = document.querySelector('#profile-copy');
this._profileMoveUpButton = document.querySelector('#profile-move-up');
this._profileMoveDownButton = document.querySelector('#profile-move-down');
- this._profileRemoveModal = new Modal(document.querySelector('#profile-remove-modal'));
- this._profileCopyModal = new Modal(document.querySelector('#profile-copy-modal'));
+ this._profileRemoveModal = this._modalController.getModal('profile-remove-modal');
+ this._profileCopyModal = this._modalController.getModal('profile-copy-modal');
this._profileActiveSelect.addEventListener('change', this._onProfileActiveChange.bind(this), false);
this._profileTargetSelect.addEventListener('change', this._onProfileTargetChange.bind(this), false);
diff --git a/ext/bg/settings.html b/ext/bg/settings.html
index c36bd8bf..18e3e389 100644
--- a/ext/bg/settings.html
+++ b/ext/bg/settings.html
@@ -1246,6 +1246,7 @@
+