Dictionary controller refactor (#912)

* Support multiple main dictionary selects

* Update progress container

* Change class name

* Simplify dictionary info

* Update outdated node visibility

* Simplify node usage

* Simplify title

* Update classes

* Update IDs/classes

* Remove details container visibility assignment

* Use a template for dictionary details

* Fix progress bar visibility

* Fix incorrect property

* Rename dict-details to dictionary-details

* Remove unused classes

* Update class names for dictionary templates

* Rename templates

* More id renaming

* Remove unused id

* Rename more IDs
This commit is contained in:
toasted-nutbread 2020-10-11 17:31:58 -04:00 committed by GitHub
parent a8601ec95c
commit 5b5b45b88e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 149 additions and 147 deletions

View File

@ -23,7 +23,7 @@
html:root:not([data-options-anki-enable=true]) #anki-general, html:root:not([data-options-anki-enable=true]) #anki-general,
html:root:not([data-options-general-debug-info=true]) .debug, html:root:not([data-options-general-debug-info=true]) .debug,
html:root:not([data-options-general-show-advanced=true]) .options-advanced, html:root:not([data-options-general-show-advanced=true]) .options-advanced,
html:root:not([data-options-general-result-output-mode=merge]) #dict-main-group { html:root:not([data-options-general-result-output-mode=merge]) #dictionary-main-group {
display: none; display: none;
} }
@ -309,23 +309,26 @@ input[type=checkbox].storage-button-checkbox {
height: 320px; height: 320px;
} }
.dict-delete-table { .dictionary-delete-table {
display: table; display: table;
width: 100%; width: 100%;
} }
.dict-delete-table>*:first-child { .dictionary-delete-table>*:first-child {
display: table-cell; display: table-cell;
vertical-align: middle; vertical-align: middle;
padding-right: 1em; padding-right: 1em;
} }
.dict-delete-table>*:nth-child(n+2) { .dictionary-delete-table>*:nth-child(n+2) {
display: table-cell; display: table-cell;
width: 100%; width: 100%;
vertical-align: middle; vertical-align: middle;
} }
.dict-delete-table .progress { .dictionary-delete-table .progress {
margin: 0; margin: 0;
} }
.dictionary-delete-table>*[hidden] {
display: none;
}
.error-data-show-button { .error-data-show-button {
display: inline-block; display: inline-block;
@ -377,44 +380,44 @@ html:root[data-operating-system=openbsd] [data-hide-for-operating-system~=openbs
display: none; display: none;
} }
#dict-groups { #dictionary-list {
display: flex; display: flex;
flex-flow: column; flex-flow: column;
} }
.dict-details-container { .dictionary-details-container {
margin: 0.5em 0; margin: 0.5em 0;
} }
.dict-details-toggle-link { .dictionary-details-toggle-link {
cursor: pointer; cursor: pointer;
} }
.dict-details { .dictionary-details {
margin-left: 1em; margin-left: 1em;
} }
.dict-details-table { .dictionary-details-table {
display: table; display: table;
width: 100% width: 100%
} }
.dict-details-entry { .dictionary-details-entry {
display: table-row; display: table-row;
} }
.dict-details-entry+.dict-details-entry>* { .dictionary-details-entry+.dictionary-details-entry>* {
padding-top: 0.25em; padding-top: 0.25em;
} }
.dict-details-entry-label { .dictionary-details-entry-label {
display: table-cell; display: table-cell;
font-weight: bold; font-weight: bold;
white-space: nowrap; white-space: nowrap;
padding-right: 0.5em; padding-right: 0.5em;
} }
.dict-details-entry-info { .dictionary-details-entry-info {
display: table-cell; display: table-cell;
white-space: pre-line; white-space: pre-line;
} }

View File

@ -27,15 +27,8 @@ class DictionaryEntry {
this._dictionaryController = dictionaryController; this._dictionaryController = dictionaryController;
this._node = node; this._node = node;
this._dictionaryInfo = dictionaryInfo; this._dictionaryInfo = dictionaryInfo;
this._dictionaryTitle = dictionaryInfo.title;
this._eventListeners = new EventListenerCollection(); this._eventListeners = new EventListenerCollection();
this._enabledCheckbox = node.querySelector('.dict-enabled'); this._detailsContainer = null;
this._allowSecondarySearchesCheckbox = node.querySelector('.dict-allow-secondary-searches');
this._priorityInput = node.querySelector('.dict-priority');
this._deleteButton = node.querySelector('.dict-delete-button');
this._detailsToggleLink = node.querySelector('.dict-details-toggle-link');
this._detailsContainer = node.querySelector('.dict-details');
this._detailsTable = node.querySelector('.dict-details-table');
} }
get node() { get node() {
@ -43,31 +36,42 @@ class DictionaryEntry {
} }
get dictionaryTitle() { get dictionaryTitle() {
return this._dictionaryTitle; return this._dictionaryInfo.title;
} }
prepare() { prepare() {
const node = this._node; const node = this._node;
const dictionaryInfo = this._dictionaryInfo; const {title, revision, prefixWildcardsSupported, version} = this._dictionaryInfo;
const {title, revision, prefixWildcardsSupported} = dictionaryInfo;
if (dictionaryInfo.version < 3) { this._detailsContainer = node.querySelector('.dictionary-details');
node.querySelector('.dict-outdated').hidden = false;
}
node.querySelector('.dict-title').textContent = title; const enabledCheckbox = node.querySelector('.dictionary-enabled');
node.querySelector('.dict-revision').textContent = `rev.${revision}`; const allowSecondarySearchesCheckbox = node.querySelector('.dictionary-allow-secondary-searches');
node.querySelector('.dict-prefix-wildcard-searches-supported').checked = !!prefixWildcardsSupported; const priorityInput = node.querySelector('.dictionary-priority');
const deleteButton = node.querySelector('.dictionary-delete-button');
const detailsTable = node.querySelector('.dictionary-details-table');
const detailsToggleLink = node.querySelector('.dictionary-details-toggle-link');
const outdatedContainer = node.querySelector('.dictionary-outdated-notification');
const titleNode = node.querySelector('.dictionary-title');
const versionNode = node.querySelector('.dictionary-version');
const wildcardSupportedCheckbox = node.querySelector('.dictionary-prefix-wildcard-searches-supported');
this._setupDetails(dictionaryInfo); const hasDetails = this._setupDetails(detailsTable);
this._enabledCheckbox.dataset.setting = ObjectPropertyAccessor.getPathString(['dictionaries', title, 'enabled']); titleNode.textContent = title;
this._allowSecondarySearchesCheckbox.dataset.setting = ObjectPropertyAccessor.getPathString(['dictionaries', title, 'allowSecondarySearches']); versionNode.textContent = `rev.${revision}`;
this._priorityInput.dataset.setting = ObjectPropertyAccessor.getPathString(['dictionaries', title, 'priority']); wildcardSupportedCheckbox.checked = !!prefixWildcardsSupported;
this._eventListeners.addEventListener(this._deleteButton, 'click', this._onDeleteButtonClicked.bind(this), false); outdatedContainer.hidden = (version >= 3);
this._eventListeners.addEventListener(this._detailsToggleLink, 'click', this._onDetailsToggleLinkClicked.bind(this), false); detailsToggleLink.hidden = !hasDetails;
this._eventListeners.addEventListener(this._priorityInput, 'settingChanged', this._onPriorityChanged.bind(this), false);
enabledCheckbox.dataset.setting = ObjectPropertyAccessor.getPathString(['dictionaries', title, 'enabled']);
allowSecondarySearchesCheckbox.dataset.setting = ObjectPropertyAccessor.getPathString(['dictionaries', title, 'allowSecondarySearches']);
priorityInput.dataset.setting = ObjectPropertyAccessor.getPathString(['dictionaries', title, 'priority']);
this._eventListeners.addEventListener(deleteButton, 'click', this._onDeleteButtonClicked.bind(this), false);
this._eventListeners.addEventListener(detailsToggleLink, 'click', this._onDetailsToggleLinkClicked.bind(this), false);
this._eventListeners.addEventListener(priorityInput, 'settingChanged', this._onPriorityChanged.bind(this), false);
} }
cleanup() { cleanup() {
@ -79,7 +83,7 @@ class DictionaryEntry {
} }
setCounts(counts) { setCounts(counts) {
const node = this._node.querySelector('.dict-counts'); const node = this._node.querySelector('.dictionary-counts');
node.textContent = JSON.stringify({info: this._dictionaryInfo, counts}, null, 4); node.textContent = JSON.stringify({info: this._dictionaryInfo, counts}, null, 4);
node.hidden = false; node.hidden = false;
} }
@ -88,7 +92,7 @@ class DictionaryEntry {
_onDeleteButtonClicked(e) { _onDeleteButtonClicked(e) {
e.preventDefault(); e.preventDefault();
this._dictionaryController.deleteDictionary(this._dictionaryTitle); this._dictionaryController.deleteDictionary(this.dictionaryTitle);
} }
_onDetailsToggleLinkClicked(e) { _onDetailsToggleLinkClicked(e) {
@ -101,7 +105,7 @@ class DictionaryEntry {
this._node.style.order = `${-value}`; this._node.style.order = `${-value}`;
} }
_setupDetails(dictionaryInfo) { _setupDetails(detailsTable) {
const targets = [ const targets = [
['Author', 'author'], ['Author', 'author'],
['URL', 'url'], ['URL', 'url'],
@ -109,37 +113,24 @@ class DictionaryEntry {
['Attribution', 'attribution'] ['Attribution', 'attribution']
]; ];
const dictionaryInfo = this._dictionaryInfo;
const fragment = document.createDocumentFragment(); const fragment = document.createDocumentFragment();
let count = 0; let any = false;
for (const [label, key] of targets) { for (const [label, key] of targets) {
const info = dictionaryInfo[key]; const info = dictionaryInfo[key];
if (typeof info !== 'string') { continue; } if (typeof info !== 'string') { continue; }
const n1 = document.createElement('div'); const details = this._dictionaryController.instantiateTemplate('dictionary-details-entry');
n1.className = 'dict-details-entry'; details.dataset.type = key;
n1.dataset.type = key; details.querySelector('.dictionary-details-entry-label').textContent = `${label}:`;
details.querySelector('.dictionary-details-entry-info').textContent = info;
fragment.appendChild(details);
const n2 = document.createElement('span'); any = true;
n2.className = 'dict-details-entry-label';
n2.textContent = `${label}:`;
n1.appendChild(n2);
const n3 = document.createElement('span');
n3.className = 'dict-details-entry-info';
n3.textContent = info;
n1.appendChild(n3);
fragment.appendChild(n1);
++count;
} }
if (count > 0) { detailsTable.appendChild(fragment);
this._detailsTable.appendChild(fragment); return any;
} else {
this._detailsContainer.hidden = true;
this._detailsToggleLink.hidden = true;
}
} }
} }
@ -152,7 +143,6 @@ class DictionaryController {
this._databaseStateToken = null; this._databaseStateToken = null;
this._checkingIntegrity = false; this._checkingIntegrity = false;
this._warningNode = null; this._warningNode = null;
this._mainDictionarySelect = null;
this._checkIntegrityButton = null; this._checkIntegrityButton = null;
this._dictionaryEntryContainer = null; this._dictionaryEntryContainer = null;
this._integrityExtraInfoContainer = null; this._integrityExtraInfoContainer = null;
@ -162,16 +152,15 @@ class DictionaryController {
} }
async prepare() { async prepare() {
this._warningNode = document.querySelector('#dict-warning'); this._warningNode = document.querySelector('#dictionary-warning');
this._mainDictionarySelect = document.querySelector('#dict-main'); this._checkIntegrityButton = document.querySelector('#dictionary-check-integrity');
this._checkIntegrityButton = document.querySelector('#dict-check-integrity'); this._dictionaryEntryContainer = document.querySelector('#dictionary-list');
this._dictionaryEntryContainer = document.querySelector('#dict-groups'); this._integrityExtraInfoContainer = document.querySelector('#dictionary-list-extra');
this._integrityExtraInfoContainer = document.querySelector('#dict-groups-extra'); this._deleteDictionaryModal = this._modalController.getModal('dictionary-confirm-delete');
this._deleteDictionaryModal = this._modalController.getModal('dict-delete-modal');
yomichan.on('databaseUpdated', this._onDatabaseUpdated.bind(this)); yomichan.on('databaseUpdated', this._onDatabaseUpdated.bind(this));
document.querySelector('#dict-delete-confirm').addEventListener('click', this._onDictionaryConfirmDelete.bind(this), false); document.querySelector('#dictionary-confirm-delete-button').addEventListener('click', this._onDictionaryConfirmDelete.bind(this), false);
this._checkIntegrityButton.addEventListener('click', this._onCheckIntegrityButtonClick.bind(this), false); this._checkIntegrityButton.addEventListener('click', this._onCheckIntegrityButtonClick.bind(this), false);
await this._onDatabaseUpdated(); await this._onDatabaseUpdated();
@ -181,10 +170,14 @@ class DictionaryController {
if (this._isDeleting) { return; } if (this._isDeleting) { return; }
const modal = this._deleteDictionaryModal; const modal = this._deleteDictionaryModal;
modal.node.dataset.dictionaryTitle = dictionaryTitle; modal.node.dataset.dictionaryTitle = dictionaryTitle;
modal.node.querySelector('#dict-remove-modal-dict-name').textContent = dictionaryTitle; modal.node.querySelector('#dictionary-confirm-delete-name').textContent = dictionaryTitle;
modal.setVisible(true); modal.setVisible(true);
} }
instantiateTemplate(name) {
return this._settingsController.instantiateTemplate(name);
}
// Private // Private
async _onDatabaseUpdated() { async _onDatabaseUpdated() {
@ -227,25 +220,26 @@ class DictionaryController {
} }
_updateMainDictionarySelectOptions(dictionaries) { _updateMainDictionarySelectOptions(dictionaries) {
const fragment = document.createDocumentFragment(); for (const select of document.querySelectorAll('[data-setting="general.mainDictionary"]')) {
const fragment = document.createDocumentFragment();
let option = document.createElement('option'); let option = document.createElement('option');
option.className = 'text-muted'; option.className = 'text-muted';
option.value = ''; option.value = '';
option.textContent = 'Not selected'; option.textContent = 'Not selected';
fragment.appendChild(option);
for (const {title, sequenced} of dictionaries) {
if (!sequenced) { continue; }
option = document.createElement('option');
option.value = title;
option.textContent = title;
fragment.appendChild(option); fragment.appendChild(option);
}
const select = this._mainDictionarySelect; for (const {title, sequenced} of dictionaries) {
select.textContent = ''; // Empty if (!sequenced) { continue; }
select.appendChild(fragment); option = document.createElement('option');
option.value = title;
option.textContent = title;
fragment.appendChild(option);
}
select.textContent = ''; // Empty
select.appendChild(fragment);
}
} }
async _checkIntegrity() { async _checkIntegrity() {
@ -294,12 +288,12 @@ class DictionaryController {
} }
_createExtra(totalCounts, remainders, totalRemainder) { _createExtra(totalCounts, remainders, totalRemainder) {
const node = this._settingsController.instantiateTemplate('dict-extra'); const node = this.instantiateTemplate('dictionary-extra');
this._integrityExtraInfoNode = node; this._integrityExtraInfoNode = node;
node.querySelector('.dict-total-count').textContent = `${totalRemainder} item${totalRemainder !== 1 ? 's' : ''}`; node.querySelector('.dictionary-total-count').textContent = `${totalRemainder} item${totalRemainder !== 1 ? 's' : ''}`;
const n = node.querySelector('.dict-counts'); const n = node.querySelector('.dictionary-counts');
n.textContent = JSON.stringify({counts: totalCounts, remainders}, null, 4); n.textContent = JSON.stringify({counts: totalCounts, remainders}, null, 4);
n.hidden = false; n.hidden = false;
@ -318,7 +312,7 @@ class DictionaryController {
} }
_createDictionaryEntry(dictionary) { _createDictionaryEntry(dictionary) {
const node = this._settingsController.instantiateTemplate('dict'); const node = this.instantiateTemplate('dictionary');
this._dictionaryEntryContainer.appendChild(node); this._dictionaryEntryContainer.appendChild(node);
const entry = new DictionaryEntry(this, node, dictionary); const entry = new DictionaryEntry(this, node, dictionary);
@ -334,7 +328,7 @@ class DictionaryController {
const entry = this._dictionaryEntries[index]; const entry = this._dictionaryEntries[index];
const node = entry.node; const node = entry.node;
const progress = node.querySelector('.progress'); const progress = node.querySelector('.progress-container');
const progressBar = node.querySelector('.progress-bar'); const progressBar = node.querySelector('.progress-bar');
const prevention = this._settingsController.preventPageExit(); const prevention = this._settingsController.preventPageExit();
try { try {
@ -365,7 +359,7 @@ class DictionaryController {
_setButtonsEnabled(value) { _setButtonsEnabled(value) {
value = !value; value = !value;
for (const node of document.querySelectorAll('.dictionary-modifying-input')) { for (const node of document.querySelectorAll('.dictionary-database-mutating-input')) {
node.disabled = value; node.disabled = value;
} }
} }

View File

@ -51,17 +51,17 @@ class DictionaryImportController {
} }
async prepare() { async prepare() {
this._purgeButton = document.querySelector('#dict-purge-button'); this._purgeButton = document.querySelector('#dictionary-delete-all-button');
this._purgeConfirmButton = document.querySelector('#dict-purge-confirm'); this._purgeConfirmButton = document.querySelector('#dictionary-confirm-delete-all-button');
this._importFileButton = document.querySelector('#dict-file-button'); this._importFileButton = document.querySelector('#dictionary-import-file-button');
this._importFileInput = document.querySelector('#dict-file'); this._importFileInput = document.querySelector('#dictionary-import-file-input');
this._purgeConfirmModal = this._modalController.getModal('dict-purge-modal'); this._purgeConfirmModal = this._modalController.getModal('dictionary-confirm-delete-all');
this._errorContainer = document.querySelector('#dict-error'); this._errorContainer = document.querySelector('#dictionary-error');
this._spinner = document.querySelector('#dict-spinner'); this._spinner = document.querySelector('#dictionary-spinner');
this._progressContainer = document.querySelector('#dict-import-progress'); this._progressContainer = document.querySelector('#dictionary-import-progress-container');
this._progressBar = this._progressContainer.querySelector('.progress-bar'); this._progressBar = this._progressContainer.querySelector('.progress-bar');
this._purgeNotification = document.querySelector('#dict-purge'); this._purgeNotification = document.querySelector('#dictionary-delete-all-status');
this._importInfo = document.querySelector('#dict-import-info'); this._importInfo = document.querySelector('#dictionary-import-info');
this._purgeButton.addEventListener('click', this._onPurgeButtonClick.bind(this), false); this._purgeButton.addEventListener('click', this._onPurgeButtonClick.bind(this), false);
this._purgeConfirmButton.addEventListener('click', this._onPurgeConfirmButtonClick.bind(this), false); this._purgeConfirmButton.addEventListener('click', this._onPurgeConfirmButtonClick.bind(this), false);
@ -301,7 +301,7 @@ class DictionaryImportController {
_setButtonsEnabled(value) { _setButtonsEnabled(value) {
value = !value; value = !value;
for (const node of document.querySelectorAll('.dictionary-modifying-input')) { for (const node of document.querySelectorAll('.dictionary-database-mutating-input')) {
node.disabled = value; node.disabled = value;
} }
} }

View File

@ -656,7 +656,7 @@
<div class="ignore-form-changes"> <div class="ignore-form-changes">
<div> <div>
<img src="/mixed/img/spinner.gif" class="pull-right" id="dict-spinner" alt hidden> <img src="/mixed/img/spinner.gif" class="pull-right" id="dictionary-spinner" alt hidden>
<h3>Dictionaries</h3> <h3>Dictionaries</h3>
</div> </div>
@ -664,38 +664,38 @@
Yomichan can import and use a variety of dictionary formats. Unneeded dictionaries can be disabled. Yomichan can import and use a variety of dictionary formats. Unneeded dictionaries can be disabled.
</p> </p>
<div class="form-group" id="dict-main-group"> <div class="form-group" id="dictionary-main-group">
<label for="dict-main">Main dictionary for merged mode</label> <label for="dictionary-main">Main dictionary for merged mode</label>
<select class="form-control" id="dict-main" data-setting="general.mainDictionary"></select> <select class="form-control" id="dictionary-main" data-setting="general.mainDictionary"></select>
</div> </div>
<div class="text-danger" id="dict-purge" hidden>Dictionary data is being purged, please be patient...</div> <div class="text-danger" id="dictionary-delete-all-status" hidden>Dictionary data is being purged, please be patient...</div>
<div class="alert alert-warning" id="dict-warning" hidden>No dictionaries have been installed</div> <div class="alert alert-warning" id="dictionary-warning" hidden>No dictionaries have been installed</div>
<div class="alert alert-danger" id="dict-error" hidden></div> <div class="alert alert-danger" id="dictionary-error" hidden></div>
<div id="dict-groups"></div> <div id="dictionary-list"></div>
<div id="dict-groups-extra"></div> <div id="dictionary-list-extra"></div>
<div id="dict-import-progress" hidden> <div id="dictionary-import-progress-container" hidden>
Dictionary data is being imported, please be patient... Dictionary data is being imported, please be patient...
<span id="dict-import-info" hidden></span> <span id="dictionary-import-info" hidden></span>
<div class="progress"> <div class="progress">
<div class="progress-bar progress-bar-striped" style="width: 0%"></div> <div class="progress-bar progress-bar-striped" style="width: 0%"></div>
</div> </div>
</div> </div>
<div id="dict-importer"> <div>
<p class="help-block"> <p class="help-block">
Select a dictionary to import for use below. Please visit the Yomichan homepage to Select a dictionary to import for use below. Please visit the Yomichan homepage to
<a href="https://foosoft.net/projects/yomichan" target="_blank" rel="noopener">download free dictionaries</a> <a href="https://foosoft.net/projects/yomichan" target="_blank" rel="noopener">download free dictionaries</a>
for use with this extension and to learn about importing proprietary EPWING dictionaries. for use with this extension and to learn about importing proprietary EPWING dictionaries.
</p> </p>
<div> <div>
<button class="btn btn-primary dictionary-modifying-input" id="dict-file-button">Import Dictionary</button> <button class="btn btn-primary dictionary-database-mutating-input" id="dictionary-import-file-button">Import Dictionary</button>
<button class="btn btn-danger dictionary-modifying-input" id="dict-purge-button">Purge Database</button> <button class="btn btn-danger dictionary-database-mutating-input" id="dictionary-delete-all-button">Purge Database</button>
<button class="btn btn-default dictionary-modifying-input" id="dict-check-integrity">Check integrity</button> <button class="btn btn-default dictionary-database-mutating-input" id="dictionary-check-integrity">Check integrity</button>
</div> </div>
<div hidden><input type="file" id="dict-file" accept=".zip,application/zip" multiple></div> <div hidden><input type="file" id="dictionary-import-file-input" accept=".zip,application/zip" multiple></div>
</div> </div>
<div> <div>
@ -710,7 +710,7 @@
</p> </p>
</div> </div>
<div class="modal fade" tabindex="-1" role="dialog" id="dict-purge-modal"> <div class="modal fade" tabindex="-1" role="dialog" id="dictionary-confirm-delete-all">
<div class="modal-dialog modal-dialog-centered"> <div class="modal-dialog modal-dialog-centered">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
@ -722,13 +722,13 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-danger" id="dict-purge-confirm">Purge Database</button> <button type="button" class="btn btn-danger" id="dictionary-confirm-delete-all-button">Purge Database</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="modal fade" tabindex="-1" role="dialog" id="dict-delete-modal"> <div class="modal fade" tabindex="-1" role="dialog" id="dictionary-confirm-delete">
<div class="modal-dialog modal-dialog-centered"> <div class="modal-dialog modal-dialog-centered">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
@ -736,58 +736,63 @@
<h4 class="modal-title">Confirm dictionary deletion</h4> <h4 class="modal-title">Confirm dictionary deletion</h4>
</div> </div>
<div class="modal-body"> <div class="modal-body">
Are you sure you want to delete the dictionary <em id="dict-remove-modal-dict-name"></em>? Are you sure you want to delete the dictionary <em id="dictionary-confirm-delete-name"></em>?
This operation may take some time and the responsiveness of this browser tab may be reduced. This operation may take some time and the responsiveness of this browser tab may be reduced.
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-danger dictionary-modifying-input" id="dict-delete-confirm">Delete Dictionary</button> <button type="button" class="btn btn-danger dictionary-database-mutating-input" id="dictionary-confirm-delete-button">Delete Dictionary</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<template id="dict-template"><div class="dict-group well well-sm"> <template id="dictionary-template"><div class="well well-sm">
<h4><span class="text-muted glyphicon glyphicon-book"></span> <span class="dict-title"></span> <small class="dict-revision"></small></h4> <h4><span class="text-muted glyphicon glyphicon-book"></span> <span class="dictionary-title"></span> <small class="dictionary-version"></small></h4>
<p class="text-warning dict-outdated" hidden>This dictionary is outdated and may not support new extension features; please import the latest version.</p> <p class="text-warning dictionary-outdated-notification" hidden>This dictionary is outdated and may not support new extension features; please import the latest version.</p>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" class="dict-enabled"> Enable search</label> <label><input type="checkbox" class="dictionary-enabled"> Enable search</label>
</div> </div>
<div class="checkbox options-advanced"> <div class="checkbox options-advanced">
<label><input type="checkbox" class="dict-allow-secondary-searches"> Allow secondary searches</label> <label><input type="checkbox" class="dictionary-allow-secondary-searches"> Allow secondary searches</label>
</div> </div>
<div class="checkbox dict-prefix-wildcard-searches-supported-container"> <div class="checkbox">
<label><input type="checkbox" class="dict-prefix-wildcard-searches-supported" disabled> Prefix wildcard searches supported</label> <label><input type="checkbox" class="dictionary-prefix-wildcard-searches-supported" disabled> Prefix wildcard searches supported</label>
</div> </div>
<div class="form-group options-advanced"> <div class="form-group options-advanced">
<label class="dict-result-priority-label">Result priority</label> <label>Result priority</label>
<input type="number" class="form-control dict-priority"> <input type="number" class="form-control dictionary-priority">
</div> </div>
<div class="dict-details-container"> <div class="dictionary-details-container">
<a class="dict-details-toggle-link">Details...</a> <a class="dictionary-details-toggle-link">Details...</a>
<div class="dict-details" hidden><div class="dict-details-table"></div></div> <div class="dictionary-details" hidden><div class="dictionary-details-table"></div></div>
</div> </div>
<div class="dict-delete-table"> <div class="dictionary-delete-table">
<div> <div>
<button class="btn btn-default dict-delete-button dictionary-modifying-input">Delete Dictionary</button> <button class="btn btn-default dictionary-delete-button dictionary-database-mutating-input">Delete Dictionary</button>
</div> </div>
<div> <div class="progress-container" hidden>
<div class="progress" hidden> <div class="progress">
<div class="progress-bar progress-bar-striped" style="width: 0%"></div> <div class="progress-bar progress-bar-striped" style="width: 0%"></div>
</div> </div>
</div> </div>
</div> </div>
<pre class="debug dict-counts" hidden></pre> <pre class="debug dictionary-counts" hidden></pre>
</div></template> </div></template>
<template id="dict-extra-template"><div class="well well-sm"> <template id="dictionary-details-entry-template"><div class="dictionary-details-entry">
<h4><span class="text-muted glyphicon glyphicon-alert"></span> <span class="dict-title">Unassociated Data</span> <small class="dict-total-count"></small></h4> <span class="dictionary-details-entry-label"></span>
<span class="dictionary-details-entry-info"></span>
</div></template>
<template id="dictionary-extra-template"><div class="well well-sm">
<h4><span class="text-muted glyphicon glyphicon-alert"></span> <span class="dictionary-title">Unassociated Data</span> <small class="dictionary-total-count"></small></h4>
<p class="text-warning"> <p class="text-warning">
The database contains extra data which is not associated with any installed dictionary. The database contains extra data which is not associated with any installed dictionary.
Purging the database can fix this issue. Purging the database can fix this issue.
</p> </p>
<pre class="debug dict-counts" hidden></pre> <pre class="debug dictionary-counts" hidden></pre>
</div></template> </div></template>
</div> </div>