A Star Wars API exercise.
This exercise does not need a package.json
but you will need a server in order to use AJAX.
If you don’t have it already installed, I recommend to use live-server
(which can be installed with npm i -g live-server
and then run from the terminal with the live-server
command in the directory of your project).
Create an index.html
file with:
header
tag which contains:
h1
tag with the following content: “Star Wars Browser”main
tag to which you add the attribute role
with value main
footer
tag with the following content:
Developed with 💙 in Berlin, using the <a href="https://swapi.co/">Star Wars open API</a>.
index.js
file and add the script
tag in your index.html
.index.js
file:
var mainElement = document.querySelector('main');
//
function loadPeople(done) {
/*
fill here
---------
- make a GET request to: 'https://swapi.co/api/people/'
- call the function "done" and pass it the result of the request
*/
}
//
function renderPeople(people) {
/*
fill here
---------
For each given people (use a loop or Array.forEach())
- create a section element (with the document.createElement())
- fill the innerHTML (maybe have a look at template literals) of the section with:
- A header tag which has
- A h1 tag containing the name of the person
- A div tag which has a list of the following information:
- Birth Year
- Eye Color
- Skin Color
- Hair Color
- Height
- Mass
The list items have 2 children span
(one with the class "label" and the other with the class "value")
- Add the section element to the main element of the index.html
*/
}
// call the loadPeople with the renderPeople function as parameter
loadPeople(renderPeople);
background.gif
file and save it at the root of your project.style.css
(don’t forget to add the link
tag):
*,
*:before,
*:after {
box-sizing:/* fill here */;
}
html {
height:/* fill here */;
}
body {
font-family:/* fill here */;
line-height:/* fill here */;
color:/* fill here */;
background-color:/* fill here */;
display:/* fill here */;
flex-direction:/* fill here */;
margin:/* fill here */;
height:/* fill here */;
background-image:/* fill here */;
background-attachment:/* fill here */;
}
a,
a:link,
a:hover,
a:visited {
color:/* fill here */;
text-decoration:/* fill here */;
}
h1,
h2,
h3 {
margin:/* fill here */;
font-weight:/* fill here */;
}
header,
footer {
color:/* fill here */;
background-color:/* fill here */;
}
body>header,
body>footer {
padding-left:/* fill here */;
padding-right:/* fill here */;
}
body>header,
body>footer {
padding-top:/* fill here */;
padding-bottom:/* fill here */;
}
body>header {
border-bottom:/* fill here */;
}
main {
flex-grow:/* fill here */;
overflow:/* fill here */;
display:/* fill here */;
flex-wrap:/* fill here */;
}
body>footer {
border-top:/* fill here */;
}
.person {
width:/* fill here */;
margin:/* fill here */;
background-color:/* fill here */;
border:/* fill here */;
border-radius:/* fill here */;
}
.person>header,
.person>div {
padding:/* fill here */;
}
.person>header {
border-bottom:/* fill here */;
}
.person ul {
padding:/* fill here */;
}
.person li {
display:/* fill here */;
padding:/* fill here */;
}
.person .label {
flex-grow:/* fill here */;
width:/* fill here */;
}
.person .gender {
color:/* fill here */;
}
.person .value {
color:/* fill here */;
}
In your index.js
:
createModal
which returns an element which has a class modal
and has the following HTML content:
<div class="body">
<div class="controls">
<button>close</button>
</div>
<div class="content"></div>
</div>
<div class="underlay"></div>
showModal
with 1 argument: contentElement
and which
content
contentElement
to the modal child element with class content
open
hideModal
which removes the the class open
from theloadData
with arguments url
and done
(basically, move the content of your loadPeople
inside it) and replace the content of your loadPeople
function with loadData('https://swapi.co/api/people/', done);
loadPlanet
with arguments url
and done
loadData
function so that you can pass a url
argument (before the done
argument, in the end it should look like function loadData(url, done) {/* */}
).renderPeople
function:
button
tag above the listbuttonElement.onclick = function(){/* */}
or with buttonElement.addEventListener('click', function() {/* */})
)Add the following code to your style.css
and complete it where necessary.
/* -------------------------------- */
.modal,
.modal>.underlay,
.modal>.body {
position: absolute;
}
.modal,
.modal>.underlay {
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.modal {
height: 0;
z-index: 10;
overflow: hidden;
transition: height 300ms ease;
}
.modal.open {
height: 100%;
}
.modal>.underlay {
z-index: 10;
background-color: rgba(255, 255, 255, 0.7);
}
.modal>.body {
/* fill here */
}
.modal .controls {
/* fill here */
}
.modal .content {
/* fill here */
}
As you have seen, the “people” object that you recieve from your AJAX call is looking a bit like:
{
results: [
{name: /* ... */},
{name: /* ... */},
{name: /* ... */},
/* ... */
],
count: 87,
next: 'https://swapi.co/api/people/?page=2',
previous: null
}
In the “results” array they are only 10 records, but the total amount of people is 87. So basically, it does not give you the complete list of people but only the first 10. In order to load (and display) the next 10 people, you will need to make an other request to the “people.next” URL.
loadData
which takes 2 arguments (url
and done
)renderPeople
function add:
mainElement
nav
element (using document.createElement())button
with:
previous
loadData
with the “people.previous” and renderPeople
button
with:
next
loadData
with the “people.next” and renderPeople
nav
element you creatednav
element to the mainElement
div
element (with a class cards
) and add it to mainElement
section
elements of your loop are append to the div
element you just createdIn your CSS, make changes so that it looks like the previous layout and make styles for the pager buttons (so that they look a bit nicer).
index.html
file, add a nav
with a ul
inside it.index.js
:
renderers
renderPeople
, add a property people
to the renderers
object which reference the renderPeople
function.renderUnimplemented
which will replace the content of the mainElement
by a message like: “Sorry, this is not implemented yet.”renderMenu
which takes a data
argument and add links (use Object.keys(data).forEach(function(key) {/*...*/})
to iterate) in the ul
of the header.
data
objectrenderers
object is found, it calls the loadData
with the renderers[topic]
renderUnimplemented
function (without calling loadData
)loadData
) and then renders the menu.renderPlanets
(similar to the renderPeople
) which renders the planets information and add a reference to the renderPlanets
in the renderers
object like you did with renderPeople
(renderers.planets = renderPlanets;
). You may need to make some changes to your CSS.You probably have a lot of code which looks similar accross your functions. Try to clean that up. :)
Add a visual indication of the loading (between the click on the menu link until the content renders).
Using the hashchange
.
Animate the opening crawl of the films in a star wars fashion.