diff options
| -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 | ||||
| -rw-r--r-- | tmpl/footer.html | 3 | ||||
| -rw-r--r-- | tmpl/header.html | 22 | ||||
| -rw-r--r-- | tmpl/kanji-list.html | 4 | ||||
| -rw-r--r-- | tmpl/kanji.html | 4 | ||||
| -rw-r--r-- | tmpl/term-list.html | 4 | ||||
| -rw-r--r-- | tmpl/term.html | 10 | 
13 files changed, 247 insertions, 350 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"      ] diff --git a/tmpl/footer.html b/tmpl/footer.html deleted file mode 100644 index 3840600f..00000000 --- a/tmpl/footer.html +++ /dev/null @@ -1,3 +0,0 @@ -    <script src="{{root}}/js/frame.js"></script> -    </body> -</html> diff --git a/tmpl/header.html b/tmpl/header.html deleted file mode 100644 index 476c3403..00000000 --- a/tmpl/header.html +++ /dev/null @@ -1,22 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> -    <head> -        <meta charset="UTF-8"> -        <title></title> -        <style> -            @font-face { -                font-family: kanji-stroke-orders; -                src:         url('{{root}}/ttf/kanji-stroke-orders.ttf'); -            } -            @font-face { -                font-family: vl-gothic-regular; -                src:         url('{{root}}/ttf/vl-gothic-regular.ttf'); -            } -        </style> -        <link rel="stylesheet" href="{{root}}/css/frame.css"> -    </head> -    <body> - -    <div class="spinner"> -        <img src="{{root}}/img/spinner.gif"> -    </div> diff --git a/tmpl/kanji-list.html b/tmpl/kanji-list.html index af38d485..0ee81463 100644 --- a/tmpl/kanji-list.html +++ b/tmpl/kanji-list.html @@ -1,9 +1,7 @@ -{{> header.html}}  {{#if definitions}}      {{#each definitions}} -    {{> kanji.html addable=../addable root=../root options=../options sequence=../sequence}} +    {{> kanji.html addable=../addable root=../root}}      {{/each}}  {{else}}      <p>No results found</p>  {{/if}} -{{> footer.html}} diff --git a/tmpl/kanji.html b/tmpl/kanji.html index 1dc19983..a3f37cbf 100644 --- a/tmpl/kanji.html +++ b/tmpl/kanji.html @@ -1,7 +1,7 @@  <div class="kanji-definition"> -    <div class="action-bar" data-sequence="{{sequence}}"> +    <div class="action-bar">          {{#if addable}} -        <a href="#" title="Add Kanji" class="action-add-note pending disabled" data-mode="kanji" data-index="{{@index}}"><img src="{{root}}/img/add_kanji.png"></a> +        <a href="#" title="Add Kanji" class="action-add-note pending disabled" data-mode="kanji" data-index="{{@index}}"><img src="img/add_kanji.png"></a>          {{/if}}      </div> diff --git a/tmpl/term-list.html b/tmpl/term-list.html index 2088ac71..b4c9d997 100644 --- a/tmpl/term-list.html +++ b/tmpl/term-list.html @@ -1,9 +1,7 @@ -{{> header.html}}  {{#if definitions}}      {{#each definitions}} -    {{> term.html addable=../addable root=../root options=../options sequence=../sequence}} +    {{> term.html addable=../addable playback=../playback}}      {{/each}}  {{else}}      <p>No results found</p>  {{/if}} -{{> footer.html}} diff --git a/tmpl/term.html b/tmpl/term.html index e931e5cf..b4d72d4b 100644 --- a/tmpl/term.html +++ b/tmpl/term.html @@ -1,11 +1,11 @@  <div class="term-definition"> -    <div class="action-bar" data-sequence="{{sequence}}"> +    <div class="action-bar">          {{#if addable}} -        <a href="#" title="Add term as expression" class="action-add-note pending disabled" data-mode="term_kanji" data-index="{{@index}}"><img src="{{root}}/img/add_term_kanji.png"></a> -        <a href="#" title="Add term as reading" class="action-add-note pending disabled" data-mode="term_kana" data-index="{{@index}}"><img src="{{root}}/img/add_term_kana.png"></a> +        <a href="#" title="Add term as expression" class="action-add-note pending disabled" data-mode="term_kanji" data-index="{{@index}}"><img src="img/add_term_kanji.png"></a> +        <a href="#" title="Add term as reading" class="action-add-note pending disabled" data-mode="term_kana" data-index="{{@index}}"><img src="img/add_term_kana.png"></a>          {{/if}} -        {{#if options.enableAudioPlayback}} -        <a href="#" title="Play audio" class="action-play-audio" data-index="{{@index}}"><img src="{{root}}/img/play_audio.png"></a> +        {{#if playback}} +        <a href="#" title="Play audio" class="action-play-audio" data-index="{{@index}}"><img src="img/play_audio.png"></a>          {{/if}}      </div> |