diff options
-rw-r--r-- | ext/bg/js/search-main.js | 1 | ||||
-rw-r--r-- | ext/bg/js/search.js | 91 | ||||
-rw-r--r-- | ext/bg/search.html | 166 | ||||
-rw-r--r-- | ext/fg/float.html | 131 | ||||
-rw-r--r-- | ext/fg/js/float.js | 2 | ||||
-rw-r--r-- | ext/mixed/css/display.css | 17 | ||||
-rw-r--r-- | ext/mixed/css/search.css | 326 | ||||
-rw-r--r-- | ext/mixed/js/display.js | 11 |
8 files changed, 532 insertions, 213 deletions
diff --git a/ext/bg/js/search-main.js b/ext/bg/js/search-main.js index cf9282fd..07130631 100644 --- a/ext/bg/js/search-main.js +++ b/ext/bg/js/search-main.js @@ -28,6 +28,7 @@ const displaySearch = new DisplaySearch(); await displaySearch.prepare(); + document.documentElement.dataset.loaded = 'true'; yomichan.ready(); } catch (e) { yomichan.logError(e); diff --git a/ext/bg/js/search.js b/ext/bg/js/search.js index af88bb76..bd840981 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search.js @@ -25,12 +25,14 @@ class DisplaySearch extends Display { constructor() { - super(document.querySelector('#spinner'), document.querySelector('#content')); - this._searchButton = document.querySelector('#search'); - this._queryInput = document.querySelector('#query'); + super(); + this._searchButton = document.querySelector('#search-button'); + this._queryInput = document.querySelector('#search-textbox'); this._introElement = document.querySelector('#intro'); this._clipboardMonitorEnableCheckbox = document.querySelector('#clipboard-monitor-enable'); this._wanakanaEnableCheckbox = document.querySelector('#wanakana-enable'); + this._queryInputEvents = new EventListenerCollection(); + this._wanakanaEnabled = false; this._isPrepared = false; this._introVisible = true; this._introAnimationTimer = null; @@ -42,7 +44,7 @@ class DisplaySearch extends Display { }); this._onKeyDownIgnoreKeys = new Map([ ['ANY_MOD', new Set([ - 'Tab', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'PageDown', 'PageUp', 'Home', 'End', + 'Tab', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'PageDown', 'PageUp', 'Home', 'End', 'Enter', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'F13', 'F14', 'F15', 'F16', 'F17', 'F18', 'F19', 'F20', 'F21', 'F22', 'F23', 'F24' @@ -71,22 +73,16 @@ class DisplaySearch extends Display { this.queryParserVisible = true; this.setHistorySettings({useBrowserHistory: true}); - const options = this.getOptions(); - if (options.general.enableWanakana === true) { - this._wanakanaEnableCheckbox.checked = true; - wanakana.bind(this._queryInput); - } else { - this._wanakanaEnableCheckbox.checked = false; - } + const enableWanakana = !!this.getOptions().general.enableWanakana; + this._wanakanaEnableCheckbox.checked = enableWanakana; + this._setWanakanaEnabled(enableWanakana); this._searchButton.addEventListener('click', this._onSearch.bind(this), false); - this._queryInput.addEventListener('input', this._onSearchInput.bind(this), false); this._wanakanaEnableCheckbox.addEventListener('change', this._onWanakanaEnableChange.bind(this)); window.addEventListener('copy', this._onCopy.bind(this)); this._clipboardMonitor.on('change', this._onExternalSearchUpdate.bind(this)); this._clipboardMonitorEnableCheckbox.addEventListener('change', this._onClipboardMonitorEnableChange.bind(this)); - this._updateSearchButton(); this._onModeChange(); await this._prepareNestedPopups(); @@ -141,7 +137,7 @@ class DisplaySearch extends Display { } postProcessQuery(query) { - if (this._isWanakanaEnabled()) { + if (this._wanakanaEnabled) { try { query = wanakana.toKana(query); } catch (e) { @@ -173,28 +169,27 @@ class DisplaySearch extends Display { if (typeof source !== 'string') { source = ''; } this._queryInput.value = source; + this._updateSearchHeight(); this._setIntroVisible(!valid, animate); - this._updateSearchButton(); } _onSearchInput() { - this._updateSearchButton(); - - const queryElementRect = this._queryInput.getBoundingClientRect(); - if (queryElementRect.top < 0 || queryElementRect.bottom > window.innerHeight) { - this._queryInput.scrollIntoView(); - } + this._updateSearchHeight(); } - _onSearch(e) { - if (this._queryInput === null) { - return; - } + _onSearchKeydown(e) { + if (e.code !== 'Enter' || e.shiftKey) { return; } + // Search e.preventDefault(); + e.stopImmediatePropagation(); + e.currentTarget.blur(); + this._search(); + } - const query = this._queryInput.value; - this._onSearchQueryUpdated(query, true); + _onSearch(e) { + e.preventDefault(); + this._search(); } _onCopy() { @@ -228,11 +223,7 @@ class DisplaySearch extends Display { _onWanakanaEnableChange(e) { const value = e.target.checked; - if (value) { - wanakana.bind(this._queryInput); - } else { - wanakana.unbind(this._queryInput); - } + this._setWanakanaEnabled(value); api.modifySettings([{ action: 'set', path: 'general.enableWanakana', @@ -254,8 +245,22 @@ class DisplaySearch extends Display { this._updateClipboardMonitorEnabled(); } - _isWanakanaEnabled() { - return this._wanakanaEnableCheckbox !== null && this._wanakanaEnableCheckbox.checked; + _setWanakanaEnabled(enabled) { + const input = this._queryInput; + this._queryInputEvents.removeAllEventListeners(); + + this._queryInputEvents.addEventListener(input, 'keydown', this._onSearchKeydown.bind(this), false); + + if (this._wanakanaEnabled !== enabled) { + this._wanakanaEnabled = enabled; + if (enabled) { + wanakana.bind(input); + } else { + wanakana.unbind(input); + } + } + + this._queryInputEvents.addEventListener(input, 'input', this._onSearchInput.bind(this), false); } _setIntroVisible(visible, animate) { @@ -314,10 +319,6 @@ class DisplaySearch extends Display { this._introElement.style.height = '0'; } - _updateSearchButton() { - this._searchButton.disabled = this._introVisible && (this._queryInput === null || this._queryInput.value.length === 0); - } - async _prepareNestedPopups() { let complete = false; @@ -388,4 +389,18 @@ class DisplaySearch extends Display { ); }); } + + _search() { + const query = this._queryInput.value; + this._onSearchQueryUpdated(query, true); + } + + _updateSearchHeight() { + const node = this._queryInput; + const {scrollHeight} = node; + const currentHeight = node.getBoundingClientRect().height; + if (scrollHeight >= currentHeight - 1) { + node.style.height = `${scrollHeight}px`; + } + } } diff --git a/ext/bg/search.html b/ext/bg/search.html index 8df20581..6988a235 100644 --- a/ext/bg/search.html +++ b/ext/bg/search.html @@ -1,105 +1,95 @@ <!DOCTYPE html> <html lang="en" data-yomichan-page="search"> - <head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width,initial-scale=1" /> - <title>Yomichan Search</title> - <link rel="icon" type="image/png" href="/mixed/img/icon16.png" sizes="16x16"> - <link rel="icon" type="image/png" href="/mixed/img/icon19.png" sizes="19x19"> - <link rel="icon" type="image/png" href="/mixed/img/icon32.png" sizes="32x32"> - <link rel="icon" type="image/png" href="/mixed/img/icon38.png" sizes="38x38"> - <link rel="icon" type="image/png" href="/mixed/img/icon48.png" sizes="48x48"> - <link rel="icon" type="image/png" href="/mixed/img/icon64.png" sizes="64x64"> - <link rel="icon" type="image/png" href="/mixed/img/icon128.png" sizes="128x128"> - <link rel="stylesheet" type="text/css" href="/mixed/lib/bootstrap/css/bootstrap.min.css"> - <link rel="stylesheet" type="text/css" href="/mixed/lib/bootstrap/css/bootstrap-theme.min.css"> - <link rel="stylesheet" type="text/css" href="/mixed/css/display.css"> - </head> - <body> - <div class="container"> - <div id="intro" style="overflow: hidden;"> - <div class="page-header"> - <h1>Yomichan Search</h1> - </div> - <p style="margin-bottom: 0;">Search your installed dictionaries by entering a Japanese expression into the field below.</p> - </div> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>Yomichan Search</title> + <link rel="icon" type="image/png" href="/mixed/img/icon16.png" sizes="16x16"> + <link rel="icon" type="image/png" href="/mixed/img/icon19.png" sizes="19x19"> + <link rel="icon" type="image/png" href="/mixed/img/icon32.png" sizes="32x32"> + <link rel="icon" type="image/png" href="/mixed/img/icon38.png" sizes="38x38"> + <link rel="icon" type="image/png" href="/mixed/img/icon48.png" sizes="48x48"> + <link rel="icon" type="image/png" href="/mixed/img/icon64.png" sizes="64x64"> + <link rel="icon" type="image/png" href="/mixed/img/icon128.png" sizes="128x128"> + <link rel="stylesheet" type="text/css" href="/mixed/css/search.css"> + <link rel="stylesheet" type="text/css" href="/mixed/css/display.css"> +</head> +<body> - <div class="search-input"> - <div class="input-group" style="padding-top: 20px;"> - <span title="Enable kana input method" class="input-group-text"> - <input type="checkbox" id="wanakana-enable" class="icon-checkbox" /> - <label for="wanakana-enable" class="scan-disable">あ</label> - </span> - <span title="Enable clipboard monitor" class="input-group-text"> - <input type="checkbox" id="clipboard-monitor-enable" class="icon-checkbox" /> - <label for="clipboard-monitor-enable"><span class="glyphicon glyphicon-paste"></span></label> - </span> - </div> +<div class="content"><div class="content-center"> - <form class="input-group"> - <input type="text" class="form-control" placeholder="Search for..." id="query" autofocus> - <span class="input-group-btn"> - <input type="submit" class="btn btn-default form-control" id="search" value="Search"> - </span> - </form> - </div> + <div id="intro"> + <h1>Yomichan Search</h1> + </div> - <div id="spinner" hidden><img src="/mixed/img/spinner.gif"></div> - - <div class="scan-disable" id="query-parser-container"> - <div id="query-parser-select-container" class="input-group"></div> - <div id="query-parser-content"></div> - </div> + <div class="scan-disable"> + <div class="search-options"> + <label class="search-option"> + <label class="toggle"><input type="checkbox" id="wanakana-enable"><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> + <span class="search-option-label">Automatic kana conversion</span> + </label> + <label class="search-option"> + <label class="toggle"><input type="checkbox" id="clipboard-monitor-enable"><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> + <span class="search-option-label">Clipboard monitor</span> + </label> + </div> + <div class="search-textbox-container"> + <textarea id="search-textbox" placeholder="Input a term, expression, sentence, or block of text" autocomplete="false" autofocus></textarea> + <button id="search-button"><span class="icon-button-icon" data-icon="magnifying-glass"></span></button> + </div> + </div> - <hr> + <div id="spinner" hidden><img src="/mixed/img/spinner.gif"></div> - <div id="navigation-header" class="navigation-header" hidden><div class="navigation-header-actions"> - <button class="action-button action-previous" data-icon="source-term" title="Source term (Alt + B)"></button> - <button class="action-button action-next" data-icon="source-term" title="Next term (Alt + F)"></button> - </div></div><div class="navigation-header-spacer"></div> + <div class="scan-disable" id="query-parser-container"> + <div id="query-parser-select-container"></div> + <div id="query-parser-content"></div> + </div> - <div id="content"></div> + <div id="definitions"></div> - <div id="no-results" hidden> - <div class="entry"> - <p>No results found.</p> - </div> - </div> + <div id="no-results" hidden> + <div class="entry"> + <p>No results found.</p> </div> + </div> + +</div></div> + +<script src="/mixed/lib/wanakana.min.js"></script> - <script src="/mixed/lib/wanakana.min.js"></script> +<script src="/mixed/js/core.js"></script> +<script src="/mixed/js/yomichan.js"></script> +<script src="/mixed/js/comm.js"></script> +<script src="/mixed/js/api.js"></script> +<script src="/mixed/js/japanese.js"></script> - <script src="/mixed/js/core.js"></script> - <script src="/mixed/js/yomichan.js"></script> - <script src="/mixed/js/comm.js"></script> - <script src="/mixed/js/api.js"></script> - <script src="/mixed/js/japanese.js"></script> +<script src="/mixed/js/cache-map.js"></script> +<script src="/mixed/js/document-util.js"></script> +<script src="/fg/js/dom-text-scanner.js"></script> +<script src="/fg/js/text-source-range.js"></script> +<script src="/fg/js/text-source-element.js"></script> +<script src="/mixed/js/audio-system.js"></script> +<script src="/mixed/js/dictionary-data-util.js"></script> +<script src="/mixed/js/display.js"></script> +<script src="/mixed/js/display-generator.js"></script> +<script src="/mixed/js/display-history.js"></script> +<script src="/mixed/js/dynamic-loader.js"></script> +<script src="/mixed/js/media-loader.js"></script> +<script src="/mixed/js/scroll.js"></script> +<script src="/mixed/js/text-scanner.js"></script> +<script src="/mixed/js/html-template-collection.js"></script> +<script src="/mixed/js/text-to-speech-audio.js"></script> - <script src="/mixed/js/cache-map.js"></script> - <script src="/mixed/js/document-util.js"></script> - <script src="/fg/js/dom-text-scanner.js"></script> - <script src="/fg/js/text-source-range.js"></script> - <script src="/fg/js/text-source-element.js"></script> - <script src="/mixed/js/audio-system.js"></script> - <script src="/mixed/js/dictionary-data-util.js"></script> - <script src="/mixed/js/display.js"></script> - <script src="/mixed/js/display-generator.js"></script> - <script src="/mixed/js/display-history.js"></script> - <script src="/mixed/js/dynamic-loader.js"></script> - <script src="/mixed/js/media-loader.js"></script> - <script src="/mixed/js/scroll.js"></script> - <script src="/mixed/js/text-scanner.js"></script> - <script src="/mixed/js/html-template-collection.js"></script> - <script src="/mixed/js/text-to-speech-audio.js"></script> +<script src="/bg/js/anki-note-builder.js"></script> +<script src="/bg/js/template-renderer-proxy.js"></script> - <script src="/bg/js/anki-note-builder.js"></script> - <script src="/bg/js/template-renderer-proxy.js"></script> +<script src="/bg/js/query-parser-generator.js"></script> +<script src="/bg/js/query-parser.js"></script> +<script src="/bg/js/clipboard-monitor.js"></script> +<script src="/bg/js/search.js"></script> - <script src="/bg/js/query-parser-generator.js"></script> - <script src="/bg/js/query-parser.js"></script> - <script src="/bg/js/clipboard-monitor.js"></script> - <script src="/bg/js/search.js"></script> +<script src="/bg/js/search-main.js"></script> - <script src="/bg/js/search-main.js"></script> - </body> +</body> </html> diff --git a/ext/fg/float.html b/ext/fg/float.html index 4a7cb616..d5172145 100644 --- a/ext/fg/float.html +++ b/ext/fg/float.html @@ -1,80 +1,81 @@ <!DOCTYPE html> <html lang="en" data-yomichan-page="float"> - <head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width,initial-scale=1" /> - <title>Yomichan Search</title> - <link rel="icon" type="image/png" href="/mixed/img/icon16.png" sizes="16x16"> - <link rel="icon" type="image/png" href="/mixed/img/icon19.png" sizes="19x19"> - <link rel="icon" type="image/png" href="/mixed/img/icon32.png" sizes="32x32"> - <link rel="icon" type="image/png" href="/mixed/img/icon38.png" sizes="38x38"> - <link rel="icon" type="image/png" href="/mixed/img/icon48.png" sizes="48x48"> - <link rel="icon" type="image/png" href="/mixed/img/icon64.png" sizes="64x64"> - <link rel="icon" type="image/png" href="/mixed/img/icon128.png" sizes="128x128"> - <link rel="stylesheet" href="/mixed/css/display.css"> - </head> - <body> - <div id="spinner" hidden><img src="/mixed/img/spinner.gif"></div> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>Yomichan Search</title> + <link rel="icon" type="image/png" href="/mixed/img/icon16.png" sizes="16x16"> + <link rel="icon" type="image/png" href="/mixed/img/icon19.png" sizes="19x19"> + <link rel="icon" type="image/png" href="/mixed/img/icon32.png" sizes="32x32"> + <link rel="icon" type="image/png" href="/mixed/img/icon38.png" sizes="38x38"> + <link rel="icon" type="image/png" href="/mixed/img/icon48.png" sizes="48x48"> + <link rel="icon" type="image/png" href="/mixed/img/icon64.png" sizes="64x64"> + <link rel="icon" type="image/png" href="/mixed/img/icon128.png" sizes="128x128"> + <link rel="stylesheet" type="text/css" href="/mixed/css/display.css"> +</head> +<body> - <div id="navigation-header" class="navigation-header" hidden><div class="navigation-header-actions"> - <button class="action-button action-previous" data-icon="source-term" title="Source term (Alt + B)"></button> - <button class="action-button action-next" data-icon="source-term" title="Next term (Alt + F)"></button> - </div></div><div class="navigation-header-spacer"></div> + <div id="spinner" hidden><img src="/mixed/img/spinner.gif"></div> - <div class="scan-disable" id="query-parser-container" hidden> - <div id="query-parser-select-container" class="input-group"></div> - <div id="query-parser-content"></div> - </div> + <div id="navigation-header" class="navigation-header" hidden><div class="navigation-header-actions"> + <button class="action-button action-previous" data-icon="source-term" title="Source term (Alt + B)"></button> + <button class="action-button action-next" data-icon="source-term" title="Next term (Alt + F)"></button> + </div></div><div class="navigation-header-spacer"></div> + + <div class="scan-disable" id="query-parser-container" hidden> + <div id="query-parser-select-container" class="input-group"></div> + <div id="query-parser-content"></div> + </div> - <div id="definitions"></div> + <div id="definitions"></div> - <div id="no-results" hidden> - <div class="entry"> - <p>No results found.</p> - </div> + <div id="no-results" hidden> + <div class="entry"> + <p>No results found.</p> </div> + </div> - <div id="error-extension-unloaded" hidden> - <div class="entry"> - <h1>Yomichan Updated!</h1> - <p> - The Yomichan extension has been updated to a new version! In order to continue - viewing definitions on this page, you must reload this tab or restart your browser. - </p> - </div> + <div id="error-extension-unloaded" hidden> + <div class="entry"> + <h1>Yomichan Updated!</h1> + <p> + The Yomichan extension has been updated to a new version! In order to continue + viewing definitions on this page, you must reload this tab or restart your browser. + </p> </div> + </div> - <script src="/mixed/js/core.js"></script> - <script src="/mixed/js/yomichan.js"></script> - <script src="/mixed/js/comm.js"></script> - <script src="/mixed/js/api.js"></script> - <script src="/mixed/js/japanese.js"></script> +<script src="/mixed/js/core.js"></script> +<script src="/mixed/js/yomichan.js"></script> +<script src="/mixed/js/comm.js"></script> +<script src="/mixed/js/api.js"></script> +<script src="/mixed/js/japanese.js"></script> - <script src="/mixed/js/cache-map.js"></script> - <script src="/mixed/js/document-util.js"></script> - <script src="/fg/js/dom-text-scanner.js"></script> - <script src="/fg/js/text-source-range.js"></script> - <script src="/fg/js/text-source-element.js"></script> - <script src="/mixed/js/audio-system.js"></script> - <script src="/mixed/js/dictionary-data-util.js"></script> - <script src="/mixed/js/display.js"></script> - <script src="/mixed/js/display-generator.js"></script> - <script src="/mixed/js/display-history.js"></script> - <script src="/mixed/js/dynamic-loader.js"></script> - <script src="/mixed/js/frame-endpoint.js"></script> - <script src="/mixed/js/media-loader.js"></script> - <script src="/mixed/js/scroll.js"></script> - <script src="/mixed/js/text-scanner.js"></script> - <script src="/mixed/js/html-template-collection.js"></script> - <script src="/mixed/js/text-to-speech-audio.js"></script> +<script src="/mixed/js/cache-map.js"></script> +<script src="/mixed/js/document-util.js"></script> +<script src="/fg/js/dom-text-scanner.js"></script> +<script src="/fg/js/text-source-range.js"></script> +<script src="/fg/js/text-source-element.js"></script> +<script src="/mixed/js/audio-system.js"></script> +<script src="/mixed/js/dictionary-data-util.js"></script> +<script src="/mixed/js/display.js"></script> +<script src="/mixed/js/display-generator.js"></script> +<script src="/mixed/js/display-history.js"></script> +<script src="/mixed/js/dynamic-loader.js"></script> +<script src="/mixed/js/frame-endpoint.js"></script> +<script src="/mixed/js/media-loader.js"></script> +<script src="/mixed/js/scroll.js"></script> +<script src="/mixed/js/text-scanner.js"></script> +<script src="/mixed/js/html-template-collection.js"></script> +<script src="/mixed/js/text-to-speech-audio.js"></script> - <script src="/bg/js/anki-note-builder.js"></script> - <script src="/bg/js/template-renderer-proxy.js"></script> +<script src="/bg/js/anki-note-builder.js"></script> +<script src="/bg/js/template-renderer-proxy.js"></script> - <script src="/bg/js/query-parser-generator.js"></script> - <script src="/bg/js/query-parser.js"></script> - <script src="/fg/js/float.js"></script> +<script src="/bg/js/query-parser-generator.js"></script> +<script src="/bg/js/query-parser.js"></script> +<script src="/fg/js/float.js"></script> - <script src="/fg/js/float-main.js"></script> - </body> +<script src="/fg/js/float-main.js"></script> +</body> </html> diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js index bfa2195e..7a6cae64 100644 --- a/ext/fg/js/float.js +++ b/ext/fg/js/float.js @@ -23,7 +23,7 @@ class DisplayFloat extends Display { constructor() { - super(document.querySelector('#spinner'), document.querySelector('#definitions')); + super(); this._nestedPopupsPrepared = false; this._frameEndpoint = new FrameEndpoint(); this._windowMessageHandlers = new Map([ diff --git a/ext/mixed/css/display.css b/ext/mixed/css/display.css index 5af211bb..3b6e3b3e 100644 --- a/ext/mixed/css/display.css +++ b/ext/mixed/css/display.css @@ -187,23 +187,6 @@ h2 { * Search page */ -.icon-checkbox { - display: none; -} - -.icon-checkbox+label { - cursor: pointer; - font-size: 1.6em; - padding: 0.1em; - user-select: none; -} - -.icon-checkbox:checked+label { - /* Invert colors */ - background-color: var(--default-text-color); - color: var(--background-color); -} - #query-parser-content { margin-top: 0.5em; font-size: 2em; diff --git a/ext/mixed/css/search.css b/ext/mixed/css/search.css new file mode 100644 index 00000000..cd986233 --- /dev/null +++ b/ext/mixed/css/search.css @@ -0,0 +1,326 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +/* Variables */ +:root { + --main-content-size: 700px; + --main-content-padding: 10px; + --shadow-color: rgba(0, 0, 0, 0.185); + --shadow-vertical: 0 1px 4px 0 var(--shadow-color), 0 2px 2px 0 var(--shadow-color); + + --font-size-default: 14px; + --line-height-default: calc(20 / 14); + --thin-border-size: 1px; + --toggle-size: 16px; + + --textarea-line-height: 1.25em; + --textarea-padding: 0.5em; + + --animation-duration: 0s; + --animation-duration2: calc(var(--animation-duration) * 2); + + --text-color-default: #222222; + --background-color: #ffffff; + --background-color-light: #ffffff; + --input-background-color: #f2f2f2; + --input-background-color-dark: #dddddd; + --input-background-color-darker: #cccccc; + --separator-color1: #cccccc; + --button-icon-color: #333333; + --toggle-track-color: #cccccc; + --toggle-knob-color: #ffffff; + --selectable-indicator-color: rgba(160, 160, 160, 0.25); + --disabled-color: #aaaaaa; + --disabled-color-light: #dddddd; + --disabled-color-lighter: #eeeeee; + --accent-color: #1a73e8; + --accent-color-lighter: #8db9f4; + --accent-color-transparent25: rgba(28, 116, 233, 0.25); +} +:root[data-loaded=true] { + --animation-duration: 0.125s; +} +:root[data-yomichan-theme=dark] { + --text-color-default: #d8d8d8; + --background-color: #1e1e1e; + --shadow-color: rgba(255, 255, 255, 0.185); + --separator-color1: #cccccc; + --input-background-color: #2f2f2f; + --input-background-color-dark: #383838; + --input-background-color-darker: #484848; + --selectable-indicator-color: rgba(100, 100, 100, 0.25); + --button-icon-color: #cccccc; + --disabled-color: #444444; + --disabled-color-light: #585858; + --disabled-color-lighter: #777777; +} + +/* Common styles */ +:root { + height: 100%; +} +body { + background-color: var(--background-color); + margin: 0; + padding: 0; + margin: 0; + font-size: var(--font-size-default); + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + color: var(--text-color-default); + line-height: var(--line-height-default); + height: 100%; + overflow: hidden; +} +h1 { + font-size: 2em; + line-height: 1.5em; + margin: 0; + padding: 0.25em 0 0; + font-weight: normal; + box-sizing: border-box; + border-bottom: var(--thin-border-size) solid var(--separator-color1); +} + +/* Material design toggle switch */ +label.toggle { + cursor: default; +} +.toggle { + font-size: var(--toggle-size); + display: inline-block; +} +.toggle>input[type=checkbox] { + opacity: 0; + width: 0; + height: 0; + display: block; + margin: 0; + padding: 0; + border: none; + appearance: none; + -moz-appearance: none; +} +.toggle-body { + display: block; + cursor: pointer; + width: 2em; + height: 1em; + position: relative; +} +.toggle-track { + display: block; + position: absolute; + left: 0.125em; + right: 0.125em; + top: 0.125em; + bottom: 0.125em; + background-color: var(--toggle-track-color); + border-radius: 0.4375em; + transition: background-color var(--animation-duration) ease-in-out; +} +.toggle-knob { + display: block; + position: absolute; + left: 0; + top: 0; + width: 1em; + height: 1em; + background-color: var(--toggle-knob-color); + border-radius: 0.5em; + box-shadow: var(--shadow-vertical); + transition: transform var(--animation-duration) ease-in-out, + background-color var(--animation-duration) ease-in-out; +} +.toggle-body>.toggle-knob::after { + position: absolute; + display: block; + content: ""; + left: -0.75em; + top: -0.75em; + right: -0.75em; + bottom: -0.75em; + border-radius: 2.5em; + background-color: var(--selectable-indicator-color); + pointer-events: none; + transform: scale(0); + opacity: 0; + visibility: hidden; + transition: transform 0s ease-in-out var(--animation-duration2), + background-color var(--animation-duration2) ease-in-out, + opacity var(--animation-duration2) ease-in-out, + visibility 0s ease-in-out var(--animation-duration2); +} +.toggle>input[type=checkbox]:focus:not(:disabled)+.toggle-body>.toggle-knob::after, +.toggle:active>input[type=checkbox]:not(:disabled)+.toggle-body>.toggle-knob::after { + transform: scale(1); + opacity: 1; + visibility: visible; + transition: transform var(--animation-duration2) ease-in-out, + background-color var(--animation-duration2) ease-in-out, + opacity var(--animation-duration2) ease-in-out, + visibility var(--animation-duration2) ease-in-out; +} +.toggle>input[type=checkbox]:focus+.toggle-body>.toggle-knob::after { + opacity: 0.5; +} +.toggle:active>input[type=checkbox]:focus+.toggle-body>.toggle-knob::after { + opacity: 1; +} +.toggle>input[type=checkbox]:checked+.toggle-body>.toggle-knob { + transform: translateX(1em); +} +.toggle>input[type=checkbox]:checked:not(:disabled)+.toggle-body>.toggle-track { + background-color: var(--accent-color-lighter); +} +.toggle>input[type=checkbox]:checked:not(:disabled)+.toggle-body>.toggle-knob { + background-color: var(--accent-color); +} +.toggle>input[type=checkbox]:focus:checked:not(:disabled)+.toggle-body>.toggle-knob::after, +.toggle:active>input[type=checkbox]:checked:not(:disabled)+.toggle-body>.toggle-knob::after { + background-color: var(--accent-color-transparent25); +} +.toggle>input[type=checkbox]:disabled+.toggle-body { + cursor: default; +} +.toggle>input[type=checkbox]:disabled+.toggle-body>.toggle-track { + background-color: var(--disabled-color-light); +} +.toggle>input[type=checkbox]:disabled+.toggle-body>.toggle-knob { + background-color: var(--disabled-color-lighter); +} + +/* Content layout */ +.content { + flex: 1 0 auto; + flex-flow: row nowrap; + width: 100%; + display: flex; + position: relative; + align-items: stretch; + justify-content: center; +} +.content-center { + flex: 1 1 auto; + width: var(--main-content-size); + padding: 0 var(--main-content-padding); + max-width: var(--main-content-size); + box-sizing: border-box; +} + +/* Search bar */ +.search-textbox-container { + display: flex; + flex-flow: row nowrap; + width: 100%; + align-items: stretch; + margin: 0; + padding: 0; + border: 0; +} +#search-textbox { + color: var(--text-color-default); + flex: 1 1 auto; + box-sizing: border-box; + padding: var(--textarea-padding); + font-family: 'Courier New', Courier, monospace; + background-color: var(--input-background-color); + border-radius: 0; + line-height: var(--textarea-line-height); + border: 0; + outline: none; + width: 100%; + height: calc(var(--textarea-line-height) + var(--textarea-padding) * 2); + min-height: calc(var(--textarea-line-height) + var(--textarea-padding) * 2); + max-height: calc(var(--textarea-line-height) * 10 + var(--textarea-padding) * 2); + resize: vertical; + font-size: var(--font-size-default); + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + color: var(--text-color-default); + white-space: pre-wrap; +} +#search-button { + flex: 0 0 auto; + position: relative; + width: 2.5em; + background-color: var(--input-background-color); + border: 0; + padding: 0; + margin: 0; + cursor: pointer; + outline: none; + transition: background-color var(--animation-duration) ease-in-out; +} +#search-button:hover, +#search-button:focus { + background-color: var(--input-background-color-dark); +} +#search-button:active { + background-color: var(--input-background-color-darker); +} + +.icon-button-icon { + display: block; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + background-color: var(--button-icon-color); + mask-repeat: no-repeat; + mask-position: center center; + mask-mode: alpha; + -webkit-mask-repeat: no-repeat; + -webkit-mask-position: center center; + -webkit-mask-mode: alpha; +} +.icon-button-icon[data-icon=magnifying-glass] { + mask-image: url(/mixed/img/magnifying-glass.svg); + -webkit-mask-image: url(/mixed/img/magnifying-glass.svg); + mask-size: 16px 16px; + -webkit-mask-size: 16px 16px; +} + +/* Search options */ +.search-options { + display: flex; + flex-flow: row wrap; + margin: 0.5em -1em; + align-items: center; +} +.search-option { + display: flex; + flex: 0 1 auto; + margin: 0.5em 1em; + align-items: center; + cursor: pointer; +} +.search-option-label { + padding-left: 0.5em; +} + +/* Search styles */ +#intro { + overflow: hidden; +} +#intro>p { + margin: 0; +} + +#query-parser-content:not(:empty) { + border-bottom: var(--thin-border-size) solid var(--separator-color1); + padding-bottom: 0.5em; +} diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 0d724aa0..38a441bd 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -32,10 +32,10 @@ */ class Display extends EventDispatcher { - constructor(spinner, container) { + constructor() { super(); - this._spinner = spinner; - this._container = container; + this._spinner = document.querySelector('#spinner'); + this._container = document.querySelector('#definitions'); this._definitions = []; this._optionsContext = {depth: 0, url: window.location.href}; this._options = null; @@ -804,7 +804,10 @@ class Display extends EventDispatcher { async _setContentTermsOrKanji(token, isTerms, urlSearchParams, eventArgs) { let source = urlSearchParams.get('query'); - if (!source) { return false; } + if (!source) { + this._setQueryParserText(''); + return false; + } let {state, content} = this._history; let changeHistory = false; |