// ==UserScript== // @name WaniKani Vocab Sentences // @namespace http://mozartpetter.com/wanikani // @version 0.2 // @description Loads sentences from jisho.org and displays it into the vocab screen of the WaniKani website. // @match http://www.wanikani.com/review/session // @copyright 2013, Mozart Petter // @license http://creativecommons.org/licenses/by/3.0/deed.en_US // ==/UserScript== // --- YOU CAN CHANGE THOSE VALUES IF YOU WANT --- // // The number of sentences you want to view at once. var TOTAL_SENTENCES = 3; // This will filter sentences that contains more than X chars on it. var MAX_CHARS_INTO_SENTENCE = 30; // If you don't want to see the translations, set it to false. var SHOW_TRANSLATIONS = true; // --- YOU SHOULDN'T CHANGE THOSE VALUES --- // // Sets debug mode on. You can play with it if you want't, but it will break the webpage. ;)e var DEBUG = false; // --- DON'T TOUCH HERE UNLESS YOU KNOW WHAT YOU'RE DOING --- // /** * Checks if the current screen is a vocab screen. */ function checkIfVocab() { var header = document.getElementsByTagName("h1")[0]; var isVocab = header.className == "vocabulary"; if (isVocab) { var vocab = header.childNodes[0].innerHTML; getSentencesForVocab(vocab); } } /** * Parses the given html code. * * @param html The HTML code to be parsed. * @parma vocab The current vocab word. */ function parseContent(html, vocab) { var wrapper = document.createElement('div'); wrapper.innerHTML = html; var sentenceNode = wrapper.getElementsByClassName('japanese'); var translationNode = wrapper.getElementsByClassName('english'); var content = getContentFromDom(sentenceNode, translationNode, vocab); showContent(content); } /** * Extracts the sentences and translations from the given DOM object. * * @param sentenceNodes A collection of the HTML elements containing the sentences. * @param translationNodes A collection of the HTML elements containing the translations. * @param vocab The current vocab word. */ function getContentFromDom(sentenceNodes, translationNodes, vocab) { var excludedIndexes = []; var content = []; for (var i = 0, c = 0; c < TOTAL_SENTENCES && i < sentenceNodes.length; i++) { var randomIndex = getRandomNumber(sentenceNodes.length, excludedIndexes); excludedIndexes.push(randomIndex); var sentenceNode = sentenceNodes[randomIndex]; var translationNode = translationNodes[randomIndex]; var sentence = sentenceNode.innerText; if (sentence.length > MAX_CHARS_INTO_SENTENCE) continue; var translation = translationNode.innerText; var hightlightedVocab = '<strong class="kanji-highlight" style="padding-left: 2px; padding-right: 2px;color:#666;background-color:#EEE">' + vocab + '</strong>'; sentence = sentence.replace(vocab, hightlightedVocab, "gi"); content[c] = []; content[c].push(sentence); content[c].push(translation); c++; } return content; } /** * Generates a random number using max as a limit and excluding * any numbers from exclude collection. * * @param max The limit for the random number. * @param exclude A list with numbers to be excluded from the randomization. */ function getRandomNumber(max, exclude) { var result = Math.floor(Math.random() * max); for (var i = 0; i < exclude.length; i++) { if (exclude[i] == result) { return getRandomNumber(max, exclude); } } return result; } /** * Show the sentences from the given collection. * * @param sentences A collection of sentences to be displayed. */ function showContent(sentences) { var container = document.getElementById('item-info-main'); var htmlCode = '<h3>Usage Examples</h3>'; htmlCode += '<ul style="padding: 0px;line-height: 1.8em;list-style: decimal inside;">'; for (var i = 0; i < sentences.length; i++) { htmlCode += '<li style="font-weight: bold;color: #888;">'; htmlCode += '<span style="font-weight: normal; color: #333;padding-left: 5px;display:block;">' + sentences[i][0] + '</span>'; if (SHOW_TRANSLATIONS) { htmlCode += '<span style="display: block;margin-bottom: 10px;font-weight: normal;color: #888;padding-left: 20px;">' + sentences[i][1] + '</span>'; } htmlCode += '</li>'; } htmlCode += '<ul>'; htmlCode += '</ul>'; var node = document.createElement('div'); node.style.display = 'block'; node.style.marginBottom = '40px'; node.innerHTML = htmlCode; container.insertBefore(node, container.firstChild); } /** * Loads the sentences for the given vocab. * * @param vocab The current vocab word. */ function getSentencesForVocab(vocab) { GM_xmlhttpRequest ({ method: "GET", url: "http://www.jisho.org/sentences?jap=" + vocab, onload: function (response) { parseContent(response.responseText, vocab); } }); } /** * Do a setup to handle events from the question form. */ function setupForm() { var form = document.getElementById('question-form'); form.addEventListener("submit", function() { checkIfVocab(); }); } /** * Called when the document is ready. */ document.onreadystatechange = function () { var state = document.readyState; if (state == 'complete') { setupForm(); } if (DEBUG) { var infoElem = document.getElementById('information'); var itemInfoElem = document.getElementById('item-info'); infoElem.style.display = itemInfoElem.style.display = 'block'; checkIfVocab(); } } // --- I TOLD YOU SO! NOW THE CODE IS BROKEN... :( --- //