-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
173 lines (157 loc) · 5.58 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/**
* Returns a list of objects grouped by some property. For example:
* groupBy([{name: 'Steve', team:'blue'}, {name: 'Jack', team: 'red'}, {name: 'Carol', team: 'blue'}], 'team')
*
* returns:
* { 'blue': [{name: 'Steve', team: 'blue'}, {name: 'Carol', team: 'blue'}],
* 'red': [{name: 'Jack', team: 'red'}]
* }
*
* @param {any[]} objects: An array of objects
* @param {string|Function} property: A property to group objects by
* @returns An object where the keys representing group names and the values are the items in objects that are in that group
*/
function groupBy(objects, property) {
// If property is not a function, convert it to a function that accepts one argument (an object) and returns that object's
// value for property (obj[property])
if(typeof property !== 'function') {
const propName = property;
property = (obj) => obj[propName];
}
const groupedObjects = new Map(); // Keys: group names, value: list of items in that group
for(const object of objects) {
const groupName = property(object);
//Make sure that the group exists
if(!groupedObjects.has(groupName)) {
groupedObjects.set(groupName, []);
}
groupedObjects.get(groupName).push(object);
}
// Create an object with the results. Sort the keys so that they are in a sensible "order"
const result = {};
for(const key of Array.from(groupedObjects.keys()).sort()) {
result[key] = groupedObjects.get(key);
}
return result;
}
// Initialize DOM elements that will be used.
const outputDescription = document.querySelector('#output_description');
const wordOutput = document.querySelector('#word_output');
const showRhymesButton = document.querySelector('#show_rhymes');
const showSynonymsButton = document.querySelector('#show_synonyms');
const wordInput = document.querySelector('#word_input');
const savedWords = document.querySelector('#saved_words');
savedWords.textContent = "(none)"
// Stores saved words.
const savedWordsArray = [];
/**
* Makes a request to Datamuse and updates the page with the
* results.
*
* Use the getDatamuseRhymeUrl()/getDatamuseSimilarToUrl() functions to make
* calling a given endpoint easier:
* - RHYME: `datamuseRequest(getDatamuseRhymeUrl(), () => { <your callback> })
* - SIMILAR TO: `datamuseRequest(getDatamuseRhymeUrl(), () => { <your callback> })
*
* @param {String} url
* The URL being fetched.
* @param {Function} callback
* A function that updates the page.
*/
function datamuseRequest(url, callback) {
fetch(url)
.then((response) => response.json())
.then((data) => {
// This invokes the callback that updates the page.
callback(data);
}, (err) => {
console.error(err);
});
}
/**
* Gets a URL to fetch rhymes from Datamuse
*
* @param {string} rel_rhy
* The word to be rhymed with.
*
* @returns {string}
* The Datamuse request URL.
*/
function getDatamuseRhymeUrl(rel_rhy) {
return `https://api.datamuse.com/words?${(new URLSearchParams({'rel_rhy': rel_rhy})).toString()}`;
}
/**
* Gets a URL to fetch 'similar to' from Datamuse.
*
* @param {string} ml
* The word to find similar words for.
*
* @returns {string}
* The Datamuse request URL.
*/
function getDatamuseSimilarToUrl(ml) {
return `https://api.datamuse.com/words?${(new URLSearchParams({'ml': ml})).toString()}`;
}
/**
* Add a word to the saved words array and update the #saved_words `<span>`.
*
* @param {string} word
* The word to add.
*/
function addToSavedWords(event) {
let fullText = event.target.parentElement.innerText
savedWordsArray.push(fullText.substring(0, fullText.length - 5))
savedWords.textContent = savedWordsArray.join(', ')
// You'll need to finish this...
}
// Add additional functions/callbacks here.
// Add event listeners here.
function createList(data) {
wordOutput.innerHTML += "<ul>"
data.forEach((row) => {
wordOutput.innerHTML +=
`<li>
${row['word']}
<button onclick="addToSavedWords(event)" style="background-color: green; color: white">save</button>
</li>`
})
wordOutput.innerHTML += "</ul>"
}
function showRyhmes(data) {
outputDescription.textContent = `Words that rhyme with ${wordInput.value}:`
groupedData = (groupBy(data, 'numSyllables'))
if (data.length == 0) wordOutput.innerHTML = "(no results)";
else {
wordOutput.innerHTML = ""
Object.entries(groupedData).forEach(entry => {
const [key, dataInGroup] = entry
wordOutput.innerHTML += `<h3>Syllables: ${key}</h3>`
createList(dataInGroup)
})
}
}
function showSynonyms(data) {
outputDescription.textContent = `Words with a meaning similar to ${wordInput.value}:`
if (data.length == 0) wordOutput.innerHTML = "(no results)";
else {
wordOutput.innerHTML = ""
createList(data)
}
}
showRhymesButton.addEventListener('click', () => {
outputDescription.textContent = "Loading..."
wordOutput.innerHTML = "Loading..."
datamuseRequest(getDatamuseRhymeUrl(wordInput.value), showRyhmes)
})
showSynonymsButton.addEventListener('click', () => {
outputDescription.textContent = "Loading..."
wordOutput.innerHTML = "Loading..."
datamuseRequest(getDatamuseSimilarToUrl(wordInput.value), showSynonyms)
})
wordInput.addEventListener('keydown', (event) => {
if (event.keyCode === 13) {
outputDescription.textContent = "Loading..."
wordOutput.innerHTML = "Loading..."
datamuseRequest(getDatamuseRhymeUrl(wordInput.value), showRyhmes)
}
})