This commit is contained in:
Alex Yatskov 2017-03-02 22:35:02 -08:00
parent a01ca1f17c
commit faf13d696c
6 changed files with 77 additions and 56 deletions

View File

@ -126,11 +126,11 @@ class Yomichan {
return note; return note;
} }
api_getOptions({callback}) { api_optionsGet({callback}) {
promiseCallback(optionsLoad(), callback); promiseCallback(optionsLoad(), callback);
} }
api_findKanji({text, callback}) { api_kanjiFind({text, callback}) {
promiseCallback( promiseCallback(
this.translator.findKanji(text, dictEnabled(this.options)).then(definitions => { this.translator.findKanji(text, dictEnabled(this.options)).then(definitions => {
return definitions.slice(0, this.options.general.maxResults); return definitions.slice(0, this.options.general.maxResults);
@ -139,7 +139,7 @@ class Yomichan {
); );
} }
api_findTerms({text, callback}) { api_termsFind({text, callback}) {
promiseCallback( promiseCallback(
this.translator.findTerms(text, dictEnabled(this.options), this.options.general.softKatakana).then(({definitions, length}) => { this.translator.findTerms(text, dictEnabled(this.options), this.options.general.softKatakana).then(({definitions, length}) => {
return {length, definitions: definitions.slice(0, this.options.general.maxResults)}; return {length, definitions: definitions.slice(0, this.options.general.maxResults)};
@ -148,7 +148,7 @@ class Yomichan {
); );
} }
api_findTermsGrouped({text, callback}) { api_termsFindGrouped({text, callback}) {
promiseCallback( promiseCallback(
this.translator.findTermsGrouped(text, dictEnabled(this.options), this.options.general.softKatakana).then(({definitions, length}) => { this.translator.findTermsGrouped(text, dictEnabled(this.options), this.options.general.softKatakana).then(({definitions, length}) => {
return {length, definitions: definitions.slice(0, this.options.general.maxResults)}; return {length, definitions: definitions.slice(0, this.options.general.maxResults)};
@ -157,16 +157,16 @@ class Yomichan {
); );
} }
api_renderText({template, data, callback}) { api_textRender({template, data, callback}) {
callback({result: Handlebars.templates[template](data)}); callback({result: Handlebars.templates[template](data)});
} }
api_addDefinition({definition, mode, callback}) { api_definitionAdd({definition, mode, callback}) {
const note = this.formatNote(definition, mode); const note = this.formatNote(definition, mode);
promiseCallback(this.anki.addNote(note), callback); promiseCallback(this.anki.addNote(note), callback);
} }
api_canAddDefinitions({definitions, modes, callback}) { api_definitionsAddable({definitions, modes, callback}) {
const notes = []; const notes = [];
for (const definition of definitions) { for (const definition of definitions) {
for (const mode of modes) { for (const mode of modes) {

View File

@ -28,7 +28,7 @@ class Driver {
this.pendingLookup = false; this.pendingLookup = false;
this.options = null; this.options = null;
getOptions().then(options => { bgOptionsGet().then(options => {
this.options = options; this.options = options;
window.addEventListener('mouseover', this.onMouseOver.bind(this)); window.addEventListener('mouseover', this.onMouseOver.bind(this));
window.addEventListener('mousedown', this.onMouseDown.bind(this)); window.addEventListener('mousedown', this.onMouseDown.bind(this));
@ -115,7 +115,7 @@ class Driver {
return; return;
} }
const textSource = textSourceFromPoint(point, this.options.scanning.imposter); const textSource = docRangeFromPoint(point, this.options.scanning.imposter);
if (textSource === null || !textSource.containsPoint(point)) { if (textSource === null || !textSource.containsPoint(point)) {
return; return;
} }
@ -139,14 +139,14 @@ class Driver {
searchTerms(textSource) { searchTerms(textSource) {
textSource.setEndOffset(this.options.scanning.length); textSource.setEndOffset(this.options.scanning.length);
const findFunc = this.options.general.groupResults ? findTermsGrouped : findTerms; const findFunc = this.options.general.groupResults ? bgTermsFindGrouped : bgTermsFind;
return findFunc(textSource.text()).then(({definitions, length}) => { return findFunc(textSource.text()).then(({definitions, length}) => {
if (definitions.length === 0) { if (definitions.length === 0) {
return false; return false;
} else { } else {
textSource.setEndOffset(length); textSource.setEndOffset(length);
const sentence = extractSentence(textSource, this.options.anki.sentenceExt); const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt);
const url = window.location.href; const url = window.location.href;
this.popup.showNextTo(textSource.getRect()); this.popup.showNextTo(textSource.getRect());
@ -165,11 +165,11 @@ class Driver {
searchKanji(textSource) { searchKanji(textSource) {
textSource.setEndOffset(1); textSource.setEndOffset(1);
return findKanji(textSource.text()).then(definitions => { return bgKanjiFind(textSource.text()).then(definitions => {
if (definitions.length === 0) { if (definitions.length === 0) {
return false; return false;
} else { } else {
const sentence = extractSentence(textSource, this.options.anki.sentenceExt); const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt);
const url = window.location.href; const url = window.location.href;
this.popup.showNextTo(textSource.getRect()); this.popup.showNextTo(textSource.getRect());
@ -186,7 +186,7 @@ class Driver {
} }
searchClear() { searchClear() {
destroyImposters(); docImposterDestroy();
this.popup.hide(); this.popup.hide();
if (this.options.scanning.selectText && this.lastTextSource !== null) { if (this.options.scanning.selectText && this.lastTextSource !== null) {
@ -203,7 +203,7 @@ class Driver {
this.popup.showOrphaned(); this.popup.showOrphaned();
} }
} else { } else {
showError(error); errorShow(error);
} }
} }

View File

@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
class Frame { class Frame {
constructor() { constructor() {
this.definitions = []; this.definitions = [];
@ -48,14 +49,14 @@ class Frame {
this.showSpinner(false); this.showSpinner(false);
window.scrollTo(0, 0); window.scrollTo(0, 0);
renderText(params, 'terms.html').then(content => { bgTextRender(params, 'terms.html').then(content => {
$('#content').html(content); $('#content').html(content);
$('.action-add-note').click(this.onAddNote.bind(this)); $('.action-add-note').click(this.onAddNote.bind(this));
$('.kanji-link').click(e => { $('.kanji-link').click(e => {
e.preventDefault(); e.preventDefault();
const character = $(e.target).text(); const character = $(e.target).text();
findKanji(character).then(definitions => this.api_showKanjiDefs({definitions, options, context})); bgKanjiFind(character).then(definitions => this.api_showKanjiDefs({definitions, options, context}));
}); });
$('.action-play-audio').click(e => { $('.action-play-audio').click(e => {
@ -86,7 +87,7 @@ class Frame {
this.showSpinner(false); this.showSpinner(false);
window.scrollTo(0, 0); window.scrollTo(0, 0);
renderText(params, 'kanji.html').then(content => { bgTextRender(params, 'kanji.html').then(content => {
$('#content').html(content); $('#content').html(content);
$('.action-add-note').click(this.onAddNote.bind(this)); $('.action-add-note').click(this.onAddNote.bind(this));
@ -115,19 +116,19 @@ class Frame {
const definition = this.definitions[index]; const definition = this.definitions[index];
if (mode !== 'kanji') { if (mode !== 'kanji') {
const url = buildAudioUrl(definition); const url = audioUrlBuild(definition);
const filename = buildAudioFilename(definition); const filename = audioFilenameBuild(definition);
if (url && filename) { if (url && filename) {
definition.audio = {url, filename}; definition.audio = {url, filename};
} }
} }
addDefinition(definition, mode).then(success => { bgDefinitionAdd(definition, mode).then(success => {
if (success) { if (success) {
const button = this.findAddNoteButton(index, mode); const button = this.findAddNoteButton(index, mode);
button.addClass('disabled'); button.addClass('disabled');
} else { } else {
showError('note could not be added'); errorShow('note could not be added');
} }
}).catch(error => { }).catch(error => {
this.handleError(error); this.handleError(error);
@ -137,7 +138,7 @@ class Frame {
} }
updateAddNoteButtons(modes, sequence) { updateAddNoteButtons(modes, sequence) {
canAddDefinitions(this.definitions, modes).then(states => { bgDefinitionsAddable(this.definitions, modes).then(states => {
if (states === null) { if (states === null) {
return; return;
} }
@ -180,7 +181,7 @@ class Frame {
} }
} }
const url = buildAudioUrl(definition); const url = audioUrlBuild(definition);
if (!url) { if (!url) {
return; return;
} }
@ -206,7 +207,7 @@ class Frame {
if (window.orphaned) { if (window.orphaned) {
this.api_showOrphaned(); this.api_showOrphaned();
} else { } else {
showError(error); errorShow(error);
} }
} }
} }

View File

@ -20,6 +20,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
if (!document.caretRangeFromPoint) { if (!document.caretRangeFromPoint) {
document.caretRangeFromPoint = (x, y) => { document.caretRangeFromPoint = (x, y) => {
const position = document.caretPositionFromPoint(x,y); const position = document.caretPositionFromPoint(x,y);

View File

@ -17,7 +17,11 @@
*/ */
function invokeBgApi(action, params) { /*
* Background
*/
function bgInvoke(action, params) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { try {
chrome.runtime.sendMessage({action, params}, ({result, error}) => { chrome.runtime.sendMessage({action, params}, ({result, error}) => {
@ -34,39 +38,40 @@ function invokeBgApi(action, params) {
}); });
} }
function showError(error) { function bgOptionsGet() {
window.alert(`Error: ${error}`); return bgInvoke('optionsGet', {});
} }
function getOptions() { function bgTermsFind(text) {
return invokeBgApi('getOptions', {}); return bgInvoke('termsFind', {text});
} }
function findTerms(text) { function bgTermsFindGrouped(text) {
return invokeBgApi('findTerms', {text}); return bgInvoke('termsFindGrouped', {text});
} }
function findTermsGrouped(text) { function bgKanjiFind(text) {
return invokeBgApi('findTermsGrouped', {text}); return bgInvoke('kanjiFind', {text});
} }
function findKanji(text) { function bgTextRender(data, template) {
return invokeBgApi('findKanji', {text}); return bgInvoke('textRender', {data, template});
} }
function renderText(data, template) { function bgDefinitionsAddable(definitions, modes) {
return invokeBgApi('renderText', {data, template}); return bgInvoke('definitionsAddable', {definitions, modes}).catch(() => null);
} }
function canAddDefinitions(definitions, modes) { function bgDefinitionAdd(definition, mode) {
return invokeBgApi('canAddDefinitions', {definitions, modes}).catch(() => null); return bgInvoke('definitionAdd', {definition, mode});
} }
function addDefinition(definition, mode) {
return invokeBgApi('addDefinition', {definition, mode});
}
function getElementOffset(element) { /*
* Document
*/
function docOffsetCalc(element) {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft; const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
@ -80,14 +85,14 @@ function getElementOffset(element) {
return {top, left}; return {top, left};
} }
function createImposter(element) { function docImposterCreate(element) {
const styleProps = window.getComputedStyle(element); const styleProps = window.getComputedStyle(element);
const stylePairs = []; const stylePairs = [];
for (const key of styleProps) { for (const key of styleProps) {
stylePairs.push(`${key}: ${styleProps[key]};`); stylePairs.push(`${key}: ${styleProps[key]};`);
} }
const offset = getElementOffset(element); const offset = docOffsetCalc(element);
const imposter = document.createElement('div'); const imposter = document.createElement('div');
imposter.className = 'yomichan-imposter'; imposter.className = 'yomichan-imposter';
imposter.innerText = element.value; imposter.innerText = element.value;
@ -105,39 +110,39 @@ function createImposter(element) {
imposter.scrollLeft = element.scrollLeft; imposter.scrollLeft = element.scrollLeft;
} }
function destroyImposters() { function docImposterDestroy() {
for (const element of document.getElementsByClassName('yomichan-imposter')) { for (const element of document.getElementsByClassName('yomichan-imposter')) {
element.parentNode.removeChild(element); element.parentNode.removeChild(element);
} }
} }
function hideImposters() { function docImposterHide() {
for (const element of document.getElementsByClassName('yomichan-imposter')) { for (const element of document.getElementsByClassName('yomichan-imposter')) {
element.style.visibility = 'hidden'; element.style.visibility = 'hidden';
} }
} }
function textSourceFromPoint(point, imposter) { function docRangeFromPoint(point, imposter) {
const element = document.elementFromPoint(point.x, point.y); const element = document.elementFromPoint(point.x, point.y);
if (element !== null) { if (element !== null) {
if (element.nodeName === 'IMG' || element.nodeName === 'BUTTON') { if (element.nodeName === 'IMG' || element.nodeName === 'BUTTON') {
return new TextSourceElement(element); return new TextSourceElement(element);
} else if (imposter && (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA')) { } else if (imposter && (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA')) {
createImposter(element); docImposterCreate(element);
} }
} }
const range = document.caretRangeFromPoint(point.x, point.y); const range = document.caretRangeFromPoint(point.x, point.y);
if (range !== null) { if (range !== null) {
hideImposters(); docImposterHide();
return new TextSourceRange(range); return new TextSourceRange(range);
} }
destroyImposters(); docImposterDestroy();
return null; return null;
} }
function extractSentence(source, extent) { function docSentenceExtract(source, extent) {
const quotesFwd = {'「': '」', '『': '』', "'": "'", '"': '"'}; const quotesFwd = {'「': '」', '『': '』', "'": "'", '"': '"'};
const quotesBwd = {'」': '「', '』': '『', "'": "'", '"': '"'}; const quotesBwd = {'」': '「', '』': '『', "'": "'", '"': '"'};
const terminators = '…。..?!'; const terminators = '…。..?!';
@ -192,7 +197,12 @@ function extractSentence(source, extent) {
return content.substring(startPos, endPos).trim(); return content.substring(startPos, endPos).trim();
} }
function buildAudioUrl(definition) {
/*
* Audio
*/
function audioUrlBuild(definition) {
let kana = definition.reading; let kana = definition.reading;
let kanji = definition.expression; let kanji = definition.expression;
@ -216,7 +226,7 @@ function buildAudioUrl(definition) {
return `https://assets.languagepod101.com/dictionary/japanese/audiomp3.php?${params.join('&')}`; return `https://assets.languagepod101.com/dictionary/japanese/audiomp3.php?${params.join('&')}`;
} }
function buildAudioFilename(definition) { function audioFilenameBuild(definition) {
if (!definition.reading && !definition.expression) { if (!definition.reading && !definition.expression) {
return null; return null;
} }
@ -231,3 +241,12 @@ function buildAudioFilename(definition) {
return filename += '.mp3'; return filename += '.mp3';
} }
/*
* Error
*/
function errorShow(error) {
window.alert(`Error: ${error}`);
}

View File

@ -16,10 +16,10 @@
"matches": ["http://*/*", "https://*/*", "file://*/*"], "matches": ["http://*/*", "https://*/*", "file://*/*"],
"js": [ "js": [
"fg/js/gecko.js", "fg/js/gecko.js",
"fg/js/util.js",
"fg/js/source-range.js", "fg/js/source-range.js",
"fg/js/source-element.js", "fg/js/source-element.js",
"fg/js/popup.js", "fg/js/popup.js",
"fg/js/util.js",
"fg/js/driver.js" "fg/js/driver.js"
], ],
"css": ["fg/css/client.css"] "css": ["fg/css/client.css"]