wip
This commit is contained in:
parent
7fbe2ddaf3
commit
aac2a58b5f
@ -20,6 +20,7 @@
|
|||||||
<script src="/bg/js/templates.js"></script>
|
<script src="/bg/js/templates.js"></script>
|
||||||
<script src="/bg/js/translator.js"></script>
|
<script src="/bg/js/translator.js"></script>
|
||||||
<script src="/bg/js/util.js"></script>
|
<script src="/bg/js/util.js"></script>
|
||||||
|
<script src="/bg/js/util.js"></script>
|
||||||
<script src="/mixed/js/audio.js"></script>
|
<script src="/mixed/js/audio.js"></script>
|
||||||
<script src="/mixed/js/japanese.js"></script>
|
<script src="/mixed/js/japanese.js"></script>
|
||||||
<script src="/mixed/js/request.js"></script>
|
<script src="/mixed/js/request.js"></script>
|
||||||
|
@ -17,26 +17,26 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
window.displayWindow = new class extends Display {
|
window.yomichan_window = new class extends Display {
|
||||||
constructor() {
|
constructor() {
|
||||||
super($('#spinner'), $('#content'));
|
super($('#spinner'), $('#content'));
|
||||||
|
|
||||||
this.search = $('#search').click(this.onSearch.bind(this));
|
this.search = $('#search').click(this.onSearch.bind(this));
|
||||||
this.query = $('#query').on('input', this.inputSearch.bind(this));
|
this.query = $('#query').on('input', this.onSearchInput.bind(this));
|
||||||
this.intro = $('#intro');
|
this.intro = $('#intro');
|
||||||
|
|
||||||
window.wanakana.bind(this.query.get(0));
|
window.wanakana.bind(this.query.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleError(error) {
|
onError(error) {
|
||||||
window.alert(`Error: ${error}`);
|
window.alert(`Error: ${error}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
clearSearch() {
|
onSearchClear() {
|
||||||
this.query.focus().select();
|
this.query.focus().select();
|
||||||
}
|
}
|
||||||
|
|
||||||
inputSearch() {
|
onSearchInput() {
|
||||||
this.search.prop('disabled', this.query.val().length === 0);
|
this.search.prop('disabled', this.query.val().length === 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,9 +46,9 @@ window.displayWindow = new class extends Display {
|
|||||||
try {
|
try {
|
||||||
this.intro.slideUp();
|
this.intro.slideUp();
|
||||||
const {length, definitions} = await apiTermsFind(this.query.val());
|
const {length, definitions} = await apiTermsFind(this.query.val());
|
||||||
super.showTermDefs(definitions, await apiOptionsGet());
|
super.termsShow(definitions, await apiOptionsGet());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.handleError(e);
|
this.onError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -40,10 +40,10 @@
|
|||||||
<script src="/bg/js/dictionary.js"></script>
|
<script src="/bg/js/dictionary.js"></script>
|
||||||
<script src="/bg/js/handlebars.js"></script>
|
<script src="/bg/js/handlebars.js"></script>
|
||||||
<script src="/bg/js/templates.js"></script>
|
<script src="/bg/js/templates.js"></script>
|
||||||
|
<script src="/bg/js/util.js"></script>
|
||||||
<script src="/mixed/js/audio.js"></script>
|
<script src="/mixed/js/audio.js"></script>
|
||||||
<script src="/mixed/js/display.js"></script>
|
<script src="/mixed/js/display.js"></script>
|
||||||
<script src="/mixed/js/japanese.js"></script>
|
<script src="/mixed/js/japanese.js"></script>
|
||||||
<script src="/mixed/js/request.js"></script>
|
|
||||||
|
|
||||||
<script src="/bg/js/display-window.js"></script>
|
<script src="/bg/js/display-window.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
@ -18,9 +18,9 @@
|
|||||||
<img src="/mixed/img/spinner.gif">
|
<img src="/mixed/img/spinner.gif">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="content"></div>
|
<div id="definitions"></div>
|
||||||
|
|
||||||
<div id="orphan">
|
<div id="error-orphaned">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<h1>Yomichan Updated!</h1>
|
<h1>Yomichan Updated!</h1>
|
||||||
<p>
|
<p>
|
||||||
|
@ -17,65 +17,45 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
window.displayFrame = new class extends Display {
|
window.yomichan_frame = new class extends Display {
|
||||||
constructor() {
|
constructor() {
|
||||||
super($('#spinner'), $('#content'));
|
super($('#spinner'), $('#content'));
|
||||||
$(window).on('message', this.onMessage.bind(this));
|
$(window).on('message', this.onMessage.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
definitionAdd(definition, mode) {
|
onError(error) {
|
||||||
return apiDefinitionAdd(definition, mode);
|
if (window.yomichan_orphaned) {
|
||||||
}
|
this.onOrphaned();
|
||||||
|
|
||||||
definitionsAddable(definitions, modes) {
|
|
||||||
return apiDefinitionsAddable(definitions, modes);
|
|
||||||
}
|
|
||||||
|
|
||||||
noteView(noteId) {
|
|
||||||
return apiNoteView(noteId);
|
|
||||||
}
|
|
||||||
|
|
||||||
templateRender(template, data) {
|
|
||||||
return apiTemplateRender(template, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
kanjiFind(character) {
|
|
||||||
return apiKanjiFind(character);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleError(error) {
|
|
||||||
if (window.yomichanOrphaned) {
|
|
||||||
this.showOrphaned();
|
|
||||||
} else {
|
} else {
|
||||||
window.alert(`Error: ${error}`);
|
window.alert(`Error: ${error}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clearSearch() {
|
onOrphaned() {
|
||||||
|
$('#definitions').hide();
|
||||||
|
$('#error-orphaned').show();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchClear() {
|
||||||
window.parent.postMessage('popupClose', '*');
|
window.parent.postMessage('popupClose', '*');
|
||||||
}
|
}
|
||||||
|
|
||||||
selectionCopy() {
|
onSelectionCopy() {
|
||||||
window.parent.postMessage('selectionCopy', '*');
|
window.parent.postMessage('selectionCopy', '*');
|
||||||
}
|
}
|
||||||
|
|
||||||
showOrphaned() {
|
|
||||||
$('#content').hide();
|
|
||||||
$('#orphan').show();
|
|
||||||
}
|
|
||||||
|
|
||||||
onMessage(e) {
|
onMessage(e) {
|
||||||
const handlers = {
|
const handlers = {
|
||||||
showTermDefs: ({definitions, options, context}) => {
|
termsShow: ({definitions, options, context}) => {
|
||||||
this.showTermDefs(definitions, options, context);
|
this.termsShow(definitions, options, context);
|
||||||
},
|
},
|
||||||
|
|
||||||
showKanjiDefs: ({definitions, options, context}) => {
|
kanjiShow: ({definitions, options, context}) => {
|
||||||
this.showKanjiDefs(definitions, options, context);
|
this.kanjiShow(definitions, options, context);
|
||||||
},
|
},
|
||||||
|
|
||||||
showOrphaned: () => {
|
orphaned: () => {
|
||||||
this.showOrphaned();
|
this.onOrphaned();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -89,8 +69,8 @@ window.displayFrame = new class extends Display {
|
|||||||
onKeyDown(e) {
|
onKeyDown(e) {
|
||||||
const handlers = {
|
const handlers = {
|
||||||
67: /* c */ () => {
|
67: /* c */ () => {
|
||||||
if (e.ctrlKey && window.getSelection().toString() === '') {
|
if (e.ctrlKey && !window.getSelection().toString()) {
|
||||||
this.selectionCopy();
|
this.onSelectionCopy();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
window.yomichanFrontend = new class {
|
window.yomichan_frontend = new class {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.popup = new Popup();
|
this.popup = new Popup();
|
||||||
this.popupTimer = null;
|
this.popupTimer = null;
|
||||||
@ -27,17 +27,23 @@ window.yomichanFrontend = new class {
|
|||||||
this.lastTextSource = null;
|
this.lastTextSource = null;
|
||||||
this.pendingLookup = false;
|
this.pendingLookup = false;
|
||||||
this.options = null;
|
this.options = null;
|
||||||
|
}
|
||||||
|
|
||||||
apiOptionsGet().then(options => {
|
async prepare() {
|
||||||
this.options = options;
|
try {
|
||||||
window.addEventListener('mouseover', this.onMouseOver.bind(this));
|
this.options = await apiOptionsGet();
|
||||||
window.addEventListener('mousedown', this.onMouseDown.bind(this));
|
} catch (e) {
|
||||||
window.addEventListener('mouseup', this.onMouseUp.bind(this));
|
this.onError(e);
|
||||||
window.addEventListener('mousemove', this.onMouseMove.bind(this));
|
}
|
||||||
window.addEventListener('resize', e => this.searchClear());
|
|
||||||
window.addEventListener('message', this.onFrameMessage.bind(this));
|
window.addEventListener('message', this.onFrameMessage.bind(this));
|
||||||
chrome.runtime.onMessage.addListener(this.onBgMessage.bind(this));
|
window.addEventListener('mousedown', this.onMouseDown.bind(this));
|
||||||
}).catch(this.handleError.bind(this));
|
window.addEventListener('mousemove', this.onMouseMove.bind(this));
|
||||||
|
window.addEventListener('mouseover', this.onMouseOver.bind(this));
|
||||||
|
window.addEventListener('mouseup', this.onMouseUp.bind(this));
|
||||||
|
window.addEventListener('resize', this.onResize.bind(this));
|
||||||
|
|
||||||
|
chrome.runtime.onMessage.addListener(this.onBgMessage.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
popupTimerSet(callback) {
|
popupTimerSet(callback) {
|
||||||
@ -144,7 +150,11 @@ window.yomichanFrontend = new class {
|
|||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
searchAt(point) {
|
onResize() {
|
||||||
|
this.onSearchClear();
|
||||||
|
}
|
||||||
|
|
||||||
|
async searchAt(point) {
|
||||||
if (this.pendingLookup) {
|
if (this.pendingLookup) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -160,70 +170,69 @@ window.yomichanFrontend = new class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.pendingLookup = true;
|
this.pendingLookup = true;
|
||||||
this.searchTerms(textSource).then(found => {
|
|
||||||
if (!found) {
|
try {
|
||||||
return this.searchKanji(textSource);
|
if (!await this.searchTerms(textSource)) {
|
||||||
|
await this.searchKanji(textSource);
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
} catch (e) {
|
||||||
this.handleError(error, textSource);
|
this.onError(e);
|
||||||
}).then(() => {
|
}
|
||||||
docImposterDestroy();
|
|
||||||
this.pendingLookup = false;
|
docImposterDestroy();
|
||||||
});
|
this.pendingLookup = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
searchTerms(textSource) {
|
async searchTerms(textSource) {
|
||||||
textSource.setEndOffset(this.options.scanning.length);
|
textSource.setEndOffset(this.options.scanning.length);
|
||||||
|
|
||||||
return apiTermsFind(textSource.text()).then(({definitions, length}) => {
|
const {definitions, length} = await apiTermsFind(textSource.text());
|
||||||
if (definitions.length === 0) {
|
if (definitions.length === 0) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
textSource.setEndOffset(length);
|
|
||||||
|
|
||||||
const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt);
|
textSource.setEndOffset(length);
|
||||||
const url = window.location.href;
|
|
||||||
this.popup.showTermDefs(
|
|
||||||
textSource.getRect(),
|
|
||||||
definitions,
|
|
||||||
this.options,
|
|
||||||
{sentence, url}
|
|
||||||
);
|
|
||||||
|
|
||||||
this.lastTextSource = textSource;
|
const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt);
|
||||||
if (this.options.scanning.selectText) {
|
const url = window.location.href;
|
||||||
textSource.select();
|
this.popup.termsShow(
|
||||||
}
|
textSource.getRect(),
|
||||||
|
definitions,
|
||||||
|
this.options,
|
||||||
|
{sentence, url}
|
||||||
|
);
|
||||||
|
|
||||||
return true;
|
this.lastTextSource = textSource;
|
||||||
}
|
if (this.options.scanning.selectText) {
|
||||||
});
|
textSource.select();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
searchKanji(textSource) {
|
async searchKanji(textSource) {
|
||||||
textSource.setEndOffset(1);
|
textSource.setEndOffset(1);
|
||||||
|
|
||||||
return apiKanjiFind(textSource.text()).then(definitions => {
|
const definitions = await apiKanjiFind(textSource.text());
|
||||||
if (definitions.length === 0) {
|
if (definitions.length === 0) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt);
|
|
||||||
const url = window.location.href;
|
|
||||||
this.popup.showKanjiDefs(
|
|
||||||
textSource.getRect(),
|
|
||||||
definitions,
|
|
||||||
this.options,
|
|
||||||
{sentence, url}
|
|
||||||
);
|
|
||||||
|
|
||||||
this.lastTextSource = textSource;
|
const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt);
|
||||||
if (this.options.scanning.selectText) {
|
const url = window.location.href;
|
||||||
textSource.select();
|
this.popup.showKanji(
|
||||||
}
|
textSource.getRect(),
|
||||||
|
definitions,
|
||||||
|
this.options,
|
||||||
|
{sentence, url}
|
||||||
|
);
|
||||||
|
|
||||||
return true;
|
this.lastTextSource = textSource;
|
||||||
}
|
if (this.options.scanning.selectText) {
|
||||||
});
|
textSource.select();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
searchClear() {
|
searchClear() {
|
||||||
@ -238,7 +247,7 @@ window.yomichanFrontend = new class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleError(error, textSource) {
|
handleError(error, textSource) {
|
||||||
if (window.yomichanOrphaned) {
|
if (window.yomichan_orphaned) {
|
||||||
if (textSource && this.options.scanning.modifier !== 'none') {
|
if (textSource && this.options.scanning.modifier !== 'none') {
|
||||||
this.popup.showOrphaned(textSource.getRect(), this.options);
|
this.popup.showOrphaned(textSource.getRect(), this.options);
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ function utilInvoke(action, params={}) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
window.yomichanOrphaned = true;
|
window.yomichan_orphaned = true;
|
||||||
reject(e.message);
|
reject(e.message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -32,171 +32,57 @@ class Display {
|
|||||||
$(document).keydown(this.onKeyDown.bind(this));
|
$(document).keydown(this.onKeyDown.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleError(error) {
|
onError(error) {
|
||||||
throw 'override me';
|
throw 'override me';
|
||||||
}
|
}
|
||||||
|
|
||||||
clearSearch() {
|
onSearchClear() {
|
||||||
throw 'override me';
|
throw 'override me';
|
||||||
}
|
}
|
||||||
|
|
||||||
showTermDefs(definitions, options, context) {
|
onSourceTermView(e) {
|
||||||
window.focus();
|
|
||||||
|
|
||||||
this.spinner.hide();
|
|
||||||
this.definitions = definitions;
|
|
||||||
this.options = options;
|
|
||||||
this.context = context;
|
|
||||||
|
|
||||||
const sequence = ++this.sequence;
|
|
||||||
const params = {
|
|
||||||
definitions,
|
|
||||||
addable: options.anki.enable,
|
|
||||||
grouped: options.general.groupResults,
|
|
||||||
playback: options.general.audioSource !== 'disabled',
|
|
||||||
debug: options.general.debugInfo
|
|
||||||
};
|
|
||||||
|
|
||||||
if (context) {
|
|
||||||
for (const definition of definitions) {
|
|
||||||
if (context.sentence) {
|
|
||||||
definition.cloze = Display.clozeBuild(context.sentence, definition.source);
|
|
||||||
}
|
|
||||||
|
|
||||||
definition.url = context.url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
apiTemplateRender('terms.html', params).then(content => {
|
|
||||||
this.container.html(content);
|
|
||||||
this.entryScroll(context && context.index || 0);
|
|
||||||
|
|
||||||
$('.action-add-note').click(this.onAddNote.bind(this));
|
|
||||||
$('.action-view-note').click(this.onViewNote.bind(this));
|
|
||||||
$('.action-play-audio').click(this.onPlayAudio.bind(this));
|
|
||||||
$('.kanji-link').click(this.onKanjiLookup.bind(this));
|
|
||||||
|
|
||||||
return this.adderButtonsUpdate(['term-kanji', 'term-kana'], sequence);
|
|
||||||
}).catch(this.handleError.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
showKanjiDefs(definitions, options, context) {
|
|
||||||
window.focus();
|
|
||||||
|
|
||||||
this.spinner.hide();
|
|
||||||
this.definitions = definitions;
|
|
||||||
this.options = options;
|
|
||||||
this.context = context;
|
|
||||||
|
|
||||||
const sequence = ++this.sequence;
|
|
||||||
const params = {
|
|
||||||
definitions,
|
|
||||||
source: context && context.source,
|
|
||||||
addable: options.anki.enable,
|
|
||||||
debug: options.general.debugInfo
|
|
||||||
};
|
|
||||||
|
|
||||||
if (context) {
|
|
||||||
for (const definition of definitions) {
|
|
||||||
if (context.sentence) {
|
|
||||||
definition.cloze = Display.clozeBuild(context.sentence);
|
|
||||||
}
|
|
||||||
|
|
||||||
definition.url = context.url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
apiTemplateRender('kanji.html', params).then(content => {
|
|
||||||
this.container.html(content);
|
|
||||||
this.entryScroll(context && context.index || 0);
|
|
||||||
|
|
||||||
$('.action-add-note').click(this.onAddNote.bind(this));
|
|
||||||
$('.source-term').click(this.onSourceTerm.bind(this));
|
|
||||||
|
|
||||||
return this.adderButtonsUpdate(['kanji'], sequence);
|
|
||||||
}).catch(this.handleError.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
adderButtonsUpdate(modes, sequence) {
|
|
||||||
return apiDefinitionsAddable(this.definitions, modes).then(states => {
|
|
||||||
if (!states || sequence !== this.sequence) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
states.forEach((state, index) => {
|
|
||||||
for (const mode in state) {
|
|
||||||
const button = Display.adderButtonFind(index, mode);
|
|
||||||
if (state[mode]) {
|
|
||||||
button.removeClass('disabled');
|
|
||||||
} else {
|
|
||||||
button.addClass('disabled');
|
|
||||||
}
|
|
||||||
|
|
||||||
button.removeClass('pending');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
entryScroll(index, smooth) {
|
|
||||||
index = Math.min(index, this.definitions.length - 1);
|
|
||||||
index = Math.max(index, 0);
|
|
||||||
|
|
||||||
$('.current').hide().eq(index).show();
|
|
||||||
|
|
||||||
const container = $('html,body').stop();
|
|
||||||
const entry = $('.entry').eq(index);
|
|
||||||
const target = index === 0 ? 0 : entry.offset().top;
|
|
||||||
|
|
||||||
if (smooth) {
|
|
||||||
container.animate({scrollTop: target}, 200);
|
|
||||||
} else {
|
|
||||||
container.scrollTop(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.index = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
onSourceTerm(e) {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.sourceBack();
|
this.sourceBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
onKanjiLookup(e) {
|
async onKanjiLookup(e) {
|
||||||
e.preventDefault();
|
try {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
const link = $(e.target);
|
const link = $(e.target);
|
||||||
const context = {
|
const context = {
|
||||||
source: {
|
source: {
|
||||||
definitions: this.definitions,
|
definitions: this.definitions,
|
||||||
index: Display.entryIndexFind(link)
|
index: Display.entryIndexFind(link)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.context) {
|
||||||
|
context.sentence = this.context.sentence;
|
||||||
|
context.url = this.context.url;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
if (this.context) {
|
const kanjiDefs = await apiKanjiFind(link.text());
|
||||||
context.sentence = this.context.sentence;
|
this.kanjiShow(kanjiDefs, this.options, context);
|
||||||
context.url = this.context.url;
|
} catch (e) {
|
||||||
|
this.onError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
apiKanjiFind(link.text()).then(kanjiDefs => {
|
|
||||||
this.showKanjiDefs(kanjiDefs, this.options, context);
|
|
||||||
}).catch(this.handleError.bind(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onPlayAudio(e) {
|
onAudioPlay(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const index = Display.entryIndexFind($(e.currentTarget));
|
const index = Display.entryIndexFind($(e.currentTarget));
|
||||||
this.audioPlay(this.definitions[index]);
|
this.audioPlay(this.definitions[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAddNote(e) {
|
onNoteAdd(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const link = $(e.currentTarget);
|
const link = $(e.currentTarget);
|
||||||
const index = Display.entryIndexFind(link);
|
const index = Display.entryIndexFind(link);
|
||||||
this.noteAdd(this.definitions[index], link.data('mode'));
|
this.noteAdd(this.definitions[index], link.data('mode'));
|
||||||
}
|
}
|
||||||
|
|
||||||
onViewNote(e) {
|
onNoteView(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const link = $(e.currentTarget);
|
const link = $(e.currentTarget);
|
||||||
const index = Display.entryIndexFind(link);
|
const index = Display.entryIndexFind(link);
|
||||||
@ -220,48 +106,48 @@ class Display {
|
|||||||
|
|
||||||
const handlers = {
|
const handlers = {
|
||||||
27: /* escape */ () => {
|
27: /* escape */ () => {
|
||||||
this.clearSearch();
|
this.onSearchClear();
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
33: /* page up */ () => {
|
33: /* page up */ () => {
|
||||||
if (e.altKey) {
|
if (e.altKey) {
|
||||||
this.entryScroll(this.index - 3, true);
|
this.entryScrollIntoView(this.index - 3, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
34: /* page down */ () => {
|
34: /* page down */ () => {
|
||||||
if (e.altKey) {
|
if (e.altKey) {
|
||||||
this.entryScroll(this.index + 3, true);
|
this.entryScrollIntoView(this.index + 3, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
35: /* end */ () => {
|
35: /* end */ () => {
|
||||||
if (e.altKey) {
|
if (e.altKey) {
|
||||||
this.entryScroll(this.definitions.length - 1, true);
|
this.entryScrollIntoView(this.definitions.length - 1, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
36: /* home */ () => {
|
36: /* home */ () => {
|
||||||
if (e.altKey) {
|
if (e.altKey) {
|
||||||
this.entryScroll(0, true);
|
this.entryScrollIntoView(0, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
38: /* up */ () => {
|
38: /* up */ () => {
|
||||||
if (e.altKey) {
|
if (e.altKey) {
|
||||||
this.entryScroll(this.index - 1, true);
|
this.entryScrollIntoView(this.index - 1, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
40: /* down */ () => {
|
40: /* down */ () => {
|
||||||
if (e.altKey) {
|
if (e.altKey) {
|
||||||
this.entryScroll(this.index + 1, true);
|
this.entryScrollIntoView(this.index + 1, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -317,6 +203,135 @@ class Display {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async termsShow(definitions, options, context) {
|
||||||
|
try {
|
||||||
|
window.focus();
|
||||||
|
|
||||||
|
this.definitions = definitions;
|
||||||
|
this.options = options;
|
||||||
|
this.context = context;
|
||||||
|
|
||||||
|
const sequence = ++this.sequence;
|
||||||
|
const params = {
|
||||||
|
definitions,
|
||||||
|
addable: options.anki.enable,
|
||||||
|
grouped: options.general.groupResults,
|
||||||
|
playback: options.general.audioSource !== 'disabled',
|
||||||
|
debug: options.general.debugInfo
|
||||||
|
};
|
||||||
|
|
||||||
|
if (context) {
|
||||||
|
for (const definition of definitions) {
|
||||||
|
if (context.sentence) {
|
||||||
|
definition.cloze = Display.clozeBuild(context.sentence, definition.source);
|
||||||
|
}
|
||||||
|
|
||||||
|
definition.url = context.url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const content = await apiTemplateRender('terms.html', params);
|
||||||
|
this.container.html(content);
|
||||||
|
this.entryScrollIntoView(context && context.index || 0);
|
||||||
|
|
||||||
|
$('.action-add-note').click(this.onNoteAdd.bind(this));
|
||||||
|
$('.action-view-note').click(this.onNoteView.bind(this));
|
||||||
|
$('.action-play-audio').click(this.onAudioPlay.bind(this));
|
||||||
|
$('.kanji-link').click(this.onKanjiLookup.bind(this));
|
||||||
|
|
||||||
|
await this.adderButtonUpdate(['term-kanji', 'term-kana'], sequence);
|
||||||
|
} catch (e) {
|
||||||
|
this.onError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async kanjiShow(definitions, options, context) {
|
||||||
|
try {
|
||||||
|
window.focus();
|
||||||
|
|
||||||
|
this.definitions = definitions;
|
||||||
|
this.options = options;
|
||||||
|
this.context = context;
|
||||||
|
|
||||||
|
const sequence = ++this.sequence;
|
||||||
|
const params = {
|
||||||
|
definitions,
|
||||||
|
source: context && context.source,
|
||||||
|
addable: options.anki.enable,
|
||||||
|
debug: options.general.debugInfo
|
||||||
|
};
|
||||||
|
|
||||||
|
if (context) {
|
||||||
|
for (const definition of definitions) {
|
||||||
|
if (context.sentence) {
|
||||||
|
definition.cloze = Display.clozeBuild(context.sentence);
|
||||||
|
}
|
||||||
|
|
||||||
|
definition.url = context.url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const content = await apiTemplateRender('kanji.html', params);
|
||||||
|
this.container.html(content);
|
||||||
|
this.entryScrollIntoView(context && context.index || 0);
|
||||||
|
|
||||||
|
$('.action-add-note').click(this.onNoteAdd.bind(this));
|
||||||
|
$('.source-term').click(this.onSourceTermView.bind(this));
|
||||||
|
|
||||||
|
await this.adderButtonUpdate(['kanji'], sequence);
|
||||||
|
} catch (e) {
|
||||||
|
this.onError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async adderButtonUpdate(modes, sequence) {
|
||||||
|
try {
|
||||||
|
this.spinner.show();
|
||||||
|
|
||||||
|
const states = apiDefinitionsAddable(this.definitions, modes);
|
||||||
|
if (!states || sequence !== this.sequence) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < states.length; ++i) {
|
||||||
|
const state = states[i];
|
||||||
|
for (const mode in state) {
|
||||||
|
const button = Display.adderButtonFind(i, mode);
|
||||||
|
if (state[mode]) {
|
||||||
|
button.removeClass('disabled');
|
||||||
|
} else {
|
||||||
|
button.addClass('disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
button.removeClass('pending');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.onError(e);
|
||||||
|
} finally {
|
||||||
|
this.spinner.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entryScrollIntoView(index, smooth) {
|
||||||
|
index = Math.min(index, this.definitions.length - 1);
|
||||||
|
index = Math.max(index, 0);
|
||||||
|
|
||||||
|
$('.current').hide().eq(index).show();
|
||||||
|
|
||||||
|
const container = $('html,body').stop();
|
||||||
|
const entry = $('.entry').eq(index);
|
||||||
|
const target = index === 0 ? 0 : entry.offset().top;
|
||||||
|
|
||||||
|
if (smooth) {
|
||||||
|
container.animate({scrollTop: target}, 200);
|
||||||
|
} else {
|
||||||
|
container.scrollTop(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
sourceBack() {
|
sourceBack() {
|
||||||
if (this.context && this.context.source) {
|
if (this.context && this.context.source) {
|
||||||
const context = {
|
const context = {
|
||||||
@ -325,35 +340,42 @@ class Display {
|
|||||||
index: this.context.source.index
|
index: this.context.source.index
|
||||||
};
|
};
|
||||||
|
|
||||||
this.showTermDefs(this.context.source.definitions, this.options, context);
|
this.termsShow(this.context.source.definitions, this.options, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
noteAdd(definition, mode) {
|
async noteAdd(definition, mode) {
|
||||||
this.spinner.show();
|
try {
|
||||||
return apiDefinitionAdd(definition, mode).then(noteId => {
|
this.spinner.show();
|
||||||
|
|
||||||
|
const noteId = await apiDefinitionAdd(definition, mode);
|
||||||
if (noteId) {
|
if (noteId) {
|
||||||
const index = this.definitions.indexOf(definition);
|
const index = this.definitions.indexOf(definition);
|
||||||
Display.adderButtonFind(index, mode).addClass('disabled');
|
Display.adderButtonFind(index, mode).addClass('disabled');
|
||||||
Display.viewerButtonFind(index).removeClass('pending disabled').data('noteId', noteId);
|
Display.viewerButtonFind(index).removeClass('pending disabled').data('noteId', noteId);
|
||||||
} else {
|
} else {
|
||||||
this.handleError('note could not be added');
|
throw 'note could note be added';
|
||||||
}
|
}
|
||||||
}).catch(this.handleError.bind(this)).then(() => this.spinner.hide());
|
} catch (e) {
|
||||||
|
this.onError(e);
|
||||||
|
} finally {
|
||||||
|
this.spinner.hide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
audioPlay(definition) {
|
async audioPlay(definition) {
|
||||||
this.spinner.show();
|
try {
|
||||||
|
this.spinner.show();
|
||||||
|
|
||||||
for (const key in this.audioCache) {
|
let url = await audioBuildUrl(definition, this.options.general.audioSource, this.responseCache);
|
||||||
this.audioCache[key].pause();
|
|
||||||
}
|
|
||||||
|
|
||||||
audioBuildUrl(definition, this.options.general.audioSource, this.responseCache).then(url => {
|
|
||||||
if (!url) {
|
if (!url) {
|
||||||
url = '/mixed/mp3/button.mp3';
|
url = '/mixed/mp3/button.mp3';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const key in this.audioCache) {
|
||||||
|
this.audioCache[key].pause();
|
||||||
|
}
|
||||||
|
|
||||||
let audio = this.audioCache[url];
|
let audio = this.audioCache[url];
|
||||||
if (audio) {
|
if (audio) {
|
||||||
audio.currentTime = 0;
|
audio.currentTime = 0;
|
||||||
@ -371,7 +393,11 @@ class Display {
|
|||||||
audio.play();
|
audio.play();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}).catch(this.handleError.bind(this)).then(() => this.spinner.hide());
|
} catch (e) {
|
||||||
|
this.onError(e);
|
||||||
|
} finally {
|
||||||
|
this.spinner.hide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static clozeBuild(sentence, source) {
|
static clozeBuild(sentence, source) {
|
||||||
|
Loading…
Reference in New Issue
Block a user