-
Notifications
You must be signed in to change notification settings - Fork 4
/
3-doggofetch-finished.html
199 lines (164 loc) · 8.45 KB
/
3-doggofetch-finished.html
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<title>Doggo Fetch</title>
<style>
body {
margin: 1rem auto;
padding: 3rem;
font-family: sans-serif;
}
header {
width: 70%;
margin: 1em auto;
}
main {
max-width: 70%;
margin: 0px auto;
display:flex;
flex-direction: column;
}
img {
max-width: 100%;
}
#image-frame {
font-size: x-large;
text-align: center;
margin: 1rem auto;
}
#explanation, #score {
padding: 1rem;
text-align: center;
}
#options {
max-width: 100%;
display: flex;
flex-direction: column;
}
button {
padding: 0.5rem;
font-size: medium;
border-radius: 5px;
}
.correct {
background-color: lightgreen;
}
.incorrect {
background-color: lightpink;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<header>
<h1>Guess the Doggo</h1>
<p>What breed is the dog in this image?</p>
</header>
<main>
<div id="image-frame" >
</div>
<div id="options">
</div>
</main>
</body>
<script type="module">
const RANDOM_IMG_ENDPOINT = "https://dog.ceo/api/breeds/image/random";
const BREEDS = ["affenpinscher", "african", "airedale", "akita", "appenzeller", "shepherd australian", "basenji", "beagle", "bluetick", "borzoi", "bouvier", "boxer", "brabancon", "briard", "norwegian buhund", "boston bulldog", "english bulldog", "french bulldog", "staffordshire bullterrier", "australian cattledog", "chihuahua", "chow", "clumber", "cockapoo", "border collie", "coonhound", "cardigan corgi", "cotondetulear", "dachshund", "dalmatian", "great dane", "scottish deerhound", "dhole", "dingo", "doberman", "norwegian elkhound", "entlebucher", "eskimo", "lapphund finnish", "bichon frise", "germanshepherd", "italian greyhound", "groenendael", "havanese", "afghan hound", "basset hound", "blood hound", "english hound", "ibizan hound", "plott hound", "walker hound", "husky", "keeshond", "kelpie", "komondor", "kuvasz", "labradoodle", "labrador", "leonberg", "lhasa", "malamute", "malinois", "maltese", "bull mastiff", "english mastiff", "tibetan mastiff", "mexicanhairless", "mix", "bernese mountain", "swiss mountain", "newfoundland", "otterhound", "caucasian ovcharka", "papillon", "pekinese", "pembroke", "miniature pinscher", "pitbull", "german pointer", "germanlonghair pointer", "pomeranian", "medium poodle", "miniature poodle", "standard poodle", "toy poodle", "pug", "puggle", "pyrenees", "redbone", "chesapeake retriever", "curly retriever", "flatcoated retriever", "golden retriever", "rhodesian ridgeback", "rottweiler", "saluki", "samoyed", "schipperke", "giant schnauzer", "miniature schnauzer", "english setter", "gordon setter", "irish setter", "sharpei", "english sheepdog", "shetland sheepdog", "shiba", "shihtzu", "blenheim spaniel", "brittany spaniel", "cocker spaniel", "irish spaniel", "japanese spaniel", "sussex spaniel", "welsh spaniel", "english springer", "stbernard", "american terrier", "australian terrier", "bedlington terrier", "border terrier", "cairn terrier", "dandie terrier", "fox terrier", "irish terrier", "kerryblue terrier", "lakeland terrier", "norfolk terrier", "norwich terrier", "patterdale terrier", "russell terrier", "scottish terrier", "sealyham terrier", "silky terrier", "tibetan terrier", "toy terrier", "welsh terrier", "westhighland terrier", "wheaten terrier", "yorkshire terrier", "tervuren", "vizsla", "spanish waterdog", "weimaraner", "whippet", "irish wolfhound"];
// Utility function to get a randomly selected item from an array
function getRandomElement(array) {
const i = Math.floor(Math.random() * array.length);
return array[i];
}
// Utility function to shuffle the order of items in an array in-place
function shuffleArray(array) {
return array.sort((a,b) => Math.random() - 0.5);
}
// TODO 1
// Given an array of possible answers, a correct answer value, and a number of choices to get,
// return a list of that many choices, including the correct answer and others from the array
function getMultipleChoices(n, correctAnswer, array) {
// Use a while loop and the getRandomElement() function
// Make sure there are no duplicates in the array
const choices = [correctAnswer];
while (choices.length < n) {
let candidate = getRandomElement(array);
if (choices.indexOf(candidate) < 0) { // check if this is already in the array
choices.push(candidate); // if not, add it
}
}
return shuffleArray(choices);
}
// TODO 2
// Given a URL such as "https://images.dog.ceo/breeds/poodle-standard/n02113799_2280.jpg"
// return the breed name string as formatted in the breed list, e.g. "standard poodle"
function getBreedFromURL(url) {
// The string method .split(char) may come in handy
// Try to use destructuring as much as you can
const [,path] = url.split("/breeds/");
const [breedID] = path.split("/");
const [breed, subtype] = breedID.split("-");
return [subtype, breed].join(" ");
}
// TODO 3
// Given a URL, fetch the resource at that URL,
// then parse the response as a JSON object,
// finally return the "message" property of its body
async function fetchMessage(url) {
const response = await fetch(url); // Fetch the resource at the given URL
const {message} = await response.json(); // Parse the response as JSON & remember its 'message' value
return message; // Return the message
}
// Function to add the multiple-choice buttons to the page
function renderButtons(choicesArray, correctAnswer) {
// Event handler function to compare the clicked button's value to correctAnswer
// and add "correct"/"incorrect" classes to the buttons as appropriate
function buttonHandler(e) {
if (e.target.value === correctAnswer) {
e.target.classList.add("correct");
} else {
e.target.classList.add("incorrect");
document.querySelector(`button[value="${correctAnswer}"]`).classList.add("correct");
}
}
const options = document.getElementById("options"); // Container for the multiple-choice buttons
// TODO 4
// For each of the choices in choicesArray,
// Create a button element whose name, value, and textContent properties are the value of that choice,
// attach a "click" event listener with the buttonHandler function,
// and append the button as a child of the options element
choicesArray.map(choice => {
let button = document.createElement("button");
button.value = button.name = button.textContent = choice;
button.addEventListener("click", buttonHandler);
options.appendChild(button);
})
}
// Function to add the quiz content to the page
function renderQuiz(imgUrl, correctAnswer, choices) {
const image = document.createElement("img");
image.setAttribute("src", imgUrl);
const frame = document.getElementById("image-frame");
image.addEventListener("load", () => {
// Wait until the image has finished loading before trying to add elements to the page
frame.replaceChildren(image);
renderButtons(choices, correctAnswer);
})
}
// Function to load the data needed to display the quiz
async function loadQuizData() {
document.getElementById("image-frame").textContent = "Fetching doggo...";
const doggoImgUrl = await fetchMessage(RANDOM_IMG_ENDPOINT);
const correctBreed = getBreedFromURL(doggoImgUrl);
const breedChoices = getMultipleChoices(3, correctBreed, BREEDS);
return [doggoImgUrl, correctBreed, breedChoices];
}
// TODO 5
// Asynchronously call the loadQuizData() function,
// Then call renderQuiz() with the returned imageUrl, correctAnswer, and choices
const [imageUrl, correctAnswer, choices] = await loadQuizData();
renderQuiz(imageUrl, correctAnswer, choices);
</script>
</html>