diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/bg/js/templates.js | 72 | ||||
-rw-r--r-- | ext/fg/css/frame.css | 9 | ||||
-rw-r--r-- | ext/fg/frame.html | 18 | ||||
-rw-r--r-- | ext/fg/js/driver.js | 198 | ||||
-rw-r--r-- | ext/fg/js/frame.js | 195 | ||||
-rw-r--r-- | ext/fg/js/popup.js | 57 | ||||
-rw-r--r-- | ext/manifest.json | 1 |
7 files changed, 238 insertions, 312 deletions
diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js index 339ea31b..f3d991de 100644 --- a/ext/bg/js/templates.js +++ b/ext/bg/js/templates.js @@ -31,34 +31,12 @@ templates['dictionary.html'] = template({"1":function(container,depth0,helpers,p + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.enableKanji : depth0),{"name":"if","hash":{},"fn":container.program(3, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "> Enable Kanji search</label>\n </div>\n</div>\n"; },"useData":true}); -templates['footer.html'] = template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { - var helper; - - return " <script src=\"" - + container.escapeExpression(((helper = (helper = helpers.root || (depth0 != null ? depth0.root : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : {},{"name":"root","hash":{},"data":data}) : helper))) - + "/js/frame.js\"></script>\n </body>\n</html>\n"; -},"useData":true}); -templates['header.html'] = template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { - var helper, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - - return "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <title></title>\n <style>\n @font-face {\n font-family: kanji-stroke-orders;\n src: url('" - + alias4(((helper = (helper = helpers.root || (depth0 != null ? depth0.root : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"root","hash":{},"data":data}) : helper))) - + "/ttf/kanji-stroke-orders.ttf');\n }\n @font-face {\n font-family: vl-gothic-regular;\n src: url('" - + alias4(((helper = (helper = helpers.root || (depth0 != null ? depth0.root : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"root","hash":{},"data":data}) : helper))) - + "/ttf/vl-gothic-regular.ttf');\n }\n </style>\n <link rel=\"stylesheet\" href=\"" - + alias4(((helper = (helper = helpers.root || (depth0 != null ? depth0.root : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"root","hash":{},"data":data}) : helper))) - + "/css/frame.css\">\n </head>\n <body>\n\n <div class=\"spinner\">\n <img src=\"" - + alias4(((helper = (helper = helpers.root || (depth0 != null ? depth0.root : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"root","hash":{},"data":data}) : helper))) - + "/img/spinner.gif\">\n </div>\n"; -},"useData":true}); templates['kanji.html'] = template({"1":function(container,depth0,helpers,partials,data) { - var helper, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + var helper; return " <a href=\"#\" title=\"Add Kanji\" class=\"action-add-note pending disabled\" data-mode=\"kanji\" data-index=\"" - + alias4(((helper = (helper = helpers.index || (data && data.index)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"index","hash":{},"data":data}) : helper))) - + "\"><img src=\"" - + alias4(((helper = (helper = helpers.root || (depth0 != null ? depth0.root : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"root","hash":{},"data":data}) : helper))) - + "/img/add_kanji.png\"></a>\n"; + + container.escapeExpression(((helper = (helper = helpers.index || (data && data.index)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : {},{"name":"index","hash":{},"data":data}) : helper))) + + "\"><img src=\"img/add_kanji.png\"></a>\n"; },"3":function(container,depth0,helpers,partials,data) { var stack1; @@ -95,14 +73,12 @@ templates['kanji.html'] = template({"1":function(container,depth0,helpers,partia + container.escapeExpression(container.lambda(((stack1 = (depth0 != null ? depth0.glossary : depth0)) != null ? stack1["0"] : stack1), depth0)) + "\n </p>\n"; },"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { - var stack1, helper, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + var stack1, helper, alias1=depth0 != null ? depth0 : {}; - return "<div class=\"kanji-definition\">\n <div class=\"action-bar\" data-sequence=\"" - + alias4(((helper = (helper = helpers.sequence || (depth0 != null ? depth0.sequence : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"sequence","hash":{},"data":data}) : helper))) - + "\">\n" + return "<div class=\"kanji-definition\">\n <div class=\"action-bar\">\n" + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.addable : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + " </div>\n\n <div class=\"kanji-glyph\">" - + alias4(((helper = (helper = helpers.character || (depth0 != null ? depth0.character : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"character","hash":{},"data":data}) : helper))) + + container.escapeExpression(((helper = (helper = helpers.character || (depth0 != null ? depth0.character : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(alias1,{"name":"character","hash":{},"data":data}) : helper))) + "</div>\n\n <div class=\"kanji-reading\">\n <table>\n <tr>\n <th>Kunyomi:</th>\n <td>\n" + ((stack1 = helpers.each.call(alias1,(depth0 != null ? depth0.kunyomi : depth0),{"name":"each","hash":{},"fn":container.program(3, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + " </td>\n </tr>\n <tr>\n <th>Onyomi:</th>\n <td>\n" @@ -127,15 +103,13 @@ templates['kanji-list.html'] = template({"1":function(container,depth0,helpers,p },"2":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1; - return ((stack1 = container.invokePartial(partials["kanji.html"],depth0,{"name":"kanji.html","hash":{"sequence":(depths[1] != null ? depths[1].sequence : depths[1]),"options":(depths[1] != null ? depths[1].options : depths[1]),"root":(depths[1] != null ? depths[1].root : depths[1]),"addable":(depths[1] != null ? depths[1].addable : depths[1])},"data":data,"indent":" ","helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : ""); + return ((stack1 = container.invokePartial(partials["kanji.html"],depth0,{"name":"kanji.html","hash":{"root":(depths[1] != null ? depths[1].root : depths[1]),"addable":(depths[1] != null ? depths[1].addable : depths[1])},"data":data,"indent":" ","helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : ""); },"4":function(container,depth0,helpers,partials,data) { return " <p>No results found</p>\n"; },"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1; - return ((stack1 = container.invokePartial(partials["header.html"],depth0,{"name":"header.html","data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "") - + ((stack1 = helpers["if"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.definitions : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0, blockParams, depths),"inverse":container.program(4, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "") - + ((stack1 = container.invokePartial(partials["footer.html"],depth0,{"name":"footer.html","data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : ""); + return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.definitions : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0, blockParams, depths),"inverse":container.program(4, data, 0, blockParams, depths),"data":data})) != null ? stack1 : ""); },"usePartial":true,"useData":true,"useDepths":true}); templates['model.html'] = template({"1":function(container,depth0,helpers,partials,data) { return " <li><a class=\"marker-link\" href=\"#\">" @@ -159,21 +133,15 @@ templates['term.html'] = template({"1":function(container,depth0,helpers,partial return " <a href=\"#\" title=\"Add term as expression\" class=\"action-add-note pending disabled\" data-mode=\"term_kanji\" data-index=\"" + alias4(((helper = (helper = helpers.index || (data && data.index)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"index","hash":{},"data":data}) : helper))) - + "\"><img src=\"" - + alias4(((helper = (helper = helpers.root || (depth0 != null ? depth0.root : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"root","hash":{},"data":data}) : helper))) - + "/img/add_term_kanji.png\"></a>\n <a href=\"#\" title=\"Add term as reading\" class=\"action-add-note pending disabled\" data-mode=\"term_kana\" data-index=\"" + + "\"><img src=\"img/add_term_kanji.png\"></a>\n <a href=\"#\" title=\"Add term as reading\" class=\"action-add-note pending disabled\" data-mode=\"term_kana\" data-index=\"" + alias4(((helper = (helper = helpers.index || (data && data.index)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"index","hash":{},"data":data}) : helper))) - + "\"><img src=\"" - + alias4(((helper = (helper = helpers.root || (depth0 != null ? depth0.root : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"root","hash":{},"data":data}) : helper))) - + "/img/add_term_kana.png\"></a>\n"; + + "\"><img src=\"img/add_term_kana.png\"></a>\n"; },"3":function(container,depth0,helpers,partials,data) { - var helper, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + var helper; return " <a href=\"#\" title=\"Play audio\" class=\"action-play-audio\" data-index=\"" - + alias4(((helper = (helper = helpers.index || (data && data.index)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"index","hash":{},"data":data}) : helper))) - + "\"><img src=\"" - + alias4(((helper = (helper = helpers.root || (depth0 != null ? depth0.root : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"root","hash":{},"data":data}) : helper))) - + "/img/play_audio.png\"></a>\n"; + + container.escapeExpression(((helper = (helper = helpers.index || (data && data.index)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : {},{"name":"index","hash":{},"data":data}) : helper))) + + "\"><img src=\"img/play_audio.png\"></a>\n"; },"5":function(container,depth0,helpers,partials,data) { var stack1, helper, options, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing, alias3="function", buffer = " <div class=\"term-expression\"><ruby>"; @@ -231,13 +199,11 @@ templates['term.html'] = template({"1":function(container,depth0,helpers,partial + container.escapeExpression(container.lambda(((stack1 = (depth0 != null ? depth0.glossary : depth0)) != null ? stack1["0"] : stack1), depth0)) + "</p>\n"; },"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { - var stack1, helper, alias1=depth0 != null ? depth0 : {}; + var stack1, alias1=depth0 != null ? depth0 : {}; - return "<div class=\"term-definition\">\n <div class=\"action-bar\" data-sequence=\"" - + container.escapeExpression(((helper = (helper = helpers.sequence || (depth0 != null ? depth0.sequence : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(alias1,{"name":"sequence","hash":{},"data":data}) : helper))) - + "\">\n" + return "<div class=\"term-definition\">\n <div class=\"action-bar\">\n" + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.addable : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") - + ((stack1 = helpers["if"].call(alias1,((stack1 = (depth0 != null ? depth0.options : depth0)) != null ? stack1.enableAudioPlayback : stack1),{"name":"if","hash":{},"fn":container.program(3, 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(3, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + " </div>\n\n" + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.reading : depth0),{"name":"if","hash":{},"fn":container.program(5, data, 0),"inverse":container.program(8, data, 0),"data":data})) != null ? stack1 : "") + "\n <div class=\"term-reasons\">\n" @@ -255,14 +221,12 @@ templates['term-list.html'] = template({"1":function(container,depth0,helpers,pa },"2":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1; - return ((stack1 = container.invokePartial(partials["term.html"],depth0,{"name":"term.html","hash":{"sequence":(depths[1] != null ? depths[1].sequence : depths[1]),"options":(depths[1] != null ? depths[1].options : depths[1]),"root":(depths[1] != null ? depths[1].root : depths[1]),"addable":(depths[1] != null ? depths[1].addable : depths[1])},"data":data,"indent":" ","helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : ""); + return ((stack1 = container.invokePartial(partials["term.html"],depth0,{"name":"term.html","hash":{"playback":(depths[1] != null ? depths[1].playback : depths[1]),"addable":(depths[1] != null ? depths[1].addable : depths[1])},"data":data,"indent":" ","helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : ""); },"4":function(container,depth0,helpers,partials,data) { return " <p>No results found</p>\n"; },"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data,blockParams,depths) { var stack1; - return ((stack1 = container.invokePartial(partials["header.html"],depth0,{"name":"header.html","data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "") - + ((stack1 = helpers["if"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.definitions : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0, blockParams, depths),"inverse":container.program(4, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "") - + ((stack1 = container.invokePartial(partials["footer.html"],depth0,{"name":"footer.html","data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : ""); + return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.definitions : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0, blockParams, depths),"inverse":container.program(4, data, 0, blockParams, depths),"data":data})) != null ? stack1 : ""); },"usePartial":true,"useData":true,"useDepths":true}); })();
\ No newline at end of file diff --git a/ext/fg/css/frame.css b/ext/fg/css/frame.css index 01b8776c..88581f2a 100644 --- a/ext/fg/css/frame.css +++ b/ext/fg/css/frame.css @@ -18,6 +18,15 @@ /* common styles */ +@font-face { + font-family: kanji-stroke-orders; + src: url('../ttf/kanji-stroke-orders.ttf'); +} +@font-face { + font-family: vl-gothic-regular; + src: url('../ttf/vl-gothic-regular.ttf'); +} + body { background-color: #fff; color: #333; diff --git a/ext/fg/frame.html b/ext/fg/frame.html new file mode 100644 index 00000000..32758786 --- /dev/null +++ b/ext/fg/frame.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8"> + <title></title> + <link rel="stylesheet" href="css/frame.css"> + </head> + <body> + <div class="spinner"> + <img src="img/spinner.gif"> + </div> + + <div class="content"></div> + + <script src="../lib/jquery-2.2.2.min.js"></script> + <script src="js/frame.js"></script> + </body> +</html> diff --git a/ext/fg/js/driver.js b/ext/fg/js/driver.js index 0c785d31..1c797201 100644 --- a/ext/fg/js/driver.js +++ b/ext/fg/js/driver.js @@ -21,18 +21,13 @@ class Driver { constructor() { this.popup = new Popup(); this.popupTimer = null; - this.audio = {}; this.lastMousePos = null; this.lastTextSource = null; this.pendingLookup = false; this.enabled = false; this.options = null; - this.definitions = null; - this.sequence = 0; - this.fgRoot = chrome.extension.getURL('fg'); chrome.runtime.onMessage.addListener(this.onBgMessage.bind(this)); - window.addEventListener('message', this.onFrameMessage.bind(this)); window.addEventListener('mouseover', this.onMouseOver.bind(this)); window.addEventListener('mousedown', this.onMouseDown.bind(this)); window.addEventListener('mousemove', this.onMouseMove.bind(this)); @@ -114,20 +109,45 @@ class Driver { callback(); } - onFrameMessage(e) { - const {action, params} = e.data, method = this['api_' + action]; - if (typeof(method) === 'function') { - method.call(this, params); + searchAt(point, hideNotFound) { + if (this.pendingLookup) { + return; + } + + const textSource = textSourceFromPoint(point); + if (textSource === null || !textSource.containsPoint(point)) { + if (hideNotFound) { + this.hidePopup(); + } + + return; + } + + if (this.lastTextSource !== null && this.lastTextSource.equals(textSource)) { + return true; } + + this.pendingLookup = true; + this.searchTerms(textSource).then(found => { + if (!found) { + this.searchKanji(textSource).then(found => { + if (!found && hideNotFound) { + this.hidePopup(); + } + }); + } + }).catch(error => { + alert('Error: ' + error); + }).then(() => { + this.pendingLookup = false; + }); } searchTerms(textSource) { textSource.setEndOffset(this.options.scanLength); - this.pendingLookup = true; return findTerm(textSource.text()).then(({definitions, length}) => { if (definitions.length === 0) { - this.pendingLookup = false; return false; } else { textSource.setEndOffset(length); @@ -138,30 +158,10 @@ class Driver { definition.sentence = sentence; }); - const sequence = ++this.sequence; - const context = { - definitions, - sequence, - addable: this.options.ankiMethod !== 'disabled', - root: this.fgRoot, - options: this.options - }; - - return renderText(context, 'term-list.html').then(content => { - this.definitions = definitions; - this.pendingLookup = false; - this.showPopup(textSource, content); - return canAddDefinitions(definitions, ['term_kanji', 'term_kana']); - }).then(states => { - if (states !== null) { - states.forEach((state, index) => this.popup.invokeApi( - 'setActionState', - {index, state, sequence} - )); - } + this.popup.showNextTo(textSource.getRect()); + this.popup.invoke('showTermDefs', {definitions, options: this.options}); - return true; - }); + return true; } }).catch(error => { alert('Error: ' + error); @@ -171,85 +171,22 @@ class Driver { searchKanji(textSource) { textSource.setEndOffset(1); - this.pendingLookup = true; return findKanji(textSource.text()).then(definitions => { if (definitions.length === 0) { - this.pendingLookup = false; return false; } else { definitions.forEach(definition => definition.url = window.location.href); - const sequence = ++this.sequence; - const context = { - definitions, - sequence, - addable: this.options.ankiMethod !== 'disabled', - root: this.fgRoot, - options: this.options - }; - - return renderText(context, 'kanji-list.html').then(content => { - this.definitions = definitions; - this.pendingLookup = false; - this.showPopup(textSource, content); - return canAddDefinitions(definitions, ['kanji']); - }).then(states => { - if (states !== null) { - states.forEach((state, index) => this.popup.invokeApi( - 'setActionState', - {index, state, sequence} - )); - } + this.popup.showNextTo(textSource.getRect()); + this.popup.invoke('showKanjiDefs', {definitions, options: this.options}); - return true; - }); + return true; } }).catch(error => { alert('Error: ' + error); }); } - searchAt(point, hideNotFound) { - if (this.pendingLookup) { - return; - } - - const textSource = textSourceFromPoint(point); - if (textSource === null || !textSource.containsPoint(point)) { - if (hideNotFound) { - this.hidePopup(); - } - - return; - } - - if (this.lastTextSource !== null && this.lastTextSource.equals(textSource)) { - return true; - } - - this.searchTerms(textSource).then(found => { - if (!found) { - this.searchKanji(textSource).then(found => { - if (!found && hideNotFound) { - this.hidePopup(); - } - }); - } - }).catch(error => { - alert('Error: ' + error); - }); - } - - showPopup(textSource, content) { - this.popup.showNextTo(textSource.getRect(), content); - - if (this.options.selectMatchedText) { - textSource.select(); - } - - this.lastTextSource = textSource; - } - hidePopup() { this.popup.hide(); @@ -270,67 +207,6 @@ class Driver { this.hidePopup(); } } - - api_addNote({index, mode}) { - const state = {[mode]: false}; - addDefinition(this.definitions[index], mode).then(success => { - if (success) { - this.popup.invokeApi('setActionState', {index, state, sequence: this.sequence}); - } else { - alert('Note could not be added'); - } - - this.popup.invokeApi('addNoteComplete'); - }).catch(error => { - alert('Error: ' + error); - }); - } - - api_playAudio(index) { - const definition = this.definitions[index]; - - let url = `https://assets.languagepod101.com/dictionary/japanese/audiomp3.php?kanji=${encodeURIComponent(definition.expression)}`; - if (definition.reading) { - url += `&kana=${encodeURIComponent(definition.reading)}`; - } - - for (const key in this.audio) { - this.audio[key].pause(); - } - - const audio = this.audio[url] || new Audio(url); - audio.currentTime = 0; - audio.play(); - - this.audio[url] = audio; - } - - api_displayKanji(kanji) { - findKanji(kanji).then(definitions => { - definitions.forEach(definition => definition.url = window.location.href); - - const sequence = ++this.sequence; - const context = { - definitions, - sequence, - addable: this.options.ankiMethod !== 'disabled', - root: this.fgRoot, - options: this.options - }; - - return renderText(context, 'kanji-list.html').then(content => { - this.definitions = definitions; - this.popup.setContent(content, definitions); - return canAddDefinitions(definitions, ['kanji']); - }).then(states => { - if (states !== null) { - states.forEach((state, index) => this.popup.invokeApi('setActionState', {index, state, sequence})); - } - }); - }).catch(error => { - alert('Error: ' + error); - }); - } } window.driver = new Driver(); diff --git a/ext/fg/js/frame.js b/ext/fg/js/frame.js index 5878bb43..e3d152c1 100644 --- a/ext/fg/js/frame.js +++ b/ext/fg/js/frame.js @@ -17,76 +17,157 @@ */ -function invokeApi(action, params, target) { - target.postMessage({action, params}, '*'); -} +// function renderText(data, template) { +// return invokeApiBg('renderText', {data, template}); +// } -function showSpinner(show) { - const spinner = document.querySelector('.spinner'); - spinner.style.visibility = show ? 'visible' : 'hidden'; -} +// function canAddDefinitions(definitions, modes) { +// return invokeApiBg('canAddDefinitions', {definitions, modes}).catch(() => null); +// } + +// function addDefinition(definition, mode) { +// return invokeApiBg('addDefinition', {definition, mode}); +// } + +// function invokeApi(action, params, target) { +// target.postMessage({action, params}, '*'); +// } + +// function showSpinner(show) { +// const spinner = document.querySelector('.spinner'); +// spinner.style.visibility = show ? 'visible' : 'hidden'; +// } + +// function registerKanjiLinks() { +// for (const link of Array.from(document.getElementsByClassName('kanji-link'))) { +// link.addEventListener('click', e => { +// e.preventDefault(); +// invokeApi('displayKanji', e.target.innerHTML, window.parent); +// }); +// } +// } + +// function registerAddNoteLinks() { +// for (const link of Array.from(document.getElementsByClassName('action-add-note'))) { +// link.addEventListener('click', e => { +// e.preventDefault(); +// const ds = e.currentTarget.dataset; +// invokeApi('addNote', {index: ds.index, mode: ds.mode}, window.parent); +// showSpinner(true); +// }); +// } +// } -function registerKanjiLinks() { - for (const link of Array.from(document.getElementsByClassName('kanji-link'))) { - link.addEventListener('click', e => { - e.preventDefault(); - invokeApi('displayKanji', e.target.innerHTML, window.parent); +// function registerAudioLinks() { +// for (const link of Array.from(document.getElementsByClassName('action-play-audio'))) { +// link.addEventListener('click', e => { +// e.preventDefault(); +// const ds = e.currentTarget.dataset; +// invokeApi('playAudio', ds.index, window.parent); +// }); +// } +// } + +// function api_setActionState({index, state, sequence}) { +// for (const mode in state) { +// const matches = document.querySelectorAll(`.action-bar[data-sequence="${sequence}"] .action-add-note[data-index="${index}"][data-mode="${mode}"]`); +// if (matches.length === 0) { +// return; +// } + +// const classes = matches[0].classList; +// if (state[mode]) { +// classes.remove('disabled'); +// } else { +// classes.add('disabled'); +// } + +// classes.remove('pending'); +// } +// } + +class FrameContext { + constructor() { + $(window).on('message', e => { + const {action, params} = e.originalEvent.data, method = this['api_' + action]; + if (typeof(method) === 'function') { + method.call(this, params); + } }); } -} -function registerAddNoteLinks() { - for (const link of Array.from(document.getElementsByClassName('action-add-note'))) { - link.addEventListener('click', e => { - e.preventDefault(); - const ds = e.currentTarget.dataset; - invokeApi('addNote', {index: ds.index, mode: ds.mode}, window.parent); - showSpinner(true); + api_showTermDefs({definitions, options}) { + const context = { + definitions, + addable: options.ankiMethod !== 'disabled', + playback: options.enableAudioPlayback + }; + + this.renderText('term-list.html', context).then(content => { + $('.content').html(content); }); } -} -function registerAudioLinks() { - for (const link of Array.from(document.getElementsByClassName('action-play-audio'))) { - link.addEventListener('click', e => { - e.preventDefault(); - const ds = e.currentTarget.dataset; - invokeApi('playAudio', ds.index, window.parent); + api_showKanjiDefs({definitions, options}) { + const context = { + definitions, + addable: options.ankiMethod !== 'disabled' + }; + + this.renderText('kanji-list.html', context).then(content => { + $('.content').html(content); }); } -} -function api_addNoteComplete() { - showSpinner(false); -} + renderText(template, data) { + return this.invokeBgApi('renderText', {data, template}); + } -function api_setActionState({index, state, sequence}) { - for (const mode in state) { - const matches = document.querySelectorAll(`.action-bar[data-sequence="${sequence}"] .action-add-note[data-index="${index}"][data-mode="${mode}"]`); - if (matches.length === 0) { - return; - } - - const classes = matches[0].classList; - if (state[mode]) { - classes.remove('disabled'); - } else { - classes.add('disabled'); - } - - classes.remove('pending'); + invokeBgApi(action, params) { + return new Promise((resolve, reject) => { + chrome.runtime.sendMessage({action, params}, ({result, error}) => { + if (error) { + reject(error); + } else { + resolve(result); + } + }); + }); } } -document.addEventListener('DOMContentLoaded', () => { - registerKanjiLinks(); - registerAddNoteLinks(); - registerAudioLinks(); -}); +window.frameContext = new FrameContext(); -window.addEventListener('message', e => { - const {action, params} = e.data, method = window['api_' + action]; - if (typeof(method) === 'function') { - method(params); - } -}); + // api_addNote({index, mode}) { + // const state = {[mode]: false}; + // addDefinition(this.definitions[index], mode).then(success => { + // if (success) { + // this.popup.invokeApi('setActionState', {index, state, sequence: this.sequence}); + // } else { + // alert('Note could not be added'); + // } + + // this.popup.invokeApi('addNoteComplete'); + // }).catch(error => { + // alert('Error: ' + error); + // }); + // } + + // api_playAudio(index) { + // const definition = this.definitions[index]; + + // let url = `https://assets.languagepod101.com/dictionary/japanese/audiomp3.php?kanji=${encodeURIComponent(definition.expression)}`; + // if (definition.reading) { + // url += `&kana=${encodeURIComponent(definition.reading)}`; + // } + + // for (const key in this.audio) { + // this.audio[key].pause(); + // } + + // const audio = this.audio[url] || new Audio(url); + // audio.currentTime = 0; + // audio.play(); + + // this.audio[url] = audio; + // } diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 398e975e..35d7a00f 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -19,29 +19,32 @@ class Popup { constructor() { - this.container = null; this.offset = 10; - } - show(rect, content) { - this.inject(); + this.container = document.createElement('iframe'); + this.container.id = 'yomichan-popup'; + this.container.addEventListener('mousedown', e => e.stopPropagation()); + this.container.addEventListener('scroll', e => e.stopPropagation()); + this.container.setAttribute('src', chrome.extension.getURL('fg/frame.html')); + document.body.appendChild(this.container); + } + + show(rect) { this.container.style.left = rect.x + 'px'; this.container.style.top = rect.y + 'px'; this.container.style.height = rect.height + 'px'; this.container.style.width = rect.width + 'px'; this.container.style.visibility = 'visible'; - - this.setContent(content); } - showNextTo(elementRect, content) { - this.inject(); - - const containerRect = this.container.getBoundingClientRect(); + showNextTo(elementRect) { + const containerStyle = window.getComputedStyle(this.container); + const containerHeight = parseInt(containerStyle.height); + const containerWidth = parseInt(containerStyle.width); let x = elementRect.left; - let width = containerRect.width; + let width = containerWidth; if (x + width >= window.innerWidth) { const widthMax = window.innerWidth - x; width = Math.min(width, widthMax); @@ -49,14 +52,14 @@ class Popup { } let y = elementRect.bottom + this.offset; - let height = containerRect.height; + let height = containerHeight; if (y + height >= window.innerHeight) { const heightMax = window.innerHeight - y - this.offset; height = Math.min(height, heightMax); y = elementRect.top - height - this.offset; } - this.show({x, y, width, height}, content); + this.show({x, y, width, height}); } visible() { @@ -69,35 +72,9 @@ class Popup { } } - setContent(content) { - if (this.container === null) { - return; - } - - this.container.contentWindow.scrollTo(0, 0); - - const doc = this.container.contentDocument; - doc.open(); - doc.write(content); - doc.close(); - } - - invokeApi(action, params) { + invoke(action, params) { if (this.container !== null) { this.container.contentWindow.postMessage({action, params}, '*'); } } - - inject() { - if (this.container !== null) { - return; - } - - this.container = document.createElement('iframe'); - this.container.id = 'yomichan-popup'; - this.container.addEventListener('mousedown', e => e.stopPropagation()); - this.container.addEventListener('scroll', e => e.stopPropagation()); - - document.body.appendChild(this.container); - } } diff --git a/ext/manifest.json b/ext/manifest.json index 905ce2a9..9bb01c21 100644 --- a/ext/manifest.json +++ b/ext/manifest.json @@ -40,6 +40,7 @@ "fg/img/play_audio.png", "fg/img/spinner.gif", "fg/js/frame.js", + "fg/frame.html", "fg/ttf/kanji-stroke-orders.ttf", "fg/ttf/vl-gothic-regular.ttf" ] |