Merge branch 'dev'
This commit is contained in:
commit
37321e8d52
@ -7,6 +7,7 @@
|
|||||||
<script src="/mixed/lib/handlebars.min.js"></script>
|
<script src="/mixed/lib/handlebars.min.js"></script>
|
||||||
<script src="/mixed/lib/dexie.min.js"></script>
|
<script src="/mixed/lib/dexie.min.js"></script>
|
||||||
<script src="/mixed/lib/wanakana.min.js"></script>
|
<script src="/mixed/lib/wanakana.min.js"></script>
|
||||||
|
<script src="/mixed/js/util.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="/bg/js/util.js"></script>
|
||||||
<script src="/bg/js/anki-connect.js"></script>
|
<script src="/bg/js/anki-connect.js"></script>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="/mixed/lib/bootstrap-3.3.7-dist/css/bootstrap-theme.min.css">
|
<link rel="stylesheet" type="text/css" href="/mixed/lib/bootstrap-3.3.7-dist/css/bootstrap-theme.min.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container-fluid">
|
<div class="container">
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h1>Welcome to Yomichan!</h1>
|
<h1>Welcome to Yomichan!</h1>
|
||||||
</div>
|
</div>
|
||||||
@ -23,11 +23,12 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
<li>Click on the <img src="/mixed/img/icon16.png" alt> icon in the browser toolbar to open the Yomichan options page.</li>
|
<li>Click on the <img src="/mixed/img/icon16.png" alt> icon in the browser toolbar to open the Yomichan actions dialog.</li>
|
||||||
<li>Import the dictionaries (bundled or custom) you wish to use for term and Kanji searches.</li>
|
<li>Click on the <em>monkey wrench</em> icon in the middle to open the options page.</li>
|
||||||
<li>Hold down <kbd>Shift</kbd> (or the middle mouse button) as you hover over text to see term definitions.</li>
|
<li>Import the dictionaries you wish to use for term and Kanji searches.</li>
|
||||||
<li>Click on the <img src="/mixed/img/play-audio.png" alt> icon to hear the term pronounced by a native speaker (if audio is available).</li>
|
<li>Hold down <kbd>Shift</kbd> key or the middle mouse button as you move your mouse over text to display definitions.</li>
|
||||||
<li>Click on Kanji in the definition window to view additional information about that character.</li>
|
<li>Click on the <img src="/mixed/img/play-audio.png" alt> icon to hear the term pronounced by a native speaker.</li>
|
||||||
|
<li>Click on individual Kanji in the term definition results to view additional information about those characters.</li>
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -90,7 +90,7 @@ class Deinflection {
|
|||||||
source: this.term,
|
source: this.term,
|
||||||
rules: this.rules,
|
rules: this.rules,
|
||||||
definitions: this.definitions,
|
definitions: this.definitions,
|
||||||
reasons: [this.reason]
|
reasons: this.reason.length > 0 ? [this.reason] : []
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,8 +20,13 @@
|
|||||||
window.displayWindow = new class extends Display {
|
window.displayWindow = new class extends Display {
|
||||||
constructor() {
|
constructor() {
|
||||||
super($('#spinner'), $('#content'));
|
super($('#spinner'), $('#content'));
|
||||||
$('#search').click(this.onSearch.bind(this));
|
|
||||||
window.wanakana.bind($('#query').get(0));
|
const search = $('#search');
|
||||||
|
search.click(this.onSearch.bind(this));
|
||||||
|
|
||||||
|
const query = $('#query');
|
||||||
|
query.on('input', () => search.prop('disabled', query.val().length === 0));
|
||||||
|
window.wanakana.bind(query.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
definitionAdd(definition, mode) {
|
definitionAdd(definition, mode) {
|
||||||
@ -44,6 +49,10 @@ window.displayWindow = new class extends Display {
|
|||||||
window.alert(`Error: ${error}`);
|
window.alert(`Error: ${error}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearSearch() {
|
||||||
|
$('#query').focus().select();
|
||||||
|
}
|
||||||
|
|
||||||
onSearch(e) {
|
onSearch(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
$('#intro').slideUp();
|
$('#intro').slideUp();
|
||||||
|
@ -18,17 +18,14 @@
|
|||||||
|
|
||||||
|
|
||||||
$(document).ready(() => {
|
$(document).ready(() => {
|
||||||
$('#open-search').click(() => window.open(chrome.extension.getURL('/bg/search.html')));
|
$('#open-search').click(() => commandExec('search'));
|
||||||
$('#open-options').click(() => chrome.runtime.openOptionsPage());
|
$('#open-options').click(() => commandExec('options'));
|
||||||
$('#open-help').click(() => window.open('http://foosoft.net/projects/yomichan'));
|
$('#open-help').click(() => commandExec('help'));
|
||||||
|
|
||||||
optionsLoad().then(options => {
|
optionsLoad().then(options => {
|
||||||
const toggle = $('#enable-search');
|
const toggle = $('#enable-search');
|
||||||
toggle.prop('checked', options.general.enable).change();
|
toggle.prop('checked', options.general.enable).change();
|
||||||
toggle.bootstrapToggle();
|
toggle.bootstrapToggle();
|
||||||
toggle.change(() => {
|
toggle.change(() => commandExec('toggle'));
|
||||||
options.general.enable = toggle.prop('checked');
|
|
||||||
optionsSave(options).then(() => instYomi().optionsSet(options));
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -284,7 +284,7 @@ templates['fields.html'] = template({"1":function(container,depth0,helpers,parti
|
|||||||
templates['kanji.html'] = template({"1":function(container,depth0,helpers,partials,data) {
|
templates['kanji.html'] = template({"1":function(container,depth0,helpers,partials,data) {
|
||||||
var stack1, helper, alias1=depth0 != null ? depth0 : {};
|
var stack1, helper, alias1=depth0 != null ? depth0 : {};
|
||||||
|
|
||||||
return "<div class=\"entry\">\n <div class=\"actions\">\n"
|
return "<div class=\"entry\" data-type=\"kanji\">\n <div class=\"actions\">\n <img src=\"/mixed/img/entry-current.png\" class=\"current\" title=\"Current entry (Alt + Up/Down/Home/End/PgUp/PgDn)\" alt>\n"
|
||||||
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.addable : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.addable : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.source : depth0),{"name":"if","hash":{},"fn":container.program(4, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.source : depth0),{"name":"if","hash":{},"fn":container.program(4, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ " </div>\n\n <div class=\"glyph\">"
|
+ " </div>\n\n <div class=\"glyph\">"
|
||||||
@ -299,9 +299,9 @@ templates['kanji.html'] = template({"1":function(container,depth0,helpers,partia
|
|||||||
+ ((stack1 = helpers["if"].call(alias1,((stack1 = (depth0 != null ? depth0.glossary : depth0)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(11, data, 0),"inverse":container.program(15, data, 0),"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers["if"].call(alias1,((stack1 = (depth0 != null ? depth0.glossary : depth0)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(11, data, 0),"inverse":container.program(15, data, 0),"data":data})) != null ? stack1 : "")
|
||||||
+ " </div>\n</div>\n";
|
+ " </div>\n</div>\n";
|
||||||
},"2":function(container,depth0,helpers,partials,data) {
|
},"2":function(container,depth0,helpers,partials,data) {
|
||||||
return " <a href=\"#\" title=\"Add Kanji\" class=\"action-add-note pending disabled\" data-mode=\"kanji\"><img src=\"/mixed/img/add-kanji.png\" alt></a>\n";
|
return " <a href=\"#\" class=\"action-add-note pending disabled\" data-mode=\"kanji\"><img src=\"/mixed/img/add-kanji.png\" title=\"Add Kanji (Alt + K)\" alt></a>\n";
|
||||||
},"4":function(container,depth0,helpers,partials,data) {
|
},"4":function(container,depth0,helpers,partials,data) {
|
||||||
return " <a href=\"#\" title=\"Source term\" class=\"source-term\"><img src=\"/mixed/img/source-term.png\" alt></a>\n";
|
return " <a href=\"#\" class=\"source-term\"><img src=\"/mixed/img/source-term.png\" title=\"Source term (Alt + B)\" alt></a>\n";
|
||||||
},"6":function(container,depth0,helpers,partials,data) {
|
},"6":function(container,depth0,helpers,partials,data) {
|
||||||
var stack1;
|
var stack1;
|
||||||
|
|
||||||
@ -442,7 +442,7 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia
|
|||||||
},"12":function(container,depth0,helpers,partials,data) {
|
},"12":function(container,depth0,helpers,partials,data) {
|
||||||
var stack1, alias1=depth0 != null ? depth0 : {};
|
var stack1, alias1=depth0 != null ? depth0 : {};
|
||||||
|
|
||||||
return "<div class=\"entry\">\n <div class=\"actions\">\n"
|
return "<div class=\"entry\" data-type=\"term\">\n <div class=\"actions\">\n <img src=\"/mixed/img/entry-current.png\" class=\"current\" title=\"Current entry (Alt + Up/Down/Home/End/PgUp/PgDn)\" alt>\n"
|
||||||
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.addable : depth0),{"name":"if","hash":{},"fn":container.program(13, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.addable : depth0),{"name":"if","hash":{},"fn":container.program(13, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.playback : depth0),{"name":"if","hash":{},"fn":container.program(15, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.playback : depth0),{"name":"if","hash":{},"fn":container.program(15, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ " </div>\n\n"
|
+ " </div>\n\n"
|
||||||
@ -453,9 +453,9 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia
|
|||||||
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.grouped : depth0),{"name":"if","hash":{},"fn":container.program(26, data, 0),"inverse":container.program(32, data, 0),"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.grouped : depth0),{"name":"if","hash":{},"fn":container.program(26, data, 0),"inverse":container.program(32, data, 0),"data":data})) != null ? stack1 : "")
|
||||||
+ " </div>\n</div>\n";
|
+ " </div>\n</div>\n";
|
||||||
},"13":function(container,depth0,helpers,partials,data) {
|
},"13":function(container,depth0,helpers,partials,data) {
|
||||||
return " <a href=\"#\" title=\"Add expression\" class=\"action-add-note pending disabled\" data-mode=\"term-kanji\"><img src=\"/mixed/img/add-term-kanji.png\" alt></a>\n <a href=\"#\" title=\"Add reading\" class=\"action-add-note pending disabled\" data-mode=\"term-kana\"><img src=\"/mixed/img/add-term-kana.png\" alt></a>\n";
|
return " <a href=\"#\" class=\"action-add-note pending disabled\" data-mode=\"term-kanji\"><img src=\"/mixed/img/add-term-kanji.png\" title=\"Add expression (Alt + E)\" alt></a>\n <a href=\"#\" class=\"action-add-note pending disabled\" data-mode=\"term-kana\"><img src=\"/mixed/img/add-term-kana.png\" title=\"Add reading (Alt + R)\" alt></a>\n";
|
||||||
},"15":function(container,depth0,helpers,partials,data) {
|
},"15":function(container,depth0,helpers,partials,data) {
|
||||||
return " <a href=\"#\" title=\"Play audio\" class=\"action-play-audio\"><img src=\"/mixed/img/play-audio.png\" alt></a>\n";
|
return " <a href=\"#\" class=\"action-play-audio\"><img src=\"/mixed/img/play-audio.png\" title=\"Play audio (Alt + P)\" alt></a>\n";
|
||||||
},"17":function(container,depth0,helpers,partials,data) {
|
},"17":function(container,depth0,helpers,partials,data) {
|
||||||
var stack1, helper, options, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing, alias3="function", buffer =
|
var stack1, helper, options, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing, alias3="function", buffer =
|
||||||
" <div class=\"expression\"><ruby>";
|
" <div class=\"expression\"><ruby>";
|
||||||
|
@ -33,6 +33,15 @@ function promiseCallback(promise, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Commands
|
||||||
|
*/
|
||||||
|
|
||||||
|
function commandExec(command) {
|
||||||
|
instYomi().onCommand(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Instance
|
* Instance
|
||||||
*/
|
*/
|
||||||
|
@ -25,12 +25,13 @@ window.yomichan = new class {
|
|||||||
this.anki = new AnkiNull();
|
this.anki = new AnkiNull();
|
||||||
this.options = null;
|
this.options = null;
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener(this.onMessage.bind(this));
|
this.translator.prepare().then(optionsLoad).then(this.optionsSet.bind(this)).then(() => {
|
||||||
if (chrome.runtime.onInstalled) {
|
chrome.commands.onCommand.addListener(this.onCommand.bind(this));
|
||||||
chrome.runtime.onInstalled.addListener(this.onInstalled.bind(this));
|
chrome.runtime.onMessage.addListener(this.onMessage.bind(this));
|
||||||
}
|
if (chrome.runtime.onInstalled) {
|
||||||
|
chrome.runtime.onInstalled.addListener(this.onInstalled.bind(this));
|
||||||
this.translator.prepare().then(optionsLoad).then(this.optionsSet.bind(this));
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
optionsSet(options) {
|
optionsSet(options) {
|
||||||
@ -55,7 +56,10 @@ window.yomichan = new class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
noteFormat(definition, mode) {
|
noteFormat(definition, mode) {
|
||||||
const note = {fields: {}, tags: this.options.anki.tags};
|
const note = {
|
||||||
|
fields: {},
|
||||||
|
tags: this.options.anki.tags
|
||||||
|
};
|
||||||
|
|
||||||
let fields = [];
|
let fields = [];
|
||||||
if (mode === 'kanji') {
|
if (mode === 'kanji') {
|
||||||
@ -116,8 +120,15 @@ window.yomichan = new class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
definitionAdd(definition, mode) {
|
definitionAdd(definition, mode) {
|
||||||
const note = this.noteFormat(definition, mode);
|
let promise = Promise.resolve();
|
||||||
return this.anki.addNote(note);
|
if (mode !== 'kanji') {
|
||||||
|
promise = audioInject(definition, this.options.anki.terms.fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
return promise.then(() => {
|
||||||
|
const note = this.noteFormat(definition, mode);
|
||||||
|
return this.anki.addNote(note);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
definitionsAddable(definitions, modes) {
|
definitionsAddable(definitions, modes) {
|
||||||
@ -153,34 +164,60 @@ window.yomichan = new class {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onCommand(command) {
|
||||||
|
const handlers = {
|
||||||
|
search: () => {
|
||||||
|
chrome.tabs.create({url: chrome.extension.getURL('/bg/search.html')});
|
||||||
|
},
|
||||||
|
|
||||||
|
help: () => {
|
||||||
|
chrome.tabs.create({url: 'https://foosoft.net/projects/yomichan/'});
|
||||||
|
},
|
||||||
|
|
||||||
|
options: () => {
|
||||||
|
chrome.runtime.openOptionsPage();
|
||||||
|
},
|
||||||
|
|
||||||
|
toggle: () => {
|
||||||
|
this.options.general.enable = !this.options.general.enable;
|
||||||
|
optionsSave(this.options).then(() => this.optionsSet(this.options));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handler = handlers[command];
|
||||||
|
if (handler) {
|
||||||
|
handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMessage(request, sender, callback) {
|
onMessage(request, sender, callback) {
|
||||||
const handlers = new class {
|
const handlers = new class {
|
||||||
api_optionsGet({callback}) {
|
optionsGet({callback}) {
|
||||||
promiseCallback(optionsLoad(), callback);
|
promiseCallback(optionsLoad(), callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
api_kanjiFind({text, callback}) {
|
kanjiFind({text, callback}) {
|
||||||
promiseCallback(this.kanjiFind(text), callback);
|
promiseCallback(this.kanjiFind(text), callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
api_termsFind({text, callback}) {
|
termsFind({text, callback}) {
|
||||||
promiseCallback(this.termsFind(text), callback);
|
promiseCallback(this.termsFind(text), callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
api_templateRender({template, data, callback}) {
|
templateRender({template, data, callback}) {
|
||||||
promiseCallback(this.templateRender(template, data), callback);
|
promiseCallback(this.templateRender(template, data), callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
api_definitionAdd({definition, mode, callback}) {
|
definitionAdd({definition, mode, callback}) {
|
||||||
promiseCallback(this.definitionAdd(definition, mode), callback);
|
promiseCallback(this.definitionAdd(definition, mode), callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
api_definitionsAddable({definitions, modes, callback}) {
|
definitionsAddable({definitions, modes, callback}) {
|
||||||
promiseCallback(this.definitionsAddable(definitions, modes), callback);
|
promiseCallback(this.definitionsAddable(definitions, modes), callback);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const {action, params} = request, method = handlers[`api_${action}`];
|
const {action, params} = request, method = handlers[action];
|
||||||
if (typeof(method) === 'function') {
|
if (typeof(method) === 'function') {
|
||||||
params.callback = callback;
|
params.callback = callback;
|
||||||
method.call(this, params);
|
method.call(this, params);
|
||||||
|
@ -18,12 +18,12 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<p>
|
<p>
|
||||||
<input type="checkbox" id="enable-search">
|
<input type="checkbox" id="enable-search" title="Toggle (Alt + Delete)">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<div class="btn-group" style="white-space: nowrap">
|
<div class="btn-group" style="white-space: nowrap">
|
||||||
<button type="button" id="open-search" title="Search" class="btn btn-default btn-xs glyphicon glyphicon-search"></button>
|
<button type="button" id="open-search" title="Search (Alt + Insert)" class="btn btn-default btn-xs glyphicon glyphicon-search"></button>
|
||||||
<button type="button" id="open-options" title="Options" class="btn btn-default btn-xs glyphicon glyphicon-wrench"></button>
|
<button type="button" id="open-options" title="Options (Alt + End)" class="btn btn-default btn-xs glyphicon glyphicon-wrench"></button>
|
||||||
<button type="button" id="open-help" title="Help" class="btn btn-default btn-xs glyphicon glyphicon-question-sign"></button>
|
<button type="button" id="open-help" title="Help" class="btn btn-default btn-xs glyphicon glyphicon-question-sign"></button>
|
||||||
</div>
|
</div>
|
||||||
</p>
|
</p>
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
<form class="input-group">
|
<form class="input-group">
|
||||||
<input type="text" class="form-control" placeholder="Search for..." id="query" autofocus>
|
<input type="text" class="form-control" placeholder="Search for..." id="query" autofocus>
|
||||||
<span class="input-group-btn">
|
<span class="input-group-btn">
|
||||||
<input type="submit" class="btn btn-default form-control" id="search" value="Search">
|
<input type="submit" class="btn btn-default form-control" id="search" value="Search" disabled>
|
||||||
</span>
|
</span>
|
||||||
</form>
|
</form>
|
||||||
</p>
|
</p>
|
||||||
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
<script src="/mixed/lib/jquery-3.1.1.min.js"></script>
|
<script src="/mixed/lib/jquery-3.1.1.min.js"></script>
|
||||||
<script src="/bg/js/util.js"></script>
|
<script src="/bg/js/util.js"></script>
|
||||||
|
<script src="/mixed/js/util.js"></script>
|
||||||
<script src="/mixed/js/display.js"></script>
|
<script src="/mixed/js/display.js"></script>
|
||||||
<script src="/mixed/lib/wanakana.min.js"></script>
|
<script src="/mixed/lib/wanakana.min.js"></script>
|
||||||
<script src="/bg/js/display-window.js"></script>
|
<script src="/bg/js/display-window.js"></script>
|
||||||
|
@ -6,28 +6,35 @@
|
|||||||
<link rel="stylesheet" href="/mixed/lib/bootstrap-3.3.7-dist/css/bootstrap.min.css">
|
<link rel="stylesheet" href="/mixed/lib/bootstrap-3.3.7-dist/css/bootstrap.min.css">
|
||||||
<link rel="stylesheet" href="/mixed/lib/bootstrap-3.3.7-dist/css/bootstrap-theme.min.css">
|
<link rel="stylesheet" href="/mixed/lib/bootstrap-3.3.7-dist/css/bootstrap-theme.min.css">
|
||||||
<link rel="stylesheet" href="/mixed/css/frame.css">
|
<link rel="stylesheet" href="/mixed/css/frame.css">
|
||||||
|
<style type="text/css">
|
||||||
|
.entry {
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container-fluid">
|
<div id="spinner">
|
||||||
<div id="spinner">
|
<img src="/mixed/img/spinner.gif">
|
||||||
<img src="/mixed/img/spinner.gif">
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="content"></div>
|
<div id="content"></div>
|
||||||
|
|
||||||
<div id="orphan">
|
<div id="orphan">
|
||||||
|
<div class="container-fluid">
|
||||||
<h1>Yomichan Updated!</h1>
|
<h1>Yomichan Updated!</h1>
|
||||||
<p>
|
<p>
|
||||||
The Yomichan extension has been updated to a new version! In order to continue
|
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.
|
viewing definitions on this page you must reload this tab or restart your browser.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/mixed/lib/jquery-3.1.1.min.js"></script>
|
|
||||||
<script src="/mixed/lib/wanakana.min.js"></script>
|
|
||||||
<script src="/fg/js/util.js"></script>
|
|
||||||
<script src="/mixed/js/display.js"></script>
|
|
||||||
<script src="/fg/js/display-frame.js"></script>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script src="/mixed/lib/jquery-3.1.1.min.js"></script>
|
||||||
|
<script src="/mixed/lib/wanakana.min.js"></script>
|
||||||
|
<script src="/fg/js/util.js"></script>
|
||||||
|
<script src="/mixed/js/util.js"></script>
|
||||||
|
<script src="/mixed/js/display.js"></script>
|
||||||
|
<script src="/fg/js/display-frame.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -47,6 +47,10 @@ window.displayFrame = new class extends Display {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearSearch() {
|
||||||
|
window.parent.postMessage('popupClose', '*');
|
||||||
|
}
|
||||||
|
|
||||||
showOrphaned() {
|
showOrphaned() {
|
||||||
$('#content').hide();
|
$('#content').hide();
|
||||||
$('#orphan').show();
|
$('#orphan').show();
|
||||||
@ -54,20 +58,20 @@ window.displayFrame = new class extends Display {
|
|||||||
|
|
||||||
onMessage(e) {
|
onMessage(e) {
|
||||||
const handlers = new class {
|
const handlers = new class {
|
||||||
api_showTermDefs({definitions, options, context}) {
|
showTermDefs({definitions, options, context}) {
|
||||||
this.showTermDefs(definitions, options, context);
|
this.showTermDefs(definitions, options, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
api_showKanjiDefs({definitions, options, context}) {
|
showKanjiDefs({definitions, options, context}) {
|
||||||
this.showKanjiDefs(definitions, options, context);
|
this.showKanjiDefs(definitions, options, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
api_showOrphaned() {
|
showOrphaned() {
|
||||||
this.showOrphaned();
|
this.showOrphaned();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const {action, params} = e.originalEvent.data, method = handlers[`api_${action}`];
|
const {action, params} = e.originalEvent.data, method = handlers[action];
|
||||||
if (typeof(method) === 'function') {
|
if (typeof(method) === 'function') {
|
||||||
method.call(this, params);
|
method.call(this, params);
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ window.driver = new class {
|
|||||||
window.addEventListener('mouseup', this.onMouseUp.bind(this));
|
window.addEventListener('mouseup', this.onMouseUp.bind(this));
|
||||||
window.addEventListener('mousemove', this.onMouseMove.bind(this));
|
window.addEventListener('mousemove', this.onMouseMove.bind(this));
|
||||||
window.addEventListener('resize', e => this.searchClear());
|
window.addEventListener('resize', e => this.searchClear());
|
||||||
|
window.addEventListener('message', this.onFrameMessage.bind(this));
|
||||||
chrome.runtime.onMessage.addListener(this.onBgMessage.bind(this));
|
chrome.runtime.onMessage.addListener(this.onBgMessage.bind(this));
|
||||||
}).catch(this.handleError.bind(this));
|
}).catch(this.handleError.bind(this));
|
||||||
}
|
}
|
||||||
@ -45,14 +46,14 @@ window.driver = new class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
popupTimerClear() {
|
popupTimerClear() {
|
||||||
if (this.popupTimer !== null) {
|
if (this.popupTimer) {
|
||||||
window.clearTimeout(this.popupTimer);
|
window.clearTimeout(this.popupTimer);
|
||||||
this.popupTimer = null;
|
this.popupTimer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseOver(e) {
|
onMouseOver(e) {
|
||||||
if (e.target === this.popup.container && this.popuptimer !== null) {
|
if (e.target === this.popup.container && this.popupTimer) {
|
||||||
this.popupTimerClear();
|
this.popupTimerClear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,14 +102,30 @@ window.driver = new class {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onBgMessage({action, params}, sender, callback) {
|
onFrameMessage(e) {
|
||||||
const handlers = new class {
|
const handlers = {
|
||||||
api_optionsSet(options) {
|
popupClose: () => {
|
||||||
this.options = options;
|
this.searchClear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const method = handlers[`api_${action}`];
|
const handler = handlers[e.data];
|
||||||
|
if (handler) {
|
||||||
|
handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onBgMessage({action, params}, sender, callback) {
|
||||||
|
const handlers = new class {
|
||||||
|
optionsSet(options) {
|
||||||
|
this.options = options;
|
||||||
|
if (!this.options.enable) {
|
||||||
|
this.searchClear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const method = handlers[action];
|
||||||
if (typeof(method) === 'function') {
|
if (typeof(method) === 'function') {
|
||||||
method.call(this, params);
|
method.call(this, params);
|
||||||
}
|
}
|
||||||
@ -122,11 +139,11 @@ window.driver = new class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const textSource = docRangeFromPoint(point, this.options.scanning.imposter);
|
const textSource = docRangeFromPoint(point, this.options.scanning.imposter);
|
||||||
if (textSource === null || !textSource.containsPoint(point)) {
|
if (!textSource || !textSource.containsPoint(point)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.lastTextSource !== null && this.lastTextSource.equals(textSource)) {
|
if (this.lastTextSource && this.lastTextSource.equals(textSource)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +217,7 @@ window.driver = new class {
|
|||||||
docImposterDestroy();
|
docImposterDestroy();
|
||||||
this.popup.hide();
|
this.popup.hide();
|
||||||
|
|
||||||
if (this.options.scanning.selectText && this.lastTextSource !== null) {
|
if (this.options.scanning.selectText && this.lastTextSource) {
|
||||||
this.lastTextSource.deselect();
|
this.lastTextSource.deselect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"name": "Yomichan",
|
"name": "Yomichan",
|
||||||
"version": "1.1.7",
|
"version": "1.1.8",
|
||||||
|
|
||||||
"description": "Japanese dictionary with Anki integration",
|
"description": "Japanese dictionary with Anki integration",
|
||||||
"icons": {"16": "mixed/img/icon16.png", "48": "mixed/img/icon48.png", "128": "mixed/img/icon128.png"},
|
"icons": {"16": "mixed/img/icon16.png", "48": "mixed/img/icon48.png", "128": "mixed/img/icon128.png"},
|
||||||
@ -31,6 +31,26 @@
|
|||||||
"<all_urls>",
|
"<all_urls>",
|
||||||
"storage"
|
"storage"
|
||||||
],
|
],
|
||||||
|
"commands": {
|
||||||
|
"toggle": {
|
||||||
|
"suggested_key": {
|
||||||
|
"default": "Alt+Delete"
|
||||||
|
},
|
||||||
|
"description": "Toggle text scanning"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"suggested_key": {
|
||||||
|
"default": "Alt+Insert"
|
||||||
|
},
|
||||||
|
"description": "Open search window"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"suggested_key": {
|
||||||
|
"default": "Alt+End"
|
||||||
|
},
|
||||||
|
"description": "Open options page"
|
||||||
|
}
|
||||||
|
},
|
||||||
"web_accessible_resources": ["fg/frame.html"],
|
"web_accessible_resources": ["fg/frame.html"],
|
||||||
"applications": {
|
"applications": {
|
||||||
"gecko": {
|
"gecko": {
|
||||||
|
@ -52,7 +52,8 @@ hr {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
.entry {
|
.entry {
|
||||||
padding: 15px 0px 15px 0px;
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag-default {
|
.tag-default {
|
||||||
|
BIN
ext/mixed/img/entry-current.png
Normal file
BIN
ext/mixed/img/entry-current.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 743 B |
@ -25,6 +25,9 @@ class Display {
|
|||||||
this.audioCache = {};
|
this.audioCache = {};
|
||||||
this.responseCache = {};
|
this.responseCache = {};
|
||||||
this.sequence = 0;
|
this.sequence = 0;
|
||||||
|
this.index = 0;
|
||||||
|
|
||||||
|
$(document).keydown(this.onKeyDown.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
definitionAdd(definition, mode) {
|
definitionAdd(definition, mode) {
|
||||||
@ -47,9 +50,17 @@ class Display {
|
|||||||
throw 'override me';
|
throw 'override me';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearSearch() {
|
||||||
|
throw 'override me';
|
||||||
|
}
|
||||||
|
|
||||||
showTermDefs(definitions, options, context) {
|
showTermDefs(definitions, options, context) {
|
||||||
|
window.focus();
|
||||||
|
|
||||||
this.spinner.hide();
|
this.spinner.hide();
|
||||||
this.definitions = definitions;
|
this.definitions = definitions;
|
||||||
|
this.options = options;
|
||||||
|
this.context = context;
|
||||||
|
|
||||||
const sequence = ++this.sequence;
|
const sequence = ++this.sequence;
|
||||||
const params = {
|
const params = {
|
||||||
@ -68,43 +79,23 @@ class Display {
|
|||||||
|
|
||||||
this.templateRender('terms.html', params).then(content => {
|
this.templateRender('terms.html', params).then(content => {
|
||||||
this.container.html(content);
|
this.container.html(content);
|
||||||
|
this.entryScroll(context && context.index || 0);
|
||||||
|
|
||||||
let offset = 0;
|
$('.action-add-note').click(this.onAddNote.bind(this));
|
||||||
if (context && context.hasOwnProperty('index') && context.index < definitions.length) {
|
$('.action-play-audio').click(this.onPlayAudio.bind(this));
|
||||||
const entry = $('.entry').eq(context.index);
|
$('.kanji-link').click(this.onKanjiLookup.bind(this));
|
||||||
offset = entry.offset().top;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.scrollTo(0, offset);
|
|
||||||
|
|
||||||
$('.action-add-note').click(this.onActionAddNote.bind(this));
|
|
||||||
$('.action-play-audio').click(e => {
|
|
||||||
e.preventDefault();
|
|
||||||
const index = Display.entryIndexFind($(e.currentTarget));
|
|
||||||
this.audioPlay(this.definitions[index]);
|
|
||||||
});
|
|
||||||
$('.kanji-link').click(e => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const link = $(e.target);
|
|
||||||
context = context || {};
|
|
||||||
context.source = {
|
|
||||||
definitions,
|
|
||||||
index: Display.entryIndexFind(link)
|
|
||||||
};
|
|
||||||
|
|
||||||
this.kanjiFind(link.text()).then(kanjiDefs => {
|
|
||||||
this.showKanjiDefs(kanjiDefs, options, context);
|
|
||||||
}).catch(this.handleError.bind(this));
|
|
||||||
});
|
|
||||||
|
|
||||||
return this.adderButtonsUpdate(['term-kanji', 'term-kana'], sequence);
|
return this.adderButtonsUpdate(['term-kanji', 'term-kana'], sequence);
|
||||||
}).catch(this.handleError.bind(this));
|
}).catch(this.handleError.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
showKanjiDefs(definitions, options, context) {
|
showKanjiDefs(definitions, options, context) {
|
||||||
|
window.focus();
|
||||||
|
|
||||||
this.spinner.hide();
|
this.spinner.hide();
|
||||||
this.definitions = definitions;
|
this.definitions = definitions;
|
||||||
|
this.options = options;
|
||||||
|
this.context = context;
|
||||||
|
|
||||||
const sequence = ++this.sequence;
|
const sequence = ++this.sequence;
|
||||||
const params = {
|
const params = {
|
||||||
@ -122,17 +113,10 @@ class Display {
|
|||||||
|
|
||||||
this.templateRender('kanji.html', params).then(content => {
|
this.templateRender('kanji.html', params).then(content => {
|
||||||
this.container.html(content);
|
this.container.html(content);
|
||||||
window.scrollTo(0, 0);
|
this.entryScroll(context && context.index || 0);
|
||||||
|
|
||||||
$('.action-add-note').click(this.onActionAddNote.bind(this));
|
$('.action-add-note').click(this.onAddNote.bind(this));
|
||||||
$('.source-term').click(e => {
|
$('.source-term').click(this.onSourceTerm.bind(this));
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if (context && context.source) {
|
|
||||||
context.index = context.source.index;
|
|
||||||
this.showTermDefs(context.source.definitions, options, context);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return this.adderButtonsUpdate(['kanji'], sequence);
|
return this.adderButtonsUpdate(['kanji'], sequence);
|
||||||
}).catch(this.handleError.bind(this));
|
}).catch(this.handleError.bind(this));
|
||||||
@ -159,31 +143,186 @@ class Display {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onActionAddNote(e) {
|
entryScroll(index, smooth) {
|
||||||
e.preventDefault();
|
index = Math.min(index, this.definitions.length - 1);
|
||||||
this.spinner.show();
|
index = Math.max(index, 0);
|
||||||
|
|
||||||
const link = $(e.currentTarget);
|
$('.current').hide().eq(index).show();
|
||||||
const mode = link.data('mode');
|
|
||||||
const index = Display.entryIndexFind(link);
|
|
||||||
const definition = this.definitions[index];
|
|
||||||
|
|
||||||
let promise = Promise.resolve();
|
const container = $('html,body').stop();
|
||||||
if (mode !== 'kanji') {
|
const entry = $('.entry').eq(index);
|
||||||
const filename = Display.audioBuildFilename(definition);
|
const target = index === 0 ? 0 : entry.offset().top;
|
||||||
if (filename) {
|
|
||||||
promise = this.audioBuildUrl(definition).then(url => definition.audio = {url, filename}).catch(() => {});
|
if (smooth) {
|
||||||
}
|
container.animate({scrollTop: target}, 200);
|
||||||
|
} else {
|
||||||
|
container.scrollTop(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
promise.then(() => {
|
this.index = index;
|
||||||
return this.definitionAdd(definition, mode).then(success => {
|
}
|
||||||
if (success) {
|
|
||||||
Display.adderButtonFind(index, mode).addClass('disabled');
|
onSourceTerm(e) {
|
||||||
} else {
|
e.preventDefault();
|
||||||
this.handleError('note could not be added');
|
this.sourceBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
onKanjiLookup(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const link = $(e.target);
|
||||||
|
const context = {
|
||||||
|
source: {
|
||||||
|
definitions: this.definitions,
|
||||||
|
index: Display.entryIndexFind(link)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.context) {
|
||||||
|
context.sentence = this.context.sentence;
|
||||||
|
context.url = this.context.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.kanjiFind(link.text()).then(kanjiDefs => {
|
||||||
|
this.showKanjiDefs(kanjiDefs, this.options, context);
|
||||||
|
}).catch(this.handleError.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
onPlayAudio(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const index = Display.entryIndexFind($(e.currentTarget));
|
||||||
|
this.audioPlay(this.definitions[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
onAddNote(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const link = $(e.currentTarget);
|
||||||
|
const index = Display.entryIndexFind(link);
|
||||||
|
this.noteAdd(this.definitions[index], link.data('mode'));
|
||||||
|
}
|
||||||
|
|
||||||
|
onKeyDown(e) {
|
||||||
|
const noteTryAdd = mode => {
|
||||||
|
const button = Display.adderButtonFind(this.index, mode);
|
||||||
|
if (button.length !== 0 && !button.hasClass('disabled')) {
|
||||||
|
this.noteAdd(this.definitions[this.index], mode);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlers = {
|
||||||
|
27: /* escape */ () => {
|
||||||
|
this.clearSearch();
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
33: /* page up */ () => {
|
||||||
|
if (e.altKey) {
|
||||||
|
this.entryScroll(this.index - 3, true);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
|
||||||
|
34: /* page down */ () => {
|
||||||
|
if (e.altKey) {
|
||||||
|
this.entryScroll(this.index + 3, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
35: /* end */ () => {
|
||||||
|
if (e.altKey) {
|
||||||
|
this.entryScroll(this.definitions.length - 1, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
36: /* home */ () => {
|
||||||
|
if (e.altKey) {
|
||||||
|
this.entryScroll(0, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
38: /* up */ () => {
|
||||||
|
if (e.altKey) {
|
||||||
|
this.entryScroll(this.index - 1, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
40: /* down */ () => {
|
||||||
|
if (e.altKey) {
|
||||||
|
this.entryScroll(this.index + 1, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
66: /* b */ () => {
|
||||||
|
if (e.altKey) {
|
||||||
|
this.sourceBack();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
69: /* e */ () => {
|
||||||
|
if (e.altKey) {
|
||||||
|
noteTryAdd('term-kanji');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
75: /* k */ () => {
|
||||||
|
if (e.altKey) {
|
||||||
|
noteTryAdd('kanji');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
82: /* r */ () => {
|
||||||
|
if (e.altKey) {
|
||||||
|
noteTryAdd('term-kana');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
80: /* p */ () => {
|
||||||
|
if (e.altKey) {
|
||||||
|
if ($('.entry').eq(this.index).data('type') === 'term') {
|
||||||
|
this.audioPlay(this.definitions[this.index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handler = handlers[e.keyCode];
|
||||||
|
if (handler && handler()) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceBack() {
|
||||||
|
if (this.context && this.context.source) {
|
||||||
|
const context = {
|
||||||
|
url: this.context.source.url,
|
||||||
|
sentence: this.context.source.sentence,
|
||||||
|
index: this.context.source.index
|
||||||
|
};
|
||||||
|
|
||||||
|
this.showTermDefs(this.context.source.definitions, this.options, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
noteAdd(definition, mode) {
|
||||||
|
this.spinner.show();
|
||||||
|
return this.definitionAdd(definition, mode).then(success => {
|
||||||
|
if (success) {
|
||||||
|
const index = this.definitions.indexOf(definition);
|
||||||
|
Display.adderButtonFind(index, mode).addClass('disabled');
|
||||||
|
} else {
|
||||||
|
this.handleError('note could not be added');
|
||||||
|
}
|
||||||
}).catch(this.handleError.bind(this)).then(() => this.spinner.hide());
|
}).catch(this.handleError.bind(this)).then(() => this.spinner.hide());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +333,7 @@ class Display {
|
|||||||
this.audioCache[key].pause();
|
this.audioCache[key].pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.audioBuildUrl(definition).then(url => {
|
audioBuildUrl(definition, this.responseCache).then(url => {
|
||||||
if (!url) {
|
if (!url) {
|
||||||
url = '/mixed/mp3/button.mp3';
|
url = '/mixed/mp3/button.mp3';
|
||||||
}
|
}
|
||||||
@ -217,79 +356,6 @@ class Display {
|
|||||||
}).catch(this.handleError.bind(this)).then(() => this.spinner.hide());
|
}).catch(this.handleError.bind(this)).then(() => this.spinner.hide());
|
||||||
}
|
}
|
||||||
|
|
||||||
audioBuildUrl(definition) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const response = this.responseCache[definition.expression];
|
|
||||||
if (response) {
|
|
||||||
resolve(response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
post: 'dictionary_reference',
|
|
||||||
match_type: 'exact',
|
|
||||||
search_query: definition.expression
|
|
||||||
};
|
|
||||||
|
|
||||||
const params = [];
|
|
||||||
for (const key in data) {
|
|
||||||
params.push(`${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('POST', 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post');
|
|
||||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
|
||||||
xhr.addEventListener('error', () => reject('failed to scrape audio data'));
|
|
||||||
xhr.addEventListener('load', () => {
|
|
||||||
this.responseCache[definition.expression] = xhr.responseText;
|
|
||||||
resolve(xhr.responseText);
|
|
||||||
});
|
|
||||||
|
|
||||||
xhr.send(params.join('&'));
|
|
||||||
}).then(response => {
|
|
||||||
const dom = new DOMParser().parseFromString(response, 'text/html');
|
|
||||||
const entries = [];
|
|
||||||
|
|
||||||
for (const row of dom.getElementsByClassName('dc-result-row')) {
|
|
||||||
try {
|
|
||||||
const url = row.getElementsByClassName('ill-onebuttonplayer').item(0).getAttribute('data-url');
|
|
||||||
const expression = dom.getElementsByClassName('dc-vocab').item(0).innerText;
|
|
||||||
const reading = dom.getElementsByClassName('dc-vocab_kana').item(0).innerText;
|
|
||||||
|
|
||||||
if (url && expression && reading) {
|
|
||||||
entries.push({url, expression, reading});
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// NOP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return entries;
|
|
||||||
}).then(entries => {
|
|
||||||
for (const entry of entries) {
|
|
||||||
if (!definition.reading || definition.reading === entry.reading) {
|
|
||||||
return entry.url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static audioBuildFilename(definition) {
|
|
||||||
if (!definition.reading && !definition.expression) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let filename = 'yomichan';
|
|
||||||
if (definition.reading) {
|
|
||||||
filename += `_${definition.reading}`;
|
|
||||||
}
|
|
||||||
if (definition.expression) {
|
|
||||||
filename += `_${definition.expression}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return filename += '.mp3';
|
|
||||||
}
|
|
||||||
|
|
||||||
static entryIndexFind(element) {
|
static entryIndexFind(element) {
|
||||||
return $('.entry').index(element.closest('.entry'));
|
return $('.entry').index(element.closest('.entry'));
|
||||||
}
|
}
|
||||||
|
104
ext/mixed/js/util.js
Normal file
104
ext/mixed/js/util.js
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Alex Yatskov <alex@foosoft.net>
|
||||||
|
* Author: Alex Yatskov <alex@foosoft.net>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Audio
|
||||||
|
*/
|
||||||
|
|
||||||
|
function audioBuildUrl(definition, cache={}) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const response = cache[definition.expression];
|
||||||
|
if (response) {
|
||||||
|
resolve(response);
|
||||||
|
} else {
|
||||||
|
const data = {
|
||||||
|
post: 'dictionary_reference',
|
||||||
|
match_type: 'exact',
|
||||||
|
search_query: definition.expression
|
||||||
|
};
|
||||||
|
|
||||||
|
const params = [];
|
||||||
|
for (const key in data) {
|
||||||
|
params.push(`${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('POST', 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post');
|
||||||
|
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
||||||
|
xhr.addEventListener('error', () => reject('failed to scrape audio data'));
|
||||||
|
xhr.addEventListener('load', () => {
|
||||||
|
cache[definition.expression] = xhr.responseText;
|
||||||
|
resolve(xhr.responseText);
|
||||||
|
});
|
||||||
|
|
||||||
|
xhr.send(params.join('&'));
|
||||||
|
}
|
||||||
|
}).then(response => {
|
||||||
|
const dom = new DOMParser().parseFromString(response, 'text/html');
|
||||||
|
for (const row of dom.getElementsByClassName('dc-result-row')) {
|
||||||
|
try {
|
||||||
|
const url = row.getElementsByClassName('ill-onebuttonplayer').item(0).getAttribute('data-url');
|
||||||
|
const reading = row.getElementsByClassName('dc-vocab_kana').item(0).innerText;
|
||||||
|
if (url && reading && (!definition.reading || definition.reading === reading)) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// NOP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function audioBuildFilename(definition) {
|
||||||
|
if (definition.reading && definition.expression) {
|
||||||
|
let filename = 'yomichan';
|
||||||
|
if (definition.reading) {
|
||||||
|
filename += `_${definition.reading}`;
|
||||||
|
}
|
||||||
|
if (definition.expression) {
|
||||||
|
filename += `_${definition.expression}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return filename += '.mp3';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function audioInject(definition, fields) {
|
||||||
|
const filename = audioBuildFilename(definition);
|
||||||
|
if (!filename) {
|
||||||
|
return Promise.resolve(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
let usesAudio = false;
|
||||||
|
for (const name in fields) {
|
||||||
|
if (fields[name].includes('{audio}')) {
|
||||||
|
usesAudio = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!usesAudio) {
|
||||||
|
return Promise.resolve(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return audioBuildUrl(definition).then(url => {
|
||||||
|
definition.audio = {url, filename};
|
||||||
|
return true;
|
||||||
|
}).catch(() => false);
|
||||||
|
}
|
@ -1,11 +1,12 @@
|
|||||||
{{#*inline "kanji"}}
|
{{#*inline "kanji"}}
|
||||||
<div class="entry">
|
<div class="entry" data-type="kanji">
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
|
<img src="/mixed/img/entry-current.png" class="current" title="Current entry (Alt + Up/Down/Home/End/PgUp/PgDn)" alt>
|
||||||
{{#if addable}}
|
{{#if addable}}
|
||||||
<a href="#" title="Add Kanji" class="action-add-note pending disabled" data-mode="kanji"><img src="/mixed/img/add-kanji.png" alt></a>
|
<a href="#" class="action-add-note pending disabled" data-mode="kanji"><img src="/mixed/img/add-kanji.png" title="Add Kanji (Alt + K)" alt></a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if source}}
|
{{#if source}}
|
||||||
<a href="#" title="Source term" class="source-term"><img src="/mixed/img/source-term.png" alt></a>
|
<a href="#" class="source-term"><img src="/mixed/img/source-term.png" title="Source term (Alt + B)" alt></a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -18,14 +18,15 @@
|
|||||||
{{/inline}}
|
{{/inline}}
|
||||||
|
|
||||||
{{#*inline "term"}}
|
{{#*inline "term"}}
|
||||||
<div class="entry">
|
<div class="entry" data-type="term">
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
|
<img src="/mixed/img/entry-current.png" class="current" title="Current entry (Alt + Up/Down/Home/End/PgUp/PgDn)" alt>
|
||||||
{{#if addable}}
|
{{#if addable}}
|
||||||
<a href="#" title="Add expression" class="action-add-note pending disabled" data-mode="term-kanji"><img src="/mixed/img/add-term-kanji.png" alt></a>
|
<a href="#" class="action-add-note pending disabled" data-mode="term-kanji"><img src="/mixed/img/add-term-kanji.png" title="Add expression (Alt + E)" alt></a>
|
||||||
<a href="#" title="Add reading" class="action-add-note pending disabled" data-mode="term-kana"><img src="/mixed/img/add-term-kana.png" alt></a>
|
<a href="#" class="action-add-note pending disabled" data-mode="term-kana"><img src="/mixed/img/add-term-kana.png" title="Add reading (Alt + R)" alt></a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if playback}}
|
{{#if playback}}
|
||||||
<a href="#" title="Play audio" class="action-play-audio"><img src="/mixed/img/play-audio.png" alt></a>
|
<a href="#" class="action-play-audio"><img src="/mixed/img/play-audio.png" title="Play audio (Alt + P)" alt></a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user