Update GenericSettingController to use DOMSettingsBinder (#578)

This commit is contained in:
toasted-nutbread 2020-05-30 16:20:31 -04:00 committed by GitHub
parent f228078613
commit 395a0f4096
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 94 additions and 221 deletions

View File

@ -16,182 +16,47 @@
*/ */
/* globals /* globals
* DOMSettingsBinder
* utilBackgroundIsolate * utilBackgroundIsolate
*/ */
class GenericSettingController { class GenericSettingController {
constructor(settingsController) { constructor(settingsController) {
this._settingsController = settingsController; this._settingsController = settingsController;
this._settingsBinder = null;
} }
async prepare() { async prepare() {
$('input, select, textarea').not('.anki-model').not('.ignore-form-changes *').change(this._onFormOptionsChanged.bind(this)); this._settingsBinder = new DOMSettingsBinder({
getOptionsContext: () => this._settingsController.getOptionsContext(),
source: this._settingsController.source,
transforms: [
['setDocumentAttribute', this._setDocumentAttribute.bind(this)],
['splitTags', this._splitTags.bind(this)],
['joinTags', this._joinTags.bind(this)]
]
});
this._settingsBinder.observe(document.body);
this._settingsController.on('optionsChanged', this._onOptionsChanged.bind(this)); this._settingsController.on('optionsChanged', this._onOptionsChanged.bind(this));
const options = await this._settingsController.getOptions();
this._onOptionsChanged({options});
} }
// Private // Private
_onOptionsChanged({options}) { _onOptionsChanged() {
$('#enable').prop('checked', options.general.enable); this._settingsBinder.refresh();
$('#show-usage-guide').prop('checked', options.general.showGuide);
$('#compact-tags').prop('checked', options.general.compactTags);
$('#compact-glossaries').prop('checked', options.general.compactGlossaries);
$('#result-output-mode').val(options.general.resultOutputMode);
$('#show-debug-info').prop('checked', options.general.debugInfo);
$('#show-advanced-options').prop('checked', options.general.showAdvanced);
$('#max-displayed-results').val(options.general.maxResults);
$('#popup-display-mode').val(options.general.popupDisplayMode);
$('#popup-horizontal-text-position').val(options.general.popupHorizontalTextPosition);
$('#popup-vertical-text-position').val(options.general.popupVerticalTextPosition);
$('#popup-width').val(options.general.popupWidth);
$('#popup-height').val(options.general.popupHeight);
$('#popup-horizontal-offset').val(options.general.popupHorizontalOffset);
$('#popup-vertical-offset').val(options.general.popupVerticalOffset);
$('#popup-horizontal-offset2').val(options.general.popupHorizontalOffset2);
$('#popup-vertical-offset2').val(options.general.popupVerticalOffset2);
$('#popup-scaling-factor').val(options.general.popupScalingFactor);
$('#popup-scale-relative-to-page-zoom').prop('checked', options.general.popupScaleRelativeToPageZoom);
$('#popup-scale-relative-to-visual-viewport').prop('checked', options.general.popupScaleRelativeToVisualViewport);
$('#show-pitch-accent-downstep-notation').prop('checked', options.general.showPitchAccentDownstepNotation);
$('#show-pitch-accent-position-notation').prop('checked', options.general.showPitchAccentPositionNotation);
$('#show-pitch-accent-graph').prop('checked', options.general.showPitchAccentGraph);
$('#show-iframe-popups-in-root-frame').prop('checked', options.general.showIframePopupsInRootFrame);
$('#popup-theme').val(options.general.popupTheme);
$('#popup-outer-theme').val(options.general.popupOuterTheme);
$('#custom-popup-css').val(options.general.customPopupCss);
$('#custom-popup-outer-css').val(options.general.customPopupOuterCss);
$('#audio-playback-enabled').prop('checked', options.audio.enabled);
$('#auto-play-audio').prop('checked', options.audio.autoPlay);
$('#audio-playback-volume').val(options.audio.volume);
$('#audio-custom-source').val(options.audio.customSourceUrl);
$('#text-to-speech-voice').val(options.audio.textToSpeechVoice).attr('data-value', options.audio.textToSpeechVoice);
$('#middle-mouse-button-scan').prop('checked', options.scanning.middleMouse);
$('#touch-input-enabled').prop('checked', options.scanning.touchInputEnabled);
$('#select-matched-text').prop('checked', options.scanning.selectText);
$('#search-alphanumeric').prop('checked', options.scanning.alphanumeric);
$('#auto-hide-results').prop('checked', options.scanning.autoHideResults);
$('#deep-dom-scan').prop('checked', options.scanning.deepDomScan);
$('#enable-search-within-first-popup').prop('checked', options.scanning.enablePopupSearch);
$('#enable-scanning-of-popup-expressions').prop('checked', options.scanning.enableOnPopupExpressions);
$('#enable-scanning-on-search-page').prop('checked', options.scanning.enableOnSearchPage);
$('#enable-search-tags').prop('checked', options.scanning.enableSearchTags);
$('#scan-delay').val(options.scanning.delay);
$('#scan-length').val(options.scanning.length);
$('#scan-modifier-key').val(options.scanning.modifier);
$('#popup-nesting-max-depth').val(options.scanning.popupNestingMaxDepth);
$('#translation-convert-half-width-characters').val(options.translation.convertHalfWidthCharacters);
$('#translation-convert-numeric-characters').val(options.translation.convertNumericCharacters);
$('#translation-convert-alphabetic-characters').val(options.translation.convertAlphabeticCharacters);
$('#translation-convert-hiragana-to-katakana').val(options.translation.convertHiraganaToKatakana);
$('#translation-convert-katakana-to-hiragana').val(options.translation.convertKatakanaToHiragana);
$('#translation-collapse-emphatic-sequences').val(options.translation.collapseEmphaticSequences);
$('#parsing-scan-enable').prop('checked', options.parsing.enableScanningParser);
$('#parsing-mecab-enable').prop('checked', options.parsing.enableMecabParser);
$('#parsing-term-spacing').prop('checked', options.parsing.termSpacing);
$('#parsing-reading-mode').val(options.parsing.readingMode);
$('#anki-enable').prop('checked', options.anki.enable);
$('#card-tags').val(options.anki.tags.join(' '));
$('#sentence-detection-extent').val(options.anki.sentenceExt);
$('#interface-server').val(options.anki.server);
$('#duplicate-scope').val(options.anki.duplicateScope);
$('#screenshot-format').val(options.anki.screenshot.format);
$('#screenshot-quality').val(options.anki.screenshot.quality);
this._formUpdateVisibility(options);
} }
_formRead(options) { _setDocumentAttribute(value, metadata, element) {
options.general.enable = $('#enable').prop('checked'); document.documentElement.setAttribute(element.dataset.documentAttribute, `${value}`);
options.general.showGuide = $('#show-usage-guide').prop('checked'); return value;
options.general.compactTags = $('#compact-tags').prop('checked');
options.general.compactGlossaries = $('#compact-glossaries').prop('checked');
options.general.resultOutputMode = $('#result-output-mode').val();
options.general.debugInfo = $('#show-debug-info').prop('checked');
options.general.showAdvanced = $('#show-advanced-options').prop('checked');
options.general.maxResults = parseInt($('#max-displayed-results').val(), 10);
options.general.popupDisplayMode = $('#popup-display-mode').val();
options.general.popupHorizontalTextPosition = $('#popup-horizontal-text-position').val();
options.general.popupVerticalTextPosition = $('#popup-vertical-text-position').val();
options.general.popupWidth = parseInt($('#popup-width').val(), 10);
options.general.popupHeight = parseInt($('#popup-height').val(), 10);
options.general.popupHorizontalOffset = parseInt($('#popup-horizontal-offset').val(), 0);
options.general.popupVerticalOffset = parseInt($('#popup-vertical-offset').val(), 10);
options.general.popupHorizontalOffset2 = parseInt($('#popup-horizontal-offset2').val(), 0);
options.general.popupVerticalOffset2 = parseInt($('#popup-vertical-offset2').val(), 10);
options.general.popupScalingFactor = parseFloat($('#popup-scaling-factor').val());
options.general.popupScaleRelativeToPageZoom = $('#popup-scale-relative-to-page-zoom').prop('checked');
options.general.popupScaleRelativeToVisualViewport = $('#popup-scale-relative-to-visual-viewport').prop('checked');
options.general.showPitchAccentDownstepNotation = $('#show-pitch-accent-downstep-notation').prop('checked');
options.general.showPitchAccentPositionNotation = $('#show-pitch-accent-position-notation').prop('checked');
options.general.showPitchAccentGraph = $('#show-pitch-accent-graph').prop('checked');
options.general.showIframePopupsInRootFrame = $('#show-iframe-popups-in-root-frame').prop('checked');
options.general.popupTheme = $('#popup-theme').val();
options.general.popupOuterTheme = $('#popup-outer-theme').val();
options.general.customPopupCss = $('#custom-popup-css').val();
options.general.customPopupOuterCss = $('#custom-popup-outer-css').val();
options.audio.enabled = $('#audio-playback-enabled').prop('checked');
options.audio.autoPlay = $('#auto-play-audio').prop('checked');
options.audio.volume = parseFloat($('#audio-playback-volume').val());
options.audio.customSourceUrl = $('#audio-custom-source').val();
options.audio.textToSpeechVoice = $('#text-to-speech-voice').val();
options.scanning.middleMouse = $('#middle-mouse-button-scan').prop('checked');
options.scanning.touchInputEnabled = $('#touch-input-enabled').prop('checked');
options.scanning.selectText = $('#select-matched-text').prop('checked');
options.scanning.alphanumeric = $('#search-alphanumeric').prop('checked');
options.scanning.autoHideResults = $('#auto-hide-results').prop('checked');
options.scanning.deepDomScan = $('#deep-dom-scan').prop('checked');
options.scanning.enablePopupSearch = $('#enable-search-within-first-popup').prop('checked');
options.scanning.enableOnPopupExpressions = $('#enable-scanning-of-popup-expressions').prop('checked');
options.scanning.enableOnSearchPage = $('#enable-scanning-on-search-page').prop('checked');
options.scanning.enableSearchTags = $('#enable-search-tags').prop('checked');
options.scanning.delay = parseInt($('#scan-delay').val(), 10);
options.scanning.length = parseInt($('#scan-length').val(), 10);
options.scanning.modifier = $('#scan-modifier-key').val();
options.scanning.popupNestingMaxDepth = parseInt($('#popup-nesting-max-depth').val(), 10);
options.translation.convertHalfWidthCharacters = $('#translation-convert-half-width-characters').val();
options.translation.convertNumericCharacters = $('#translation-convert-numeric-characters').val();
options.translation.convertAlphabeticCharacters = $('#translation-convert-alphabetic-characters').val();
options.translation.convertHiraganaToKatakana = $('#translation-convert-hiragana-to-katakana').val();
options.translation.convertKatakanaToHiragana = $('#translation-convert-katakana-to-hiragana').val();
options.translation.collapseEmphaticSequences = $('#translation-collapse-emphatic-sequences').val();
options.parsing.enableScanningParser = $('#parsing-scan-enable').prop('checked');
options.parsing.enableMecabParser = $('#parsing-mecab-enable').prop('checked');
options.parsing.termSpacing = $('#parsing-term-spacing').prop('checked');
options.parsing.readingMode = $('#parsing-reading-mode').val();
options.anki.enable = $('#anki-enable').prop('checked');
options.anki.tags = utilBackgroundIsolate($('#card-tags').val().split(/[,; ]+/));
options.anki.sentenceExt = parseInt($('#sentence-detection-extent').val(), 10);
options.anki.server = $('#interface-server').val();
options.anki.duplicateScope = $('#duplicate-scope').val();
options.anki.screenshot.format = $('#screenshot-format').val();
options.anki.screenshot.quality = parseInt($('#screenshot-quality').val(), 10);
} }
async _onFormOptionsChanged() { _splitTags(value) {
const options = await this._settingsController.getOptionsMutable(); return `${value}`.split(/[,; ]+/).filter((v) => !!v);
this._formRead(options);
this._formUpdateVisibility(options);
await this._settingsController.save();
} }
_formUpdateVisibility(options) { _joinTags(value) {
document.documentElement.dataset.optionsAnkiEnable = `${!!options.anki.enable}`; return value.join(' ');
document.documentElement.dataset.optionsGeneralDebugInfo = `${!!options.general.debugInfo}`;
document.documentElement.dataset.optionsGeneralShowAdvanced = `${!!options.general.showAdvanced}`;
document.documentElement.dataset.optionsGeneralResultOutputMode = `${options.general.resultOutputMode}`;
} }
} }

View File

@ -28,6 +28,10 @@ class SettingsController extends EventDispatcher {
this._source = yomichan.generateId(16); this._source = yomichan.generateId(16);
} }
get source() {
return this._source;
}
get profileIndex() { get profileIndex() {
return this._profileIndex; return this._profileIndex;
} }

View File

@ -135,7 +135,7 @@
<h3>General Options</h3> <h3>General Options</h3>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="enable"> Enable content scanning</label> <label><input type="checkbox" id="enable" data-setting="general.enable"> Enable content scanning</label>
</div> </div>
<div class="checkbox ignore-form-changes" data-hide-for-browser="firefox-mobile"> <div class="checkbox ignore-form-changes" data-hide-for-browser="firefox-mobile">
@ -143,52 +143,52 @@
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="show-usage-guide"> Show usage guide on startup</label> <label><input type="checkbox" id="show-usage-guide" data-setting="general.showGuide"> Show usage guide on startup</label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="compact-tags"> Compact tags</label> <label><input type="checkbox" id="compact-tags" data-setting="general.compactTags"> Compact tags</label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="compact-glossaries"> Compact glossaries</label> <label><input type="checkbox" id="compact-glossaries" data-setting="general.compactGlossaries"> Compact glossaries</label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="show-advanced-options"> Show advanced options</label> <label><input type="checkbox" id="show-advanced-options" data-setting="general.showAdvanced" data-transform-pre="setDocumentAttribute" data-transform-post="setDocumentAttribute" data-document-attribute="data-options-general-show-advanced"> Show advanced options</label>
</div> </div>
<div class="checkbox options-advanced"> <div class="checkbox options-advanced">
<label><input type="checkbox" id="popup-scale-relative-to-page-zoom"> Change popup size relative to page zoom level</label> <label><input type="checkbox" id="popup-scale-relative-to-page-zoom" data-setting="general.popupScaleRelativeToPageZoom"> Change popup size relative to page zoom level</label>
</div> </div>
<div class="checkbox options-advanced"> <div class="checkbox options-advanced">
<label><input type="checkbox" id="popup-scale-relative-to-visual-viewport"> Change popup size relative to page viewport</label> <label><input type="checkbox" id="popup-scale-relative-to-visual-viewport" data-setting="general.popupScaleRelativeToVisualViewport"> Change popup size relative to page viewport</label>
</div> </div>
<div class="checkbox options-advanced"> <div class="checkbox options-advanced">
<label><input type="checkbox" id="show-pitch-accent-downstep-notation"> Show downstep notation for pitch accents</label> <label><input type="checkbox" id="show-pitch-accent-downstep-notation" data-setting="general.showPitchAccentDownstepNotation"> Show downstep notation for pitch accents</label>
</div> </div>
<div class="checkbox options-position"> <div class="checkbox options-position">
<label><input type="checkbox" id="show-pitch-accent-position-notation"> Show position notation for pitch accents</label> <label><input type="checkbox" id="show-pitch-accent-position-notation" data-setting="general.showPitchAccentPositionNotation"> Show position notation for pitch accents</label>
</div> </div>
<div class="checkbox options-advanced"> <div class="checkbox options-advanced">
<label><input type="checkbox" id="show-pitch-accent-graph"> Show graph for pitch accents</label> <label><input type="checkbox" id="show-pitch-accent-graph" data-setting="general.showPitchAccentGraph"> Show graph for pitch accents</label>
</div> </div>
<div class="checkbox options-advanced"> <div class="checkbox options-advanced">
<label><input type="checkbox" id="show-iframe-popups-in-root-frame"> Show iframe popups in root frame</label> <label><input type="checkbox" id="show-iframe-popups-in-root-frame" data-setting="general.showIframePopupsInRootFrame"> Show iframe popups in root frame</label>
</div> </div>
<div class="checkbox options-advanced"> <div class="checkbox options-advanced">
<label><input type="checkbox" id="show-debug-info"> Show debug information</label> <label><input type="checkbox" id="show-debug-info" data-setting="general.debugInfo" data-transform-pre="setDocumentAttribute" data-transform-post="setDocumentAttribute" data-document-attribute="data-options-general-debug-info"> Show debug information</label>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="result-output-mode">Result grouping</label> <label for="result-output-mode">Result grouping</label>
<select class="form-control" id="result-output-mode"> <select class="form-control" id="result-output-mode" data-setting="general.resultOutputMode" data-transform-pre="setDocumentAttribute" data-transform-post="setDocumentAttribute" data-document-attribute="data-options-general-result-output-mode">
<option value="group">Group results by term-reading pairs</option> <option value="group">Group results by term-reading pairs</option>
<option value="merge">Group results by main dictionary entry</option> <option value="merge">Group results by main dictionary entry</option>
<option value="split">Split definitions to their own results</option> <option value="split">Split definitions to their own results</option>
@ -197,7 +197,7 @@
<div class="form-group"> <div class="form-group">
<label for="popup-display-mode">Popup display mode</label> <label for="popup-display-mode">Popup display mode</label>
<select class="form-control" id="popup-display-mode"> <select class="form-control" id="popup-display-mode" data-setting="general.popupDisplayMode">
<option value="default">Default</option> <option value="default">Default</option>
<option value="full-width">Full width</option> <option value="full-width">Full width</option>
</select> </select>
@ -205,26 +205,26 @@
<div class="form-group"> <div class="form-group">
<label for="popup-scaling-factor">Popup size multiplier</label> <label for="popup-scaling-factor">Popup size multiplier</label>
<input type="number" min="0" id="popup-scaling-factor" class="form-control"> <input type="number" min="0" id="popup-scaling-factor" data-setting="general.popupScalingFactor" class="form-control">
</div> </div>
<div class="form-group options-advanced"> <div class="form-group options-advanced">
<label for="max-displayed-results">Maximum displayed results</label> <label for="max-displayed-results">Maximum displayed results</label>
<input type="number" min="1" id="max-displayed-results" class="form-control"> <input type="number" min="1" id="max-displayed-results" class="form-control" data-setting="general.maxResults">
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="row"> <div class="row">
<div class="col-xs-6"> <div class="col-xs-6">
<label for="popup-horizontal-text-position">Popup position for horizontal text</label> <label for="popup-horizontal-text-position">Popup position for horizontal text</label>
<select class="form-control" id="popup-horizontal-text-position"> <select class="form-control" id="popup-horizontal-text-position" data-setting="general.popupHorizontalTextPosition">
<option value="below">Below text</option> <option value="below">Below text</option>
<option value="above">Above text</option> <option value="above">Above text</option>
</select> </select>
</div> </div>
<div class="col-xs-6"> <div class="col-xs-6">
<label for="popup-vertical-text-position">Popup position for vertical text</label> <label for="popup-vertical-text-position">Popup position for vertical text</label>
<select class="form-control" id="popup-vertical-text-position"> <select class="form-control" id="popup-vertical-text-position" data-setting="general.popupVerticalTextPosition">
<option value="default">Same as for horizontal text</option> <option value="default">Same as for horizontal text</option>
<option value="before">Before text reading direction</option> <option value="before">Before text reading direction</option>
<option value="after">After text reading direction</option> <option value="after">After text reading direction</option>
@ -239,11 +239,11 @@
<div class="row"> <div class="row">
<div class="col-xs-6"> <div class="col-xs-6">
<label for="popup-width">Popup width <span class="label-light">(in pixels)</span></label> <label for="popup-width">Popup width <span class="label-light">(in pixels)</span></label>
<input type="number" min="1" id="popup-width" class="form-control"> <input type="number" min="1" id="popup-width" class="form-control" data-setting="general.popupWidth">
</div> </div>
<div class="col-xs-6"> <div class="col-xs-6">
<label for="popup-height">Popup height <span class="label-light">(in pixels)</span></label> <label for="popup-height">Popup height <span class="label-light">(in pixels)</span></label>
<input type="number" min="1" id="popup-height" class="form-control"> <input type="number" min="1" id="popup-height" class="form-control" data-setting="general.popupHeight">
</div> </div>
</div> </div>
</div> </div>
@ -252,11 +252,11 @@
<div class="row"> <div class="row">
<div class="col-xs-6"> <div class="col-xs-6">
<label for="popup-horizontal-offset">Horizontal popup offset <span class="label-light">(in pixels)</span></label> <label for="popup-horizontal-offset">Horizontal popup offset <span class="label-light">(in pixels)</span></label>
<input type="number" min="0" id="popup-horizontal-offset" class="form-control"> <input type="number" min="0" id="popup-horizontal-offset" class="form-control" data-setting="general.popupHorizontalOffset">
</div> </div>
<div class="col-xs-6"> <div class="col-xs-6">
<label for="popup-vertical-offset">Vertical popup offset <span class="label-light">(in pixels)</span></label> <label for="popup-vertical-offset">Vertical popup offset <span class="label-light">(in pixels)</span></label>
<input type="number" min="0" id="popup-vertical-offset" class="form-control"> <input type="number" min="0" id="popup-vertical-offset" class="form-control" data-setting="general.popupVerticalOffset">
</div> </div>
</div> </div>
</div> </div>
@ -265,11 +265,11 @@
<div class="row"> <div class="row">
<div class="col-xs-6"> <div class="col-xs-6">
<label for="popup-horizontal-offset2">Horizontal popup offset for vertical text <span class="label-light">(in pixels)</span></label> <label for="popup-horizontal-offset2">Horizontal popup offset for vertical text <span class="label-light">(in pixels)</span></label>
<input type="number" min="0" id="popup-horizontal-offset2" class="form-control"> <input type="number" min="0" id="popup-horizontal-offset2" class="form-control" data-setting="general.popupHorizontalOffset2">
</div> </div>
<div class="col-xs-6"> <div class="col-xs-6">
<label for="popup-vertical-offset2">Vertical popup offset for vertical text <span class="label-light">(in pixels)</span></label> <label for="popup-vertical-offset2">Vertical popup offset for vertical text <span class="label-light">(in pixels)</span></label>
<input type="number" min="0" id="popup-vertical-offset2" class="form-control"> <input type="number" min="0" id="popup-vertical-offset2" class="form-control" data-setting="general.popupVerticalOffset2">
</div> </div>
</div> </div>
</div> </div>
@ -278,14 +278,14 @@
<div class="row"> <div class="row">
<div class="col-xs-6"> <div class="col-xs-6">
<label for="popup-theme">Popup theme</label> <label for="popup-theme">Popup theme</label>
<select class="form-control" id="popup-theme"> <select class="form-control" id="popup-theme" data-setting="general.popupTheme">
<option value="default">Light</option> <option value="default">Light</option>
<option value="dark">Dark</option> <option value="dark">Dark</option>
</select> </select>
</div> </div>
<div class="col-xs-6"> <div class="col-xs-6">
<label for="popup-outer-theme">Popup shadow theme</label> <label for="popup-outer-theme">Popup shadow theme</label>
<select class="form-control" id="popup-outer-theme"> <select class="form-control" id="popup-outer-theme" data-setting="general.popupOuterTheme">
<option value="auto">Auto-detect</option> <option value="auto">Auto-detect</option>
<option value="default">Light</option> <option value="default">Light</option>
<option value="dark">Dark</option> <option value="dark">Dark</option>
@ -298,11 +298,11 @@
<div class="row"> <div class="row">
<div class="col-xs-6"> <div class="col-xs-6">
<label for="custom-popup-css">Custom popup CSS</label> <label for="custom-popup-css">Custom popup CSS</label>
<div><textarea autocomplete="off" spellcheck="false" wrap="soft" id="custom-popup-css" class="form-control"></textarea></div> <div><textarea autocomplete="off" spellcheck="false" wrap="soft" id="custom-popup-css" class="form-control" data-setting="general.customPopupCss"></textarea></div>
</div> </div>
<div class="col-xs-6"> <div class="col-xs-6">
<label for="custom-popup-outer-css">Custom popup outer CSS</label> <label for="custom-popup-outer-css">Custom popup outer CSS</label>
<div><textarea autocomplete="off" spellcheck="false" wrap="soft" id="custom-popup-outer-css" class="form-control" placeholder="iframe.yomichan-float { /*styles*/ }"></textarea></div> <div><textarea autocomplete="off" spellcheck="false" wrap="soft" id="custom-popup-outer-css" class="form-control" data-setting="general.customPopupOuterCss" placeholder="iframe.yomichan-float { /*styles*/ }"></textarea></div>
</div> </div>
</div> </div>
</div> </div>
@ -324,22 +324,22 @@
<h3>Audio Options</h3> <h3>Audio Options</h3>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="audio-playback-enabled"> Enable audio playback in search results</label> <label><input type="checkbox" id="audio-playback-enabled" data-setting="audio.enabled"> Enable audio playback in search results</label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="auto-play-audio"> Play audio automatically</label> <label><input type="checkbox" id="auto-play-audio" data-setting="audio.autoPlay"> Play audio automatically</label>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="audio-playback-volume">Audio playback volume <span class="label-light">(percent)</span></label> <label for="audio-playback-volume">Audio playback volume <span class="label-light">(percent)</span></label>
<input type="number" min="0" max="100" id="audio-playback-volume" class="form-control"> <input type="number" min="0" max="100" id="audio-playback-volume" class="form-control" data-setting="audio.volume">
</div> </div>
<div class="form-group" id="text-to-speech-voice-container" hidden> <div class="form-group" id="text-to-speech-voice-container" hidden>
<label for="text-to-speech-voice">Text-to-speech voice</label> <label for="text-to-speech-voice">Text-to-speech voice</label>
<div class="input-group"> <div class="input-group">
<select class="form-control" id="text-to-speech-voice"></select> <select class="form-control" id="text-to-speech-voice" data-setting="audio.textToSpeechVoice"></select>
<div class="input-group-btn"> <div class="input-group-btn">
<button class="btn btn-default" id="text-to-speech-voice-test" title="Test voice" data-speech-text="よみちゃん"><span class="glyphicon glyphicon-volume-up"></span></button> <button class="btn btn-default" id="text-to-speech-voice-test" title="Test voice" data-speech-text="よみちゃん"><span class="glyphicon glyphicon-volume-up"></span></button>
</div> </div>
@ -348,7 +348,7 @@
<div class="form-group options-advanced"> <div class="form-group options-advanced">
<label for="audio-custom-source">Custom audio source <span class="label-light">(URL)</span></label> <label for="audio-custom-source">Custom audio source <span class="label-light">(URL)</span></label>
<input type="text" id="audio-custom-source" class="form-control" placeholder="Example: http://localhost/audio.mp3?expression={expression}&reading={reading}"> <input type="text" id="audio-custom-source" class="form-control" data-setting="audio.customSourceUrl" placeholder="Example: http://localhost/audio.mp3?expression={expression}&reading={reading}">
</div> </div>
<div class="form-group ignore-form-changes"> <div class="form-group ignore-form-changes">
@ -377,42 +377,42 @@
<h3>Scanning Options</h3> <h3>Scanning Options</h3>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="middle-mouse-button-scan"> Middle mouse button scans</label> <label><input type="checkbox" id="middle-mouse-button-scan" data-setting="scanning.middleMouse"> Middle mouse button scans</label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="touch-input-enabled"> Touch input enabled</label> <label><input type="checkbox" id="touch-input-enabled" data-setting="scanning.touchInputEnabled"> Touch input enabled</label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="select-matched-text"> Select matched text</label> <label><input type="checkbox" id="select-matched-text" data-setting="scanning.selectText"> Select matched text</label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="search-alphanumeric"> Search alphanumeric text</label> <label><input type="checkbox" id="search-alphanumeric" data-setting="scanning.alphanumeric"> Search alphanumeric text</label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="auto-hide-results"> Automatically hide results</label> <label><input type="checkbox" id="auto-hide-results" data-setting="scanning.autoHideResults"> Automatically hide results</label>
</div> </div>
<div class="checkbox options-advanced"> <div class="checkbox options-advanced">
<label><input type="checkbox" id="deep-dom-scan"> Deep DOM scan</label> <label><input type="checkbox" id="deep-dom-scan" data-setting="scanning.deepDomScan"> Deep DOM scan</label>
</div> </div>
<div class="form-group options-advanced"> <div class="form-group options-advanced">
<label for="scan-delay">Scan delay <span class="label-light">(in milliseconds)</span></label> <label for="scan-delay">Scan delay <span class="label-light">(in milliseconds)</span></label>
<input type="number" min="0" id="scan-delay" class="form-control"> <input type="number" min="0" id="scan-delay" class="form-control" data-setting="scanning.delay">
</div> </div>
<div class="form-group options-advanced"> <div class="form-group options-advanced">
<label for="scan-length">Scan length <span class="label-light">(in characters)</span></label> <label for="scan-length">Scan length <span class="label-light">(in characters)</span></label>
<input type="number" min="1" step="1" id="scan-length" class="form-control"> <input type="number" min="1" step="1" id="scan-length" class="form-control" data-setting="scanning.length">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="scan-modifier-key">Scan modifier key</label> <label for="scan-modifier-key">Scan modifier key</label>
<select class="form-control" id="scan-modifier-key"></select> <select class="form-control" id="scan-modifier-key" data-setting="scanning.modifier"></select>
</div> </div>
</div> </div>
@ -447,7 +447,7 @@
<div class="form-group"> <div class="form-group">
<label for="translation-convert-half-width-characters">Convert half width characters to full width <span class="label-light">(ヨミチャン &rarr; ヨミチャン)</span></label> <label for="translation-convert-half-width-characters">Convert half width characters to full width <span class="label-light">(ヨミチャン &rarr; ヨミチャン)</span></label>
<select class="form-control" id="translation-convert-half-width-characters"> <select class="form-control" id="translation-convert-half-width-characters" data-setting="translation.convertHalfWidthCharacters">
<option value="false">Disabled</option> <option value="false">Disabled</option>
<option value="true">Enabled</option> <option value="true">Enabled</option>
<option value="variant">Use both variants</option> <option value="variant">Use both variants</option>
@ -456,7 +456,7 @@
<div class="form-group"> <div class="form-group">
<label for="translation-convert-numeric-characters">Convert numeric characters to full width <span class="label-light">(1234 &rarr; )</span></label> <label for="translation-convert-numeric-characters">Convert numeric characters to full width <span class="label-light">(1234 &rarr; )</span></label>
<select class="form-control" id="translation-convert-numeric-characters"> <select class="form-control" id="translation-convert-numeric-characters" data-setting="translation.convertNumericCharacters">
<option value="false">Disabled</option> <option value="false">Disabled</option>
<option value="true">Enabled</option> <option value="true">Enabled</option>
<option value="variant">Use both variants</option> <option value="variant">Use both variants</option>
@ -465,7 +465,7 @@
<div class="form-group"> <div class="form-group">
<label for="translation-convert-alphabetic-characters">Convert alphabetic characters to hiragana <span class="label-light">(yomichan &rarr; よみちゃん)</span></label> <label for="translation-convert-alphabetic-characters">Convert alphabetic characters to hiragana <span class="label-light">(yomichan &rarr; よみちゃん)</span></label>
<select class="form-control" id="translation-convert-alphabetic-characters"> <select class="form-control" id="translation-convert-alphabetic-characters" data-setting="translation.convertAlphabeticCharacters">
<option value="false">Disabled</option> <option value="false">Disabled</option>
<option value="true">Enabled</option> <option value="true">Enabled</option>
<option value="variant">Use both variants</option> <option value="variant">Use both variants</option>
@ -474,7 +474,7 @@
<div class="form-group"> <div class="form-group">
<label for="translation-convert-hiragana-to-katakana">Convert hiragana to katakana <span class="label-light">(よみちゃん &rarr; ヨミチャン)</span></label> <label for="translation-convert-hiragana-to-katakana">Convert hiragana to katakana <span class="label-light">(よみちゃん &rarr; ヨミチャン)</span></label>
<select class="form-control" id="translation-convert-hiragana-to-katakana"> <select class="form-control" id="translation-convert-hiragana-to-katakana" data-setting="translation.convertHiraganaToKatakana">
<option value="false">Disabled</option> <option value="false">Disabled</option>
<option value="true">Enabled</option> <option value="true">Enabled</option>
<option value="variant">Use both variants</option> <option value="variant">Use both variants</option>
@ -483,7 +483,7 @@
<div class="form-group"> <div class="form-group">
<label for="translation-convert-katakana-to-hiragana">Convert katakana to hiragana <span class="label-light">(ヨミチャン &rarr; よみちゃん)</span></label> <label for="translation-convert-katakana-to-hiragana">Convert katakana to hiragana <span class="label-light">(ヨミチャン &rarr; よみちゃん)</span></label>
<select class="form-control" id="translation-convert-katakana-to-hiragana"> <select class="form-control" id="translation-convert-katakana-to-hiragana" data-setting="translation.convertKatakanaToHiragana">
<option value="false">Disabled</option> <option value="false">Disabled</option>
<option value="true">Enabled</option> <option value="true">Enabled</option>
<option value="variant">Use both variants</option> <option value="variant">Use both variants</option>
@ -492,7 +492,7 @@
<div class="form-group"> <div class="form-group">
<label for="translation-collapse-emphatic-sequences">Collapse emphatic character sequences <span class="label-light">(すっっごーーい &rarr; すっごーい / すごい)</span></label> <label for="translation-collapse-emphatic-sequences">Collapse emphatic character sequences <span class="label-light">(すっっごーーい &rarr; すっごーい / すごい)</span></label>
<select class="form-control" id="translation-collapse-emphatic-sequences"> <select class="form-control" id="translation-collapse-emphatic-sequences" data-setting="translation.collapseEmphaticSequences">
<option value="false">Disabled</option> <option value="false">Disabled</option>
<option value="true">Collapse into single character</option> <option value="true">Collapse into single character</option>
<option value="full">Remove all characters</option> <option value="full">Remove all characters</option>
@ -509,24 +509,24 @@
</p> </p>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="enable-search-within-first-popup"> Enable search when clicking glossary entries and tags</label> <label><input type="checkbox" id="enable-search-within-first-popup" data-setting="scanning.enablePopupSearch"> Enable search when clicking glossary entries and tags</label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="enable-scanning-on-search-page"> Enable scanning on search page</label> <label><input type="checkbox" id="enable-scanning-on-search-page" data-setting="scanning.enableOnSearchPage"> Enable scanning on search page</label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="enable-scanning-of-popup-expressions"> Enable scanning of expressions in search results</label> <label><input type="checkbox" id="enable-scanning-of-popup-expressions" data-setting="scanning.enableOnPopupExpressions"> Enable scanning of expressions in search results</label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="enable-search-tags"> Enable clickable and scannable tags for searching expressions and their readings</label> <label><input type="checkbox" id="enable-search-tags" data-setting="scanning.enableSearchTags"> Enable clickable and scannable tags for searching expressions and their readings</label>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="popup-nesting-max-depth">Maximum number of additional popups</label> <label for="popup-nesting-max-depth">Maximum number of additional popups</label>
<input type="number" min="0" step="1" id="popup-nesting-max-depth" class="form-control"> <input type="number" min="0" step="1" id="popup-nesting-max-depth" class="form-control" data-setting="scanning.popupNestingMaxDepth">
</div> </div>
</div> </div>
@ -551,20 +551,20 @@
</p> </p>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="parsing-scan-enable"> Enable text parsing using installed dictionaries</label> <label><input type="checkbox" id="parsing-scan-enable" data-setting="parsing.enableScanningParser"> Enable text parsing using installed dictionaries</label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="parsing-mecab-enable"> Enable text parsing using MeCab</label> <label><input type="checkbox" id="parsing-mecab-enable" data-setting="parsing.enableMecabParser"> Enable text parsing using MeCab</label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="parsing-term-spacing"> Enable small spaces between parsed words</label> <label><input type="checkbox" id="parsing-term-spacing" data-setting="parsing.termSpacing"> Enable small spaces between parsed words</label>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="parsing-reading-mode">Reading mode</label> <label for="parsing-reading-mode">Reading mode</label>
<select class="form-control" id="parsing-reading-mode"> <select class="form-control" id="parsing-reading-mode" data-setting="parsing.readingMode">
<option value="hiragana">ひらがな</option> <option value="hiragana">ひらがな</option>
<option value="katakana">カタカナ</option> <option value="katakana">カタカナ</option>
<option value="romaji">Romaji</option> <option value="romaji">Romaji</option>
@ -621,7 +621,7 @@
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="database-enable-prefix-wildcard-searches"> Enable prefix wildcard searches</label> <label><input type="checkbox" id="database-enable-prefix-wildcard-searches" data-setting="global.database.prefixWildcardsSupported" data-scope="global"> Enable prefix wildcard searches</label>
<p class="help-block"> <p class="help-block">
This option only applies to newly imported dictionaries. This option only applies to newly imported dictionaries.
Enabling this option will also cause dictionary data to take up slightly more storage space. Enabling this option will also cause dictionary data to take up slightly more storage space.
@ -781,7 +781,7 @@
</p> </p>
<div class="checkbox"> <div class="checkbox">
<label><input type="checkbox" id="anki-enable"> Enable Anki integration</label> <label><input type="checkbox" id="anki-enable" data-setting="anki.enable" data-transform-pre="setDocumentAttribute" data-transform-post="setDocumentAttribute" data-document-attribute="data-options-anki-enable"> Enable Anki integration</label>
</div> </div>
<div id="anki-general"> <div id="anki-general">
@ -804,22 +804,22 @@
<div class="form-group"> <div class="form-group">
<label for="card-tags">Card tags <span class="label-light">(comma or space separated)</span></label> <label for="card-tags">Card tags <span class="label-light">(comma or space separated)</span></label>
<input type="text" id="card-tags" class="form-control"> <input type="text" id="card-tags" class="form-control" data-setting="anki.tags" data-transform-pre="splitTags" data-transform-post="joinTags">
</div> </div>
<div class="form-group options-advanced"> <div class="form-group options-advanced">
<label for="sentence-detection-extent">Sentence detection extent <span class="label-light">(in characters)</span></label> <label for="sentence-detection-extent">Sentence detection extent <span class="label-light">(in characters)</span></label>
<input type="number" min="1" step="1" id="sentence-detection-extent" class="form-control"> <input type="number" min="1" step="1" id="sentence-detection-extent" class="form-control" data-setting="anki.sentenceExt">
</div> </div>
<div class="form-group options-advanced"> <div class="form-group options-advanced">
<label for="interface-server">Interface server <span class="label-light">(Default: http://127.0.0.1:8765)</span></label> <label for="interface-server">Interface server <span class="label-light">(Default: http://127.0.0.1:8765)</span></label>
<input type="text" id="interface-server" class="form-control"> <input type="text" id="interface-server" class="form-control" data-setting="anki.server">
</div> </div>
<div class="form-group options-advanced"> <div class="form-group options-advanced">
<label for="duplicate-scope">Duplicate scope</label> <label for="duplicate-scope">Duplicate scope</label>
<select class="form-control" id="duplicate-scope"> <select class="form-control" id="duplicate-scope" data-setting="anki.duplicateScope">
<option value="collection">Collection</option> <option value="collection">Collection</option>
<option value="deck">Deck</option> <option value="deck">Deck</option>
</select> </select>
@ -827,7 +827,7 @@
<div class="form-group options-advanced"> <div class="form-group options-advanced">
<label for="screenshot-format">Screenshot format</label> <label for="screenshot-format">Screenshot format</label>
<select class="form-control" id="screenshot-format"> <select class="form-control" id="screenshot-format" data-setting="anki.screenshot.format">
<option value="png">PNG</option> <option value="png">PNG</option>
<option value="jpeg">JPEG</option> <option value="jpeg">JPEG</option>
</select> </select>
@ -835,7 +835,7 @@
<div class="form-group options-advanced"> <div class="form-group options-advanced">
<label for="screenshot-quality">Screenshot quality <span class="label-light">(JPEG only)</span></label> <label for="screenshot-quality">Screenshot quality <span class="label-light">(JPEG only)</span></label>
<input type="number" min="0" max="100" step="1" id="screenshot-quality" class="form-control"> <input type="number" min="0" max="100" step="1" id="screenshot-quality" class="form-control" data-setting="anki.screenshot.quality">
</div> </div>
<div id="anki-format"> <div id="anki-format">
@ -1144,11 +1144,15 @@
<script src="/bg/js/settings/clipboard-popups-controller.js"></script> <script src="/bg/js/settings/clipboard-popups-controller.js"></script>
<script src="/bg/js/settings/conditions-ui.js"></script> <script src="/bg/js/settings/conditions-ui.js"></script>
<script src="/bg/js/settings/dictionaries.js"></script> <script src="/bg/js/settings/dictionaries.js"></script>
<script src="/bg/js/settings/dom-settings-binder.js"></script>
<script src="/bg/js/settings/generic-setting-controller.js"></script> <script src="/bg/js/settings/generic-setting-controller.js"></script>
<script src="/bg/js/settings/popup-preview.js"></script> <script src="/bg/js/settings/popup-preview.js"></script>
<script src="/bg/js/settings/profiles.js"></script> <script src="/bg/js/settings/profiles.js"></script>
<script src="/bg/js/settings/settings-controller.js"></script> <script src="/bg/js/settings/settings-controller.js"></script>
<script src="/bg/js/settings/storage.js"></script> <script src="/bg/js/settings/storage.js"></script>
<script src="/mixed/js/object-property-accessor.js"></script>
<script src="/mixed/js/task-accumulator.js"></script>
<script src="/mixed/js/dom-data-binder.js"></script>
<script src="/bg/js/settings/main.js"></script> <script src="/bg/js/settings/main.js"></script>
</body> </body>