diff options
| author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2020-11-08 12:34:23 -0500 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-11-08 12:34:23 -0500 | 
| commit | 8cf10d685d52d5ae75d65c4aea4adcb6d101e9a4 (patch) | |
| tree | 3a1874942370917e328976854c5a5c7352d9e085 | |
| parent | db9ec4c4495404ad3ebc9ce56866c3631cedf8dc (diff) | |
Search and display style updates (#1005)
* Use same selectors
* Use consistent stylesheet declaration
* Fix query parser not being cleared
* Set property upon load
* Don't focus for Enter key press
* Update search page styles
* Update indent and nodes
* Support dark style
* Add missing var
| -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; |