Skip to content

Commit 03b4823

Browse files
committed
Preparation class17 week3
1 parent 40a97b3 commit 03b4823

File tree

11 files changed

+271
-877
lines changed

11 files changed

+271
-877
lines changed

src/lecture3/App.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/* global fetchJSON, createAndAppend, Laureate */
2+
'use strict';
3+
4+
// eslint-disable-next-line
5+
class App {
6+
constructor(queries) {
7+
this.queries = queries;
8+
}
9+
10+
async fetchAndRender(url, container) {
11+
container.innerHTML = '';
12+
const ul = createAndAppend('ul', container, { id: 'list-container' });
13+
try {
14+
const resp = await fetchJSON(url);
15+
resp.laureates
16+
.map(laureate => new Laureate(laureate))
17+
.forEach(laureate => laureate.render(ul));
18+
} catch (err) {
19+
createAndAppend('p', container, { text: err.message });
20+
}
21+
}
22+
23+
start() {
24+
const root = document.getElementById('root');
25+
const select = createAndAppend('select', root);
26+
27+
this.queries.forEach((query, index) => {
28+
createAndAppend('option', select, { value: index, text: query.description });
29+
});
30+
31+
select.addEventListener('change', () => {
32+
const query = this.queries[select.value];
33+
this.fetchAndRender(query.url, container);
34+
});
35+
36+
const container = createAndAppend('div', root, { id: 'list-container' });
37+
this.fetchAndRender(this.queries[0].url, container);
38+
}
39+
}

src/lecture3/Laureate.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/* global createAndAppend */
2+
3+
'use strict';
4+
5+
// eslint-disable-next-line no-unused-vars
6+
class Laureate {
7+
constructor(laureate) {
8+
this.laureate = laureate;
9+
}
10+
11+
addRow(label, value, tbody) {
12+
const tr = createAndAppend('tr', tbody);
13+
createAndAppend('td', tr, { class: 'label', text: label });
14+
createAndAppend('td', tr, { text: value });
15+
}
16+
17+
render(container) {
18+
const li = createAndAppend('li', container, { class: 'list-item' });
19+
const table = createAndAppend('table', li);
20+
const tbody = createAndAppend('tbody', table);
21+
const fullName = `${this.laureate.firstname} ${this.laureate.surname}`;
22+
this.addRow('Name:', fullName, tbody);
23+
const bornDetails = `${this.laureate.born}, ${this.laureate.bornCity}`;
24+
this.addRow('Born:', bornDetails, tbody);
25+
}
26+
}

src/lecture3/index.html

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
8+
<title>Nobel Prizes</title>
9+
<link rel="stylesheet" href="style.css">
10+
</head>
11+
12+
<body>
13+
<div id="root"></div>
14+
<script src="util.js"></script>
15+
<script src="Laureate.js"></script>
16+
<script src="App.js"></script>
17+
<script src="index.js"></script>
18+
</body>
19+
20+
</html>

src/lecture3/index.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/* global App */
2+
'use strict';
3+
{
4+
const QUERIES = [
5+
{
6+
description: 'All Dutch laureates',
7+
url: 'http://api.nobelprize.org/v1/laureate.json?bornCountryCode=NL'
8+
},
9+
{
10+
description: 'All female laureates',
11+
url: 'http://api.nobelprize.org/v1/laureate.json?gender=female'
12+
}
13+
];
14+
15+
const app = new App(QUERIES);
16+
window.onload = () => app.start();
17+
}

src/lecture3/style.css

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
body {
2+
font-family: 'Roboto', sans-serif;
3+
width: 640px;
4+
margin-left: auto;
5+
margin-right: auto;
6+
background-color: #fafafa;
7+
}
8+
9+
.toolbar {
10+
display: flex;
11+
flex-direction: row;
12+
justify-content: flex-start;
13+
align-content: center;
14+
padding: 8px;
15+
border: solid 1px darkgray;
16+
border-radius: 0.25rem;
17+
background-color: white;
18+
}
19+
20+
select {
21+
margin-bottom: 16px;
22+
font-size: 14px;
23+
width: 100%;
24+
height: 32px;
25+
}
26+
27+
table {
28+
margin-top: 16px;
29+
padding: 16px;
30+
table-layout: fixed;
31+
color: rgb(0, 0, 0, 81%);
32+
}
33+
34+
td {
35+
padding: 10px;
36+
vertical-align: top;
37+
}
38+
39+
td:first-child {
40+
width: 80px;
41+
}
42+
43+
td.label {
44+
font-weight: bold;
45+
}
46+
47+
td ul {
48+
margin-top: 0;
49+
margin-bottom: 0;
50+
padding-left: 16px;
51+
}
52+
53+
td li {
54+
padding-bottom: 8px;
55+
}
56+
57+
#list-container {
58+
display: flex;
59+
flex-direction: column;
60+
list-style-type: none;
61+
padding: 0;
62+
margin: 0;
63+
}
64+
65+
.list-item {
66+
margin-bottom: 8px;
67+
border: none;
68+
border-radius: 2px;
69+
background-color: #fff;
70+
box-shadow: 0 1px 8px 0 rgba(0, 0, 0, 0.2), 0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 3px 3px -2px rgba(0, 0, 0, 0.12);
71+
}
72+
73+
.alert {
74+
padding: .75rem 1.25rem;
75+
margin-bottom: 1rem;
76+
border-radius: .25rem;
77+
}
78+
79+
.alert-error {
80+
color: #721c24;
81+
background-color: #f8d7da;
82+
}
83+
84+
.motivation {
85+
font-style: italic;
86+
}

src/lecture3/util.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
3+
// eslint-disable-next-line no-unused-vars
4+
function fetchJSON(url) {
5+
return new Promise((resolve, reject) => {
6+
const xhr = new XMLHttpRequest();
7+
xhr.open('GET', url);
8+
xhr.responseType = 'json';
9+
xhr.onload = () => {
10+
if (xhr.status < 400) {
11+
resolve(xhr.response);
12+
} else {
13+
reject(new Error(`Network error: ${xhr.status} - ${xhr.statusText}`));
14+
}
15+
};
16+
xhr.onerror = () => reject(new Error('Network request failed'));
17+
xhr.send();
18+
});
19+
}
20+
21+
// eslint-disable-next-line no-unused-vars
22+
function createAndAppend(name, parent, options = {}) {
23+
const elem = document.createElement(name);
24+
parent.appendChild(elem);
25+
for (const key of Object.keys(options)) {
26+
if (key === 'text') {
27+
elem.innerText = options.text;
28+
} else {
29+
elem.setAttribute(key, options[key]);
30+
}
31+
}
32+
return elem;
33+
}

src/live/app.js

Lines changed: 50 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
11
'use strict';
22
{
3-
// cb(err, data)
3+
function fetchJSON(url) {
4+
return new Promise((resolve, reject) => {
5+
const xhr = new XMLHttpRequest();
6+
xhr.open('GET', url);
7+
xhr.responseType = 'json';
8+
xhr.onload = () => {
9+
if (xhr.status < 400) {
10+
resolve(xhr.response);
11+
} else {
12+
reject(new Error(`Network error: ${xhr.status} - ${xhr.statusText}`));
13+
}
14+
};
15+
xhr.onerror = () => reject(new Error('Network request failed'));
16+
xhr.send();
17+
});
18+
}
419

520
function createAndAppend(name, parent, options = {}) {
621
const elem = document.createElement(name);
@@ -21,54 +36,52 @@
2136
createAndAppend('td', tr, { text: value });
2237
}
2338

24-
function renderLaureates(ul, data) {
25-
ul.innerHTML = '';
26-
27-
data.laureates.forEach(laureate => {
28-
const li = createAndAppend('li', ul, { class: 'list-item' });
29-
const table = createAndAppend('table', li);
30-
const tbody = createAndAppend('tbody', table);
31-
const fullName = `${laureate.firstname} ${laureate.surname}`;
32-
addRow('Name:', fullName, tbody);
33-
const bornDetails = `${laureate.born}, ${laureate.bornCity}`;
34-
addRow('Born:', bornDetails, tbody);
35-
});
39+
async function fetchAndRender(url, container) {
40+
container.innerHTML = '';
41+
const ul = createAndAppend('ul', container, { id: 'list-container' });
42+
try {
43+
const resp = await fetchJSON(url);
44+
resp.laureates.forEach(laureate => {
45+
const li = createAndAppend('li', ul, { class: 'list-item' });
46+
const table = createAndAppend('table', li);
47+
const tbody = createAndAppend('tbody', table);
48+
const fullName = `${laureate.firstname} ${laureate.surname}`;
49+
addRow('Name:', fullName, tbody);
50+
const bornDetails = `${laureate.born}, ${laureate.bornCity}`;
51+
addRow('Born:', bornDetails, tbody);
52+
});
53+
} catch (err) {
54+
createAndAppend('p', container, { text: err.message });
55+
}
3656
}
3757

38-
function main() {
39-
const queries = [
40-
{
41-
description: 'All Dutch lauerates',
42-
url: 'http://api.nobelprize.org/v1/laureate.json?bornCountryCode=NL'
43-
},
44-
{
45-
description: 'All female laureates',
46-
url: 'http://api.nobelprize.org/v1/laureate.json?gender=female'
47-
}
48-
];
49-
58+
function main(queries) {
5059
const root = document.getElementById('root');
5160
const select = createAndAppend('select', root);
61+
5262
queries.forEach((query, index) => {
5363
createAndAppend('option', select, { value: index, text: query.description });
5464
});
5565

56-
const ul = createAndAppend('ul', root, { id: 'list-container' });
57-
5866
select.addEventListener('change', () => {
59-
console.log(select.value);
6067
const query = queries[select.value];
61-
fetchJSON(query.url, (err, data) => {
62-
renderLaureates(ul, data);
63-
});
64-
});
65-
66-
67-
fetchJSON(queries[0].url, (err, data) => {
68-
renderLaureates(ul, data);
68+
fetchAndRender(query.url, container);
6969
});
7070

71+
const container = createAndAppend('div', root, { id: 'list-container' });
72+
fetchAndRender(queries[0].url, container);
7173
}
7274

73-
window.onload = main;
75+
const QUERIES = [
76+
{
77+
description: 'All Dutch lauerates',
78+
url: 'http://api.nobelprize.org/v1/laureate.json?bornCountryCode=NL'
79+
},
80+
{
81+
description: 'All female laureates',
82+
url: 'http://api.nobelprize.org/v1/laureate.json?gender=female'
83+
}
84+
];
85+
86+
window.onload = () => main(QUERIES);
7487
}

src/live/fetchjson.js

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)