diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js
index 906aaa30..285b8016 100644
--- a/ext/bg/js/api.js
+++ b/ext/bg/js/api.js
@@ -25,6 +25,10 @@ function apiAudioGetUrl(definition, source, optionsContext) {
return _apiInvoke('audioGetUrl', {definition, source, optionsContext});
}
+function apiGetDisplayTemplatesHtml() {
+ return _apiInvoke('getDisplayTemplatesHtml');
+}
+
function _apiInvoke(action, params={}) {
const data = {action, params};
return new Promise((resolve, reject) => {
diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js
index 28b0201e..391d6243 100644
--- a/ext/bg/js/backend.js
+++ b/ext/bg/js/backend.js
@@ -522,6 +522,11 @@ class Backend {
return result;
}
+ async _onApiGetDisplayTemplatesHtml() {
+ const url = chrome.runtime.getURL('/mixed/display-templates.html');
+ return await requestText(url, 'GET');
+ }
+
// Command handlers
async _onCommandSearch(params) {
@@ -735,7 +740,8 @@ Backend._messageHandlers = new Map([
['frameInformationGet', (self, ...args) => self._onApiFrameInformationGet(...args)],
['injectStylesheet', (self, ...args) => self._onApiInjectStylesheet(...args)],
['getEnvironmentInfo', (self, ...args) => self._onApiGetEnvironmentInfo(...args)],
- ['clipboardGet', (self, ...args) => self._onApiClipboardGet(...args)]
+ ['clipboardGet', (self, ...args) => self._onApiClipboardGet(...args)],
+ ['getDisplayTemplatesHtml', (self, ...args) => self._onApiGetDisplayTemplatesHtml(...args)]
]);
Backend._commandHandlers = new Map([
diff --git a/ext/bg/js/request.js b/ext/bg/js/request.js
index b584c9a9..778f933b 100644
--- a/ext/bg/js/request.js
+++ b/ext/bg/js/request.js
@@ -17,10 +17,10 @@
*/
-function requestJson(url, action, params) {
+function requestText(url, action, params) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
- xhr.overrideMimeType('application/json');
+ xhr.overrideMimeType('text/plain');
xhr.addEventListener('load', () => resolve(xhr.responseText));
xhr.addEventListener('error', () => reject(new Error('Failed to connect')));
xhr.open(action, url);
@@ -29,12 +29,15 @@ function requestJson(url, action, params) {
} else {
xhr.send();
}
- }).then((responseText) => {
- try {
- return JSON.parse(responseText);
- }
- catch (e) {
- return Promise.reject(new Error('Invalid response'));
- }
});
}
+
+async function requestJson(url, action, params) {
+ const responseText = await requestText(url, action, params);
+ try {
+ return JSON.parse(responseText);
+ }
+ catch (e) {
+ throw new Error('Invalid response');
+ }
+}
diff --git a/ext/bg/search.html b/ext/bg/search.html
index 819c8505..74afbb68 100644
--- a/ext/bg/search.html
+++ b/ext/bg/search.html
@@ -66,84 +66,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Glossary |
- Readings |
- Statistics |
-
-
-
|
-
|
- |
-
- Classifications |
- |
- Codepoints |
- |
- Dictionary Indices |
- |
-
-
-
-
- |
- No data found |
-
-
-
-
-
-
diff --git a/ext/fg/float.html b/ext/fg/float.html
index 9cc0dc39..bec5ae68 100644
--- a/ext/fg/float.html
+++ b/ext/fg/float.html
@@ -40,84 +40,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Glossary |
- Readings |
- Statistics |
-
-
-
|
-
|
- |
-
- Classifications |
- |
- Codepoints |
- |
- Dictionary Indices |
- |
-
-
-
-
- |
- No data found |
-
-
-
-
-
-
diff --git a/ext/mixed/display-templates.html b/ext/mixed/display-templates.html
new file mode 100644
index 00000000..01cfeffc
--- /dev/null
+++ b/ext/mixed/display-templates.html
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Glossary |
+ Readings |
+ Statistics |
+
+
+
|
+
|
+ |
+
+ Classifications |
+ |
+ Codepoints |
+ |
+ Dictionary Indices |
+ |
+
+
+
+
+ |
+No data found |
+
+
+
+
+
+
+
diff --git a/ext/mixed/js/api.js b/ext/mixed/js/api.js
index 8ed1d996..9f0835b0 100644
--- a/ext/mixed/js/api.js
+++ b/ext/mixed/js/api.js
@@ -101,6 +101,10 @@ function apiClipboardGet() {
return _apiInvoke('clipboardGet');
}
+function apiGetDisplayTemplatesHtml() {
+ return _apiInvoke('getDisplayTemplatesHtml');
+}
+
function _apiInvoke(action, params={}) {
const data = {action, params};
return new Promise((resolve, reject) => {
diff --git a/ext/mixed/js/display-generator.js b/ext/mixed/js/display-generator.js
index 44b250e7..8eb699e0 100644
--- a/ext/mixed/js/display-generator.js
+++ b/ext/mixed/js/display-generator.js
@@ -19,22 +19,39 @@
class DisplayGenerator {
constructor() {
- this._termEntryTemplate = document.querySelector('#term-entry-template');
- this._termExpressionTemplate = document.querySelector('#term-expression-template');
- this._termDefinitionItemTemplate = document.querySelector('#term-definition-item-template');
- this._termDefinitionOnlyTemplate = document.querySelector('#term-definition-only-template');
- this._termGlossaryItemTemplate = document.querySelector('#term-glossary-item-template');
- this._termReasonTemplate = document.querySelector('#term-reason-template');
+ this._isInitialized = false;
+ this._initializationPromise = null;
- this._kanjiEntryTemplate = document.querySelector('#kanji-entry-template');
- this._kanjiInfoTableTemplate = document.querySelector('#kanji-info-table-template');
- this._kanjiInfoTableItemTemplate = document.querySelector('#kanji-info-table-item-template');
- this._kanjiInfoTableEmptyTemplate = document.querySelector('#kanji-info-table-empty-template');
- this._kanjiGlossaryItemTemplate = document.querySelector('#kanji-glossary-item-template');
- this._kanjiReadingTemplate = document.querySelector('#kanji-reading-template');
+ this._termEntryTemplate = null;
+ this._termExpressionTemplate = null;
+ this._termDefinitionItemTemplate = null;
+ this._termDefinitionOnlyTemplate = null;
+ this._termGlossaryItemTemplate = null;
+ this._termReasonTemplate = null;
- this._tagTemplate = document.querySelector('#tag-template');
- this._tagFrequencyTemplate = document.querySelector('#tag-frequency-template');
+ this._kanjiEntryTemplate = null;
+ this._kanjiInfoTableTemplate = null;
+ this._kanjiInfoTableItemTemplate = null;
+ this._kanjiInfoTableEmptyTemplate = null;
+ this._kanjiGlossaryItemTemplate = null;
+ this._kanjiReadingTemplate = null;
+
+ this._tagTemplate = null;
+ this._tagFrequencyTemplate = null;
+ }
+
+ isInitialized() {
+ return this._isInitialized;
+ }
+
+ initialize() {
+ if (this._isInitialized) {
+ return Promise.resolve();
+ }
+ if (this._initializationPromise === null) {
+ this._initializationPromise = this._initializeInternal();
+ }
+ return this._initializationPromise;
}
createTermEntry(details) {
@@ -259,6 +276,31 @@ class DisplayGenerator {
return node;
}
+ async _initializeInternal() {
+ const html = await apiGetDisplayTemplatesHtml();
+ const doc = new DOMParser().parseFromString(html, 'text/html');
+ this._setTemplates(doc);
+ }
+
+ _setTemplates(doc) {
+ this._termEntryTemplate = doc.querySelector('#term-entry-template');
+ this._termExpressionTemplate = doc.querySelector('#term-expression-template');
+ this._termDefinitionItemTemplate = doc.querySelector('#term-definition-item-template');
+ this._termDefinitionOnlyTemplate = doc.querySelector('#term-definition-only-template');
+ this._termGlossaryItemTemplate = doc.querySelector('#term-glossary-item-template');
+ this._termReasonTemplate = doc.querySelector('#term-reason-template');
+
+ this._kanjiEntryTemplate = doc.querySelector('#kanji-entry-template');
+ this._kanjiInfoTableTemplate = doc.querySelector('#kanji-info-table-template');
+ this._kanjiInfoTableItemTemplate = doc.querySelector('#kanji-info-table-item-template');
+ this._kanjiInfoTableEmptyTemplate = doc.querySelector('#kanji-info-table-empty-template');
+ this._kanjiGlossaryItemTemplate = doc.querySelector('#kanji-glossary-item-template');
+ this._kanjiReadingTemplate = doc.querySelector('#kanji-reading-template');
+
+ this._tagTemplate = doc.querySelector('#tag-template');
+ this._tagFrequencyTemplate = doc.querySelector('#tag-frequency-template');
+ }
+
_appendKanjiLinks(container, text) {
let part = '';
for (const c of text) {
diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js
index eabb73ca..75b43aa0 100644
--- a/ext/mixed/js/display.js
+++ b/ext/mixed/js/display.js
@@ -356,6 +356,11 @@ class Display {
window.focus();
}
+ if (!this.displayGenerator.isInitialized()) {
+ await this.displayGenerator.initialize();
+ if (this.setContentToken !== token) { return; }
+ }
+
this.definitions = definitions;
if (context.disableHistory) {
delete context.disableHistory;
@@ -415,6 +420,11 @@ class Display {
window.focus();
}
+ if (!this.displayGenerator.isInitialized()) {
+ await this.displayGenerator.initialize();
+ if (this.setContentToken !== token) { return; }
+ }
+
this.definitions = definitions;
if (context.disableHistory) {
delete context.disableHistory;