diff options
| author | Alex Yatskov <alex@foosoft.net> | 2017-04-02 12:08:49 -0700 | 
|---|---|---|
| committer | Alex Yatskov <alex@foosoft.net> | 2017-04-02 12:08:49 -0700 | 
| commit | ccb740da58068633a0ef5bd1c26bd4dd10625dce (patch) | |
| tree | 6e0e90351eb6d0294ffbf27fefbe7fc6d064645b | |
| parent | 372cdbf14bd4412c8078e26a6324edd534b6daf4 (diff) | |
| parent | 9ac55fb5d11e5037e808939598591d55d1368b43 (diff) | |
Merge branch 'dev'
| -rw-r--r-- | ext/bg/js/options.js | 4 | ||||
| -rw-r--r-- | ext/bg/js/util.js | 90 | ||||
| -rw-r--r-- | ext/bg/js/yomichan.js | 2 | ||||
| -rw-r--r-- | ext/bg/options.html | 11 | ||||
| -rw-r--r-- | ext/manifest.json | 2 | ||||
| -rw-r--r-- | ext/mixed/js/display.js | 4 | ||||
| -rw-r--r-- | ext/mixed/js/util.js | 101 | 
7 files changed, 85 insertions, 129 deletions
| diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 75f39d24..ad8d83d8 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -25,7 +25,7 @@ function formRead() {      return optionsLoad().then(optionsOld => {          const optionsNew = $.extend(true, {}, optionsOld); -        optionsNew.general.audioPlayback = $('#audio-playback-buttons').prop('checked'); +        optionsNew.general.audioSource = $('#audio-playback-source').val();          optionsNew.general.audioVolume = $('#audio-playback-volume').val();          optionsNew.general.groupResults = $('#group-terms-results').prop('checked');          optionsNew.general.softKatakana = $('#soft-katakana-search').prop('checked'); @@ -111,7 +111,7 @@ $(document).ready(() => {      handlebarsRegister();      optionsLoad().then(options => { -        $('#audio-playback-buttons').prop('checked', options.general.audioPlayback); +        $('#audio-playback-source').val(options.general.audioSource);          $('#audio-playback-volume').val(options.general.audioVolume);          $('#group-terms-results').prop('checked', options.general.groupResults);          $('#soft-katakana-search').prop('checked', options.general.softKatakana); diff --git a/ext/bg/js/util.js b/ext/bg/js/util.js index 78258c97..05c7ff27 100644 --- a/ext/bg/js/util.js +++ b/ext/bg/js/util.js @@ -25,9 +25,6 @@ function promiseCallback(promise, callback) {      return promise.then(result => {          callback({result});      }).catch(error => { -        /* eslint-disable */ -        console.log(error); -        /* eslint-enable */          callback({error});      });  } @@ -84,7 +81,7 @@ function optionsSetDefaults(options) {      const defaults = {          general: {              enable: true, -            audioPlayback: true, +            audioSource: 'jpod101',              audioVolume: 100,              groupResults: true,              softKatakana: true, @@ -137,84 +134,15 @@ function optionsSetDefaults(options) {  function optionsVersion(options) {      const fixups = [ +        () => { }, +        () => { }, +        () => { }, +        () => { },          () => { -            const copy = (targetDict, targetKey, sourceDict, sourceKey) => { -                targetDict[targetKey] = sourceDict.hasOwnProperty(sourceKey) ? sourceDict[sourceKey] : targetDict[targetKey]; -            }; - -            copy(options.general, 'autoStart', options, 'activateOnStartup'); -            copy(options.general, 'audioPlayback', options, 'enableAudioPlayback'); -            copy(options.general, 'softKatakana', options, 'enableSoftKatakanaSearch'); -            copy(options.general, 'groupResults', options, 'groupTermResults'); -            copy(options.general, 'showAdvanced', options, 'showAdvancedOptions'); - -            copy(options.scanning, 'requireShift', options, 'holdShiftToScan'); -            copy(options.scanning, 'selectText', options, 'selectMatchedText'); -            copy(options.scanning, 'delay', options, 'scanDelay'); -            copy(options.scanning, 'length', options, 'scanLength'); - -            options.anki.enable = options.ankiMethod === 'ankiconnect'; - -            copy(options.anki, 'tags', options, 'ankiCardTags'); -            copy(options.anki, 'sentenceExt', options, 'sentenceExtent'); -            copy(options.anki.terms, 'deck', options, 'ankiTermDeck'); -            copy(options.anki.terms, 'model', options, 'ankiTermModel'); -            copy(options.anki.terms, 'fields', options, 'ankiTermFields'); -            copy(options.anki.kanji, 'deck', options, 'ankiKanjiDeck'); -            copy(options.anki.kanji, 'model', options, 'ankiKanjiModel'); -            copy(options.anki.kanji, 'fields', options, 'ankiKanjiFields'); - -            for (const title in options.dictionaries) { -                const dictionary = options.dictionaries[title]; -                dictionary.enabled = dictionary.enableTerms || dictionary.enableKanji; -                dictionary.priority = 0; -            } -        }, -        () => { -            const fixupFields = fields => { -                const fixups = { -                    '{expression-furigana}': '{furigana}', -                    '{glossary-list}': '{glossary}' -                }; - -                for (const name in fields) { -                    for (const fixup in fixups) { -                        fields[name] = fields[name].replace(fixup, fixups[fixup]); -                    } -                } -            }; - -            fixupFields(options.anki.terms.fields); -            fixupFields(options.anki.kanji.fields); -        }, -        () => { -            let hasEnabledDict = false; -            for (const title in options.dictionaries) { -                if (options.dictionaries[title].enabled) { -                    hasEnabledDict = true; -                    break; -                } -            } - -            if (!hasEnabledDict) { -                for (const title in options.dictionaries) { -                    options.dictionaries[title].enabled = true; -                } -            } -        }, -        () => { -            let hasEnabledDict = false; -            for (const title in options.dictionaries) { -                if (options.dictionaries[title].enabled) { -                    hasEnabledDict = true; -                    break; -                } -            } - -            if (!hasEnabledDict) { -                for (const title in options.dictionaries) { -                    options.dictionaries[title].enabled = true; -                } +            if (options.general.audioPlayback) { +                options.general.audioSource = 'jpod101'; +            } else { +                options.general.audioSource = 'disabled';              }          }      ]; diff --git a/ext/bg/js/yomichan.js b/ext/bg/js/yomichan.js index 7a26d6c7..feb74b6e 100644 --- a/ext/bg/js/yomichan.js +++ b/ext/bg/js/yomichan.js @@ -121,7 +121,7 @@ window.yomichan = new class {      definitionAdd(definition, mode) {          let promise = Promise.resolve();          if (mode !== 'kanji') { -            promise = audioInject(definition, this.options.anki.terms.fields); +            promise = audioInject(definition, this.options.anki.terms.fields, this.options.general.audioSource);          }          return promise.then(() => { diff --git a/ext/bg/options.html b/ext/bg/options.html index c483c656..939227b0 100644 --- a/ext/bg/options.html +++ b/ext/bg/options.html @@ -37,8 +37,13 @@                      <label><input type="checkbox" id="soft-katakana-search"> Soft Katakana search</label>                  </div> -                <div class="checkbox"> -                    <label><input type="checkbox" id="audio-playback-buttons"> Audio playback buttons</label> +                <div class="form-group"> +                    <label for="audio-playback-source">Audio playback source</label> +                    <select class="form-control" id="audio-playback-source"> +                        <option value="disabled">Disabled</option> +                        <option value="jpod101">JapanesePod101</option> +                        <option value="jpod101-alternate">JapanesePod101 (Alternate)</option> +                    </select>                  </div>                  <div class="form-group options-advanced"> @@ -52,7 +57,7 @@                  </div>                  <div class="form-group options-advanced"> -                    <label>Popup size (in pixels)</label> +                    <label>Popup size (width x height, in pixels)</label>                      <div class="row">                          <div class="col-xs-6"><input type="number" min="1" id="popup-width" class="form-control"></div>                          <div class="col-xs-6"><input type="number" min="1" id="popup-height" class="form-control"></div> diff --git a/ext/manifest.json b/ext/manifest.json index 16c801c1..ba31a35d 100644 --- a/ext/manifest.json +++ b/ext/manifest.json @@ -1,7 +1,7 @@  {      "manifest_version": 2,      "name": "Yomichan", -    "version": "1.1.10", +    "version": "1.1.11",      "description": "Japanese dictionary with Anki integration",      "icons": {"16": "mixed/img/icon16.png", "48": "mixed/img/icon48.png", "128": "mixed/img/icon128.png"}, diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 36609525..f5ad4849 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -69,7 +69,7 @@ class Display {              definitions,              addable: options.anki.enable,              grouped: options.general.groupResults, -            playback: options.general.audioPlayback +            playback: options.general.audioSource !== 'disabled'          };          if (context) { @@ -335,7 +335,7 @@ class Display {              this.audioCache[key].pause();          } -        audioBuildUrl(definition, this.responseCache).then(url => { +        audioBuildUrl(definition, this.options.general.audioSource, this.responseCache).then(url => {              if (!url) {                  url = '/mixed/mp3/button.mp3';              } diff --git a/ext/mixed/js/util.js b/ext/mixed/js/util.js index 4ce60e4f..edd49873 100644 --- a/ext/mixed/js/util.js +++ b/ext/mixed/js/util.js @@ -21,48 +21,71 @@   * Audio   */ -function audioBuildUrl(definition, cache={}) { -    return new Promise((resolve, reject) => { -        const response = cache[definition.expression]; -        if (response) { -            resolve(response); -        } else { -            const data = { -                post: 'dictionary_reference', -                match_type: 'exact', -                search_query: definition.expression -            }; +function audioBuildUrl(definition, mode, cache={}) { +    if (mode === 'jpod101') { +        let kana = definition.reading; +        let kanji = definition.expression; -            const params = []; -            for (const key in data) { -                params.push(`${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`); -            } - -            const xhr = new XMLHttpRequest(); -            xhr.open('POST', 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post'); -            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); -            xhr.addEventListener('error', () => reject('failed to scrape audio data')); -            xhr.addEventListener('load', () => { -                cache[definition.expression] = xhr.responseText; -                resolve(xhr.responseText); -            }); +        if (!kana && wanakana.isHiragana(kanji)) { +            kana = kanji; +            kanji = null; +        } -            xhr.send(params.join('&')); +        const params = []; +        if (kanji) { +            params.push(`kanji=${encodeURIComponent(kanji)}`);          } -    }).then(response => { -        const dom = new DOMParser().parseFromString(response, 'text/html'); -        for (const row of dom.getElementsByClassName('dc-result-row')) { -            try { -                const url = row.getElementsByClassName('ill-onebuttonplayer').item(0).getAttribute('data-url'); -                const reading = row.getElementsByClassName('dc-vocab_kana').item(0).innerText; -                if (url && reading && (!definition.reading || definition.reading === reading)) { -                    return url; +        if (kana) { +            params.push(`kana=${encodeURIComponent(kana)}`); +        } + +        const url = `https://assets.languagepod101.com/dictionary/japanese/audiomp3.php?${params.join('&')}`; +        return Promise.resolve(url); +    } else if (mode === 'jpod101-alternate') { +        return new Promise((resolve, reject) => { +            const response = cache[definition.expression]; +            if (response) { +                resolve(response); +            } else { +                const data = { +                    post: 'dictionary_reference', +                    match_type: 'exact', +                    search_query: definition.expression +                }; + +                const params = []; +                for (const key in data) { +                    params.push(`${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`);                  } -            } catch (e) { -                // NOP + +                const xhr = new XMLHttpRequest(); +                xhr.open('POST', 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post'); +                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); +                xhr.addEventListener('error', () => reject('failed to scrape audio data')); +                xhr.addEventListener('load', () => { +                    cache[definition.expression] = xhr.responseText; +                    resolve(xhr.responseText); +                }); + +                xhr.send(params.join('&'));              } -        } -    }); +        }).then(response => { +            const dom = new DOMParser().parseFromString(response, 'text/html'); +            for (const row of dom.getElementsByClassName('dc-result-row')) { +                try { +                    const url = row.getElementsByClassName('ill-onebuttonplayer').item(0).getAttribute('data-url'); +                    const reading = row.getElementsByClassName('dc-vocab_kana').item(0).innerText; +                    if (url && reading && (!definition.reading || definition.reading === reading)) { +                        return url; +                    } +                } catch (e) { +                    // NOP +                } +            } +        }); +    } else { +        return Promise.reject('unsupported audio source'); +    }  }  function audioBuildFilename(definition) { @@ -79,7 +102,7 @@ function audioBuildFilename(definition) {      }  } -function audioInject(definition, fields) { +function audioInject(definition, fields, mode) {      const filename = audioBuildFilename(definition);      if (!filename) {          return Promise.resolve(true); @@ -97,7 +120,7 @@ function audioInject(definition, fields) {          return Promise.resolve(true);      } -    return audioBuildUrl(definition).then(url => { +    return audioBuildUrl(definition, mode).then(url => {          definition.audio = {url, filename};          return true;      }).catch(() => false); |