diff options
author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2020-10-20 19:08:17 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-20 19:08:17 -0400 |
commit | ecbac2c5ea4aecfb4d43d5beb20792f644e334d0 (patch) | |
tree | 0890783bbecf2886610324625e7463155da969fa | |
parent | 23230b8a7c5eb66357d5bcafb4184def13c5954b (diff) |
Popup preview improvements (#947)
* Move CSS
* Update indent
* Refactor HTML/CSS
* Add support for editing the source text
* Add WanaKana binding for input
* Rename file
-rw-r--r-- | ext/bg/css/popup-preview.css | 144 | ||||
-rw-r--r-- | ext/bg/js/settings/popup-preview-controller.js | 2 | ||||
-rw-r--r-- | ext/bg/js/settings/popup-preview-frame.js | 53 | ||||
-rw-r--r-- | ext/bg/popup-preview.html | 60 | ||||
-rw-r--r-- | ext/bg/settings-popup-preview.html | 141 | ||||
-rw-r--r-- | ext/fg/js/frontend.js | 1 |
6 files changed, 251 insertions, 150 deletions
diff --git a/ext/bg/css/popup-preview.css b/ext/bg/css/popup-preview.css new file mode 100644 index 00000000..fd8df47a --- /dev/null +++ b/ext/bg/css/popup-preview.css @@ -0,0 +1,144 @@ +/* + * 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/>. + */ + +html { + --text-color: #333333; + --background-color: #ffffff; + --theme-transition: background-color 0.25s linear 0s, color 0.25s linear 0s; + transition: var(--theme-transition); + background-color: var(--background-color); + color: var(--text-color); +} +html.dark { + --text-color: #d4d4d4; + --background-color: #1e1e1e; +} +html, +body { + margin: 0; + padding: 0; + border: 0; + overflow: hidden; + width: 100%; + height: 100%; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; +} + +.content { + display: flex; + min-width: 100%; + min-height: 100%; + box-sizing: border-box; + padding: 1em; + flex-flow: column nowrap; + align-items: center; + justify-content: center; +} +.content-body { + max-width: 100%; + width: 400px; +} +.top-options { + max-width: 100%; + display: flex; + flex-flow: row nowrap; + align-items: center; +} +.top-options-left { + flex: 1 1 auto; + overflow-x: hidden; +} +.top-options-right { + flex: 0 0 auto; +} + +.example-text-container { + position: relative; +} +.example-text { + display: block; + width: 100%; + font-size: 24px; + line-height: 1.25em; + height: 1.25em; + box-sizing: border-box; + border: 1px solid rgba(221, 221, 221, 0); + margin: 0; + padding: 0; + outline: none; + color: inherit; + background-color: transparent; + white-space: pre; + transition: background-color 0.25s linear 0s, border-color 0.25s linear 0s; +} +.example-text:hover, +.example-text-input { + border-color: #dddddd; +} +.example-text[hidden] { + display: none; +} +.example-text-input { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + background-color: var(--background-color); +} + +.popup-placeholder { + display: flex; + width: 100%; + height: 250px; + padding-top: 10px; + border: 1px solid rgba(0, 0, 0, 0); + flex-flow: column nowrap; + justify-content: center; +} +.placeholder-info { + flex: 0 1 auto; + visibility: hidden; + opacity: 0; + transition: opacity 0.5s linear 0s, visibility 0s linear 0.5s; +} +.placeholder-info.placeholder-info-visible { + visibility: visible; + opacity: 1; + transition: opacity 0.5s linear 0s, visibility 0s linear 0s; +} + +.theme-button { + display: inline-block; + margin-left: 0.5em; + text-decoration: none; + cursor: pointer; + white-space: nowrap; + line-height: 0; +} +.theme-button>input { + vertical-align: middle; + margin: 0 0.25em 0 0; + padding: 0; +} +.theme-button>span { + vertical-align: middle; +} +.theme-button:hover>span { + text-decoration: underline; +} diff --git a/ext/bg/js/settings/popup-preview-controller.js b/ext/bg/js/settings/popup-preview-controller.js index d4145b76..796b23ea 100644 --- a/ext/bg/js/settings/popup-preview-controller.js +++ b/ext/bg/js/settings/popup-preview-controller.js @@ -60,7 +60,7 @@ class PopupPreviewController { customOuterCss.addEventListener('input', this._onCustomOuterCssChange.bind(this), false); this._settingsController.on('optionsContextChanged', this._onOptionsContextChange.bind(this)); - frame.src = '/bg/settings-popup-preview.html'; + frame.src = '/bg/popup-preview.html'; frame.id = 'settings-popup-preview-frame'; container.appendChild(frame); diff --git a/ext/bg/js/settings/popup-preview-frame.js b/ext/bg/js/settings/popup-preview-frame.js index bce5919d..7e177453 100644 --- a/ext/bg/js/settings/popup-preview-frame.js +++ b/ext/bg/js/settings/popup-preview-frame.js @@ -20,6 +20,7 @@ * Popup * TextSourceRange * api + * wanakana */ class PopupPreviewFrame { @@ -34,10 +35,12 @@ class PopupPreviewFrame { this._themeChangeTimeout = null; this._textSource = null; this._optionsContext = null; + this._exampleText = null; + this._exampleTextInput = null; this._targetOrigin = chrome.runtime.getURL('/').replace(/\/$/, ''); this._windowMessageHandlers = new Map([ - ['setText', this._setText.bind(this)], + ['setText', this._onSetText.bind(this)], ['setCustomCss', this._setCustomCss.bind(this)], ['setCustomOuterCss', this._setCustomOuterCss.bind(this)], ['updateOptionsContext', this._updateOptionsContext.bind(this)] @@ -45,10 +48,20 @@ class PopupPreviewFrame { } async prepare() { + this._exampleText = document.querySelector('#example-text'); + this._exampleTextInput = document.querySelector('#example-text-input'); + + if (this._exampleTextInput !== null && typeof wanakana !== 'undefined') { + wanakana.bind(this._exampleTextInput); + } + window.addEventListener('message', this._onMessage.bind(this), false); // Setup events document.querySelector('#theme-dark-checkbox').addEventListener('change', this._onThemeDarkCheckboxChanged.bind(this), false); + this._exampleText.addEventListener('click', this._onExampleTextClick.bind(this), false); + this._exampleTextInput.addEventListener('blur', this._onExampleTextInputBlur.bind(this), false); + this._exampleTextInput.addEventListener('input', this._onExampleTextInputInput.bind(this), false); // Overwrite API functions this._apiOptionsGetOld = api.optionsGet.bind(api); @@ -142,11 +155,36 @@ class PopupPreviewFrame { }, 300); } - _setText({text}) { - const exampleText = document.querySelector('#example-text'); - if (exampleText === null) { return; } + _onExampleTextClick() { + if (this._exampleTextInput === null) { return; } + const visible = this._exampleTextInput.hidden; + this._exampleTextInput.hidden = !visible; + if (!visible) { return; } + this._exampleTextInput.focus(); + this._exampleTextInput.select(); + } + + _onExampleTextInputBlur() { + if (this._exampleTextInput === null) { return; } + this._exampleTextInput.hidden = true; + } + + _onExampleTextInputInput(e) { + this._setText(e.currentTarget.value); + } + + _onSetText({text}) { + this._setText(text, true); + } + + _setText(text, setInput) { + if (setInput && this._exampleTextInput !== null) { + this._exampleTextInput.value = text; + } + + if (this._exampleText === null) { return; } - exampleText.textContent = text; + this._exampleText.textContent = text; if (this._frontend === null) { return; } this._updateSearch(); } @@ -180,10 +218,9 @@ class PopupPreviewFrame { } async _updateSearch() { - const exampleText = document.querySelector('#example-text'); - if (exampleText === null) { return; } + if (this._exampleText === null) { return; } - const textNode = exampleText.firstChild; + const textNode = this._exampleText.firstChild; if (textNode === null) { return; } const range = document.createRange(); diff --git a/ext/bg/popup-preview.html b/ext/bg/popup-preview.html new file mode 100644 index 00000000..61df0876 --- /dev/null +++ b/ext/bg/popup-preview.html @@ -0,0 +1,60 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>Yomichan Popup Preview</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="/bg/css/popup-preview.css"> + <link rel="stylesheet" type="text/css" href="/fg/css/client.css" id="client-css"> +</head> +<body> + +<div class="content"><div class="content-body"> + <div class="top-options"> + <div class="top-options-left"> + <div class="example-text-container"> + <input type="text" class="example-text example-text-input" id="example-text-input" value="読め" hidden> + <span class="example-text" id="example-text">読め</span> + </div> + </div> + <div class="top-options-right"> + <label class="theme-button"><input type="checkbox" id="theme-dark-checkbox"><span>dark</span></label> + </div> + </div> + <div class="popup-placeholder"><div class="placeholder-info"> + This page uses the dictionaries you have installed in order to show a preview. + If you see this message, make sure you have a dictionary installed. + </div></div> +</div></div> + +<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/dynamic-loader.js"></script> +<script src="/mixed/js/frame-client.js"></script> +<script src="/mixed/js/text-scanner.js"></script> + +<script src="/mixed/js/document-util.js"></script> +<script src="/fg/js/dom-text-scanner.js"></script> +<script src="/fg/js/popup.js"></script> +<script src="/fg/js/text-source-range.js"></script> +<script src="/fg/js/text-source-element.js"></script> +<script src="/fg/js/popup-factory.js"></script> +<script src="/fg/js/frontend.js"></script> +<script src="/fg/js/frame-offset-forwarder.js"></script> +<script src="/bg/js/settings/popup-preview-frame.js"></script> + +<script src="/bg/js/settings/popup-preview-frame-main.js"></script> + +</body> +</html> diff --git a/ext/bg/settings-popup-preview.html b/ext/bg/settings-popup-preview.html deleted file mode 100644 index 6487bd25..00000000 --- a/ext/bg/settings-popup-preview.html +++ /dev/null @@ -1,141 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width,initial-scale=1" /> - <title>Yomichan Popup Preview</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="/fg/css/client.css" id="client-css"> - <style> - html { - transition: background-color 0.25s linear 0s, color 0.25s linear 0s; - color: #333333; - } - html.dark { - background-color: #1e1e1e; - color: #d4d4d4; - } - html, body { - margin: 0; - padding: 0; - border: 0; - overflow: hidden; - width: 100%; - height: 100%; - font-family: "Helvetica Neue", Helvetica, Arial ,sans-serif; - font-size: 14px; - } - iframe.yomichan-float { - resize: none; - } - .vertical-align-outer { - width: 100%; - height: 100%; - white-space: nowrap; - } - .vertical-align-outer::before { - content: ""; - display: inline-block; - vertical-align: middle; - width: 0; - height: 100%; - } - .vertical-align-inner { - display: inline-block; - vertical-align: middle; - white-space: normal; - width: 100%; - } - .horizontal-size { - max-width: 400px; - padding: 15px; - margin: 0 auto; - } - .example-text-container { - font-size: 24px; - line-height: 1.25em; - height: 1.25em; - } - .popup-placeholder { - height: 250px; - padding-top: 10px; - border: 1px solid rgba(0, 0, 0, 0); - } - .placeholder-info { - visibility: hidden; - opacity: 0; - transition: opacity 0.5s linear 0s, visibility 0s linear 0.5s; - } - .placeholder-info.placeholder-info-visible { - visibility: visible; - opacity: 1; - transition: opacity 0.5s linear 0s, visibility 0s linear 0s; - } - - .options { - float: right; - font-size: 14px; - line-height: 30px; - } - .theme-button { - display: inline-block; - margin-left: 0.5em; - text-decoration: none; - cursor: pointer; - white-space: nowrap; - line-height: 0; - } - .theme-button>input { - vertical-align: middle; - margin: 0 0.25em 0 0; - padding: 0; - } - .theme-button>span { - vertical-align: middle; - } - .theme-button:hover>span { - text-decoration: underline; - } - </style> - </head> - <body> - <div class="vertical-align-outer"><div class="vertical-align-inner"><div class="horizontal-size"> - <div class="example-text-container"> - <div class="options"><label class="theme-button"><input type="checkbox" id="theme-dark-checkbox" /><span>dark</span></label></div> - <span id="example-text">読め</span> - </div> - <div class="popup-placeholder"> - <div class="vertical-align-outer"><div class="vertical-align-inner placeholder-info"> - This page uses the dictionaries you have installed in order to show a preview. - If you see this message, make sure you have a dictionary installed. - </div></div> - </div> - </div></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/dynamic-loader.js"></script> - <script src="/mixed/js/frame-client.js"></script> - <script src="/mixed/js/text-scanner.js"></script> - - <script src="/mixed/js/document-util.js"></script> - <script src="/fg/js/dom-text-scanner.js"></script> - <script src="/fg/js/popup.js"></script> - <script src="/fg/js/text-source-range.js"></script> - <script src="/fg/js/text-source-element.js"></script> - <script src="/fg/js/popup-factory.js"></script> - <script src="/fg/js/frontend.js"></script> - <script src="/fg/js/frame-offset-forwarder.js"></script> - <script src="/bg/js/settings/popup-preview-frame.js"></script> - - <script src="/bg/js/settings/popup-preview-frame-main.js"></script> - </body> -</html> diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 97f73075..af1a6527 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -132,6 +132,7 @@ class Frontend { } async setTextSource(textSource) { + this._textScanner.setCurrentTextSource(null); await this._textScanner.search(textSource); } |