diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/bg/guide.html | 13 | ||||
-rw-r--r-- | ext/bg/js/display-window.js | 9 | ||||
-rw-r--r-- | ext/bg/js/popup.js | 7 | ||||
-rw-r--r-- | ext/bg/js/templates.js | 12 | ||||
-rw-r--r-- | ext/bg/js/util.js | 9 | ||||
-rw-r--r-- | ext/bg/js/yomichan.js | 22 | ||||
-rw-r--r-- | ext/bg/search.html | 2 | ||||
-rw-r--r-- | ext/fg/frame.html | 30 | ||||
-rw-r--r-- | ext/fg/js/driver.js | 3 | ||||
-rw-r--r-- | ext/manifest.json | 14 | ||||
-rw-r--r-- | ext/mixed/css/frame.css | 3 | ||||
-rw-r--r-- | ext/mixed/img/entry-current.png | bin | 0 -> 743 bytes | |||
-rw-r--r-- | ext/mixed/js/display.js | 177 |
13 files changed, 222 insertions, 79 deletions
diff --git a/ext/bg/guide.html b/ext/bg/guide.html index 130d6d68..3b3dcab7 100644 --- a/ext/bg/guide.html +++ b/ext/bg/guide.html @@ -7,7 +7,7 @@ <link rel="stylesheet" type="text/css" href="/mixed/lib/bootstrap-3.3.7-dist/css/bootstrap-theme.min.css"> </head> <body> - <div class="container-fluid"> + <div class="container"> <div class="page-header"> <h1>Welcome to Yomichan!</h1> </div> @@ -23,11 +23,12 @@ </p> <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>Import the dictionaries (bundled or custom) you wish to use for term and Kanji searches.</li> - <li>Hold down <kbd>Shift</kbd> (or the middle mouse button) as you hover over text to see term definitions.</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>Click on Kanji in the definition window to view additional information about that character.</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>Click on the <em>monkey wrench</em> icon in the middle to open the options page.</li> + <li>Import the dictionaries you wish to use for term and Kanji searches.</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 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> </div> </div> diff --git a/ext/bg/js/display-window.js b/ext/bg/js/display-window.js index ad193c5b..8c732ddd 100644 --- a/ext/bg/js/display-window.js +++ b/ext/bg/js/display-window.js @@ -20,8 +20,13 @@ window.displayWindow = new class extends Display { constructor() { 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) { diff --git a/ext/bg/js/popup.js b/ext/bg/js/popup.js index 9f2567df..5bc7def4 100644 --- a/ext/bg/js/popup.js +++ b/ext/bg/js/popup.js @@ -18,7 +18,7 @@ $(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-help').click(() => window.open('http://foosoft.net/projects/yomichan')); @@ -26,9 +26,6 @@ $(document).ready(() => { const toggle = $('#enable-search'); toggle.prop('checked', options.general.enable).change(); toggle.bootstrapToggle(); - toggle.change(() => { - options.general.enable = toggle.prop('checked'); - optionsSave(options).then(() => instYomi().optionsSet(options)); - }); + toggle.change(() => commandExec('toggle')); }); }); diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js index 91518e84..f267da80 100644 --- a/ext/bg/js/templates.js +++ b/ext/bg/js/templates.js @@ -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) { var stack1, helper, alias1=depth0 != null ? depth0 : {}; - return "<div class=\"entry\">\n <div class=\"actions\">\n" + return "<div class=\"entry\">\n <div class=\"actions\">\n <img src=\"/mixed/img/entry-current.png\" class=\"current\" title=\"Current entry (arrows / home / end)\" 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.source : depth0),{"name":"if","hash":{},"fn":container.program(4, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + " </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 : "") + " </div>\n</div>\n"; },"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></a>\n"; },"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 (Backspace)\" alt></a>\n"; },"6":function(container,depth0,helpers,partials,data) { var stack1; @@ -442,7 +442,7 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia },"12":function(container,depth0,helpers,partials,data) { var stack1, alias1=depth0 != null ? depth0 : {}; - return "<div class=\"entry\">\n <div class=\"actions\">\n" + return "<div class=\"entry\">\n <div class=\"actions\">\n <img src=\"/mixed/img/entry-current.png\" class=\"current\" title=\"Current entry (arrows / home / end)\" 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.playback : depth0),{"name":"if","hash":{},"fn":container.program(15, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + " </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 : "") + " </div>\n</div>\n"; },"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></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></a>\n"; },"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></a>\n"; },"17":function(container,depth0,helpers,partials,data) { var stack1, helper, options, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing, alias3="function", buffer = " <div class=\"expression\"><ruby>"; diff --git a/ext/bg/js/util.js b/ext/bg/js/util.js index 59eb9269..6999cae3 100644 --- a/ext/bg/js/util.js +++ b/ext/bg/js/util.js @@ -34,6 +34,15 @@ function promiseCallback(promise, callback) { /* + * Commands + */ + +function commandExec(command) { + instYomi().onCommand(command); +} + + +/* * Instance */ diff --git a/ext/bg/js/yomichan.js b/ext/bg/js/yomichan.js index a61be8be..3a42c594 100644 --- a/ext/bg/js/yomichan.js +++ b/ext/bg/js/yomichan.js @@ -25,12 +25,13 @@ window.yomichan = new class { this.anki = new AnkiNull(); this.options = null; - 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)); + this.translator.prepare().then(optionsLoad).then(this.optionsSet.bind(this)).then(() => { + chrome.commands.onCommand.addListener(this.onCommand.bind(this)); + chrome.runtime.onMessage.addListener(this.onMessage.bind(this)); + if (chrome.runtime.onInstalled) { + chrome.runtime.onInstalled.addListener(this.onInstalled.bind(this)); + } + }); } optionsSet(options) { @@ -153,6 +154,15 @@ window.yomichan = new class { } } + onCommand(command) { + if (command === 'search') { + window.open(chrome.extension.getURL('/bg/search.html')); + } else if (command === 'toggle') { + this.options.general.enable = !this.options.general.enable; + optionsSave(this.options).then(() => this.optionsSet(this.options)); + } + } + onMessage(request, sender, callback) { const handlers = new class { api_optionsGet({callback}) { diff --git a/ext/bg/search.html b/ext/bg/search.html index e9c25e15..2fd44fc7 100644 --- a/ext/bg/search.html +++ b/ext/bg/search.html @@ -20,7 +20,7 @@ <form class="input-group"> <input type="text" class="form-control" placeholder="Search for..." id="query" autofocus> <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> </form> </p> diff --git a/ext/fg/frame.html b/ext/fg/frame.html index ec0acf64..09d1689e 100644 --- a/ext/fg/frame.html +++ b/ext/fg/frame.html @@ -6,28 +6,34 @@ <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/css/frame.css"> + <style type="text/css"> + .entry { + padding-left: 10px; + padding-right: 10px; + } + </style> </head> <body> - <div class="container-fluid"> - <div id="spinner"> - <img src="/mixed/img/spinner.gif"> - </div> + <div id="spinner"> + <img src="/mixed/img/spinner.gif"> + </div> - <div id="content"></div> + <div id="content"></div> - <div id="orphan"> + <div id="orphan"> + <div class="container-fluid"> <h1>Yomichan Updated!</h1> <p> 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. </p> </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> + + <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> </body> </html> diff --git a/ext/fg/js/driver.js b/ext/fg/js/driver.js index fbe89ab8..16b12d5e 100644 --- a/ext/fg/js/driver.js +++ b/ext/fg/js/driver.js @@ -105,6 +105,9 @@ window.driver = new class { const handlers = new class { api_optionsSet(options) { this.options = options; + if (!this.options.enable) { + this.searchClear(); + } } }; diff --git a/ext/manifest.json b/ext/manifest.json index 9c311b2f..215397d0 100644 --- a/ext/manifest.json +++ b/ext/manifest.json @@ -31,6 +31,20 @@ "<all_urls>", "storage" ], + "commands": { + "toggle": { + "suggested_key": { + "default": "Alt+Delete" + }, + "description": "Toggle text scanning" + }, + "search": { + "suggested_key": { + "default": "Alt+Insert" + }, + "description": "Open search window" + } + }, "web_accessible_resources": ["fg/frame.html"], "applications": { "gecko": { diff --git a/ext/mixed/css/frame.css b/ext/mixed/css/frame.css index af689cbe..a425aca8 100644 --- a/ext/mixed/css/frame.css +++ b/ext/mixed/css/frame.css @@ -52,7 +52,8 @@ hr { */ .entry { - padding: 15px 0px 15px 0px; + padding-top: 10px; + padding-bottom: 10px; } .tag-default { diff --git a/ext/mixed/img/entry-current.png b/ext/mixed/img/entry-current.png Binary files differnew file mode 100644 index 00000000..bab7cc9b --- /dev/null +++ b/ext/mixed/img/entry-current.png diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 63620dc6..45c1e08c 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -25,6 +25,9 @@ class Display { this.audioCache = {}; this.responseCache = {}; this.sequence = 0; + this.index = 0; + + $(document).keydown(this.onKeyDown.bind(this)); } definitionAdd(definition, mode) { @@ -48,8 +51,12 @@ class Display { } showTermDefs(definitions, options, context) { + window.focus(); + this.spinner.hide(); this.definitions = definitions; + this.context = context; + this.options = options; const sequence = ++this.sequence; const params = { @@ -69,42 +76,24 @@ class Display { this.templateRender('terms.html', params).then(content => { this.container.html(content); - let offset = 0; - if (context && context.hasOwnProperty('index') && context.index < definitions.length) { - const entry = $('.entry').eq(context.index); - offset = entry.offset().top; - } + const index = context && context.hasOwnProperty('index') ? context.index : 0; + this.entryScroll(index); - 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)); - }); + $('.action-add-note').click(this.onAddNote.bind(this)); + $('.action-play-audio').click(this.onPlayAudio.bind(this)); + $('.kanji-link').click(this.onKanjiLookup.bind(this)); return this.adderButtonsUpdate(['term-kanji', 'term-kana'], sequence); }).catch(this.handleError.bind(this)); } showKanjiDefs(definitions, options, context) { + window.focus(); + this.spinner.hide(); this.definitions = definitions; + this.context = context; + this.options = options; const sequence = ++this.sequence; const params = { @@ -122,17 +111,12 @@ class Display { this.templateRender('kanji.html', params).then(content => { this.container.html(content); - window.scrollTo(0, 0); - $('.action-add-note').click(this.onActionAddNote.bind(this)); - $('.source-term').click(e => { - e.preventDefault(); + const index = context && context.hasOwnProperty('index') ? context.index : 0; + this.entryScroll(index); - if (context && context.source) { - context.index = context.source.index; - this.showTermDefs(context.source.definitions, options, context); - } - }); + $('.action-add-note').click(this.onAddNote.bind(this)); + $('.source-term').click(this.onSourceTerm.bind(this)); return this.adderButtonsUpdate(['kanji'], sequence); }).catch(this.handleError.bind(this)); @@ -159,13 +143,125 @@ class Display { }); } - onActionAddNote(e) { + entryScroll(index, smooth) { + if (index < 0 || index >= this.definitions.length) { + return; + } + + $('.current').hide().eq(index).show(); + + const body = $('body').stop(); + const entry = $('.entry').eq(index); + const target = index === 0 ? 0 : entry.offset().top; + + if (smooth) { + body.animate({scrollTop: target}, 200); + } else { + body.scrollTop(target); + } + + this.index = index; + } + + onSourceTerm(e) { + e.preventDefault(); + + 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); + } + } + + onKanjiLookup(e) { + e.preventDefault(); + + const link = $(e.target); + const context = { + source: { + 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, 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(); - this.spinner.show(); const link = $(e.currentTarget); - const mode = link.data('mode'); const index = Display.entryIndexFind(link); + this.noteAdd(index, link.data('mode')); + } + + onKeyDown(e) { + const handlers = { + 36: /* home */ () => { + this.entryScroll(0, true); + }, + + 35: /* end */ () => { + this.entryScroll(this.definitions.length - 1, true); + }, + + 38: /* up */ () => { + this.entryScroll(this.index - 1, true); + }, + + 40: /* down */ () => { + this.entryScroll(this.index + 1, true); + }, + + 209: /* [ */ () => { + + }, + + 221: /* ] */ () => { + + }, + + 220: /* \ */ () => { + this.audioPlay(this.definitions[this.index]); + }, + + 8: /* backspace */ () => { + + } + }; + + const handler = handlers[e.keyCode]; + if (handler) { + e.preventDefault(); + handler(); + } + } + + sourceTerm(index) { + + + } + + noteAdd(index, mode) { + this.spinner.show(); const definition = this.definitions[index]; let promise = Promise.resolve(); @@ -187,8 +283,9 @@ class Display { }).catch(this.handleError.bind(this)).then(() => this.spinner.hide()); } - audioPlay(definition) { + audioPlay(index) { this.spinner.show(); + const definition = this.definitions[index]; for (const key in this.audioCache) { this.audioCache[key].pause(); |