spanish-quizzer

An app to quiz you on Spanish vocabulary and verb conjugations
git clone https://git.ashermorgan.net/spanish-quizzer/
Log | Files | Refs | README

commit bb441a86ba4b916e9dd53fee9f2f7405a3d9c05c
parent ea341da40a1b18269f920206e75f828cb898c1f0
Author: AsherMorgan <59518073+AsherMorgan@users.noreply.github.com>
Date:   Fri, 24 Jul 2020 08:27:13 -0700

Merge pull request #14 from AsherMorgan/verb-quizzer

Created Verb Quizzer.
Diffstat:
MOffline/index.html | 4+++-
MREADME.md | 30++++++++++++++++++++----------
DReference/index.html | 75---------------------------------------------------------------------------
AScripts/Home.js | 230+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MScripts/Quizzer.js | 326++++++++++++-------------------------------------------------------------------
MScripts/Reference.js | 3+++
MScripts/Settings.js | 515+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
AStyles/Home.css | 21+++++++++++++++++++++
MStyles/Settings.css | 13++++++-------
Mindex.html | 222+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Areference.html | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11 files changed, 847 insertions(+), 667 deletions(-)

diff --git a/Offline/index.html b/Offline/index.html @@ -22,6 +22,7 @@ <h4>Safari (iOS)</h4> <ol> <li>Go to the <a href="../">Spanish-Quizzer homepage</a>.</li> + <li>Tap on either Conjugations, Vocab, or the Reference Tables.</li> <li>Tap the share icon and select "Add to Reading List".</li> <li>Open the Settings app and select "Safari".</li> <li>Scroll down to the "Reading List" section and enable "Automatically Save Offline".</li> @@ -30,8 +31,9 @@ <h4>Firefox</h4> <ol> <li>Go to the <a href="../">Spanish-Quizzer homepage</a>.</li> + <li>Click on either Conjugations, Vocab, or the Reference Tables.</li> <li>When you are offline, click on the hamburger menu in the top right corner, click on "Web Developer", and enable "Work Offline".</li> - <li>Return to the <a href="../">homepage</a> to study offline.</li> + <li>Return to the page you clicked on to study offline.</li> <li>When you get back online, you must disable "Work Offline" in order to browse the internet again.</li> </ol> <h4>Chrome / Edge</h4> diff --git a/README.md b/README.md @@ -1,17 +1,17 @@ # Spanish-Quizzer -Quizzes you on spanish vocabulary through a customizable web interface. +Quizzes you on spanish vocabulary and verb conjugations through a customizable web interface. Try it out [here](https://ashermorgan.github.io/Spanish-Quizzer/). ## Features - Supports practice for all four language skills: reading, listening, writing, and speaking. - Lots of vocab sets and filters. - Easily type special characters (``` a` ``` → `á`, `n~` → `ñ`, `u~` → `ü`) -- Spanish vocabulary reference tables (available [here](https://ashermorgan.github.io/Spanish-Quizzer/Reference)) +- Spanish vocabulary reference tables (available [here](https://ashermorgan.github.io/Spanish-Quizzer/Reference.html)) ## Vocabulary Sets Spanish-Quizzer comes with many vocabulary sets that can be filtered by word type, tense, direction, and more. Those vocabulary sets are: - Common Words: - - Common Verbs (with conjugations) + - Common Verbs - Common Adjectives - Common Adverbs - Common Prepositions @@ -37,14 +37,24 @@ Spanish-Quizzer comes with many vocabulary filters. Not all filters may be used - Language - Spanish to English - English to Spanish -- Tense - - Present - - Preterite - - Imperfect - Word Type - Noun - Adjective - Verb -- Conjugation Type - - Regular - - Non-regular (includes irregular, stem changing, and orthographic conjugations) + +## Verb Filters +Spanish-Quizzer comes with many verb filters. +- All Conjugations +- Reverse Conjugations +- All Present Participles +- All Present Tense Conjugations +- All Preterite Tense Conjugations +- All Imperfect Tense Conjugations +- Non-Regular Present Participles +- Non-Regular Present Tense Conjugations +- Non-Regular Preterite Tense Conjugations +- Non-Regular Imperfect Tense Conjugations +- Regular Present Participles +- Regular Present Conjugations +- Regular Preterite Conjugations +- Regular Imperfect Conjugations diff --git a/Reference/index.html b/Reference/index.html @@ -1,74 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, user-scalable=no"/> - <title>Reference Tables - Spanish-Quizzer</title> - <link rel="icon" type="image/png" href="../Images/favicon-32.png"> - <link rel="apple-touch-icon" sizes="180x180" href="../Images/apple-touch-icon.png"> - <link rel="stylesheet" href="../Styles/Global.css"> - <link rel="stylesheet" href="../Styles/Reference.css"> - <script src="https://unpkg.com/papaparse@5.1.1/papaparse.min.js"></script> - <script src="../Scripts/Reference.js"></script> - </head> - - <body onload="Load()" onresize="setTableHeight()"> - <div id="title"> - <h1 onclick="window.location='..\\'">Spanish-Quizzer</h1> - </div> - - <h3 class="text">Reference Tables</h3> - - <noscript> - <h4 class="bad">You must have JavaScript enabled to run Spanish-Quizzer.</h4> - </noscript> - - <div id="controls"> - <select id="referenceSet" onchange="referenceSetChanged()"> - <option>Choose a vocab set</option> - <optgroup label="Common Words"> - <option>Verbs</option> - <option>Adjectives</option> - <option>Adverbs</option> - <option>Prepositions</option> - <option>Transitions</option> - </optgroup> - <optgroup label="Spanish 1"> - <option>Colors</option> - <option>Days</option> - <option>Months</option> - <option>Questions</option> - <option>Weather</option> - <option>Family</option> - <option>Clothes</option> - </optgroup> - <optgroup label="Spanish 2"> - <option>Nature</option> - <option>House</option> - <option>Vacation</option> - <option>Childhood</option> - <option>Professions</option> - <option>Health</option> - </optgroup> - </select> - <input type="text" id="referenceFilter" onkeyup="referenceFilterChanged()" placeholder="Search"> - </div> - - <div id="referenceTable"> - <table id="referenceTableInner"></table> - </div> - - <div class="footer"> - <div id="share" hidden> - <a href="mailto:?Subject=Spanish-Quizzer&amp;Body=https://ashermorgan.github.io/Spanish-Quizzer/Reference">Email</a>&nbsp; - <a href="http://www.facebook.com/sharer.php?u=https://ashermorgan.github.io/Spanish-Quizzer/Reference" target="_blank">Facebook</a>&nbsp; - <a href="https://twitter.com/share?url=https://ashermorgan.github.io/Spanish-Quizzer/Reference&amp;text=Spanish-Quizzer" target="_blank">Twitter</a>&nbsp; - <a href="http://reddit.com/submit?url=https://ashermorgan.github.io/Spanish-Quizzer/Reference&amp;title=Spanish-Quizzer" target="_blank">Reddit</a>&nbsp; - <a id="shareSMS" href="sms:&body=https://ashermorgan.github.io/Spanish-Quizzer/Reference" hidden>SMS</a>&nbsp; - </div> - <a href="../">Home</a>&nbsp; - <a href="../Offline">Study Offline</a>&nbsp; - <a href="javascript:document.getElementById('share').hidden = false; void 0;">Share</a>&nbsp; - </div> - </body> -</html> -\ No newline at end of file diff --git a/Scripts/Home.js b/Scripts/Home.js @@ -0,0 +1,230 @@ +// Declare global variables +let Sets; // List of parsed sets +let quizzerType = null; // Type of quizzer + + + +// Load the document +function Load() { + // Load settings + if (localStorage.getItem("darkMode") == "true") { + document.body.classList.toggle("dark"); + document.getElementById("settingsDarkMode").checked = true; + } + if (localStorage.getItem("PromptType")) { + document.getElementById("settingsPromptType").value = localStorage.getItem("PromptType"); + } + if (localStorage.getItem("InputType")) { + document.getElementById("settingsInputType").value = localStorage.getItem("InputType"); + } + if (localStorage.getItem("repeatPrompt")) { + document.getElementById("settingsRepeatPrompts").value = localStorage.getItem("repeatPrompt"); + } + + // Add event Listeners + document.addEventListener("click", function (e) { + document.getElementById('share').hidden = true; + }); + document.getElementById("quizzerInput").addEventListener("keydown", function (e) { + if (e.keyCode === 13) { + // Key was enter + if (document.getElementById("quizzerInput").readOnly) { + Continue(); + } + else { + Submit(); + } + } + }); + document.getElementById("quizzerEnter").addEventListener("click", function (e) { + if (document.getElementById("quizzerInput").readOnly) { + Continue(); + } + else { + Submit(); + } + }); + + // Load CSVs + Sets = []; + Papa.parse("Vocab/Verbs.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Verbs"] = results.data; + } + }); + Papa.parse("Vocab/Adjectives.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Adjectives"] = results.data; + } + }); + Papa.parse("Vocab/Adverbs.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Adverbs"] = results.data; + } + }); + Papa.parse("Vocab/Prepositions.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Prepositions"] = results.data; + } + }); + Papa.parse("Vocab/Transitions.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Transitions"] = results.data; + } + }); + Papa.parse("Vocab/Colors.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Colors"] = results.data; + } + }); + Papa.parse("Vocab/Days.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Days"] = results.data; + } + }); + Papa.parse("Vocab/Months.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Months"] = results.data; + } + }); + Papa.parse("Vocab/Questions.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Questions"] = results.data; + } + }); + Papa.parse("Vocab/Weather.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Weather"] = results.data; + } + }); + Papa.parse("Vocab/Family.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Family"] = results.data; + } + }); + Papa.parse("Vocab/Clothes.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Clothes"] = results.data; + } + }); + Papa.parse("Vocab/Nature.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Nature"] = results.data; + } + }); + Papa.parse("Vocab/House.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["House"] = results.data; + } + }); + Papa.parse("Vocab/Vacation.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Vacation"] = results.data; + } + }); + Papa.parse("Vocab/Childhood.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Childhood"] = results.data; + } + }); + Papa.parse("Vocab/Professions.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Professions"] = results.data; + } + }); + Papa.parse("Vocab/Health.csv", { + download: true, + complete: function(results) { + // Set verbs + Sets["Health"] = results.data; + } + }); +} + + + +// Shows specific groups of elements +function Show(div) { + // Hide all elements + document.getElementById("home").hidden = true; + document.getElementById("settings").hidden = true; + document.getElementById("verbSettings").hidden = true; + document.getElementById("vocabSettings").hidden = true; + document.getElementById("quizzerSettings").hidden = true; + document.getElementById("quizzer").hidden = true; + + // Reset settings error message + document.getElementById("settingsError").textContent = ""; + + // Show elements + switch (div) { + default: + case "home": + document.getElementById("home").hidden = false; + quizzerType = null; + break; + case "vocab": + document.getElementById("settings").hidden = false; + document.getElementById("vocabSettings").hidden = false; + document.getElementById("quizzerSettings").hidden = false; + quizzerType = "vocab"; + break; + case "verbs": + document.getElementById("settings").hidden = false; + document.getElementById("verbSettings").hidden = false; + document.getElementById("quizzerSettings").hidden = false; + quizzerType = "verbs"; + break; + case "quizzer": + document.getElementById("quizzer").hidden = false; + break; + } +} + + + +// Controls navigation when user clicks on title +function TitleClicked() { + if (!document.getElementById("quizzer").hidden) { + // Go to settings screen + Show(quizzerType); + } + else { + // Go to home screen + Show("home"); + } +} diff --git a/Scripts/Quizzer.js b/Scripts/Quizzer.js @@ -1,93 +1,70 @@ // Declare global variables -var Terms; // List of filtered terms -var Term; // Index of current term +let Terms; // List of prompts +let Term; // Index of current prompt +let Prefix; // Localhost prefix -// Start the quizzer -function Start() { - // Filter and load Sets into Terms - Terms = []; - for (var i = 0; i < setId; i++) - { - if (document.getElementById(`settingsSet-${i}`)) - { - // Get filter information - var set = document.getElementById(`settingsSetName-${i}`).value; - var filter = document.getElementById(`settingsSetFilter-${i}`).value; - - // Add filtered set - Terms.push(...ApplyFilter(Sets[set], filter)); - } +// Reads a peice of text +function Read(text, label) +{ + var msg = new SpeechSynthesisUtterance(text); + if (label.toLowerCase().includes("english")) { + msg.lang = 'en'; } - - // Shuffle terms - Terms = Shuffle(Terms); - - // Validate Terms - if (Terms.length == 0) { - document.getElementById("settingsError").textContent = "Your custom vocabulary set must contain at least one term."; - document.getElementById("settingsError").scrollIntoView(false); - return; + else if (label.toLowerCase().includes("spanish")){ + msg.lang = 'es'; } + window.speechSynthesis.speak(msg); +} - - // Validate browser for voice input - if (document.getElementById("settingsInputType").value != "Text") { - if (typeof InstallTrigger !== "undefined") { - // Browser is Firefox - alert("You must enable speech recognition in about:config.") - } - else if (!window.chrome || (!window.chrome.webstore && !window.chrome.runtime)) { - // Browser is not Googole Chrome or Microsoft (Chromium) Edge - alert("Your browser does not support voice input."); - return; - } - } - // Save terms to local storage - localStorage.setItem("terms", JSON.stringify(Terms)); +// Shuffles a list of items +function Shuffle(items) { + // Initialize variables + var currentIndex = items.length; + var temp; + var randomIndex; - // Give iOS devices ringer warning for prompt audio - if (document.getElementById("settingsPromptType").value != "Text") { - if (!!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform)) { - alert("Please make sure your ringer is on in order to hear audio prompts."); - } + // While there are more elements to shuffle + while (0 !== currentIndex) { + // Pick a remaining element + randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex--; + + // Swap the two elements + temp = items[currentIndex]; + items[currentIndex] = items[randomIndex]; + items[randomIndex] = temp; } - // Show and hide elements - document.getElementById("settings").hidden = true; - document.getElementById("quizzer").hidden = false; - - // Give the user a prompt - Term = -1; - Reset(); + // Return shuffled items + return items; } -// Resume the previous session -function Resume() { - // Validate selected sets - for (var i = 0; i < setId; i++) - { - if (document.getElementById(`settingsSet-${i}`)) - { - if (confirm("This will remove the vocab sets you have already selected. Are you sure?")) { - break; - } - else { - return; - } - } - } +// Starts the quizzer +function StartQuizzer(terms, term, prefix) { + // Set variables + Terms = terms; + Term = term - 1; + Prefix = prefix; + // Validate Terms + if (!Terms || isNaN(Term) || Term < -1 || Term > Terms.length) { + throw "Bad arguments."; + } + else if (Terms.length == 0) { + throw "Terms is empty."; + } + // Validate browser for voice input if (document.getElementById("settingsInputType").value != "Text") { if (typeof InstallTrigger !== "undefined") { // Browser is Firefox - alert("You must enable speech recognition in about:config.") + alert("You must enable speech recognition in about:config."); } else if (!window.chrome || (!window.chrome.webstore && !window.chrome.runtime)) { // Browser is not Googole Chrome or Microsoft (Chromium) Edge @@ -96,17 +73,9 @@ function Resume() { } } - // Load terms and progress - Terms = JSON.parse(localStorage.getItem("terms")); - Term = parseInt(localStorage.getItem("term")) - 1; + // Save terms to local storage + localStorage.setItem(Prefix + "terms", JSON.stringify(Terms)); - // Validate Terms - if (!Terms || Terms.length == 0 || isNaN(Term) || Term < -1 || Term > Terms.length) { - document.getElementById("settingsError").textContent = "An error occured while resuming the previous session."; - document.getElementById("settingsError").scrollIntoView(false); - return; - } - // Give iOS devices ringer warning for prompt audio if (document.getElementById("settingsPromptType").value != "Text") { if (!!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform)) { @@ -114,192 +83,12 @@ function Resume() { } } - // Show and hide elements - document.getElementById("settings").hidden = true; - document.getElementById("quizzer").hidden = false; - // Give the user a prompt Reset(); } -// Filters a vocabulary set given the filter name -function ApplyFilter(vocabSet, name) { - // Declare variables - var io; // Format: [[<output index>, <input index>]] - var value; // Format: [[<index>, [<values>], exclude?]] - - // Get filter - switch (name) { - case "All Definitions": - io = [[0,1], [1,0]]; - value = []; - break; - - case "Spanish Infinitives": - case "English to Spanish": - io = [[0,1]]; - value = []; - break; - - case "English Infinitives": - case "Spanish to English": - io = [[1,0]]; - value = []; - break; - - case "All Conjugations": - io = [[0,3], [0,5], [0,6], [0,7], [0,8], [0,9], [0,11], [0,12], [0,13], [0,14], [0,15], [0,17], [0,18], [0,19], [0,20], [0,21]]; - value = []; - break; - - case "Reverse Conjugations": - io = [[3,0], [5,0], [6,0], [7,0], [8,0], [9,0], [11,0], [12,0], [13,0], [14,0], [15,0], [17,0], [18,0], [19,0], [20,0], [21,0]]; - value = []; - break; - - case "Present Participles": - io = [[0,3]]; - value = []; - break; - - case "Present Tense": - io = [[0,5], [0,6], [0,7], [0,8], [0,9]]; - value = []; - break; - - case "Preterite Tense": - io = [[0,11], [0,12], [0,13], [0,14], [0,15]] - value = []; - break; - - case "Imperfect Tense": - io = [[0,17], [0,18], [0,19], [0,20], [0,21]]; - value = []; - break; - - case "Present Participle non-Regular": - io = [[0,3]]; - value = [[2, ["Regular"], true]]; - break; - - case "Present non-Regular": - io = [[0,5], [0,6], [0,7], [0,8], [0,9]]; - value = [[4, ["Regular"], true]]; - break; - - case "Preterite non-Regular": - io = [[0,11], [0,12], [0,13], [0,14], [0,15]]; - value = [[10, ["Regular"], true]]; - break; - - case "Imperfect non-Regular": - io = [[0,17], [0,18], [0,19], [0,20], [0,21]]; - value = [[16, ["Regular"], true]]; - break; - - case "Present Participle Regular": - io = [[0,3]]; - value = [[2, ["Regular"], false]]; - break; - - case "Present Regular": - io = [[0,5], [0,6], [0,7], [0,8], [0,9]]; - value = [[4, ["Regular"], false]]; - break; - - case "Preterite Regular": - io = [[0,11], [0,12], [0,13], [0,14], [0,15]]; - value = [[10, ["Regular"], false]]; - break; - - case "Imperfect Regular": - io = [[0,17], [0,18], [0,19], [0,20], [0,21]]; - value = [[16, ["Regular"], false]]; - break; - - case "Nouns": - io = [[0,1], [1,0]]; - value = [[2, ["Noun"], false]]; - break; - - case "Verbs": - io = [[0,1], [1,0]]; - value = [[2, ["Verb"], false]]; - break; - - case "Adjectives": - io = [[0,1], [1,0]]; - value = [[2, ["Adjective"], false]]; - break; - - default: - io = []; - value = []; - break; - } - - // Filter terms by value - var vSet = vocabSet.slice(1); // Format: same as vocabSet but without headers - for (var i = 0; i < value.length; i++) { - for (var j = 0; j < vSet.length; j++) { - if (value[i][2]) { - // Exclude values - if (value[i][1].includes(vSet[j][value[i][0]])) { - vSet.splice(j, 1); // Remove item - j--; // Adjust for the removal of an item - } - } - else { - // Include values - if (!value[i][1].includes(vSet[j][value[i][0]])) { - vSet.splice(j, 1); // Remove item - j--; // Adjust for the removal of an item - } - } - } - } - - // Filter terms by input/output - var ioSet = []; // Format: [<output type>, <output>, <input type>, <input>] - for (var i = 0; i < io.length; i++) { - for (var j = 0; j < vSet.length; j++) { - ioSet.push([vocabSet[0][io[i][0]], vSet[j][io[i][0]], vocabSet[0][io[i][1]], vSet[j][io[i][1]]]); - } - } - - // Return filtered set - return ioSet; -} - - - -// Shuffles a list of items -function Shuffle(items) { - // Initialize variables - var currentIndex = items.length; - var temp; - var randomIndex; - - // While there are more elements to shuffle - while (0 !== currentIndex) { - // Pick a remaining element - randomIndex = Math.floor(Math.random() * currentIndex); - currentIndex--; - - // Swap the two elements - temp = items[currentIndex]; - items[currentIndex] = items[randomIndex]; - items[randomIndex] = temp; - } - - // Return shuffled items - return items; -} - - - // Give the user a new prompt function Reset() { // Show and hide elements @@ -322,7 +111,7 @@ function Reset() { } // Save progress to local storage - localStorage.setItem("term", Term); + localStorage.setItem(Prefix + "term", Term); // Update progress document.getElementById("quizzerProgress").textContent = `${Term} / ${Terms.length}`; @@ -385,21 +174,6 @@ function Reset() { -// Reads a peice of text -function Read(text, label) -{ - var msg = new SpeechSynthesisUtterance(text); - if (label.toLowerCase().includes("english")) { - msg.lang = 'en'; - } - else if (label.toLowerCase().includes("spanish")){ - msg.lang = 'es'; - } - window.speechSynthesis.speak(msg); -} - - - // Processes a user's submitted responce function Submit() { // Parse responce @@ -482,7 +256,7 @@ function Continue() { } // Save terms to local storage - localStorage.setItem("terms", JSON.stringify(Terms)); + localStorage.setItem(Prefix + "terms", JSON.stringify(Terms)); // Reset quizzer Reset(); diff --git a/Scripts/Reference.js b/Scripts/Reference.js @@ -14,6 +14,9 @@ function Load() { setTableHeight(); // Add event Listeners + document.getElementById("title").addEventListener("click", function (e) { + window.location = "/"; + }); document.addEventListener("click", function (e) { document.getElementById('share').hidden = true; }); diff --git a/Scripts/Settings.js b/Scripts/Settings.js @@ -1,215 +1,36 @@ // Declare global variables -var Sets; // List of parsed sets -var setId = 0; // Next valid set id number +let setId = 0; // Next valid vocab set id number -// Load the document -function Load() { - // Load settings - if (localStorage.getItem("darkMode") == "true") { - document.body.classList.toggle("dark"); - document.getElementById("settingsDarkMode").checked = true; - } - if (localStorage.getItem("PromptType")) { - document.getElementById("settingsPromptType").value = localStorage.getItem("PromptType"); - } - if (localStorage.getItem("InputType")) { - document.getElementById("settingsInputType").value = localStorage.getItem("InputType"); - } - if (localStorage.getItem("repeatPrompt")) { - document.getElementById("settingsRepeatPrompts").value = localStorage.getItem("repeatPrompt"); - } - - // Add event Listeners - document.addEventListener("click", function (e) { - document.getElementById('share').hidden = true; - }); - document.getElementById("quizzerInput").addEventListener("keydown", function (e) { - if (e.keyCode === 13) { - // Key was enter - if (document.getElementById("quizzerInput").readOnly) { - Continue(); - } - else { - Submit(); - } - } - }); - document.getElementById("quizzerEnter").addEventListener("click", function (e) { - if (document.getElementById("quizzerInput").readOnly) { - Continue(); - } - else { - Submit(); - } - }); - - // Load CSVs - Sets = []; - Papa.parse("Vocab/Verbs.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Verbs"] = results.data; - } - }); - Papa.parse("Vocab/Adjectives.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Adjectives"] = results.data; - } - }); - Papa.parse("Vocab/Adverbs.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Adverbs"] = results.data; - } - }); - Papa.parse("Vocab/Prepositions.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Prepositions"] = results.data; - } - }); - Papa.parse("Vocab/Transitions.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Transitions"] = results.data; - } - }); - Papa.parse("Vocab/Colors.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Colors"] = results.data; - } - }); - Papa.parse("Vocab/Days.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Days"] = results.data; - } - }); - Papa.parse("Vocab/Months.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Months"] = results.data; - } - }); - Papa.parse("Vocab/Questions.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Questions"] = results.data; - } - }); - Papa.parse("Vocab/Weather.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Weather"] = results.data; - } - }); - Papa.parse("Vocab/Family.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Family"] = results.data; - } - }); - Papa.parse("Vocab/Clothes.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Clothes"] = results.data; - } - }); - Papa.parse("Vocab/Nature.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Nature"] = results.data; - } - }); - Papa.parse("Vocab/House.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["House"] = results.data; - } - }); - Papa.parse("Vocab/Vacation.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Vacation"] = results.data; - } - }); - Papa.parse("Vocab/Childhood.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Childhood"] = results.data; - } - }); - Papa.parse("Vocab/Professions.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Professions"] = results.data; - } - }); - Papa.parse("Vocab/Health.csv", { - download: true, - complete: function(results) { - // Set verbs - Sets["Health"] = results.data; - } - }); - - // Add set - AddSet(); - - // Show and hide elements - Reload(); -} - - - -// Reload the document -function Reload() { - document.getElementById("settings").hidden = false; - document.getElementById("settingsError").textContent = ""; - document.getElementById("quizzer").hidden = true; +// Update local storage +function UpdateLocalStorage() { + localStorage.setItem("darkMode", document.getElementById("settingsDarkMode").checked); + localStorage.setItem("PromptType", document.getElementById("settingsPromptType").value); + localStorage.setItem("InputType", document.getElementById("settingsInputType").value); + localStorage.setItem("repeatPrompt", document.getElementById("settingsRepeatPrompts").value); } // Add a filtered set -function AddSet() { +function AddVocabSet() { // Create row - var clone = document.getElementById("settingsSetTemplate").content.cloneNode(true); + var clone = document.getElementById("vocabSetTemplate").content.cloneNode(true); // Set row ids - clone.children[0].setAttribute("id", `settingsSet-${setId}`); - clone.getElementById("settingsSetName").setAttribute("id", `settingsSetName-${setId}`); - clone.getElementById("settingsSetFilter").setAttribute("id", `settingsSetFilter-${setId}`); + clone.children[0].setAttribute("id", `vocabSet-${setId}`); + clone.getElementById("vocabSetName").setAttribute("id", `vocabSetName-${setId}`); + clone.getElementById("vocabSetFilter").setAttribute("id", `vocabSetFilter-${setId}`); // Add remove button onclick attribute - clone.getElementById("settingsSetRemove").setAttribute("onclick", `var element = document.getElementById('settingsSet-${setId}'); element.parentNode.removeChild(element);`); + clone.getElementById("vocabSetRemove").setAttribute("onclick", `var element = document.getElementById('vocabSet-${setId}'); element.parentNode.removeChild(element);`); // Add row - document.getElementById("settingsSetsInner").appendChild(clone); + document.getElementById("vocabSetsInner").appendChild(clone); // Add filters - settingsSetChanged(document.getElementById(`settingsSetName-${setId}`)); + VocabSetChanged(document.getElementById(`vocabSetName-${setId}`)); // Increment setId setId++; // increment fileId to get a unique ID for the new element @@ -218,17 +39,13 @@ function AddSet() { // Update the filter option -function settingsSetChanged(setName) { +function VocabSetChanged(setName) { // Get filter options var items = []; switch(setName.value) { case "Verbs": - items = ["All Definitions", "Spanish Infinitives", "English Infinitives", - "All Conjugations", "Reverse Conjugations", - "Present Participles", "Present Tense", "Preterite Tense", "Imperfect Tense", - "Present Participle non-Regular", "Present non-Regular", "Preterite non-Regular", "Imperfect non-Regular", - "Present Participle Regular", "Present Regular", "Preterite Regular", "Imperfect Regular"]; + items = ["All Definitions", "Spanish Infinitives", "English Infinitives", "Reverse Conjugations"]; break; case "Adjectives": @@ -271,16 +88,297 @@ function settingsSetChanged(setName) { } // Set html - filterId = setName.id.replace("settingsSetName", "settingsSetFilter"); + filterId = setName.id.replace("vocabSetName", "vocabSetFilter"); document.getElementById(filterId).innerHTML = html; } -// Update local storage -function UpdateLocalStorage() { - localStorage.setItem("darkMode", document.getElementById("settingsDarkMode").checked); - localStorage.setItem("PromptType", document.getElementById("settingsPromptType").value); - localStorage.setItem("InputType", document.getElementById("settingsInputType").value); - localStorage.setItem("repeatPrompt", document.getElementById("settingsRepeatPrompts").value); -} -\ No newline at end of file +// Start a new session +function CreateSession() { + // Get terms and localStorage prefix + let terms; + let prefix; + if (!document.getElementById("vocabSettings").hidden) { + // Filter and load Sets into Terms + terms = []; + for (var i = 0; i < setId; i++) + { + if (document.getElementById(`vocabSet-${i}`)) + { + // Get filter information + var set = document.getElementById(`vocabSetName-${i}`).value; + var filter = document.getElementById(`vocabSetFilter-${i}`).value; + + // Add filtered set + terms.push(...ApplyVocabFilter(Sets[set], filter)); + } + } + + // Shuffle terms + terms = Shuffle(terms); + + // Set prefix + prefix = "vocab-" + } + else if (!document.getElementById("verbSettings").hidden) { + // Filter and load Sets into Terms + let filter = document.getElementById(`verbSetFilter`).value; + terms = ApplyVerbFilter(Sets["Verbs"], filter); + + // Shuffle terms + terms = Shuffle(terms); + + // Set prefix + prefix = "verb-" + } + + // Start quizzer + try { + // Start quizzer + StartQuizzer(terms, 0, prefix); + + // Show and hide elements + Show("quizzer"); + } + catch (e) { + switch (e) { + case "Terms is empty.": + document.getElementById("settingsError").textContent = "Your custom vocabulary set must contain at least one term."; + document.getElementById("settingsError").scrollIntoView(false); + break; + default: + document.getElementById("settingsError").textContent = "An error occured."; + document.getElementById("settingsError").scrollIntoView(false); + break; + } + } +} + + + +// Resume the previous session +function ResumeSession() { + // Get localStorage prefix + let prefix; + if (!document.getElementById("vocabSettings").hidden) { + prefix = "vocab-" + } + else if (!document.getElementById("verbSettings").hidden) { + prefix = "verb-" + } + + // Load terms and progress + let terms = JSON.parse(localStorage.getItem(prefix + "terms")); + let term = parseInt(localStorage.getItem(prefix + "term")); + + // Start quizzer + try { + StartQuizzer(terms, term, prefix); + + // Show and hide elements + document.getElementById("settings").hidden = true; + document.getElementById("quizzer").hidden = false; + } + catch (e) { + switch (e) { + case "Bad arguments.": + document.getElementById("settingsError").textContent = "An error occured while resuming the previous session."; + document.getElementById("settingsError").scrollIntoView(false); + break; + case "Terms is empty.": + document.getElementById("settingsError").textContent = "Your custom vocabulary set must contain at least one term."; + document.getElementById("settingsError").scrollIntoView(false); + break; + default: + document.getElementById("settingsError").textContent = "An error occured."; + document.getElementById("settingsError").scrollIntoView(false); + break; + } + } +} + + + +// Filters a vocabulary set given the filter name +function ApplyVocabFilter(vocabSet, name) { + // Declare variables + var io; // Format: [[<output index>, <input index>]] + var value; // Format: [[<index>, [<values>], exclude?]] + + // Get filter + switch (name) { + case "All Definitions": + io = [[0,1], [1,0]]; + value = []; + break; + + case "Spanish Infinitives": + case "English to Spanish": + io = [[0,1]]; + value = []; + break; + + case "English Infinitives": + case "Spanish to English": + io = [[1,0]]; + value = []; + break; + + case "Reverse Conjugations": + io = [[3,0], [5,0], [6,0], [7,0], [8,0], [9,0], [11,0], [12,0], [13,0], [14,0], [15,0], [17,0], [18,0], [19,0], [20,0], [21,0]]; + value = []; + break; + } + + // Filter terms by value + var vSet = vocabSet.slice(1); // Format: same as vocabSet but without headers + for (var i = 0; i < value.length; i++) { + for (var j = 0; j < vSet.length; j++) { + if (value[i][2]) { + // Exclude values + if (value[i][1].includes(vSet[j][value[i][0]])) { + vSet.splice(j, 1); // Remove item + j--; // Adjust for the removal of an item + } + } + else { + // Include values + if (!value[i][1].includes(vSet[j][value[i][0]])) { + vSet.splice(j, 1); // Remove item + j--; // Adjust for the removal of an item + } + } + } + } + + // Filter terms by input/output + var ioSet = []; // Format: [<output type>, <output>, <input type>, <input>] + for (var i = 0; i < io.length; i++) { + for (var j = 0; j < vSet.length; j++) { + ioSet.push([vocabSet[0][io[i][0]], vSet[j][io[i][0]], vocabSet[0][io[i][1]], vSet[j][io[i][1]]]); + } + } + + // Return filtered set + return ioSet; +} + + + +// Filters verbs set given the filter name +function ApplyVerbFilter(vocabSet, name) { + // Declare variables + var io; // Format: [[<output index>, <input index>]] + var value; // Format: [[<index>, [<values>], exclude?]] + + // Get filter + switch (name) { + case "All Conjugations": + io = [[0,3], [0,5], [0,6], [0,7], [0,8], [0,9], [0,11], [0,12], [0,13], [0,14], [0,15], [0,17], [0,18], [0,19], [0,20], [0,21]]; + value = []; + break; + + case "Reverse Conjugations": + io = [[3,0], [5,0], [6,0], [7,0], [8,0], [9,0], [11,0], [12,0], [13,0], [14,0], [15,0], [17,0], [18,0], [19,0], [20,0], [21,0]]; + value = []; + break; + + case "Present Participles": + io = [[0,3]]; + value = []; + break; + + case "Present Tense": + io = [[0,5], [0,6], [0,7], [0,8], [0,9]]; + value = []; + break; + + case "Preterite Tense": + io = [[0,11], [0,12], [0,13], [0,14], [0,15]] + value = []; + break; + + case "Imperfect Tense": + io = [[0,17], [0,18], [0,19], [0,20], [0,21]]; + value = []; + break; + + case "Present Participle non-Regular": + io = [[0,3]]; + value = [[2, ["Regular"], true]]; + break; + + case "Present non-Regular": + io = [[0,5], [0,6], [0,7], [0,8], [0,9]]; + value = [[4, ["Regular"], true]]; + break; + + case "Preterite non-Regular": + io = [[0,11], [0,12], [0,13], [0,14], [0,15]]; + value = [[10, ["Regular"], true]]; + break; + + case "Imperfect non-Regular": + io = [[0,17], [0,18], [0,19], [0,20], [0,21]]; + value = [[16, ["Regular"], true]]; + break; + + case "Present Participle Regular": + io = [[0,3]]; + value = [[2, ["Regular"], false]]; + break; + + case "Present Regular": + io = [[0,5], [0,6], [0,7], [0,8], [0,9]]; + value = [[4, ["Regular"], false]]; + break; + + case "Preterite Regular": + io = [[0,11], [0,12], [0,13], [0,14], [0,15]]; + value = [[10, ["Regular"], false]]; + break; + + case "Imperfect Regular": + io = [[0,17], [0,18], [0,19], [0,20], [0,21]]; + value = [[16, ["Regular"], false]]; + break; + + default: + io = []; + value = []; + break; + } + + // Filter terms by value + var vSet = vocabSet.slice(1); // Format: same as vocabSet but without headers + for (var i = 0; i < value.length; i++) { + for (var j = 0; j < vSet.length; j++) { + if (value[i][2]) { + // Exclude values + if (value[i][1].includes(vSet[j][value[i][0]])) { + vSet.splice(j, 1); // Remove item + j--; // Adjust for the removal of an item + } + } + else { + // Include values + if (!value[i][1].includes(vSet[j][value[i][0]])) { + vSet.splice(j, 1); // Remove item + j--; // Adjust for the removal of an item + } + } + } + } + + // Filter terms by input/output + var ioSet = []; // Format: [<output type>, <output>, <input type>, <input>] + for (var i = 0; i < io.length; i++) { + for (var j = 0; j < vSet.length; j++) { + ioSet.push([vocabSet[0][io[i][0]], vSet[j][io[i][0]], vocabSet[0][io[i][1]], vSet[j][io[i][1]]]); + } + } + + // Return filtered set + return ioSet; +} diff --git a/Styles/Home.css b/Styles/Home.css @@ -0,0 +1,21 @@ +#home h3 { + margin-bottom: 10px; +} + +#home button { + border: 1px solid var(--border-color); + width: 150px; + height: 50px; + line-height: 50px; + margin: 10px; + display: inline-block; + font-size: 15px; +} + +#home button:hover { + background-color: var(--hover-color); +} + +#home #referenceLink { + margin-top: 10px; +} diff --git a/Styles/Settings.css b/Styles/Settings.css @@ -14,24 +14,24 @@ h3 { text-align: center; } -#settingsSets { +#vocabSets { overflow-x: auto; white-space: nowrap; } -.settingsSet { +.vocabSet { padding-top: 5px; } -.settingsSetName { +.vocabSetName { width: 115px; } -.settingsSetFilter { +.vocabSetFilter { width: 160px; } -.settingsSetRemove, .dark .settingsSetRemove { +.vocabSetRemove, .dark .vocabSetRemove { cursor: pointer; color: var(--foreground-color); } @@ -41,4 +41,4 @@ h3 { margin-bottom: 5px; width: 75px; height: 25px; -} -\ No newline at end of file +} diff --git a/index.html b/index.html @@ -8,114 +8,158 @@ <link rel="icon" type="image/png" href="Images/favicon-32.png"> <link rel="apple-touch-icon" sizes="180x180" href="Images/apple-touch-icon.png"> <link rel="stylesheet" href="Styles/Global.css"> + <link rel="stylesheet" href="Styles/Home.css"> <link rel="stylesheet" href="Styles/Settings.css"> <link rel="stylesheet" href="Styles/Quizzer.css"> <script src="https://unpkg.com/papaparse@5.1.1/papaparse.min.js"></script> + <script src="Scripts/Home.js"></script> <script src="Scripts/Settings.js"></script> <script src="Scripts/Quizzer.js"></script> </head> - <body onload="Load()"> + <body onload="Load();"> <div id="title"> - <h1 onclick="Reload()">Spanish-Quizzer</h1> + <h1 onclick="TitleClicked();">Spanish-Quizzer</h1> </div> - <noscript> - <h4 class="bad"> - You must have JavaScript enabled to run Spanish-Quizzer. - </h4> - </noscript> - - <div id="settings"> - <template id="settingsSetTemplate"> - <div class="settingsSet"> - <select id="settingsSetName" class="settingsSetName" onchange="settingsSetChanged(this)"> - <optgroup label="Common Words"> - <option>Verbs</option> - <option>Adjectives</option> - <option>Adverbs</option> - <option>Prepositions</option> - <option>Transitions</option> - </optgroup> - <optgroup label="Spanish 1"> - <option>Colors</option> - <option>Days</option> - <option>Months</option> - <option>Questions</option> - <option>Weather</option> - <option>Family</option> - <option>Clothes</option> - </optgroup> - <optgroup label="Spanish 2"> - <option>Nature</option> - <option>House</option> - <option>Vacation</option> - <option>Childhood</option> - <option>Professions</option> - <option>Health</option> - </optgroup> - </select> - <select id="settingsSetFilter" class="settingsSetFilter"> - <!-- Generated by settingsSetChanged() --> - </select> - <a id="settingsSetRemove" class="settingsSetRemove">╳</a> - </div> - </template> - <div class="centered"> - Choose your settings and then click start. + <div id="home"> + <h3>What do you want to study?</h3> + + <div> + <button onclick="Show('verbs');" class="option">Conjugations</button> + <button onclick="Show('vocab');" class="option">Vocab</button> </div> + + <div id="referenceLink"> + <a href="reference.html">Or look something up in the Reference Tables</a> + </div> + </div> - <h3> - Vocabulary Sets - <button id="settingsAddSet" onclick="AddSet();">Add set</button> - </h3> - <div id="settingsSets"> - <div id="settingsSetsInner"> + <div id="settings" hidden> + <div id="verbSettings" hidden> + <div class="centered"> + Choose your settings and then click start. </div> + + <h3>Filter: + <select id="verbSetFilter"> + <option>All Conjugations</option> + <option>Reverse Conjugations</option> + <option>Present Participles</option> + <option>Present Tense</option> + <option>Preterite Tense</option> + <option>Imperfect Tense</option> + <option>Present Participle non-Regular</option> + <option>Present non-Regular</option> + <option>Preterite non-Regular</option> + <option>Imperfect non-Regular</option> + <option>Present Participle Regular</option> + <option>Present Regular</option> + <option>Preterite Regular</option> + <option>Imperfect Regular</option> + </select> + </h3> </div> - <h3>Quizzer Settings</h3> - <div> - <input type="checkbox" id="settingsDarkMode" onchange="document.body.classList.toggle('dark'); UpdateLocalStorage();"> - <label for="settingsDarkMode">Dark Mode</label> - </div> - <div> - <label for="settingsPromptType">Prompt type</label> - <select id="settingsPromptType" onchange="UpdateLocalStorage();"> - <option>Text</option> - <option>Audio</option> - <option>Both</option> - </select> - </div> - <div> - <label for="settingsInputType">Input type</label> - <select id="settingsInputType" onchange="UpdateLocalStorage();"> - <option>Text</option> - <option>Voice</option> - <option>Either</option> - </select> - </div> - <div> - <label for="settingsRepeatPrompts">Repeat missed prompts</label> - <select id="settingsRepeatPrompts" onchange="UpdateLocalStorage();"> - <option>Never</option> - <option>Immediately</option> - <option>5 prompts later</option> - <option>At the end</option> - </select> + + <div id="vocabSettings" hidden> + <template id="vocabSetTemplate"> + <div class="vocabSet"> + <select id="vocabSetName" class="vocabSetName" onchange="VocabSetChanged(this);"> + <optgroup label="Common Words"> + <option>Verbs</option> + <option>Adjectives</option> + <option>Adverbs</option> + <option>Prepositions</option> + <option>Transitions</option> + </optgroup> + <optgroup label="Spanish 1"> + <option>Colors</option> + <option>Days</option> + <option>Months</option> + <option>Questions</option> + <option>Weather</option> + <option>Family</option> + <option>Clothes</option> + </optgroup> + <optgroup label="Spanish 2"> + <option>Nature</option> + <option>House</option> + <option>Vacation</option> + <option>Childhood</option> + <option>Professions</option> + <option>Health</option> + </optgroup> + </select> + <select id="vocabSetFilter" class="vocabSetFilter"> + <!-- Generated by VocabSetChanged() --> + </select> + <a id="vocabSetRemove" class="vocabSetRemove">╳</a> + </div> + </template> + + <div class="centered"> + Choose your settings and then click start. + </div> + + <h3> + Vocabulary Sets + <button id="vocabAddSet" onclick="AddVocabSet();">Add set</button> + </h3> + + <div id="vocabSets"> + <div id="vocabSetsInner"> + </div> + </div> </div> - <div class="centered"> - <button id="settingsStart" onclick="Start()">Start</button> - <button id="settingsResume" onclick="Resume()">Resume</button> + + <div id="quizzerSettings"> + <h3>Quizzer Settings</h3> + + <div> + <input type="checkbox" id="settingsDarkMode" onchange="document.body.classList.toggle('dark'); UpdateLocalStorage();"> + <label for="settingsDarkMode">Dark Mode</label> + </div> + <div> + <label for="settingsPromptType">Prompt type</label> + <select id="settingsPromptType" onchange="UpdateLocalStorage();"> + <option>Text</option> + <option>Audio</option> + <option>Both</option> + </select> + </div> + <div> + <label for="settingsInputType">Input type</label> + <select id="settingsInputType" onchange="UpdateLocalStorage();"> + <option>Text</option> + <option>Voice</option> + <option>Either</option> + </select> + </div> + <div> + <label for="settingsRepeatPrompts">Repeat missed prompts</label> + <select id="settingsRepeatPrompts" onchange="UpdateLocalStorage();"> + <option>Never</option> + <option>Immediately</option> + <option>5 prompts later</option> + <option>At the end</option> + </select> + </div> + + <div class="centered"> + <button id="settingsStart" onclick="CreateSession();">Start</button> + <button id="settingsResume" onclick="ResumeSession();">Resume</button> + </div> + + <div id="settingsError" class="centered bad"></div> </div> - - <div id="settingsError" class="centered bad"></div> </div> - - <div id="quizzer" hidden="true"> + + + <div id="quizzer" hidden> <h3 id="quizzerProgress"></h3> <div> @@ -130,7 +174,7 @@ <div id="quizzerButtons"> <button id="quizzerEnter">Submit</button> - <button id="quizzerSkip" onclick="Reset()">Skip</button> + <button id="quizzerSkip" onclick="Reset();">Skip</button> </div> <div id="quizzerFeedback" class="bad"> @@ -140,6 +184,7 @@ <div id="quizzerCongrats" class="good"></div> </div> + <div class="footer"> <div id="share" hidden> <a href="mailto:?Subject=Spanish-Quizzer&amp;Body=https://ashermorgan.github.io/Spanish-Quizzer">Email</a>&nbsp; @@ -149,7 +194,6 @@ <a id="shareSMS" href="sms:&body=https://ashermorgan.github.io/Spanish-Quizzer" hidden>SMS</a>&nbsp; </div> <a href="Offline">Study Offline</a>&nbsp; - <a href="Reference">Reference Tables</a>&nbsp; <a href="javascript:document.getElementById('share').hidden = false; void 0;">Share</a>&nbsp; </div> </body> diff --git a/reference.html b/reference.html @@ -0,0 +1,74 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"/> + <meta name="viewport" content="width=device-width, user-scalable=no"/> + <title>Reference Tables - Spanish-Quizzer</title> + <link rel="icon" type="image/png" href="Images/favicon-32.png"> + <link rel="apple-touch-icon" sizes="180x180" href="Images/apple-touch-icon.png"> + <link rel="stylesheet" href="Styles/Global.css"> + <link rel="stylesheet" href="Styles/Reference.css"> + <script src="https://unpkg.com/papaparse@5.1.1/papaparse.min.js"></script> + <script src="Scripts/Reference.js"></script> + </head> + + <body onload="Load()" onresize="setTableHeight()"> + <div id="title"> + <h1>Spanish-Quizzer</h1> + </div> + + <h3 class="text">Reference Tables</h3> + + <noscript> + <h4 class="bad">You must have JavaScript enabled to run Spanish-Quizzer.</h4> + </noscript> + + <div id="controls"> + <select id="referenceSet" onchange="referenceSetChanged()"> + <option>Choose a vocab set</option> + <optgroup label="Common Words"> + <option>Verbs</option> + <option>Adjectives</option> + <option>Adverbs</option> + <option>Prepositions</option> + <option>Transitions</option> + </optgroup> + <optgroup label="Spanish 1"> + <option>Colors</option> + <option>Days</option> + <option>Months</option> + <option>Questions</option> + <option>Weather</option> + <option>Family</option> + <option>Clothes</option> + </optgroup> + <optgroup label="Spanish 2"> + <option>Nature</option> + <option>House</option> + <option>Vacation</option> + <option>Childhood</option> + <option>Professions</option> + <option>Health</option> + </optgroup> + </select> + <input type="text" id="referenceFilter" onkeyup="referenceFilterChanged()" placeholder="Search"> + </div> + + <div id="referenceTable"> + <table id="referenceTableInner"></table> + </div> + + <div class="footer"> + <div id="share" hidden> + <a href="mailto:?Subject=Spanish-Quizzer&amp;Body=https://ashermorgan.github.io/Spanish-Quizzer/Reference">Email</a>&nbsp; + <a href="http://www.facebook.com/sharer.php?u=https://ashermorgan.github.io/Spanish-Quizzer/Reference" target="_blank">Facebook</a>&nbsp; + <a href="https://twitter.com/share?url=https://ashermorgan.github.io/Spanish-Quizzer/Reference&amp;text=Spanish-Quizzer" target="_blank">Twitter</a>&nbsp; + <a href="http://reddit.com/submit?url=https://ashermorgan.github.io/Spanish-Quizzer/Reference&amp;title=Spanish-Quizzer" target="_blank">Reddit</a>&nbsp; + <a id="shareSMS" href="sms:&body=https://ashermorgan.github.io/Spanish-Quizzer/Reference" hidden>SMS</a>&nbsp; + </div> + <a href="/">Home</a>&nbsp; + <a href="Offline">Study Offline</a>&nbsp; + <a href="javascript:document.getElementById('share').hidden = false; void 0;">Share</a>&nbsp; + </div> + </body> +</html> +\ No newline at end of file