├── favicon.ico ├── index.html ├── log.html ├── style.css ├── guide.html └── script.js /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CollinBrennan/GenGo/HEAD/favicon.ico -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | GenGo 6 | 7 | 28 | 29 | 30 | 31 |

32 | Gengo word generator has been retired and moved to 33 | Wrdz. 34 |

35 | 36 | 37 | -------------------------------------------------------------------------------- /log.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | GenGo 7 | 8 | 9 | 10 | 11 | 12 |
13 | GenGo 14 | Guide 15 | Change Log 16 | GitHub 17 |
18 | 19 |
20 |

Change Log 2020

21 | 22 |
23 |

May 12th

24 |

-Fixed a bug where affricates wouldn't display correctly

25 | 26 |
27 |

May 11th

28 |

-Fixed a bug where IPA buttons would only add a character at the end of a text field. 29 |
-Fixed a bug where input fields would be too small while the IPA chart was open. 30 |
31 |
-Added ability to comment out groups (//) and letter(s) (/) 32 |
-Added ability to use floating points as weights to make characters less likely to be picked 33 |

34 | 35 |
36 |

May 10th

37 |

Public release.

38 | 39 |
40 |
41 | 42 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | html { 2 | overflow-y: scroll; 3 | } 4 | 5 | body { 6 | background-color: #FCFCFC; 7 | font-family: arial; 8 | font-size: 16px; 9 | font-weight: bold; 10 | text-align: center; 11 | margin: 0; 12 | padding: 0; 13 | } 14 | 15 | header { 16 | background-color: #333; 17 | padding-top: 10px; 18 | padding-bottom: 10px; 19 | font-size: 18px; 20 | } 21 | 22 | nav { 23 | font-size: 18px; 24 | margin-top: 16px; 25 | } 26 | 27 | nav > a { 28 | color: #333; 29 | margin: 10px; 30 | } 31 | 32 | a { 33 | text-decoration: none; 34 | color: #F67280; 35 | } 36 | 37 | header > a { 38 | color: white; 39 | padding: 4px; 40 | } 41 | 42 | footer { 43 | font-weight: normal; 44 | margin-bottom: 16px; 45 | } 46 | 47 | .content { 48 | max-width: 960px; 49 | margin-left: auto; 50 | margin-right: auto; 51 | margin-top: 16px; 52 | margin-bottom: 16px; 53 | } 54 | 55 | .textareas { 56 | width: 100%; 57 | display: flex; 58 | flex-wrap: wrap; 59 | align-items: stretch; 60 | align-content: flex-start; 61 | justify-content: space-between; 62 | } 63 | 64 | .box { 65 | flex-grow: 2; 66 | margin-left: 4px; 67 | margin-right: 4px; 68 | margin-bottom: 4px; 69 | } 70 | 71 | textarea, input, button { 72 | border-radius: 10px; 73 | border: 1px solid #AAA; 74 | outline: none; 75 | } 76 | 77 | textarea:focus, input[type=text]:focus, input[type=number]:focus { 78 | border: 1px dotted #F67280; 79 | } 80 | 81 | textarea, input[type=text], input[type=number] { 82 | font-size: 15px; 83 | } 84 | 85 | textarea { 86 | font-family: monospace; 87 | position: relative; 88 | resize: none; 89 | width: 98%; 90 | height: 200px; 91 | padding: 4px; 92 | } 93 | 94 | .inputs > div { 95 | display: flex; 96 | justify-content: center; 97 | align-items: center; 98 | margin-bottom: 8px; 99 | margin-left: 4px; 100 | margin-right: 4px; 101 | } 102 | 103 | .list > label, .options > label { 104 | margin-right: 4px; 105 | } 106 | 107 | .list > input { 108 | flex: 1; 109 | } 110 | 111 | .options { 112 | display: flex; 113 | flex-wrap: wrap; 114 | } 115 | 116 | .options > div { 117 | margin-right: 15px; 118 | } 119 | 120 | input { 121 | -webkit-appearance: none; 122 | padding: 4px; 123 | } 124 | 125 | input[type=submit], button { 126 | cursor: pointer; 127 | border: none; 128 | border-radius: 5px; 129 | background-color: #333; 130 | color: white; 131 | font-weight: bold; 132 | padding: 8px; 133 | } 134 | 135 | input[type=submit]:active, button:active { 136 | background-color: #DDD; 137 | } 138 | 139 | 140 | input[type=checkbox] { 141 | cursor: pointer; 142 | vertical-align: middle; 143 | margin-bottom: 4px; 144 | top: 0; 145 | left: 0; 146 | width: 18px; 147 | height: 18px; 148 | border-radius: 50%; 149 | } 150 | 151 | input[type=checkbox]:checked { 152 | background-color: #333; 153 | } 154 | 155 | /* IPA stuff */ 156 | table { 157 | border-top: 2px dotted lightgrey; 158 | border-left: 2px dotted lightgrey; 159 | margin-left: auto; 160 | margin-right: auto; 161 | width: 100%; 162 | font-size: 16px; 163 | margin-top: 4px; 164 | border-radius: 10px; 165 | } 166 | 167 | tbody > tr:last-child > td:last-child { 168 | border-bottom-right-radius: 10px; 169 | } 170 | 171 | .letter, .punct, th { 172 | width: 32px; 173 | height: 32px; 174 | border-bottom: 2px dotted lightgrey; 175 | border-right: 2px dotted lightgrey; 176 | } 177 | 178 | .letter, .punct { 179 | font-size: 16px; 180 | cursor: pointer; 181 | background-color: inherit; 182 | color: #F67280; 183 | font-weight: normal; 184 | } 185 | 186 | .punct { 187 | font-size: 18px; 188 | font-weight: bold; 189 | } 190 | 191 | .letter:hover, .punct:hover { 192 | background-color: #F5F5F5; 193 | } 194 | 195 | #divider { 196 | margin-top: 16px; 197 | margin-bottom: 16px; 198 | } 199 | 200 | hr { 201 | border: none; 202 | border-top: 2px dotted lightgrey; 203 | margin: 0; 204 | padding: 0; 205 | } 206 | 207 | #info { 208 | font-weight: normal; 209 | font-style: italic; 210 | padding-top: 6px; 211 | padding-bottom: 4px; 212 | } 213 | 214 | #lexicon { 215 | font-weight: normal; 216 | display: block; 217 | white-space: pre-wrap; 218 | margin: 4px; 219 | margin-top: 6px; 220 | margin-bottom: 16px; 221 | } 222 | 223 | /* Guide CSS */ 224 | p, ul, blockquote, h1, h2, h3, h4, h5, h6 { 225 | text-align: left; 226 | } 227 | 228 | p, ul, blockquote { 229 | font-weight: normal; 230 | } 231 | 232 | blockquote { 233 | background-color: #EEE; 234 | max-width: 480px; 235 | font-family: monospace; 236 | } 237 | 238 | ul { 239 | list-style: none; 240 | } 241 | 242 | .c1 { 243 | color: #F67280; 244 | } 245 | 246 | .c2 { 247 | color: #C06C84; 248 | } 249 | 250 | .c3 { 251 | color: #355C7D; 252 | } 253 | 254 | .c4 { 255 | color: #F8B195; 256 | } 257 | 258 | .hide { 259 | visibility: hidden; 260 | } -------------------------------------------------------------------------------- /guide.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | GenGo 7 | 8 | 9 | 10 | 11 | 12 |
13 | GenGo 14 | Guide 15 | Change Log 16 | GitHub 17 |
18 | 19 | 26 | 27 |
28 | 29 |
30 | 31 |

About

32 |

GenGo is generator that makes words from different groups of characters. It is most often used for constructed languages and worldbuilding. It's good for anything from creating a lexicon for your conlang to names for your fictional population.

33 | 34 |
35 | 36 |

Characters

37 |

Characters are the letters or symbols that make up your words.

38 |

Syntax

39 | 40 |

The basic syntax for a character group is...

41 |
X: sh å Д β タ 語 음,
42 | 48 |

Character groups can be written on the same line or across several lines, as long as they are seperated by a comma.

49 | 50 |

Weights

51 |

You can assign weight to a character to make it more likely to be picked using an asterisk followed by a number.

52 |

In this example...

53 |
54 | C: p t k m n s w*5 l j 55 |
56 |

...the letter 'w' is 5 times more likely to be picked than the rest of the characters individually.

57 |

Since characters have a default weight of 1, you can use a decimal to make characters less likely to be picked...

58 |
C: p t k m n s w*.25 l j
59 |

Giving a character a weight of 0 still gives it a chance of being picked. If you don't want a character to be picked at all, you can comment it out. 60 | 61 |

Commenting

62 |

Sometimes you might want to remove characters from a group without actually deleting them from the text field. To do this, you can use a slash to "comment" them out. 63 |

For example, this...

64 |
C: p t k m n s /w l j
65 |

Gets interpreted as this...

66 |
C: p t k m n s l j
67 |

To comment out a group entirely, just put the slash before the name of the group...

68 |
/C: p t k m n s w l j
69 |

Commenting out also works in rewrites, patterns, and filters.

70 | 71 | 72 |
73 | 74 |

Patterns

75 |

Patterns are the syllable structure of your words. If the pattern contains the name of a character group, the character will be replaced by one of the characters in its group at random. Multiple patterns can be used but need to be seperated by commas.

76 |

For example, if you had the pattern 'CVC' and these character groups...

77 |
C: p t k,
V: a i
78 |

...each character in the pattern would be replaced with a random character within its group...

79 | 84 |

...and the final outputted word would be 'kat'.

85 |

If a pattern contains a character that isn't the name of a group, the character itself is added to the word. For example, if you had the same characters from the above example, but instead had the pattern 'CVs'...

86 | 91 |

...'s' in the pattern isn't the name of a group so it is just added to the word 'kas'.

92 |

Parentheses ( )

93 |

Any part of a pattern within parantheses has a chance to be filtered out.

94 |

The pattern 'CV(C)' can output...

95 | 99 |

Brackets [ ]

100 |

Any part of a pattern within brackets picks from one of the choices seperated by spaces.

101 |

The pattern 'CV[C s]' can output...

102 | 106 |

Brackets and parentheses can both be nested any amount of times...

107 | 112 | 119 | 120 |
121 | 122 |

Rewrites

123 |

Sometimes there are certain combinations of characters that you don't want in your words. That's where rewrites come in.

124 | 125 |

Syntax

126 |

Rewrites are written very similarly to character groups...

127 |
mn: m n,
128 | 134 |

For example, if you had the word 'samna' and the cluster rewrite from above...

135 | 139 | 140 |

Tips

141 |

If you want the cluster to just be removed from the word, don't enter anything for the replacement characters. Make sure to still seperate it with a comma if there are multiple rewrites...

142 |
143 | nm: ,
144 | mn: m n 145 |
146 | 149 |

(Not yet implemented) Rewrites and filters also accept group names. If we had the pattern 'CVVC' and this rewrite...

150 |
151 | VV: V 152 |
153 | 156 |

(Not yet implemented) If you wanted a character that is also a name of a character group, you can put it in double quotes...

157 |
158 | VV: "V" 159 |
160 | 163 |

You can also use character weights in rewrites.

164 |
165 | 166 | 167 |

Filters & Options

168 |

Filters - If a word contains any of the characters or clusters, the whole word will be removed from the final word list.

169 |

Words - Total number of words to be generated.

170 |

Syllable min and max - The minimum and maximum number of patterns allowed in a word

171 |

Duplicates - Removes any duplicates in the final word list. The more complicated your words can be, the less likely duplicates are to be generated

172 |

List - Displays each word on a new line instead of a paragraph

173 |

IPA - Stands for 'International Phonetic Alphabet', which you can learn more about here 174 |


175 | 176 |
177 | 178 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | // Ideas: 2 | // -rewrite boxes in the correct way after forms are submitted 3 | // -max possible words counter 4 | // -Remove spaces from final word 5 | // -night mode 6 | // -add seperate IPA chart for mobile, dont add table head just make it a group of characters 7 | // -add titles to IPA symbols 8 | // -made comments italicized 9 | 10 | // To Add: 11 | // -add LITERAL notation ("C")V(N), C"V"N 12 | // -make phonetic groups possible in replacemenets and filters (VV: V) 13 | // -floating point weights (fix the equation in general) 14 | // -favicon 15 | 16 | // To Fix: 17 | // -Affricate buttons put cursor after the first letter of the affricate 18 | 19 | function generate( 20 | _min, 21 | _max, 22 | _count, 23 | _patterns, 24 | _filters, 25 | _rewrites, 26 | _characters, 27 | _duplicates, 28 | _charWeights, 29 | _writeWeights 30 | ) { 31 | // Variables 32 | const min = _min 33 | const max = _max 34 | const count = _count 35 | const patterns = unique(_patterns) 36 | const filters = unique(_filters) 37 | const rewrites = new Map(_rewrites) 38 | const characters = new Map(_characters) 39 | const duplicates = _duplicates 40 | 41 | const charWeights = new Map(_charWeights) 42 | const writeWeights = new Map(_writeWeights) 43 | 44 | let lexicon = [] 45 | // Test if patterns are valid 46 | if (patterns.length < 1) {return lexicon} 47 | 48 | // Functions 49 | function unique(list) { 50 | return Array.from(new Set(list)) 51 | } 52 | 53 | function random(min, max) { 54 | return Math.floor(Math.random() * (max - min)) + min 55 | } 56 | 57 | function weightedRandom(items, weights) { 58 | 59 | function float(min, max) { 60 | return Math.random() * (max - min) + min 61 | } 62 | 63 | const sum = weights.reduce((a, b) => a + b, 0) 64 | let ran = float(0, sum) 65 | for (let i = 0; i < items.length; i++) { 66 | if (ran < weights[i]) { 67 | return [items[i]] 68 | } 69 | else { 70 | ran -= weights[i] 71 | } 72 | } 73 | } 74 | // Loop 75 | while (lexicon.length < count) { 76 | // Create the template 77 | let syllableCount = random(min, max + 1) 78 | let template = '' 79 | for (let i = 0; i < syllableCount; i++) { 80 | template += patterns[random(0, patterns.length)] 81 | } 82 | // Pick random letter(s) in brackets 83 | const bRegex = /\[([^\[]*?)\]/ 84 | while (bRegex.test(template)) { 85 | let matches = bRegex.exec(template)[1].split(/\s+/) 86 | template = template.replace(bRegex, matches[random(0, matches.length)]) 87 | } 88 | // Make word from template 89 | let word = '' 90 | for (let key of template) { 91 | let letters = characters.get(key) 92 | let weights = charWeights.get(key) 93 | word += letters && letters.length > 0 ? weightedRandom(letters, weights) : key 94 | } 95 | // Randomly keep or delete letters in parentheses 96 | const pRegex = /\(([^\(]*?)\)/ 97 | while (pRegex.test(word)) { 98 | word = word.replace(pRegex, random(0, 2) === 1 ? pRegex.exec(word)[1] : '') 99 | } 100 | // Rewrites 101 | for (let key of rewrites.keys()) { 102 | let letters = rewrites.get(key) 103 | let weights = writeWeights.get(key) 104 | while (word.includes(key)) { 105 | word = word.replace(key, letters.length > 0 ? weightedRandom(letters, weights) : '') 106 | } 107 | } 108 | // Filters 109 | let push = true 110 | for (let filter of filters) { 111 | if (word.includes(filter)) { 112 | push = false 113 | } 114 | } 115 | // Add word to lexicon 116 | if (push) { 117 | lexicon.push(word) 118 | } 119 | } 120 | // Remove duplicates 121 | if (!duplicates) { 122 | lexicon = unique(lexicon) 123 | } 124 | // Return 125 | console.log('Characters:', characters, '\n') 126 | console.log('Character Weights:', charWeights, '\n') 127 | console.log('Rewrites:', rewrites, '\n') 128 | console.log('Rewrite Weights:', writeWeights, '\n') 129 | console.log('Filters:', filters, '\n') 130 | console.log('Patterns:', patterns, '\n') 131 | return lexicon 132 | } 133 | 134 | // Format inputs and display list to the page 135 | function takeInput() { 136 | // Functions 137 | function format(element, regex) { 138 | const array = [] 139 | // Remove comments 140 | element = element.replace(/\/[^\s,]*/g, '') 141 | // Create the arrays 142 | const matches = element.match(regex) 143 | if (matches !== null) { 144 | for (match of matches) { 145 | let items = [] 146 | match = match.replace(/\(|\)|\[|\]|"|:/g, ' ') 147 | match = match.match(/\S+/g) 148 | let name = match[0] 149 | let contents = match.slice(1, match.length) 150 | array.push([name, contents]) 151 | } 152 | } 153 | return array 154 | } 155 | 156 | function listFormat(element) { 157 | // Remove comments 158 | element = element.replace(/\/[^\s,]*/g, '') 159 | // Split list 160 | const regex = /[^\s,][^,]*[^\s,]|[^\s,]/g 161 | return element.match(regex) 162 | } 163 | 164 | function makeWeights(input) { 165 | const array = [] 166 | const regex = /(.+)\*((\d+\.*\d*)|(\.\d+))/ 167 | for (item of input) { 168 | let pair = [] 169 | let weights = [] 170 | let contents = item[1] 171 | pair.push(item[0]) 172 | for (i in contents) { 173 | if (regex.test(contents[i])) { 174 | weights.push(Number(regex.exec(contents[i])[2])) 175 | item[1][i] = regex.exec(contents[i])[1] 176 | } else { 177 | weights.push(1) 178 | } 179 | } 180 | pair.push(weights) 181 | array.push(pair) 182 | } 183 | return array 184 | } 185 | 186 | // Variables 187 | const myMin = Number(document.getElementById("min").value) 188 | const myMax = Number(document.getElementById("max").value) 189 | const myCount = Number(document.getElementById("words").value) 190 | const myPatterns = listFormat(document.getElementById("patterns").value) 191 | const myFilters = listFormat(document.getElementById("filters").value) 192 | const myRewrites = format(document.getElementById("rewrites").value, /[^\s,]+\s*:[^,]*/g) 193 | const myCharacters = format(document.getElementById("characters").value, /[^\s,]\s*:[^,]*/g) 194 | const myDuplicate = document.getElementById("duplicates").checked 195 | 196 | const myCharWeights = makeWeights(myCharacters) 197 | const myWriteWeights = makeWeights(myRewrites) 198 | 199 | const newLine = document.getElementById("new").checked 200 | 201 | const myLexicon = generate( 202 | myMin, 203 | myMax, 204 | myCount, 205 | myPatterns, 206 | myFilters, 207 | myRewrites, 208 | myCharacters, 209 | myDuplicate, 210 | myCharWeights, 211 | myWriteWeights 212 | ) 213 | // Fix form inputs 214 | myMax < myMin ? document.getElementById("max").value = myMin : null 215 | // Clear words 216 | const list = document.getElementById("lexicon") 217 | list.innerHTML = '' 218 | // Display words 219 | for (item of myLexicon) { 220 | list.innerHTML += item + (newLine ? '\n' : ' ') 221 | } 222 | // Information 223 | const divider = document.getElementById("divider") 224 | divider.style.display = "block" 225 | const info = document.getElementById("info") 226 | info.innerHTML = '~ ' + myLexicon.length + ' words generated ~' 227 | } 228 | 229 | 230 | // Copy list 231 | function copyToClipboard() { 232 | const copy = document.getElementById("copy") 233 | const list = document.getElementById("lexicon").innerHTML 234 | let info = document.getElementById("info") 235 | if (list !== '') { 236 | navigator.clipboard.writeText(list) 237 | info.innerHTML = "~ Copied to clipboard! ~" 238 | } 239 | } 240 | 241 | // Test if user is on mobile device 242 | const onMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) 243 | 244 | // Show IPA chart 245 | function showIPA() { 246 | const ipa = !onMobile ? document.getElementById("ipaChart") : document.getElementById("ipaMobile") 247 | const button = document.getElementById("ipa") 248 | if (ipa.style.display !== "block") { 249 | ipa.style.display = "block" 250 | button.innerHTML = "IPA" 251 | } else { 252 | ipa.style.display = "none" 253 | button.innerHTML = "IPA" 254 | } 255 | } 256 | 257 | // If number is greater than max number, set number to max 258 | const inputs = document.getElementsByTagName("input") 259 | const numbers = [] 260 | for (let input of inputs) { 261 | if (input.type === "number") { 262 | numbers.push(input) 263 | } 264 | } 265 | for (let number of numbers) { 266 | number.addEventListener("input", () => { 267 | let max = number.max 268 | if (Number(number.value) > Number(max)) { 269 | number.value = max 270 | } 271 | }) 272 | } 273 | 274 | // When symbol is clicked, add it to the current focused input 275 | const letters = document.getElementsByClassName("letter") 276 | for (let letter of letters) { 277 | letter.addEventListener("mousedown", () => { 278 | let active = document.activeElement 279 | if (active.id === "characters" || active.id === "rewrites" || active.id === "patterns" || active.id === "filters") { 280 | let start = active.selectionStart; 281 | let end = active.selectionEnd; 282 | if (start || start <= '0') { 283 | active.value = active.value.substring(0, start) 284 | + letter.innerHTML 285 | + active.value.substring(end, active.value.length); 286 | } 287 | let newStart = start + letter.innerHTML.length 288 | active.setSelectionRange(newStart, newStart) 289 | } 290 | event.preventDefault() 291 | }) 292 | } 293 | 294 | const puncts = document.getElementsByClassName("punct") 295 | for (let punct of puncts) { 296 | punct.addEventListener("mousedown", () => { 297 | let active = document.activeElement 298 | if (active.id === "characters" || active.id === "rewrites" || active.id === "patterns" || active.id === "filters") { 299 | let start = active.selectionStart; 300 | let end = active.selectionEnd; 301 | console.log(start) 302 | if (start || start <= '0') { 303 | active.value = active.value.substring(0, start) 304 | + punct.getAttribute("value") 305 | + active.value.substring(end, active.value.length); 306 | } 307 | active.setSelectionRange(start + 1, start + 1) 308 | } 309 | event.preventDefault() 310 | }) 311 | } 312 | 313 | // Fix input's position if scrolled too far down 314 | if (!onMobile) { 315 | function resetInputs () { 316 | document.getElementById("characters").style.position = "initial" 317 | document.getElementById("characters").style.minWidth = "initial" 318 | document.getElementById("characters").style.left = "initial" 319 | document.getElementById("characters").style.top = "initial" 320 | 321 | document.getElementById("rewrites").style.position = "initial" 322 | document.getElementById("rewrites").style.minWidth = "initial" 323 | document.getElementById("rewrites").style.left = "initial" 324 | document.getElementById("rewrites").style.top = "initial" 325 | 326 | document.getElementById("patterns").style.position = "initial" 327 | document.getElementById("patterns").style.minWidth = "initial" 328 | document.getElementById("patterns").style.maxWidth = "initial" 329 | document.getElementById("patterns").style.left = "initial" 330 | document.getElementById("patterns").style.top = "initial" 331 | 332 | document.getElementById("filters").style.position = "initial" 333 | document.getElementById("filters").style.minWidth = "initial" 334 | document.getElementById("filters").style.maxWidth = "initial" 335 | document.getElementById("filters").style.left = "initial" 336 | document.getElementById("filters").style.top = "initial" 337 | } 338 | 339 | function fixInput() { 340 | let active = document.activeElement 341 | if ( 342 | active.id === "characters" 343 | || active.id === "rewrites" 344 | || active.id === "patterns" 345 | || active.id === "filters" 346 | ) { 347 | if (document.getElementById("ipaChart").style.display === "block") { 348 | if (window.scrollY > 300 && window.scrollY < 1200) { 349 | active.style.position = "initial" 350 | let calculate = window.innerWidth/2 - (active.id === "rewrites" ? active.offsetWidth : active.innerWidth)/2 351 | active.style.left = calculate + 'px' 352 | active.style.top = "16px" 353 | active.style.minWidth = "480px" 354 | active.style.maxWidth = "480px" 355 | active.style.position = "fixed" 356 | } else { 357 | resetInputs() 358 | } 359 | } else { 360 | resetInputs() 361 | } 362 | } else { 363 | resetInputs() 364 | } 365 | } 366 | window.setInterval(fixInput, 250) 367 | } 368 | 369 | --------------------------------------------------------------------------------