aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2020-10-20 19:08:17 -0400
committerGitHub <noreply@github.com>2020-10-20 19:08:17 -0400
commitecbac2c5ea4aecfb4d43d5beb20792f644e334d0 (patch)
tree0890783bbecf2886610324625e7463155da969fa
parent23230b8a7c5eb66357d5bcafb4184def13c5954b (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.css144
-rw-r--r--ext/bg/js/settings/popup-preview-controller.js2
-rw-r--r--ext/bg/js/settings/popup-preview-frame.js53
-rw-r--r--ext/bg/popup-preview.html60
-rw-r--r--ext/bg/settings-popup-preview.html141
-rw-r--r--ext/fg/js/frontend.js1
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);
}