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 f53680008a8bf6c68aeaf6d6345f8fc894c065ec
parent 7ae260318028a0fc36318e62fe4e5e2538ab53fd
Author: AsherMorgan <59518073+AsherMorgan@users.noreply.github.com>
Date:   Sun,  1 Nov 2020 14:07:06 -0800

Fix broken keyboard shortcuts (resolves #20).

Diffstat:
Mjs/quizzer.js | 62++++++++++++++++++++++++++++++++++++++++++++------------------
Mjs/settings.js | 32++++++++++++++++----------------
2 files changed, 60 insertions(+), 34 deletions(-)

diff --git a/js/quizzer.js b/js/quizzer.js @@ -47,7 +47,7 @@ let quizzer = Vue.component("quizzer", { // Update prompts this.prompts = this.startingPrompts; this.index = this.startingIndex - 1; - + // Reset quizzer this.Reset(); } @@ -56,10 +56,27 @@ let quizzer = Vue.component("quizzer", { methods: { /** + * Handles keyup events and implements quizzer keyboard shortcuts. + */ + keyup: function(e) { + // Check if Quizzer is active + if (!this.active) { + return; + } + + if (e.keyCode === 13 && e.ctrlKey) { + this.Reset(); + } + else if (e.keyCode === 13 && !e.ctrlKey) { + this.Enter(); + } + }, + + /** * Give the user the next prompt and reset the quizzer. */ Reset: function() { - // Check is Quizzer is active + // Check if Quizzer is active if (!this.active) { return; } @@ -71,7 +88,7 @@ let quizzer = Vue.component("quizzer", { this.$refs.input.focus(); } catch { } - + // Get new prompt this.index++; if (this.index === this.prompts.length) { @@ -95,7 +112,7 @@ let quizzer = Vue.component("quizzer", { if (this.settings.inputType !== "Text") { // Create recognition object var recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition || window.mozSpeechRecognition || window.msSpeechRecognition)(); - + // Set language if (this.prompt[2].toLowerCase().includes("english")) { recognition.lang = 'en-US'; @@ -127,7 +144,7 @@ let quizzer = Vue.component("quizzer", { * Process the user's responce. */ Submit: function() { - // Check is Quizzer is active + // Check if Quizzer is active if (!this.active) { return; } @@ -185,11 +202,11 @@ let quizzer = Vue.component("quizzer", { * Process an incorrect responce and then reset the quizzer. */ Continue: function() { - // Check is Quizzer is active + // Check if Quizzer is active if (!this.active) { return; } - + // Repeat prompt switch (this.settings.repeatPrompts) { @@ -219,16 +236,16 @@ let quizzer = Vue.component("quizzer", { // Reset quizzer this.Reset(); }, - + /** * Calls Submit or Continue depending on the value of responceActive. */ Enter: function() { - // Check is Quizzer is active + // Check if Quizzer is active if (!this.active) { return; } - + if (this.responceActive) { this.Submit(); } @@ -252,32 +269,41 @@ let quizzer = Vue.component("quizzer", { } } }, - + + created: function() { + // Add keyup handler + window.addEventListener("keyup", this.keyup); + }, + + destroyed: function() { + // Remove keyup handler + window.removeEventListener("keyup", this.keyup); + }, + template: ` <div> <p id="quizzerProgress">{{ index }} / {{ prompts.length }}</p> - + <section> <label id="quizzerPromptType" for="quizzerPrompt">{{ prompt[0] }}</label> <span id="quizzerPrompt" :lang="getLang(prompt[0])" @click="Read(prompt[1], prompt[0]);">{{ settings.promptType === "Audio" ? "Click to hear again" : prompt[1] }}</span> </section> - + <section> <label id="quizzerInputType" for="quizzerInput">{{ prompt[2] }}</label> <input id="quizzerInput" ref="input" type="text" v-model="responce" :readonly="!responceActive || settings.inputType === 'Voice'" - @keyup.ctrl.enter.exact="Reset();" @keyup.enter.exact="Enter();" :lang="getLang(prompt[2])" - autocomplete="off" spellcheck="false" autocorrect="off" placeholder="Type the answer"> + :lang="getLang(prompt[2])" autocomplete="off" spellcheck="false" autocorrect="off" placeholder="Type the answer"> </section> - + <div id="quizzerButtons"> <button v-if="responceActive" :disabled="settings.inputType === 'Voice'" @click="Submit();">Submit</button> <button v-else @click="Continue();">Continue</button> <button @click="Reset();">Skip</button> </div> - + <div id="quizzerFeedback" ref="feedback" v-show="!responceActive" class="bad"> <span v-if="settings.onMissedPrompt === 'Correct me'"> - The correct answer is + The correct answer is <span id="quizzerFeedbackTerm" @click="Read(prompt[3], prompt[2]);">{{ prompt[3].toLowerCase() }}</span>. </span> <span v-if="settings.onMissedPrompt === 'Tell me'"> diff --git a/js/settings.js b/js/settings.js @@ -94,7 +94,7 @@ let settings = Vue.component("settings", { getTenseSubjects: function(index) { // Set default filters let filters = {"All Subjects":true, "Yo":true, "Tú":true, "Él":true, "Nosotros":true, "Ellos":true} - + if (this.verbFilters[index].tense === "Present Participles") { // Override filters filters["Yo"] = false; @@ -102,7 +102,7 @@ let settings = Vue.component("settings", { filters["Él"] = false; filters["Nosotros"] = false; filters["Ellos"] = false; - + // Reset subject this.verbFilters[index].subject = "All Subjects"; } @@ -126,7 +126,7 @@ let settings = Vue.component("settings", { filters["Nouns"] = false; filters["Verbs"] = false; break; - + case "Adjectives": filters["Nouns"] = false; filters["Verbs"] = false; @@ -145,18 +145,18 @@ let settings = Vue.component("settings", { filters["Nouns"] = false; filters["Verbs"] = false; break; - + case "Colors": filters["Nouns"] = false; filters["Verbs"] = false; break; - + case "Days": case "Months": filters["Adjectives"] = false; filters["Verbs"] = false; break; - + case "Weather": case "Professions": filters["Adjectives"] = false; @@ -166,7 +166,7 @@ let settings = Vue.component("settings", { case "Clothes": filters["Verbs"] = false; break; - + case "Nature": case "House": case "Vacation": @@ -215,7 +215,7 @@ let settings = Vue.component("settings", { alert("Your custom vocabulary set must contain at least one term."); return; } - + // Start quizzer this.$emit("start-session", prompts, promptIndex, this.settings); }, @@ -309,7 +309,7 @@ let settings = Vue.component("settings", { } catch { return; } if (!parsedSettings) { return; } - + // Load settings if (parsedSettings.promptType && ["Text", "Audio", "Both"].includes(parsedSettings.promptType)) { this.settings.promptType = parsedSettings.promptType; @@ -327,9 +327,9 @@ let settings = Vue.component("settings", { destroyed: function() { // Remove keyup handler - window.removeEventListener("keydown", this.keyup); + window.removeEventListener("keyup", this.keyup); }, - + template: ` <div class="settings" ref="container"> <div class="verbSettings" v-show="category === 'verbs'"> @@ -339,7 +339,7 @@ let settings = Vue.component("settings", { Verb Filters <button @click="AddFilter();">Add Filter</button> </h2> - + <div v-for="(filter, index) in verbFilters" class="filter"> <select v-model="filter.tense"> <option>All Tenses</option> @@ -539,7 +539,7 @@ function ApplyVerbFilter(terms, filterInfo) { filters.push({ tense: filter.tense.toLowerCase(), type: filter.type, subject: filter.subject, direction: filter.direction }); } } - + // Expand "All Subjects" filters for (let filter of filters) { if (filter.subject.toLowerCase() === "all subjects" && filter.tense !== "present participles") { @@ -691,7 +691,7 @@ function ApplyVerbFilter(terms, filterInfo) { throw `Unrecognized subject: ${filter.subject}.`; } break; - + default: throw `Unrecognized tense: ${filter.tense}.`; } @@ -731,13 +731,13 @@ function Shuffle(items) { 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];