reference.js (7514B)
1 // reference-tables component 2 const referenceTables = Vue.component("referenceTables", { 3 props: { 4 data: { 5 type: Object, 6 default: {}, 7 } 8 }, 9 data: function() { 10 return { 11 category: "Choose a category", 12 conjugationColors: true, 13 tableTheme: null, 14 table: null, 15 } 16 }, 17 watch: { 18 category: function(value) { 19 // Update table 20 this.table.setData({ 21 headers: this.tableData[value][0], 22 body: this.tableData[value].slice(1), 23 bodyClasses: value === "verbs" && this.conjugationColors ? this.conjugationColorClasses : null, 24 }); 25 this.table.sort(0, true); 26 }, 27 tableTheme: function(value) { 28 // Update table theme 29 this.table.theme = value; 30 }, 31 conjugationColors: function(value) { 32 // Update table body classes 33 this.table.setData({ 34 bodyClasses: this.category === "verbs" && value ? this.conjugationColorClasses : null, 35 }); 36 } 37 }, 38 computed: { 39 /** 40 * The color classes for verb conjugation cells 41 */ 42 conjugationColorClasses: function() { 43 let result = []; 44 for (let row in this.tableData.verbs) { 45 result.push([]); 46 for (let column = 0; column < this.tableData.verbs[row].length; column++) { 47 // Check if cell is a type cell 48 if (!this.tableData.verbs[0][column].includes("Type")) { 49 if (column > 0) { 50 // Cell isn't a type cell, use color class of previous cell 51 result[row].push(result[row][column-1]); 52 } 53 else { 54 // Cell is in the first column 55 result[row].push("normal"); 56 } 57 } 58 59 // Get color class 60 else if (this.tableData.verbs[row][column].includes("Irregular")) { 61 result[row].push("irregular"); 62 } 63 else if (this.tableData.verbs[row][column].includes("Regular")) { 64 result[row].push("regular"); 65 } 66 else if (this.tableData.verbs[row][column].includes("Stem Changing") || this.tableData.verbs[row][column].includes("Orthographic")) { 67 result[row].push("nonregular"); 68 } 69 else { 70 result[row].push("normal"); 71 } 72 } 73 } 74 return result.slice(1); 75 }, 76 /** 77 * The data used by the table 78 */ 79 tableData: function() { 80 return {...{"Choose a category":[]}, ...this.data}; 81 }, 82 }, 83 methods: { 84 /** 85 * Search for a string in the table 86 * @param {Object} args - The event args (optional) 87 */ 88 search: function(args) { 89 if (args) args.target.blur(); 90 this.$refs.search.blur(); 91 this.table.search(this.$refs.search.value); 92 }, 93 94 /** 95 * Set the table height. 96 */ 97 setTableHeight: function() { 98 this.$refs.referenceTable.style.height = `${window.innerHeight - this.$refs.referenceTable.offsetTop - 10}px`; 99 }, 100 101 /** 102 * Get the language code that matches a label. 103 * @param {String} label - The label. 104 * @returns {String} - The language code ("en", "es", etc.) 105 */ 106 getLang: function(label) { 107 if (label.toLowerCase().includes("english") || label.toLowerCase().includes("type") || label.toLowerCase().includes("category")) { 108 return "en"; 109 } 110 else { 111 return "es"; 112 } 113 }, 114 115 /** 116 * Read a peice of text. 117 * @param {String} text - The text to read. 118 * @param {String} label - The language of the text. 119 */ 120 Read: function(text, label) 121 { 122 var msg = new SpeechSynthesisUtterance(text); 123 msg.lang = this.getLang(label); 124 window.speechSynthesis.speak(msg); 125 }, 126 127 /** 128 * Handle a keyup event (implements keyboard shortcuts). 129 * @param {object} e - The event args. 130 */ 131 keyup: function(e) { 132 if (this._inactive || e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) return; 133 if (e.keyCode === 13 && this.$refs.search === document.activeElement) this.search(); 134 if (this.$refs.search === document.activeElement) return; 135 if (e.key === "h" || e.key == "/") { 136 try { 137 this.$refs.search.focus(); 138 } catch {} 139 } 140 if (e.key === "c") this.category = "verbs" 141 if (e.key === "v") this.category = "vocab"; 142 if (e.key === ",") this.$router.push({name:"settings", params:{referer:this.$route.name}}); 143 }, 144 }, 145 mounted: function() { 146 // Generate table 147 this.table = new DataTable(".referenceTable", { 148 sortable: true, 149 unsortable: false, 150 bodyEventHandlers: { 151 click: (row, column, args) => { 152 this.Read(this.tableData[this.category][row + 1][column], this.tableData[this.category][0][column]); 153 } 154 } 155 }); 156 157 // Set table height 158 this.setTableHeight(); 159 160 // Add onresize handler 161 window.addEventListener("resize", this.setTableHeight); 162 163 // Add keyup handler 164 window.addEventListener("keyup", this.keyup); 165 }, 166 destroyed: function() { 167 // Remove onresize handler 168 window.removeEventListener("resize", this.setTableHeight); 169 170 // Remove keyup handler 171 window.removeEventListener("keyup", this.keyup); 172 }, 173 activated: function() { 174 // Update settings 175 let settings = getSettings(); 176 this.conjugationColors = settings.conjugationColors; 177 this.tableTheme = settings.darkTheme ? "basic-dark" : "basic-light"; 178 }, 179 template: ` 180 <div> 181 <div class="referenceTableControls"> 182 <select aria-label="Vocab Set" v-model="category"> 183 <option>Choose a category</option> 184 <option value="verbs">Conjugations</option> 185 <option value="vocab">Vocab</option> 186 </select> 187 <div> 188 <input type="text" ref="search" aria-label="Search" placeholder="Search" autocomplete="off" autocorrect="off"> 189 <button @click="search">Search</button> 190 </div> 191 </div> 192 193 <div class="referenceTable" ref="referenceTable"> 194 </div> 195 </div> 196 ` 197 }); 198 199 200 201 // reference-page component 202 const referencePage = Vue.component("referencePage", { 203 template: ` 204 <div class="referencePage"> 205 <page-header icon1="arrow-left" label1="Back" @click1="$emit('back');" 206 icon2="settings" label2="Settings" @click2="$router.push({name:'settings', params:{referer:$route.name}})"></page-header> 207 <main> 208 <reference-tables :data="this.$root.$data.data"></reference-tables> 209 </main> 210 </div> 211 `, 212 });